Scrier

Well, this is 2 questions you could say but for the same problem I have.

The first thing I wan't to do is to build a chunk of data to be sent over UDP and/or TCP to a reciever. The problem at hand is that I wan't to build it using bits. The best way to build this datapackage I have found is to use a bit vector (vector<bool>) but that seems to be rather old method so I'm wondering if there is some new way to do this in an effective manner, I have looked into the bitset class but I cannot resize it dynamically so that is not an option to me as the datachunk can variate in size.

The second thing is to read this package on the recieving end. Problem here is that I cannot find any class or function that can help me to take the datachunk, read 4 bits (then throw them away) and then read the next 1, 2, 3, 5, 12, 50 bits and so on. I'm not that fond of reading bytes and bitshifting as it would mean that larger chunks of bits (say 18) might have to be read over 4 different bytes, resulting in a rather slow and timeconsuming identification of the datachunk I guess.

best regards

Andreas



Re: Visual C++ General Bit handling and reading

einaros

You will have to receive whole bytes as they arrive. No winsock function will allow you to send mere bits to the other peer. When the receiving end gets new data, read as many bits as you like, then store the following in a suitable container (a pure string would do, if you don't want to adapt or write your own). When more data arrives, keep processing.

As for the actual bit handling, your own method could easily be adapted through a helper struct such as

Code Snippet

union ONEBYTE

{

unsigned char singleByte;

struct

{

unsigned char bit1 : 1;

unsigned char bit2 : 1;

unsigned char bit3 : 1;

unsigned char bit4 : 1;

unsigned char bit5 : 1;

unsigned char bit6 : 1;

unsigned char bit7 : 1;

unsigned char bit8 : 1;

};

};

Using this to e.g. add five 'a's to a string (which should give you the general idea) would be:

Code Snippet

ONEBYTE o = {0};

o.bit1 = o.bit6 = o.bit7 = 1; // this will create the single byte 0x61, which is 'a'

string s;

for(int i = 0; i < 5; ++i)

{

s.push_back(o.singleByte);

}






Re: Visual C++ General Bit handling and reading

Scrier

So, the easy way would be to build chars and then push them back into a string Is there some way that you can iterate through the bits as well instead of setting the specified ones

Reason i'm asking this is that depending if a bit is 1 or 0 it will have different followup when I'm implementing. i.e if bit 5 is 1 I will followup with the regular building of bits, if it is 0 though I will bypass that building block and set another identifier to 1 or 0 for the next information sent.

Say that bit 5 defines that I should tell the recieving part a following number (28 bit). If I dont set bit 5 I will check another case if I should send a byte instead. So if 5 is set to 1 I will build another 28 bits of data and then continue, if bit 5 is not set I will check bit 6 (34 if it was set) and build on from there. So the content of this building of a message will lead to that in the end of the message I must take into consideration alot of factors to know wich bit to set if I cant just assign a value to it through an iterator that pushes back the char when its filled.

Hope I didn't confuse you too much with this explanation.





Re: Visual C++ General Bit handling and reading

einaros

Well here's *one* possible approach. You can probably adapt it to fit your exact needs, but I don't think you should spend too much time making the problem more complex than it is. If you find, down the road, that some standard container is better, and that you'll change the encoding altogether; it would all have been a waste in either case Smile

Code Snippet

#include <string>
#include <iostream>

using namespace std;

union ONEBYTE
{
unsigned char singleByte;
struct
{
unsigned char bit1 : 1;
unsigned char bit2 : 1;
unsigned char bit3 : 1;
unsigned char bit4 : 1;
unsigned char bit5 : 1;
unsigned char bit6 : 1;
unsigned char bit7 : 1;
unsigned char bit8 : 1;
};
};

class BitIterator
{
public:
BitIterator(const char* pBuf, size_t len, size_t pos = 0)
: m_pBuf(pBuf),
m_len(len),
m_pos(pos)
{}

bool getNextBit(bool* bit)
{
if(getBitAtIndex(bit, m_pos))
{
++m_pos;
return true;
}
return false;
}

bool getBitAtIndex(bool* bit, size_t pos)
{
size_t bytePos = pos / 8;
if(bytePos < m_len)
{
size_t bitPos = pos % 8;
*bit = (m_pBuf[bytePos] >> bitPos) & 1;
return true;
}
return false;
}

private:
const char* m_pBuf;
size_t m_len;
size_t m_pos;
};

int main()
{
ONEBYTE o = {0};
o.bit1 = o.bit3 = o.bit5 = o.bit7 = 1;

// create buffer
string s;
for(size_t i = 0; i < 5; ++i)
{
s.push_back(o.singleByte);
}

// iterate bits throughout the buffer
BitIterator bi(s.c_str(), s.length());
bool bit;
while(bi.getNextBit(&bit))
{
cout << (bit '1' : '0') << " ";
}

// get specific bits
for(size_t i = 0; i < 8; ++i)
{
if(!bi.getBitAtIndex(&bit, i))
{
break;
}
cout << (bit '1' : '0') << " ";
}
}

You'll have to excuse the messed up formatting. The forum editor manages to change the indenting at random.