views:

1785

answers:

5

I have a big lump of binary data in a char[] array which I need to interpret as an array of packed 6-bit values.

I could sit down and write some code to do this but I'm thinking there has to be a good extant class or function somebody has written already.

What I need is something like:

int get_bits(char* data, unsigned bitOffset, unsigned numBits);

so I could get the 7th 6-bit character in the data by calling:

const unsigned BITSIZE = 6;
char ch = static_cast<char>(get_bits(data, 7 * BITSIZE, BITSIZE));
+1  A: 

May be you will find some inspiration in this Base64.cpp code ?

VonC
+4  A: 

Boost.DynamicBitset - try it.

Igor Semenov
Yeah, I considered that but I was hoping for something that would pack the bits back into an int when I got them out
AndrewR
A: 

I think something in the line of the following might work.

int get_bit(char *data, unsigned bitoffset) // returns the n-th bit
{
    int c = (int)(data[bitoffset >> 3]); // X>>3 is X/8
    int bitmask = 1 << (bitoffset & 7);  // X&7 is X%8
    return ((c & bitmask)!=0) ? 1 : 0;
}

int get_bits(char* data, unsigned bitOffset, unsigned numBits)
{
    int bits = 0;
    for (int currentbit = bitOffset; currentbit < bitOffset + numBits; currentbit++)
    {
     bits = bits << 1;
     bits = bits | get_bit(data, currentbit);
    }
    return bits;
}

I've not debugged nor tested it, but you can use it as a start point.

Also, take into account bit order. You might want to change

    int bitmask = 1 << (bitoffset & 7);  // X&7 is X%8

to

    int bitmask = 1 << (7 - (bitoffset & 7));  // X&7 is X%8

depending on how the bit array has been generated.

Marco M.
+1  A: 

This may not work for sizes greater than 8, depending on endian system. It's basically what Marco posted, though I'm not entirely sure why he'd gather one bit at a time.

int get_bits(char* data, unsigned int bitOffset, unsigned int numBits) {
    numBits = pow(2,numBits) - 1; //this will only work up to 32 bits, of course
    data += bitOffset/8;
    bitOffset %= 8;
    return (*((int*)data) >> bitOffset) & numBits;  //little endian
    //return (flip(data[0]) >> bitOffset) & numBits; //big endian
}

//flips from big to little or vice versa
int flip(int x) {
    char temp, *t = (char*)&x;
    temp = t[0];
    t[0] = t[3];
    t[3] = temp;
    temp = t[1];
    t[1] = t[2];
    t[2] = temp;
    return x;
}
This did the trick. Thanks.
AndrewR
what's the trick for more than 32 bits (e.g. "long long")?what might the code for storing the values in a char array look like?
Will
A: 

https://svn.mcs.anl.gov/repos/ITAPS/MOAB/tags/version_101/MBBits.hpp

HTH

plan9assembler