欢迎访问:常州市武进区嘉泽中心小学网站 !今天是:
栏目列表
您现在的位置是:首页>>教师>>计算机技术>>程序设计>>一般性编程问题>>C++、MFC>>文章内容
基于位操作的类CBitBuffer
发布时间:2008-11-20   点击:   来源:本站原创   录入者:佚名
" width="21" height="15" align="absmiddle"> 基于位操作的类CBitBuffer
作者:阳光

由于工作的需要,我写了一个基于位操作的类,由CFile类模仿而来。写的比较仓促,许多操作效率较低,有待改进。
该代码对我比较有用,如果你对代码有任何改进希望你能告诉我。Email:mymong@{域名已经过期}

一、类定义

class CBitBuffer  

{

private:

 LONGLONG  m_llLength;     // 缓存的大小,单位(位)。 

 BYTE *    m_pBegin;       // 缓存的起始指针,字节指针,指向缓存的第一个字节。

 BYTE *    m_pEnd;         // 缓存的末尾指针,字节指针,指向缓存的最后一个字节的下一个字节。

 BYTE *    m_pCurByte;     // 缓存的当前指针,字节指针,指向当前字节。

 BYTE      m_nCurOffset;   // 从当前字节起始的位偏移量,值范围0-7。

 BOOL      m_bLocked;      // 缓存是否被锁住,当你创建一块缓存时,该缓存在释放前为锁住状态,不能重新赋值头指针及缓存大小。 

 // 注意:m_pCurByte与m_nCurOffset联合构成位指针,可以指向当前位。
public:

// 【状态相关】: 

 BOOL IsLocked();          // 当前是否为缓存锁住状态。 

 BOOL IsByteAligned();     // 当前位指针是否为字节对齐。
// 【输入输出】: 

 // 将当前位写为‘0’,位指针自动后移一位。 

 void WriteBit0();
 // 将当前位写为‘1’,位指针自动后移一位。

 void WriteBit1();
 // 从当前位指针开始读取nCount个位,并将其转换为整数输出,位指针自动后移。

 // (in/out) nCount: 读取的位的个数。

 // 注意:该数值范围是0-32,并且确保使用该函数时保证读取数值不会越界,

 //      考虑到效率比较低,函数体内没有加入任何校验,需要使用者小心。

 int Read(BYTE nCount);
 //  从当前位指针开始写入一串二进制数,该数以字符串形式输入,位指针自动后移。

 //  参数例子: "0011 1011 0111 1111" ,空格会被忽略。 

 //            "*000 1111 1111 *111" ,星号所在的位会被略过而不被写入。

 void WriteBinary(char * pBinStr);
 // 从当前字节指针开始写入一个16进制数,该数以字符串形式输入,位指针自动后移,位偏移置0。

 // 参数例子: "00 01 BA", 空格会被忽略,字符串中不能有“0X”字符,且字母均大写。

 // 注意:使用该函数前必须确保已经字节对齐了、没有"0X"、字母均大写等,函数体内没有进行校验! 

 void WriteHex(char * pHexStr);
 // 从当前位指针开始写入nCount个位,这nCount个位对应一个指定的数值,该数值可以以十进制或十六进制输入。

 void WriteDecimal(UINT nData, int nCount);
 // 复制一段数据到当前的缓存,从当前字节指针开始写入,位指针自动后移,位偏移置0。

 //  (in) pSubBuff: 源数据的头指针。

 //  (in/out) nCount: 复制的长度,注意是字节的个数。 

 // actually writed byte count. The count may be less than nCount if the 

 // end of buffer was reached. 

 void WriteBuffer(BYTE * pSubBuff, int &nCount);

 

// 【位置相关】:

 // 取得缓存的起始指针。 

 BYTE * GetBegin();

 

 // 取得缓存的末尾指针,该指针指向缓存最后一个字节的下一个字节。

 BYTE * GetEnd();

 

 // 取得当前指针。 

 BYTE * GetCurByte();

 

 // 取得当前位指针在当前字节的位偏移量。 

 BYTE GetCurOffset();

 

 // 设定缓存的大小,单位是“位”,但是必须确保是8的倍数。

 // 设定缓存大小前,需要确保缓存起始指针已经设定。

 // 返回上次设定的缓存大小,如果是第一次设定,返回0。

 // 如果缓存已经被锁定,则不能重设大小,返回-1表示失败。

 //  (in) llLen: 缓存大小,单位是“位”,且是8的倍数,最好以1024*8的形式输入。

 LONGLONG SetLength(LONGLONG llLen);
 // 取得缓存的大小,单位是“位”,应该是8的倍数。

 LONGLONG GetLength();
 // 移动当前位指针到缓存的末尾,实际指向缓存最后一个字节的下一个字节的第一个位。

 // 返回缓存的大小,单位是“位”,应该是8的倍数。

 LONGLONG SeekToEnd();

 

 // 移动当前位指针到缓存的起始处,实际指向缓存的第一个字节的第一个位。

 void SeekToBegin();

 

 // 移动当前位指针一个指定的数值偏移量,偏移量是正数时向末尾移动,偏移量是负数时向起始移动,偏移量单位时“位”。

 // 返回当前位指针相对起始地址的偏移量,单位时“位”,返回值如果是负数时表示失败。

 // (in) llOff: 偏移量,单位"位"。

 LONGLONG Seek(LONGLONG llOff);
// 【构造函数】: 

 // 缺省构造函数没有设定缓存及其大小等,注意在使用前要设定相关内容。

 CBitBuffer();
 // 该构造函数设定了缓存及其大小。缓存大小缺省为0。

 // 缓存大小缺省为0,你必须在实际使用前设定正确的缓存大小。

 // 注意:最好不要使用该构造函数,推荐使用ShareBuffer()函数。

 CBitBuffer(BYTE * pBegin, LONGLONG llLen = 0);

 

 // 该函数重设缓存的起始地址以及缓存大小,并计算结束地址。

 // 如果你没有设定缓存的大小,缺省会被设为0,在使用前一定要设定正确的数值。

 // 如果已经有一块数据区,你希望使用CBitBuffer来管理,推荐使用该函数进行初始化。

 // 注意:

 //  如果是在其他地方分配的内存,使用CBitBuffer来管理,则该内存的释放不是CBitBuffer的职责。

 //  如果该CBitBuffer对象已经使用Create()函数创建了缓存,则在调用Release()函数进行释放前不能使用该函数重新设定缓存。

 //  如果该CBitBuffer对象已经有缓存,并且也是用该函数设定的,则可以使用该函数再次设定新的缓存。

 //  使用该函数设定的缓存不被锁定,所以可以重设缓存及大小。

 //  使用该函数时,如果缓存已被锁定,则会返回FALSE表示失败。

 // (in) pBegin :被管理的数据区的首地址,指的是第一个字节的地址。

 // (in) llLen :数据区被管理的大小,单位“位”,必须是8的倍数,建议使用1024*8的形式输入。

 BOOL ShareBuffer(BYTE * pBegin, LONGLONG llLen = 0);
 // 使用输入的大小创建一块缓存,缓存大小单位是“位”,必须是8的倍数,建议使用1024*8的形式输入。

 // 缓存创建成功返回TRUE,失败返回FALSE。

 // 注意:使用该函数创建缓存成功后,缓存会被锁定;调用该函数时,如果缓存已被锁定,创建会失败。

 //      如果你确定已经不再需要该缓存时,记住调用Release()函数解锁定并释放缓存。

 BOOL Create(LONGLONG llLen);

 

 // 解除缓存锁定,并释放由Create()函数创建的缓存。

 void Release();
 virtual ~CBitBuffer();

};

二、类实现
#include "BitBuffer.h"

#include "math.h"

#define BYTEBITS 8

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////
CBitBuffer::CBitBuffer()

{

 m_llLength = 0;  // The count in bits of buffer

 m_pBegin = NULL;  // The beginning pointer of buffer, the last byte.

 m_pEnd  = NULL;  // The ending pointer of buffer

 m_pCurByte = NULL;  // The current pointer in byte of buffer

 m_nCurOffset= 0;  // The offset in bits from current pointer

 m_bLocked = FALSE; // Whether the buffer is locked

}
CBitBuffer::CBitBuffer(BYTE *pBegin, LONGLONG llLen)

{

 m_llLength = llLen;  // The count in bits of buffer

 m_pBegin = pBegin;  // The beginning pointer of buffer, the last byte.

 m_pCurByte = pBegin;  // The current pointer in byte of buffer

 m_nCurOffset= 0;   // The offset in bits from current pointer

 m_pEnd  = pBegin + llLen / BYTEBITS;   // The ending pointer of buffer

 m_bLocked = FALSE;  // Whether the buffer is locked

}
CBitBuffer::~CBitBuffer()

{
}
// Seek to the ending of buffer

// Return the length of the buffer in bits

LONGLONG CBitBuffer::SeekToEnd()

{

 m_pCurByte = m_pEnd;

 m_nCurOffset = 0;

 return m_llLength;

}
// Seek to the beginning of buffer

void CBitBuffer::SeekToBegin()

{

 m_pCurByte = m_pBegin;

 m_nCurOffset = 0;

}
// Seek from current pointer in bits

// Return the new bit offset from the beginning of the buffer

// (in) llOff: The offset in bits from current pointer in bits

LONGLONG CBitBuffer::Seek(LONGLONG llOff)

{

 LONGLONG pos = (m_pCurByte - m_pBegin) * BYTEBITS + m_nCurOffset;

 pos += llOff;

 if(pos < 0 || pos > m_llLength)

  return -1;

 m_pCurByte = m_pBegin + pos / BYTEBITS;

 m_nCurOffset = pos % BYTEBITS;
 return pos;

}
LONGLONG CBitBuffer::GetLength()

{

 return m_llLength;

}
LONGLONG CBitBuffer::SetLength(LONGLONG llLen)

{

 if(m_bLocked)

  return -1;
 LONGLONG temp = m_llLength;

 m_pEnd = m_pBegin + llLen / BYTEBITS;

 if(m_pCurByte > m_pEnd)

 {

  m_pCurByte = NULL;

  m_nCurOffset = 0;

 }

 m_llLength = llLen;
 return temp;

}
BOOL CBitBuffer::ShareBuffer(BYTE *pBegin, LONGLONG llLen)

{

 if(m_bLocked || pBegin == NULL)

  return FALSE;
 m_llLength = llLen;  // The count in bits of buffer

 m_pBegin = pBegin;  // The beginning pointer of buffer, the last byte.

 m_pCurByte = pBegin;  // The current pointer in byte of buffer

 m_nCurOffset= 0;   // The offset in bits from current pointer

 m_pEnd  = pBegin + llLen / BYTEBITS;   // The ending pointer of buffer

 m_bLocked = FALSE;  // Whether the buffer is locked
 return TRUE;

}
BOOL CBitBuffer::Create(LONGLONG llLen)

{

 if(m_bLocked)

  return FALSE;
 m_pBegin = (BYTE*)malloc(llLen / BYTEBITS);

 if(m_pBegin == NULL)

  return FALSE;
 m_llLength = llLen;

 m_pCurByte = m_pBegin;

 m_nCurOffset = 0;

 m_pEnd = m_pBegin + llLen / BYTEBITS;

 m_bLocked = TRUE;
 return TRUE;

}
void CBitBuffer::Release()

{

 if(m_bLocked && m_pBegin)

 {

  free(m_pBegin);

  m_pBegin = NULL;

  m_pCurByte = NULL;

  m_nCurOffset = 0;

  m_pEnd = NULL;

  m_bLocked = FALSE;

  

 }

 else if(m_bLocked == FALSE)



 {

  m_pBegin = NULL;

  m_pCurByte = NULL;

  m_nCurOffset= 0;

  m_pEnd  = NULL;

 }

}

int CBitBuffer::Read(BYTE nCount)

{

 DWORD64 D64 = *((DWORD64*)m_pCurByte);

 D64 = (D64 >> 8*0 << (64-8)) |

    (D64 >> 8*1 << (64-8) >> (8*1)) |

    (D64 >> 8*2 << (64-8) >> (8*2)) |

    (D64 >> 8*3 << (64-8) >> (8*3)) |

    (D64 >> 8*4 << (64-8) >> (8*4)) |

    (D64 >> 8*5 << (64-8) >> (8*5)) |

    (D64 >> 8*6 << (64-8) >> (8*6)) |

    (D64 >> 8*7 << (64-8) >> (8*7)) ;

    
 int re = (int)(D64 << m_nCurOffset >> (64-nCount));

 m_pCurByte += (m_nCurOffset + nCount)/8;

 m_nCurOffset = (m_nCurOffset + nCount)%8;

 return re;

}
void CBitBuffer::WriteBinary(char * pBinStr)

{

 int len = strlen(pBinStr);

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

 {

  if(pBinStr[i] == '1')

  {

   WriteBit1();

  }

  else if(pBinStr[i] == '0')

  {

   WriteBit0();

  }

  else if(pBinStr[i] == '*')

  {

   Seek(1);

  }

 }

}
void CBitBuffer::WriteHex(char * pHexStr)

{

 // Before use this function you should make sure BYTE ALIGNED and CAPITAL LETTER .

 // Here do not verify anything, you should verify before call this function.

 int len = strlen(pHexStr);

 int iActualLen=0;

 int h;

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

 {

  if(pHexStr[i] >= '0' && pHexStr[i] <= '9')

  {

   if((iActualLen++)%2==0)

    h = pHexStr[i]-'0';

   else

   {

    *m_pCurByte = h*16 + pHexStr[i] - '0';

    m_pCurByte++;

   }

  }

  else if(pHexStr[i] >= 'A' && pHexStr[i] <= 'F')

  {

   if((iActualLen++)%2==0)

    h = pHexStr[i]-'A'+10;

   else

   {

    *m_pCurByte = h*16 + pHexStr[i]-'A'+10;

    m_pCurByte++;

   }

  }

  else if(pHexStr[i] >= 'a' && pHexStr[i] <= 'f')

  {

   if((iActualLen++)%2==0)

    h = pHexStr[i]-'a'+10;

   else

   {

    *m_pCurByte = h*16 + pHexStr[i]-'a'+10;

    m_pCurByte++;

   }

  }

 }

 if(iActualLen%2 == 1)

 {

  *m_pCurByte = *m_pCurByte & 0x0F | (((BYTE)h)<<4);

  m_nCurOffset = 4;

 }

}
BOOL CBitBuffer::IsByteAligned()

{

 if(m_nCurOffset == 0)

  return TRUE;

 else

  return FALSE;

}
void CBitBuffer::WriteDecimal(UINT nData, int nCount)

{

 //!!nCount<=32
 int nByteCountNeed = (m_nCurOffset + nCount - 1)/BYTEBITS + 1;

 //Head:

 DWORD64 head = (*m_pCurByte) >> (BYTEBITS-m_nCurOffset) << (BYTEBITS-m_nCurOffset) + 7*BYTEBITS;

 //Bottom:

 int b = BYTEBITS-(nByteCountNeed*8-m_nCurOffset-nCount);

 DWORD64 bottom = (DWORD64)((BYTE)(*(m_pCurByte+nByteCountNeed-1) << (BYTEBITS-b)) >> b) << (64-nByteCountNeed*8);

 BYTE test = *(m_pCurByte+nByteCountNeed-1) << (BYTEBITS-b);

 test = test >> b;

 //Center:

 DWORD64 center = (DWORD64)nData << (64-m_nCurOffset-nCount);

 //Result;

 DWORD64 resu = head | center | bottom;

 

  BYTE * pResu = (BYTE *)(&resu);

 int n = 0;

 for(int i=7;i>=8-nByteCountNeed;i--)

 {

  if(n==0 && m_nCurOffset!=0)

  {

   *(m_pCurByte+n) = *(m_pCurByte+n) >> (BYTEBITS-m_nCurOffset) << (BYTEBITS-m_nCurOffset) | pResu[i];

  }

  else

   *(m_pCurByte+n) = pResu[i];

  n++;

 }

 m_pCurByte  += (m_nCurOffset+nCount)/8;

 m_nCurOffset = (m_nCurOffset+nCount)%8;

}
void CBitBuffer::WriteBuffer(BYTE *pSubBuff, int nCount)

{

 memcpy(m_pCurByte,pSubBuff,nCount);

 m_nCurOffset = 0;

}
BYTE * CBitBuffer::GetBegin()

{

 return m_pBegin;

}
BYTE * CBitBuffer::GetEnd()

{

 return m_pEnd;

}
BYTE * CBitBuffer::GetCurByte()

{

 return m_pCurByte;

}
BYTE CBitBuffer::GetCurOffset()

{

 return m_nCurOffset;

}
BOOL CBitBuffer::IsLocked()

{

 return m_bLocked;

}
void CBitBuffer::WriteBit1()

{

 *m_pCurByte = *m_pCurByte | (0x80>>m_nCurOffset);

 m_nCurOffset++;

 if(m_nCurOffset >= 8)

 {

  m_pCurByte ++;

  m_nCurOffset = 0;

 }

}
void CBitBuffer::WriteBit0()

{

 *m_pCurByte = *m_pCurByte & (~(0x80>>m_nCurOffset));

 m_nCurOffset++;

 if(m_nCurOffset >= 8)

 {

  m_pCurByte ++;

  m_nCurOffset = 0;

 }

}



附件:
    关闭窗口
    打印文档
    账号登录
    保持登录 忘记密码?
    账号与武进教师培训平台同步