Created
February 9, 2016 17:50
-
-
Save cobolfoo/0c4124308e7cc05d82b8 to your computer and use it in GitHub Desktop.
Bit packer for JAVA
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.shadebob.netcode.tools; | |
import java.util.BitSet; | |
/** | |
* Bit packer utility class | |
*/ | |
public class BitPacker { | |
private final static int MAX_SIZE = 32768; | |
private BitSet data = new BitSet(MAX_SIZE); | |
private int numBits = 0; | |
private int readCursor = 0; | |
public void clear() { | |
data.clear(); | |
numBits = 0; | |
} | |
public byte[] toBytes() { | |
pad(); | |
byte[] output = new byte[numBits / 8]; | |
for (int i=0;i<output.length;i++) { | |
output[i] = getByte(); | |
} | |
return output; | |
} | |
public void putByte(byte value) { | |
putByte(value, Byte.SIZE); | |
} | |
public void putByte(byte value, int length) { | |
if (length > Byte.SIZE) { | |
System.out.println("Invalid length (" + length +") in putByte()"); | |
System.exit(-1); | |
} | |
for (int i=0;i<length;i++) { | |
if (((value >> i) & 1) == 1) { | |
data.set(numBits++, true); | |
} else { | |
data.set(numBits++, false); | |
} | |
} | |
} | |
public void putShort(short value) { | |
putShort(value, Short.SIZE); | |
} | |
public void putShort(short value, int length) { | |
if (length > Short.SIZE) { | |
System.out.println("Invalid length (" + length +") in putShort()"); | |
System.exit(-1); | |
} | |
for (int i=0;i<length;i++) { | |
if (((value >> i) & 1) == 1) { | |
data.set(numBits++, true); | |
} else { | |
data.set(numBits++, false); | |
} | |
} | |
} | |
public void putInteger(int value) { | |
putInteger(value, Integer.SIZE); | |
} | |
public void putInteger(int value, int length) { | |
if (length > Integer.SIZE) { | |
System.out.println("Invalid length (" + length +") in putInteger()"); | |
System.exit(-1); | |
} | |
for (int i=0;i<length;i++) { | |
if (((value >> i) & 1) == 1) { | |
data.set(numBits++, true); | |
} else { | |
data.set(numBits++, false); | |
} | |
} | |
} | |
public void putLong(long value) { | |
putLong(value, Long.SIZE); | |
} | |
public void putLong(long value, int length) { | |
if (length > Long.SIZE) { | |
System.out.println("Invalid length (" + length +") in putLong()"); | |
System.exit(-1); | |
} | |
for (int i=0;i<length;i++) { | |
if (((value >> i) & 1) == 1) { | |
data.set(numBits++, true); | |
} else { | |
data.set(numBits++, false); | |
} | |
} | |
} | |
public void putFloat(float value) { | |
int raw = Float.floatToRawIntBits(value); | |
for (int i=0;i<Float.SIZE;i++) { | |
if (((raw >> i) & 1) == 1) { | |
data.set(numBits++, true); | |
} else { | |
data.set(numBits++, false); | |
} | |
} | |
} | |
public void putBoolean(boolean value) { | |
data.set(numBits++, value); | |
} | |
public void putString(String value) { | |
byte[] payload = value.getBytes(); | |
int length = payload.length; | |
if (length > 255) { | |
length = 255; | |
} | |
putInteger(length,8); | |
putBytes(payload); | |
} | |
public void putBytes(byte[] value) { | |
for (int i=0;i<value.length;i++) { | |
putByte(value[i]); | |
} | |
} | |
public static void dumpBytes(byte[] value) { | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
System.out.println("| Dumping bytes, length: " + (value.length*8) + " (" + value.length + " byte(s))"); | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
int count = 0; | |
for (int j=0;j<value.length;j++) { | |
byte v = value[j]; | |
for (int i=0;i<Byte.SIZE;i++) { | |
if (((v >> i) & 1) == 1) { | |
System.out.print("1"); | |
} else { | |
System.out.print("0"); | |
} | |
} | |
System.out.print(" "); | |
count++; | |
if (count == 12) { | |
System.out.println(); | |
count = 0; | |
} | |
} | |
System.out.println(); | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
} | |
public void dump() { | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
System.out.println("| Dumping bitset, length: " + numBits); | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
int count = 0; | |
for (int i=0;i<numBits;i++) { | |
System.out.print(data.get(i)?"1":"0"); | |
if ((i != 0) && (i % 8 == 7)) { | |
System.out.print(" "); | |
count++; | |
if (count == 12) { | |
System.out.println(); | |
count = 0; | |
} | |
} | |
} | |
System.out.println(); | |
System.out.println("+--------------- ------------- ------- ------ --- -- -- - -- -- --"); | |
} | |
public void rewind() { | |
readCursor = 0; | |
} | |
public byte getByte() { | |
return getByte(Byte.SIZE); | |
} | |
public byte getByte(int length) { | |
byte value = 0; | |
for (int i=0;i<length;i++) { | |
value |= (data.get(readCursor++)?1:0) << (i%Byte.SIZE); | |
} | |
return value; | |
} | |
public short getShort() { | |
return getShort(Short.SIZE); | |
} | |
public short getShort(int length) { | |
short value = 0; | |
for (int i=0;i<length;i++) { | |
value |= (data.get(readCursor++)?1:0) << (i%Short.SIZE); | |
} | |
return value; | |
} | |
public int getInteger() { | |
return getInteger(Integer.SIZE); | |
} | |
public int getInteger(int length) { | |
int value = 0; | |
for (int i=0;i<length;i++) { | |
if (readCursor > numBits-1) { | |
System.out.println("Out of bound error, read: " + readCursor +", numBits: " +numBits); | |
System.exit(-1); | |
} | |
value |= (data.get(readCursor++)?1:0) << (i%Integer.SIZE); | |
} | |
return value; | |
} | |
public long getLong() { | |
return getLong(Long.SIZE); | |
} | |
public long getLong(int length) { | |
long value = 0; | |
for (int i=0;i<length;i++) { | |
if (readCursor > numBits-1) { | |
System.out.println("Out of bound error, read: " + readCursor +", numBits: " +numBits); | |
System.exit(-1); | |
} | |
value |= (data.get(readCursor++)?1:0) << (i%Long.SIZE); | |
} | |
return value; | |
} | |
public float getFloat() { | |
return getFloat(Float.SIZE); | |
} | |
public float getFloat(int length) { | |
int value = 0; | |
for (int i=0;i<length;i++) { | |
if (readCursor > numBits-1) { | |
System.out.println("Out of bound error, read: " + readCursor +", numBits: " +numBits); | |
System.exit(-1); | |
} | |
value |= (data.get(readCursor++)?1:0) << (i%Float.SIZE); | |
} | |
return Float.intBitsToFloat(value); | |
} | |
public boolean getBoolean() { | |
if (readCursor > numBits-1) { | |
System.out.println("Out of bound error, read: " + readCursor +", numBits: " +numBits); | |
System.exit(-1); | |
} | |
return data.get(readCursor++); | |
} | |
public byte[] getBytes(int length) { | |
byte[] output = new byte[length]; | |
for (int i=0;i<length;i++) { | |
output[i] = getByte(); | |
} | |
return output; | |
} | |
public String getString() { | |
int length = getInteger(8); | |
byte[] payload = getBytes(length); | |
return new String(payload); | |
} | |
public void pad() { | |
int remaining = 8 - (numBits % 8); | |
for (int i=0;i<remaining;i++) { | |
putBoolean(false); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment