Blake
Blake

Reputation: 11

Writing values as an arbitrary amount of bits into a byte buffer in C++

Hey, I need to pack bit values into a byte buffer in C++. My Buffer class has a char array and a position, similar to Java's ByteBuffer. I need a good way to pack bits into this buffer, like so:

void put_bits(int amount, uint32_t value);

It needs to support up to 32 bits. I've seen a solution implemented in Java (that requires start/end access methods before bits can be packed) but I'm not sure how to do this in C++ because the endianness and other low level factors aren't hidden like they are in Java.

I have an inline function declared as endianness() which returns 0 (defined as BIG_ENDIAN) or 1 (defined as LITTLE_ENDIAN) that can be used, but I'm just not sure how to properly pack bits into a byte buffer.

This is the Java version of what I need to implement:

public void writeBits(int numBits, int value) {
    int bytePos = bitPosition >> 3;
    int bitOffset = 8 - (bitPosition & 7);
    bitPosition += numBits;

    for(; numBits > bitOffset; bitOffset = 8) {
        buffer[bytePos] &= ~ bitMaskOut[bitOffset];
        buffer[bytePos++] |= (value >> (numBits-bitOffset)) & bitMaskOut[bitOffset];

        numBits -= bitOffset;
    }
    if(numBits == bitOffset) {
        buffer[bytePos] &= ~ bitMaskOut[bitOffset];
        buffer[bytePos] |= value & bitMaskOut[bitOffset];
    }
    else {
        buffer[bytePos] &= ~ (bitMaskOut[numBits]<<(bitOffset - numBits));
        buffer[bytePos] |= (value&bitMaskOut[numBits]) << (bitOffset - numBits);
    }
}

Which requires these two methods as well:

public void initBitAccess() {
    bitPosition = currentOffset * 8;
}

public void finishBitAccess() {
    currentOffset = (bitPosition + 7) / 8;
}

How should I go about solving this? Thanks.

EDIT: I also still need to be able to write normal bytes before and after writing bits.

Upvotes: 1

Views: 1005

Answers (2)

Roland Illig
Roland Illig

Reputation: 41625

As long as you use the byte buffer only as such, you can translate the Java code one-to-one. It only gets dangerous if you interpret a byte pointer as another type and try to store a complete int in the byte buffer.

You don't even need the endianness function in this case, since you store a byte in a byte buffer, and there is nothing to convert or adjust size or whatever.

Upvotes: 2

TonyK
TonyK

Reputation: 17114

Just remove all the public keywords, and I would say that you have your C++ implementation right there.

Upvotes: 3

Related Questions