程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 基於位操作的類CBitBuffer

基於位操作的類CBitBuffer

編輯:關於C++

由於工作的需要,我寫了一個基於位操作的類,由CFile類模仿而來。寫的比較倉促,許多操作效率較低,有待改進。

該代碼對我比較有用,如果你對代碼有任何改進希望你能告訴我。Email:[email protected]

一、類定義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;
}
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved