/*
* org.openmicroscopy.shoola.util.mem.ByteArray
*
*------------------------------------------------------------------------------
* 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 org.openmicroscopy.shoola.util.mem;
//Java imports
import java.io.IOException;
import java.io.InputStream;
//Third-party libraries
//Application-internal dependencies
/**
* A read-write slice of a given array.
* This class extends {@link ReadOnlyByteArray} to allow for elements to be
* written to the array slice. This class works just like its parent; so you
* get relative indexing and any changes to the original array will be visible
* in the corresponding <code>ByteArray</code> object, and vice-versa, any
* invocation of the <code>set</code> methods will be reflected into the
* original array.
*
* @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$)
* </small>
* @since OME2.2
*/
public class ByteArray
extends ReadOnlyByteArray
{
/**
* Creates a read-write 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 ByteArray(byte[] base, int offset, int length)
{
super(base, offset, length);
}
/**
* Writes <code>value</code> into the element at the <code>index</code>
* position within this slice.
*
* @param index The index, within this slice, at which to write. Must be
* in the <code>[0, {@link ReadOnlyByteArray#length})</code>
* interval.
* @param value The value to write.
*/
public void set(int index, byte value)
{
checkIndex(index);
base[offset+index] = value;
}
/**
* Copies the values in <code>buf</code> into this slice, starting from
* <code>index</code>.
* This method first checks to see whether <code>buf.length</code> bytes
* can be written into this slice starting from <code>index</code>. If
* the check fails an {@link ArrayIndexOutOfBoundsException} is thrown
* and no data is copied at all.
*
* @param index The index, within this slice, from which to start writing.
* Must be in the <code>[0, {@link ReadOnlyByteArray#length})
* </code> interval.
* @param buf A buffer containing the values to write. Mustn't be
* <code>null</code> and must fit into this slice. If
* the length is <code>0</code>, then this method does
* nothing.
*/
public void set(int index, byte[] buf)
{
if (buf == null) throw new NullPointerException("No buffer.");
if (buf.length == 0) return;
checkIndex(index);
checkIndex(index+buf.length-1);
System.arraycopy(buf, 0, base, offset+index, buf.length);
}
/**
* Writes up to <code>maxLength</code> bytes from the supplied stream into
* this slice, starting from <code>index</code>.
* To be precise, this method will attempt to write <code>m</code> bytes
* into this slice (starting from the element at <code>index</code>),
* <code>m</code> being the minimum of the following numbers:
* <code>maxLength</code>,
* <code>this.{@link ReadOnlyByteArray#length length} - index</code>
* (that is, bytes from <code>index</code> to the end of the slice),
* and the number of bytes to the end of the supplied stream.
*
* @param index The index, within this slice, from which to start writing.
* Must be in the <code>[0, {@link ReadOnlyByteArray#length})
* </code> interval.
* @param maxLength The maximum amount of bytes to write. If not positive,
* this method does nothing and returns <code>0</code>.
* @param in The stream from which to read data. Mustn't be
* <code>null</code>.
* @return The amount of bytes actually written or <code>-1</code> if the
* end of the stream has been reached.
* @throws IOException If an I/O error occurred while reading data from
* the stream.
*/
public int set(int index, int maxLength, InputStream in)
throws IOException
{
if (in == null) throw new NullPointerException("No stream.");
if (maxLength <= 0) return 0;
checkIndex(index);
maxLength = (index+maxLength <= length ? maxLength : length-index);
return in.read(base, offset+index, maxLength);
}
}