Skip to content

Instantly share code, notes, and snippets.

@grahamedgecombe
Created June 23, 2010 19:40
Show Gist options
  • Save grahamedgecombe/450435 to your computer and use it in GitHub Desktop.
Save grahamedgecombe/450435 to your computer and use it in GitHub Desktop.
Bit packing methods for Netty.
// ****************************************
// READING
// ****************************************
/**
* Switches this builder's mode to the byte access mode.
* @throws IllegalStateException if the builder is already in byte access
* mode.
*/
public void switchToByteAccess() {
if (mode == AccessMode.BYTE_ACCESS) {
throw new IllegalStateException("Already in byte access mode");
}
mode = AccessMode.BYTE_ACCESS;
buffer.readerIndex((bitIndex + 7) / 8);
}
/**
* Switches this builder's mode to the bit access mode.
* @throws IllegalStateException if the builder is already in bit access
* mode.
*/
public void switchToBitAccess() {
if (mode == AccessMode.BIT_ACCESS) {
throw new IllegalStateException("Already in bit access mode");
}
mode = AccessMode.BIT_ACCESS;
bitIndex = buffer.readerIndex() * 8;
}
/**
* Gets {@code numBits} from the buffer.
* @param numBits The number of bits.
* @return The value.
* @throws IllegalStateException if the reader is not in bit access mode.
* @throws IllegalArgumentException if the number of bits is not between 1
* and 31 inclusive.
*/
public int getBits(int numBits) {
if (numBits < 0 || numBits > 32) {
throw new IllegalArgumentException("Number of bits must be between 1 and 32 inclusive");
}
checkBitAccess();
int bytePos = bitIndex >> 3;
int bitOffset = 8 - (bitIndex & 7);
int value = 0;
bitIndex +=numBits;
for (; numBits > bitOffset; bitOffset = 8) {
value += (buffer.getByte(bytePos++) & DataConstants.BIT_MASK[bitOffset]) << numBits - bitOffset;
numBits -= bitOffset;
}
if (numBits == bitOffset) {
value += buffer.getByte(bytePos) & DataConstants.BIT_MASK[bitOffset];
} else {
value += buffer.getByte(bytePos) >> bitOffset - numBits & DataConstants.BIT_MASK[numBits];
}
return value;
}
// ****************************************
// WRITING
// ****************************************
/**
* Switches this builder's mode to the byte access mode.
* @throws IllegalStateException if the builder is already in byte access
* mode.
*/
public void switchToByteAccess() {
if (mode == AccessMode.BYTE_ACCESS) {
throw new IllegalStateException("Already in byte access mode");
}
mode = AccessMode.BYTE_ACCESS;
buffer.writerIndex((bitIndex + 7) / 8);
}
/**
* Switches this builder's mode to the bit access mode.
* @throws IllegalStateException if the builder is already in bit access
* mode.
*/
public void switchToBitAccess() {
if (mode == AccessMode.BIT_ACCESS) {
throw new IllegalStateException("Already in bit access mode");
}
mode = AccessMode.BIT_ACCESS;
bitIndex = buffer.writerIndex() * 8;
}
/**
* Puts {@code numBits} into the buffer with the value {@code value}.
* @param numBits The number of bits to put into the buffer.
* @param value The value.
* @throws IllegalStateException if the builder is not in bit access mode.
* @throws IllegalArgumentException if the number of bits is not between 1
* and 31 inclusive.
*/
public void putBits(int numBits, int value) {
if (numBits < 0 || numBits > 32) {
throw new IllegalArgumentException("Number of bits must be between 1 and 32 inclusive");
}
checkBitAccess();
int bytePos = bitIndex >> 3;
int bitOffset = 8 - (bitIndex & 7);
bitIndex += numBits;
int requiredSpace = bytePos - buffer.writerIndex() + 1;
requiredSpace += (numBits + 7) / 8;
buffer.ensureWritableBytes(requiredSpace);
for (; numBits > bitOffset; bitOffset = 8) {
int tmp = buffer.getByte(bytePos);
tmp &= ~DataConstants.BIT_MASK[bitOffset];
tmp |= (value >> (numBits-bitOffset)) & DataConstants.BIT_MASK[bitOffset];
buffer.setByte(bytePos++, tmp);
numBits -= bitOffset;
}
if (numBits == bitOffset) {
int tmp = buffer.getByte(bytePos);
tmp &= ~DataConstants.BIT_MASK[bitOffset];
tmp |= value & DataConstants.BIT_MASK[bitOffset];
buffer.setByte(bytePos, tmp);
} else {
int tmp = buffer.getByte(bytePos);
tmp &= ~(DataConstants.BIT_MASK[numBits] << (bitOffset - numBits));
tmp |= (value & DataConstants.BIT_MASK[numBits]) << (bitOffset - numBits);
buffer.setByte(bytePos, tmp);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment