package de.lighti.util; import java.nio.ByteBuffer; import java.util.BitSet; /** * A BitInputBuffer wraps a stream of bytes so they can be read bit by bit. * * @author Tobias Mahlmann * */ public class BitInputBuffer { /** * Converts an array of bits into a (signed) integer. * @param a an array of bits. The first array element is treated as the highest bit. * @return the integer */ private static int encodeBoolAsInt( boolean[] a ) { int result = 0; for (int i = 0; i < a.length; i++) { final int value = (a[i] ? 1 : 0) << i; result = result | value; } return result; } /** * back buffer. */ private final BitSet data; /** * Current position in data. */ private int position; public BitInputBuffer( byte[] bytes ) { data = BitSet.valueOf( bytes ); } public BitInputBuffer( ByteBuffer data ) { final byte[] temp = new byte[data.capacity()]; data.get( temp ); this.data = BitSet.valueOf( temp ); } public int getPosition() { return position; } public boolean hasNext() { return position < data.length(); } public boolean readBit() { return readBits( 1 )[0]; } public void readBits( byte[] data, int bit_length ) { int remaining = bit_length; int i = 0; while (remaining >= 8) { data[i++] = (byte) readBitsAsInt( 8 ); remaining -= 8; } if (remaining > 0) { data[i++] = (byte) readBitsAsInt( remaining ); } } public boolean[] readBits( int bit_length ) { final boolean[] ret = new boolean[bit_length]; for (int i = 0; i < bit_length; i++) { ret[i] = data.get( position++ ); } return ret; } public void readBits( int[] data, int bit_length ) { int remaining = bit_length; int i = 0; while (remaining >= 8) { data[i++] = (char) readBitsAsInt( 8 ); remaining -= 8; } if (remaining > 0) { data[i++] = (char) readBitsAsInt( remaining ); } } public float readBitsAsFloat( int entryBits ) { return Float.intBitsToFloat( readBitsAsInt( entryBits ) ); } public int readBitsAsInt( int entryBits ) { return encodeBoolAsInt( readBits( entryBits ) ); } public String readString( int maxSize ) { final StringBuilder builder = new StringBuilder(); for (int i = 0; i < maxSize - 1; ++i) { final char c = (char) encodeBoolAsInt( readBits( 8 ) ); if (c == '\0') { return builder.toString(); } else { builder.append( c ); } } // builder.append( '\0' ); return builder.toString(); } public int readVar35() { int read = 0; int value = 0; int got; do { got = readBitsAsInt( 8 ); final int lower = got & 0x7F; // final int upper = got >>> 7; value |= lower << read; read += 7; } while (got >>> 7 > 0 && read < 35); return value; } }