summaryrefslogtreecommitdiff
path: root/src/fjbg/ch/epfl/lamp/util/ByteArray.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/fjbg/ch/epfl/lamp/util/ByteArray.java')
-rw-r--r--src/fjbg/ch/epfl/lamp/util/ByteArray.java140
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);
+ }
+ }
+}