一、类定义 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 {
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 {
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;
}
}

基于位操作的类CBitBuffer相关推荐

  1. 《响应式Web设计:HTML5和CSS3实践指南》——2.9节基于位置伪类的交替行样式

    本节书摘来自华章社区<响应式Web设计:HTML5和CSS3实践指南>一书中的第2章,第2.9节基于位置伪类的交替行样式,作者(美) Benjamin LaGrone,更多章节内容可以访问 ...

  2. rest_framework11:jwt简单例子/自定制基于jwt认证类

    jwt简单例子 一.登陆设置 1.不需要写login的视图类,使用jwt内置的. 2.需要前置条件,已有继承AbstractUser models,并且有数据,用于校验,返回token. urls.p ...

  3. 基于价值链的流程框架分类_基于价值的类

    基于价值链的流程框架分类 在Java 8中,某些类在Javadoc中有一个小注释,说明它们是基于值的类 . 其中包括简短说明的链接,以及有关不使用它们的限制. 这很容易被忽略,如果这样做,则可能会在将 ...

  4. ruby笔记 基于对象的类(object specific class)

    此笔记是为了帮助理解 "<<" 指令 ruby语言允许我们在一个对象的基础上定义类,使得我们可以单独扩展一个对象的行为,例子如下 test="hello&qu ...

  5. java值的传递_Java 8可选–基于值的类使用指南

    java值的传递 In this article, we will go through the use of Java 8 Optional class and understand what a ...

  6. java基于HuTool工具类ExcelWriter合并单元格

    ** java基于HuTool工具类ExcelWriter合并单元格 ** 1.基于HuTool工具类ExcelWriter合并单元格并且使用 jdk1.8 lambda表达式 效果如下: 用姓名和编 ...

  7. 基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署

    基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署 基于JAVA计算机类专业考研交流学习平台计算机毕业设计源码+数据库+lw文档+系统+部署 本源码技术栈: 项目 ...

  8. 基于JAVA餐饮类网站计算机毕业设计源码+系统+lw文档+部署

    基于JAVA餐饮类网站计算机毕业设计源码+系统+lw文档+部署 基于JAVA餐饮类网站计算机毕业设计源码+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开发软件: ...

  9. Spring基于@Configuration的类配置的内部源码实现

    概述 Spring容器启动时,即ApplicationContext接口实现类的对象实例执行refresh方法时,主要是通过执行ConfigurationClassPostProcessor这个Bea ...

最新文章

  1. 那些年,面试被虐过的红黑树 1
  2. Codeforces Round #734 (Div. 3) 题解
  3. Bifrost微前端框架及其在美团闪购中的实践
  4. php mysql存图片路径_PHP 批量下传图片 怎么保存路径到mysql
  5. linux如何配置网络设置_如何在Linux中配置网络
  6. 十二则技巧让Excel操作效率提高
  7. jquery基础知识(二)
  8. MySQL — 使用命令创建数据库、链接数据库、创建表、查询表数、删除表
  9. 项目过程的几点经验总结
  10. 基于h a d oop的海量图片存储模型 的分析和设计
  11. K线技术指标实现详解—MACD
  12. mac电脑闪屏怎么办?解决mac屏幕一闪一闪的方法
  13. 主流的商业智能BI工具推荐,学会数据分析没难度
  14. 隐马尔科夫模型HMM自学
  15. python选择结构练习(一)
  16. 关于activity的生命周期1
  17. N-Tiers设计系列(一):传统Asp运作方式
  18. ubuntu系统文件清理
  19. BAT批处理基本命令
  20. Django——admin功能、注册模型类、模型管理类

热门文章

  1. 产生粗体字的html标签,html字体加粗用css设置文字粗体样式
  2. 香港电视剧的配音怎么都是一个腔调的呢?
  3. 谈谈论文的发表(电光与控制,IEEE ACCESS)
  4. 正确将图片保存到相册的方法
  5. php crypt md5,PHP crypt()-返回的md5哈希
  6. 设计模式 - 模版模式
  7. 三种方法求最大公约数及求n个数的最小公倍数
  8. Enscape 设置预设功能能够在保存的设置之间切换
  9. CSP应用开发-CryptAPI函数库介绍
  10. php用户中心ui,Layui用户中心模板