Skip to content

Instantly share code, notes, and snippets.

@Techcable
Created May 25, 2016 23:45
Show Gist options
  • Select an option

  • Save Techcable/230c492d4f86c6b0e7aa2f97acb62b24 to your computer and use it in GitHub Desktop.

Select an option

Save Techcable/230c492d4f86c6b0e7aa2f97acb62b24 to your computer and use it in GitHub Desktop.
A list of booleans packed into a byte
@FunctionalInterface
public interface BooleanConsumer {
public void accept(boolean b);
}
import static com.google.common.base.Preconditions.*;
public class PackedBooleanList {
private final byte[] bytes;
private final int bitsInLastByte;
public PacketBooleanList(byte[] bytes) {
if (bytes.length == 0) {
bitsInLastByte = 0;
} else if (bytes.length == 1) {
throw new IllegalArgumentException("A PacketBooleanList's backing byte array can't have just one byte");
} else {
bitsInLastByte = bytes[0];
checkArgument(bitsInLastByte > 0, "Negative bits in last byte %s", bitsInLastByte);
checkArgument(bitsInLastByte < 8, "Bits in last byte %s is bigger than 7", bitsInLastByte);
}
}
public PacketBooleanList() {
this(new boolean[0]);
}
public PacketBooleanList(boolean[] booleans) {
if (booleans.length == 0) {
this.bytes = new byte[0];
bitsInLastByte = 0;
} else {
final int length = booleans.size();
byte[] result = new byte[((length + 7) / 8)];
int bitsInLastByte = result.length * 8 == length ? 8 : result.length * 8 - length;
int finalIndex = result.length - 1;
int booleanIndex = 0;
for (int byteIndex = 1; byteIndex < result.length; byteIndex++) {
int bits = byteIndex == finalIndex ? bitsInLastByte : 8;
byte b = 0;
for (int bitIndex = 0; bitIndex < bits; bitIndex++) {
int bit = booleans.get(booleanIndex++).getValue() ? 1 : 0;
b |= (bit << bitIndex);
}
result[byteIndex] = b;
}
}
}
public int size() {
int length = getNbt().c().length;
return length == 0 ? 0 : (length - 1) * 8 + bitsInLastByte;
}
public boolean get(int index) {
byte[] bytes = this.bytes;
int length = bytes.length;
int byteIndex = (index / 8);
byte b;
if (byteIndex < 0) {
throw new IllegalArgumentException("Negative index " + index);
} else if (byteIndex >= length) {
throw new IndexOutOfBoundsException("Invalid index " + index + " for size " + size());
} else {
b = bytes[byteIndex];
}
int bitIndex = index % 8;
if (bitIndex == length - 1 && bitIndex >= bitsInLastByte) {
throw new IndexOutOfBoundsException("Invalid index " + index + " for size " + size());
}
return ((b >>> bitIndex) & 0x1) != 0;
}
public boolean set(int index, boolean b) {
byte[] bytes = this.bytes;
int length = bytes.length;
int byteIndex = (index / 8);
byte b;
if (byteIndex < 0) {
throw new IllegalArgumentException("Negative index " + index);
} else if (byteIndex >= length) {
throw new IndexOutOfBoundsException("Invalid index " + index + " for size " + size());
} else {
b = bytes[byteIndex];
}
int bitIndex = index % 8;
if (bitIndex == length - 1 && bitIndex >= bitsInLastByte) {
throw new IndexOutOfBoundsException("Invalid index " + index + " for size " + size());
}
b |= ((b ? 1 : 0) <<< bitIndex);
bytes[byteIndex] = b;
}
public boolean[] toArray() {
boolean[] result = new boolean[size()];
for (int i = 0; i < result.length; i++) {
result[i] = get(index);
}
}
public byte[] toByteArray() {
byte[] bytes = this.bytes;
byte[] result = new byte[bytes.length + 1];
result[0] = (byte) bitsInLastByte;
System.arraycopy(bytes, 0, result, 1, bytes.length);
return result;
}
public void forEach(BooleanConsumer action) {
byte[] bytes = this.bytes;
int length = bytes.length;
int finalIndex = length - 1;
for (int byteIndex = 0; byteIndex < length; byteIndex++) {
int bits = byteIndex == finalIndex ? bitsInLastByte : 8;
byte b = bytes[byteIndex];
for (int bitIndex = 0; bitIndex < bits; bitIndex++) {
int bit = (b >>> bitIndex) & 0x1;
action.accept(bit != 1);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment