diff options
Diffstat (limited to 'src/fjbg/ch/epfl/lamp/util/ByteArray.java')
-rw-r--r-- | src/fjbg/ch/epfl/lamp/util/ByteArray.java | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/fjbg/ch/epfl/lamp/util/ByteArray.java b/src/fjbg/ch/epfl/lamp/util/ByteArray.java new file mode 100644 index 0000000000..800fc9d0d8 --- /dev/null +++ b/src/fjbg/ch/epfl/lamp/util/ByteArray.java @@ -0,0 +1,140 @@ +// $Id$ + +package ch.epfl.lamp.util; + +import java.io.*; + +/** + * Array of bytes. + * + * @author Michel Schinz + * @version 1.0 + */ + +public class ByteArray { + protected final static int BYTE_BLOCK_BITS = 8; + protected final static int BYTE_BLOCK_SIZE = 1 << BYTE_BLOCK_BITS; + protected final static int BYTE_BLOCK_MASK = BYTE_BLOCK_SIZE - 1; + + protected byte[][] data = new byte[][] { new byte[BYTE_BLOCK_SIZE] }; + protected int pos = 0; // The next free position. + + protected boolean frozen = false; + + public ByteArray() { } + + public ByteArray(InputStream stream, int size) throws IOException { + size = pos; + for (int block = 0; size > 0; ++block) { + int sizeToRead = Math.min(BYTE_BLOCK_SIZE, size); + stream.read(data[block], 0, sizeToRead); + + size -= sizeToRead; + if (size > 0) addNewBlock(); + } + } + + public void freeze() { frozen = true; } + + public int nextBytePosition() { + return pos; + } + + public int getSize() { + return pos; + } + + protected void addNewBlock() { + int nextBlockPos = pos >>> BYTE_BLOCK_BITS; + if (nextBlockPos == data.length) { + byte[][] newData = new byte[data.length * 2][]; + System.arraycopy(data, 0, newData, 0, data.length); + data = newData; + } + assert data[nextBlockPos] == null : pos + " " + nextBlockPos; + data[nextBlockPos] = new byte[BYTE_BLOCK_SIZE]; + } + + protected void addByte(int b) { + assert !frozen; + + if ((pos & BYTE_BLOCK_MASK) == 0 && pos > 0) + addNewBlock(); + int currPos = pos++; + data[currPos >>> BYTE_BLOCK_BITS][currPos & BYTE_BLOCK_MASK] = (byte)b; + } + + public void addU1(int i) { + assert i <= 0xFF : i; + addByte(i); + } + + public void addU2(int i) { + assert i <= 0xFFFF : i; + + addByte(i >>> 8); + addByte(i & 0xFF); + } + + public void addU4(int i) { + addByte(i >>> 24); + addByte((i >>> 16) & 0xFF); + addByte((i >>> 8) & 0xFF); + addByte(i & 0xFF); + } + + public void putByte(int targetPos, int b) { + assert !frozen; + assert targetPos < pos : targetPos + " >= " + pos; + + data[targetPos >>> BYTE_BLOCK_BITS][targetPos & BYTE_BLOCK_MASK] = (byte)b; + } + + public void putU2(int targetPos, int i) { + assert i < 0xFFFF : i; + putByte(targetPos, i >>> 8); + putByte(targetPos + 1, i & 0xFF); + } + + public void putU4(int targetPos, int i) { + putByte(targetPos, i >>> 24); + putByte(targetPos + 1, (i >>> 16) & 0xFF); + putByte(targetPos + 2, (i >>> 8) & 0xFF); + putByte(targetPos + 3, i & 0xFF); + } + + public int getU1(int sourcePos) { + assert sourcePos < pos : sourcePos + " >= " + pos; + return data[sourcePos >>> BYTE_BLOCK_BITS][sourcePos & BYTE_BLOCK_MASK] & 0xFF; + } + + public int getU2(int sourcePos) { + return (getU1(sourcePos) << 8) | getU1(sourcePos + 1); + } + + public int getU4(int sourcePos) { + return (getU2(sourcePos) << 16) | getU2(sourcePos + 2); + } + + public int getS1(int sourcePos) { + assert sourcePos < pos : sourcePos + " >= " + pos; + return data[sourcePos >>> BYTE_BLOCK_BITS][sourcePos & BYTE_BLOCK_MASK]; + } + + public int getS2(int sourcePos) { + return (getS1(sourcePos) << 8) | getU1(sourcePos + 1); + } + + public int getS4(int sourcePos) { + return (getS2(sourcePos) << 16) | getU2(sourcePos + 2); + } + + public void writeTo(OutputStream stream) throws IOException { + if (!frozen) freeze(); + + for (int i = 0; i < data.length && data[i] != null; ++i) { + int len = Math.min(BYTE_BLOCK_SIZE, pos - (i << BYTE_BLOCK_BITS)); + stream.write(data[i], 0, len); + } + } +} |