/*
* training.util.ReadOnlyByteArray
*------------------------------------------------------------------------------
* Copyright (C) 2006 University of Dundee. All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package training.util;
/**
* A read-only slice of a given array.
* Given a <code>base</code> array and an interval <code>[offset, offset+length]
* </code> contained within <code>[0, base.length]</code>, an instance of this
* class provides read access to the elements from <code>base[offset]</code> to
* <code>base[offset+length-1]</code>. However, you access the elements by
* specifying relative indeces to the {@link #get(int) get} method so
* <code>get(0)</code> returns <code>base[offset]</code>, <code>get(1)</code>
* returns <code>base[offset+1]</code>, and so on. One thing to bear in mind
* is that changes to the original <code>base</code> array will be reflected
* to the corresponding <code>ReadOnlyByteArray</code> object as this class
* simply keeps a reference to the original <code>base</code> array, without
* making an internal copy. This can be useful in those situations when you
* want to emulate a memory pointer.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author <br>Andrea Falconi
* <a href="mailto:a.falconi@dundee.ac.uk">
* a.falconi@dundee.ac.uk</a>
* @version 2.2
* @since OME2.2
*/
public class ReadOnlyByteArray
{
/** The original array. */
protected final byte[] base;
/** Marks the start of the slice. */
protected final int offset;
/** The length of the slice. */
public final int length;
/**
* Makes sure that <code>i</code> is in <code>[0, length)</code>.
* Throws an exception if this constraint is not met.
*
* @param i The index to verify.
*/
protected void checkIndex(int i)
{
if (i < 0 || length <= i)
throw new ArrayIndexOutOfBoundsException(
"Index not in [0, "+length+"): "+i+".");
}
/**
* Creates a read-only slice of <code>base</code>.
* The <code>offset</code> argument marks the start of the slice, at
* <code>base[offset]</code>. The <code>length</code> argument defines
* the length of the slice, the last element being
* <code>base[offset+length-1]</code>. Obviously enough, these two
* arguments must define an interval
* <code>[offset, offset+length]</code> in <code>[0, base.length]</code>.
*
* @param base The original array.
* @param offset The start of the slice.
* @param length The length of the slice.
*/
public ReadOnlyByteArray(byte[] base, int offset, int length)
{
if (base == null) throw new NullPointerException("No base.");
if (offset < 0 || length < 0 || base.length < offset+length)
throw new IllegalArgumentException(
"[offset="+offset+", offset+length="+(offset+length)+
"] not in [0, base.length="+base.length+"].");
this.base = base;
this.offset = offset;
this.length = length;
}
/**
* Reads the element at the <code>index</code> position within this
* slice.
*
* @param index The index. Must be in the <code>[0, {@link #length})
* </code> interval.
* @return The element at the <code>index</code> position in this slice.
*/
public byte get(int index)
{
checkIndex(index);
return base[offset+index];
}
}