How to implement bitwise access in C++
- 2020-04-02 03:13:17
- OfStack
In a project I started, in order to save network bandwidth, data transmission in the network needs to achieve compact access. In fact, there are similar requirements in many fields such as national defense, scientific research, aerospace and military industry.
Achieve compact access, not byte by byte access, but access by bit. For example, with one byte, we can store 8 bool information and share the code (note: the algorithm in the code is worth optimizing) without further ado.
// the following is the function definition
void ReadOneBit( byte* pBuffer, int nStart, int& nEnd, byte& retByte );
template<typename T>
void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, int& nEnd, T& retData );
void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, int& nEnd, char* pRetData );
void WriteOneBit( byte* pBuffer, byte btData, int nStart, int& nEnd );
template<typename T>
void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, int& nEnd );
void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, int& nEnd );
// the following is the function implementation
void ReadOneBit( byte* pBuffer, int nStart, int& nEnd, byte& retByte )
{
byte btData = pBuffer[nStart/8];
btData = btData << nStart%8;
retByte = btData >> 7;
nEnd = nStart+1;
}
template<typename T>
void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, int& nEnd, T& retData )
{
//In order to read a
retData = 0;
if ( btLength > sizeof(T)*8 )
return ;
byte btData;
T tData;
while ( btLength-- )
{
ReadOneBit(pBuffer, nStart, nStart, btData);
tData = btData << btLength;
retData |= tData;
}
nEnd = nStart;
}
void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, int& nEnd, char* pRetData )
{
for ( int nIndex=0; nIndex<nCount; nIndex++ )
{
ReadDataFromBuffer(pBuffer, nStart, 8, nStart, pRetData[nIndex]);
}
nEnd = nStart;
}
void WriteOneBit( byte* pBuffer, byte btData, int nStart, int& nEnd )
{
int nSet = nStart / 8;
byte c = pBuffer[nSet];
switch ( btData )
{
case 1:
c |= ( 1 << (7- nStart % 8) );
break;
case 0:
c &= ( ~(1 << (7- nStart % 8) ) );
break;
default:
return;
}
pBuffer [nSet] = c;
nEnd = nStart +1;
}
template<typename T>
void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, int& nEnd )
{
/* //Big end machine mode
byte btDataLength = sizeof(T);
if ( btLength > sizeof(T)*8 )
return;
int nDataStart = 0; //The first position of the data is 0, written sequentially
while ( btLength-- )
{
byte bitData;
ReadOneBit((byte*)&tData, nDataStart, nDataStart, bitData);
WriteOneBit(pBuffer, bitData, nStart, nStart);
}
nEnd = nStart;
*/
//Small endian mode: when writing to buffer, do not write bits sequentially
//Gets the template footprint size
byte btDataLength = sizeof(T);
//Verify that the length is out of bounds
if ( btLength > sizeof(T)*8 )
return;
//Converts the pending data to byte*
byte* ptData = (byte*)&tData;
//Modulus and more
int nSet = btLength / 8;
int nRin = btLength % 8;
//Defines byte data and bit data
byte bitData;
byte byteData;
int nTempEnd;
//Write the rin data first
byteData = ptData[nSet];
while ( nRin-- )
{
ReadOneBit(&byteData, 7-nRin, nTempEnd, bitData);
WriteOneBit(pBuffer, bitData, nStart, nStart);
}
//Set data
while ( nSet )
{
byteData = ptData[--nSet];
//Write a byte
int i=0;
while ( i!=8 )
{
ReadOneBit(&byteData, i++, nTempEnd, bitData);
WriteOneBit(pBuffer, bitData, nStart, nStart);
}
}
nEnd = nStart;
}
void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, int& nEnd )
{
for ( int nIndex=0; nIndex<nCount; nIndex++ )
{
WriteDataToBuffer(pBuffer, pchar[nIndex], nStart, 8, nStart);
}
nEnd = nStart;
}
The above is the entire content of this article, I hope to help you with your study.