ビットストリーム (Bit Stream)入力クラス

以前(2008年頃)書いたプログラムを引っ張り出しました。そしてバグを発見したので、少し書きなおしました。もうバグは無いと思いますが・・・

  1. //
  2. // ReadBitStream Class
  3. //// unsigned char * bpBufに sizeバイト置かれたメモリーブロックから
  4. //// bit単位で値を取り出すクラス
  5. //// エラーがあれば、throwするので、読みだす方は try ~~ catch すべき
  6. //// modified on August 25th, 2012 
  7. //// by Shigeru SAITO, MD, FACC, FSCAI, FJCC
  8. //// originally created by Shigeru SAITO in 2008
  9. //
  10.  
  11. #ifndef __READBITSTREAM_H_
  12. #define __READBITSTREAM_H_
  13.  
  14. #include <memory.h>
  15. typedef unsigned char BYTE;
  16. typedef unsigned short WORD;
  17.  
  18. class CReadBitStream
  19. {
  20. private:
  21.  
  22. protected:
  23.     BYTE *mbpRead;            // 読み出しアドレス
  24.     BYTE *mbpEndOfBuf;        // Bufferの終了アドレス
  25.     BYTE mMask;               
  26.  // bit maskであると同時に現在の読み出しビット位置 (MSB = 7, LSB = 0)
  27.     bool mReadable;            // 1: 読み出し可、 0: 読み出し不可
  28.     void IncBuf(void);        
  29. // 読み出しアドレスのインクリメントとアクセス違反のチェック
  30. public:
  31.     CReadBitStream(void);
  32.     CReadBitStream(BYTE *bpBuf, int size);    // 唯一のconstructor
  33.     virtual ~CReadBitStream(void);
  34.     BYTE GetBYTE(void);        // 1 BYTE読み出し
  35.     WORD GetWORD(void);        // 1 WORD読み出し
  36.     void CopyBYTEs(BYTE* bpDest, int n);        
  37. // n BYTEs読みだしてbpDestのアドレス以降にコピーする
  38.     void SkipBYTE(int n);                    // n BYTEs読み飛ばし
  39.     int GetBit(void);                        // 1 bit読みだして返す
  40.     int GetBits(int numOfBits);                // numOfBits数のビットを読みだして返す
  41.     BYTE* GetNextAddress(void);                // 次の読み出しアドレスを戻す
  42.     int ResetBuffer(BYTE* bpBuf, int size);    // bufferを変更する
  43. };
  44.  
  45. #endif __READBITSTREAM_H_

 

以上がheader部分です、そして.cppの方は以下です

  1. #include “ReadBitStream.h”
  2.  
  3. CReadBitStream::CReadBitStream(void)
  4. :mbpRead(0), mbpEndOfBuf(0), mMask(0), mReadable(false) {}
  5.  
  6. CReadBitStream::CReadBitStream(BYTE *bpBuf, int size) {
  7.     mbpRead = bpBuf;                        // 読み出しアドレスをbufferの先頭にセット
  8.     mbpEndOfBuf = mbpRead + size;            // bufferの最終アドレスをセット
  9.     // 状態変数の初期化
  10.     mMask = static_cast<BYTE>(0x80);        // setMSB
  11.     mReadable = true;                        // アクセスエラー無し
  12. }
  13.  
  14. int CReadBitStream::ResetBuffer(BYTE *bpBuf, int size) {
  15.     mbpRead = bpBuf;
  16.     mbpEndOfBuf = mbpRead + size;
  17.     if ((bpBuf == 0)||(size == 0)) {
  18.         mReadable = false;
  19.         return 1;
  20.     }
  21.     mMask = static_cast<BYTE>(0x80);
  22.     mReadable = true;
  23.     return 0;
  24. }
  25.  
  26. CReadBitStream::~CReadBitStream(void) {
  27.     mbpRead = 0;
  28.     mbpEndOfBuf = 0;
  29. }
  30.  
  31. BYTE CReadBitStream::GetBYTE(void) {        // 1 BYTE読み出し
  32.     if (mReadable) {
  33.         if (!(mMask > 0x80)) {                // BYTE途中は不可
  34.             IncBuf();                        // 次のBYTEに進める
  35.             mMask = static_cast<BYTE>(0x80);
  36.         }
  37.         BYTE r = *mbpRead;                // 実際に1 BYTE読みだす
  38.         IncBuf();
  39.         return r;
  40.     } else {
  41.         throw(“Error at GetBYTE”);
  42.     }
  43. }
  44.  
  45. WORD CReadBitStream::GetWORD(void) {        // 1 WORD読み出し
  46.     if (mReadable) {
  47.         if (!(mMask > 0x80)) {                // BYTE途中は不可
  48.             IncBuf();
  49.             mMask = static_cast<BYTE>(0x80);
  50.         }
  51.         WORD r = (static_cast<WORD>(*mbpRead))<<8;    
  52. // 1 BYTE読み出しそれをWORDにcastしてから8bits左シフト
  53.         IncBuf();
  54.         r |= static_cast<WORD>(*mbpRead);    
  55. // さらに1 BYTEを下のBYTEに付加する
  56.         IncBuf();
  57.         return r;
  58.     } else {
  59.         throw(“Error at GetWORD”);
  60.     }
  61. }
  62.  
  63. void CReadBitStream::CopyBYTEs(BYTE* bpDest, int n) {    
  64. // n BYTEsをpbDestに一挙にコピーしてしまう
  65.     if (mReadable) {
  66.         if (!(mMask > 0x80)) {            // BYTE途中は不可
  67.             IncBuf();
  68.             mMask = static_cast<BYTE>(0x80);
  69.         }
  70.         if (mbpRead + n > mbpEndOfBuf) {
  71.             throw(“Error at CopyBYTEs1”);
  72.         }
  73.         memcpy(bpDest, mbpRead, n);
  74.         if ((mbpRead += n) >= mbpEndOfBuf) mReadable = false;    
  75. // 次の読み出しは不可
  76.         return;
  77.     } else {
  78.         throw(“Error at CopyBYTEs2”);
  79.     }
  80. }
  81.  
  82. void CReadBitStream::SkipBYTE(int n) {            // n BYTEs読み飛ばす
  83.     if ((mbpRead + n) > mbpEndOfBuf) {
  84.         throw (“Error at SkipBYTE”);
  85.     }
  86.     if ((mbpRead += n) >= mbpEndOfBuf) mReadable = false;    
  87. // 次の読み出しは不可
  88.     mMask = static_cast<BYTE>(0x80);
  89.     return;
  90. }
  91.  
  92. int CReadBitStream::GetBit(void) {                // 1 bit読みだす
  93.     if (mReadable) {
  94.         int r;
  95.         r = (*mbpRead > mMask) ? 1:0;
  96.         mMask >>= 1;
  97.         if (mMask == 0x00) {
  98.             mMask = static_cast<BYTE>(0x80);
  99.             IncBuf();
  100.         }
  101.         return r;
  102.     } else {
  103.         throw(“Error at GetBit **”);
  104.     }
  105. }
  106.  
  107. int CReadBitStream::GetBits(int numOfBits) {    
  108. // numOfBits読みだす (0 < n <= 16)
  109.     if ((numOfBits <= 0)||(numOfBits > 16)) {
  110.         throw(“Error at GetBits of numOfBits”);
  111.     }
  112.     if (!mReadable) throw(“Error at GetBits Initial”);
  113.     int r = 0;
  114.     while (numOfBits) {
  115.         if (mReadable) {
  116.             if (mMask == 0x00) {
  117.                 mMask = static_cast<BYTE>(0x80);
  118.                 IncBuf(); 
  119.             }
  120.             r <<= 1;
  121.             r |= ((*mbpRead > mMask) ? 1: 0);
  122.             mMask >>= 1;
  123.             numOfBits–;
  124.         } else {
  125.             throw(“Error at GetBits”);
  126.         }
  127.     }
  128.     return r;
  129. }
  130.  
  131. void CReadBitStream::IncBuf(void){                           
  132.  // buffer読み出しを1 BYTE進める
  133.     if (++mbpRead >= mbpEndOfBuf) mReadable = false;       
  134.  // 次は読み出し不可にする
  135. }

どうでしょうか? 自分で書いたテスト・プログラムでは大丈夫なようです。エラーがあれば、きちんとthrowされています。