Created
June 23, 2010 19:40
-
-
Save grahamedgecombe/450435 to your computer and use it in GitHub Desktop.
Bit packing methods for Netty.
This file contains hidden or 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
// **************************************** | |
// 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