/* * ome.util.mem.ReadOnlyByteArray * * Copyright 2006 University of Dundee. All rights reserved. * Use is subject to license terms supplied in LICENSE.txt */ package ome.util.mem; /** * 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 <small> (<b>Internal version:</b> $Revision$ $Date: * 2005/06/09 15:01:57 $) </small> * @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]; } }