//
// RABytes.java
//
/*
LOCI Bio-Formats package for reading and converting biological file formats.
Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan,
Eric Kjellman and Brian Loranger.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library 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 Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package loci.formats;
import java.io.*;
/**
* A wrapper for a byte array that implements the IRandomAccess interface.
*
* <dl><dt><b>Source code:</b></dt>
* <dd><a href="https://skyking.microscopy.wisc.edu/trac/java/browser/trunk/loci/formats/RABytes.java">Trac</a>,
* <a href="https://skyking.microscopy.wisc.edu/svn/java/trunk/loci/formats/RABytes.java">SVN</a></dd></dl>
*
* @see IRandomAccess
*
* @author Curtis Rueden ctrueden at wisc.edu
*/
public class RABytes implements IRandomAccess {
// -- Fields --
/** The byte array backing this RABytes. */
protected byte[] array;
/** The file pointer. */
protected int fp;
// -- Constructors --
/**
* Creates a random access byte stream to read from, and
* write to, the bytes specified by the byte[] argument.
*/
public RABytes(byte[] bytes) {
array = bytes;
fp = 0;
}
// -- RABytes API methods --
/** Gets the byte array backing this RAFile. */
public byte[] getBytes() { return array; }
// -- IRandomAccess API methods --
/* @see IRandomAccess.close() */
public void close() { }
/* @see IRandomAccess.getFilePointer() */
public long getFilePointer() {
return fp;
}
/* @see IRandomAccess.length() */
public long length() {
return array.length;
}
/* @see IRandomAccess.read() */
public int read() {
return fp < array.length ? array[fp++] : 0;
}
/* @see IRandomAccess.read(byte[]) */
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
/* @see IRandomAccess.read(byte[], int, int) */
public int read(byte[] b, int off, int len) throws IOException {
if (fp + len > array.length) len = array.length - fp;
System.arraycopy(array, fp, b, off, len);
fp += len;
return len;
}
/* @see IRandomAccess.seek(long) */
public void seek(long pos) throws IOException {
if (pos < 0) throw new IOException("pos < 0");
if (pos > Integer.MAX_VALUE) throw new IOException("pos is too large");
fp = (int) pos;
}
/* @see IRandomAccess.setLength(long) */
public void setLength(long newLength) throws IOException {
if (newLength > Integer.MAX_VALUE) {
throw new IOException("newLength is too large");
}
int len = (int) newLength;
byte[] bytes = new byte[len];
System.arraycopy(array, 0, bytes, 0,
array.length < len ? array.length : len);
array = bytes;
}
// -- DataInput API methods --
/* @see java.io.DataInput.readBoolean() */
public boolean readBoolean() throws IOException {
return readByte() != 0;
}
/* @see java.io.DataInput.readByte() */
public byte readByte() throws IOException {
if (fp + 1 > array.length) throw new EOFException();
return array[fp++];
}
/* @see java.io.DataInput.readChar() */
public char readChar() throws IOException {
if (fp + 2 > array.length) throw new EOFException();
char c = (char) DataTools.bytesToShort(array, fp, false);
fp += 2;
return c;
}
/* @see java.io.DataInput.readDouble() */
public double readDouble() throws IOException {
if (fp + 8 > array.length) throw new EOFException();
double d = Double.longBitsToDouble(DataTools.bytesToLong(array, fp, false));
fp += 8;
return d;
}
/* @see java.io.DataInput.readFloat() */
public float readFloat() throws IOException {
if (fp + 4 > array.length) throw new EOFException();
float f = Float.intBitsToFloat(DataTools.bytesToInt(array, fp, false));
fp += 4;
return f;
}
/* @see java.io.DataInput.readFully(byte[]) */
public void readFully(byte[] b) throws IOException {
readFully(b, 0, b.length);
}
/* @see java.io.DataInput.readFully(byte[], int, int) */
public void readFully(byte[] b, int off, int len) throws IOException {
if (fp + len > array.length) throw new EOFException();
System.arraycopy(array, fp, b, off, len);
fp += len;
}
/* @see java.io.DataInput.readInt() */
public int readInt() throws IOException {
if (fp + 4 > array.length) throw new EOFException();
int i = DataTools.bytesToInt(array, fp, false);
fp += 4;
return i;
}
/* @see java.io.DataInput.readLine() */
public String readLine() throws IOException {
throw new IOException("Unimplemented");
}
/* @see java.io.DataInput.readLong() */
public long readLong() throws IOException {
if (fp + 8 > array.length) throw new EOFException();
long l = DataTools.bytesToLong(array, fp, false);
fp += 8;
return l;
}
/* @see java.io.DataInput.readShort() */
public short readShort() throws IOException {
if (fp + 2 > array.length) throw new EOFException();
short s = DataTools.bytesToShort(array, fp, false);
fp += 2;
return s;
}
/* @see java.io.DataInput.readUnsignedByte() */
public int readUnsignedByte() throws IOException {
if (fp + 1 > array.length) throw new EOFException();
return DataTools.bytesToInt(array, fp++, 1, false);
}
/* @see java.io.DataInput.readUnsignedShort() */
public int readUnsignedShort() throws IOException {
if (fp + 2 > array.length) throw new EOFException();
int i = DataTools.bytesToInt(array, fp, 2, false);
fp += 2;
return i;
}
/* @see java.io.DataInput.readUTF() */
public String readUTF() throws IOException {
throw new IOException("Unimplemented");
}
/* @see java.io.DataInput.skipBytes(int) */
public int skipBytes(int n) {
if (n < 0) n = 0;
if (fp + n > array.length) n = array.length - fp;
fp += n;
return n;
}
// -- DataOutput API metthods --
/* @see java.io.DataOutput.write(byte[]) */
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
/* @see java.io.DataOutput.write(byte[], int, int) */
public void write(byte[] b, int off, int len) throws IOException {
if (fp + len > array.length) setLength(fp + len);
System.arraycopy(b, off, array, fp, len);
fp += b.length;
}
/* @see java.io.DataOutput.write(int b) */
public void write(int b) throws IOException {
if (fp + 1 > array.length) setLength(fp + 1);
array[fp++] = (byte) b;
}
/* @see java.io.DataOutput.writeBoolean(boolean) */
public void writeBoolean(boolean v) throws IOException {
write(v ? 1 : 0);
}
/* @see java.io.DataOutput.writeByte(int) */
public void writeByte(int v) throws IOException {
write(v);
}
/* @see java.io.DataOutput.writeBytes(String) */
public void writeBytes(String s) throws IOException {
char[] c = s.toCharArray();
byte[] b = new byte[c.length];
for (int i=0; i<c.length; i++) b[i] = (byte) c[i];
write(b);
}
/* @see java.io.DataOutput.writeChar(int) */
public void writeChar(int v) throws IOException {
if (fp + 2 > array.length) setLength(fp + 2);
array[fp++] = (byte) (0xff & (v >> 8));
array[fp++] = (byte) (0xff & v);
}
/* @see java.io.DataOutput.writeChars(String) */
public void writeChars(String s) throws IOException {
int len = 2 * s.length();
if (fp + len > array.length) setLength(fp + len);
char[] c = s.toCharArray();
for (int i=0; i<c.length; i++) {
char v = c[i];
array[fp++] = (byte) (0xff & (v >> 8));
array[fp++] = (byte) (0xff & v);
}
}
/* @see java.io.DataOutput.writeDouble(double) */
public void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
/* @see java.io.DataOutput.writeFloat(float) */
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
/* @see java.io.DataOutput.writeInt(int) */
public void writeInt(int v) throws IOException {
if (fp + 4 > array.length) setLength(fp + 4);
array[fp++] = (byte) (0xff & (v >> 24));
array[fp++] = (byte) (0xff & (v >> 16));
array[fp++] = (byte) (0xff & (v >> 8));
array[fp++] = (byte) (0xff & v);
}
/* @see java.io.DataOutput.writeLong(long) */
public void writeLong(long v) throws IOException {
if (fp + 8 > array.length) setLength(fp + 8);
array[fp++] = (byte) (0xff & (v >> 56));
array[fp++] = (byte) (0xff & (v >> 48));
array[fp++] = (byte) (0xff & (v >> 40));
array[fp++] = (byte) (0xff & (v >> 32));
array[fp++] = (byte) (0xff & (v >> 24));
array[fp++] = (byte) (0xff & (v >> 16));
array[fp++] = (byte) (0xff & (v >> 8));
array[fp++] = (byte) (0xff & v);
}
/* @see java.io.DataOutput.writeShort(int) */
public void writeShort(int v) throws IOException {
if (fp + 2 > array.length) setLength(fp + 2);
array[fp++] = (byte) (0xff & (v >> 24));
array[fp++] = (byte) (0xff & (v >> 16));
array[fp++] = (byte) (0xff & (v >> 8));
array[fp++] = (byte) (0xff & v);
}
/* @see java.io.DataOutput.writeUTF(String) */
public void writeUTF(String str) throws IOException {
throw new IOException("Unimplemented");
}
}