rlm@1
|
1 // BitlDecoder.h -- the Least Significant Bit of byte is First
|
rlm@1
|
2
|
rlm@1
|
3 #ifndef __BITL_DECODER_H
|
rlm@1
|
4 #define __BITL_DECODER_H
|
rlm@1
|
5
|
rlm@1
|
6 #include "../IStream.h"
|
rlm@1
|
7
|
rlm@1
|
8 namespace NBitl {
|
rlm@1
|
9
|
rlm@1
|
10 const int kNumBigValueBits = 8 * 4;
|
rlm@1
|
11
|
rlm@1
|
12 const int kNumValueBytes = 3;
|
rlm@1
|
13 const int kNumValueBits = 8 * kNumValueBytes;
|
rlm@1
|
14
|
rlm@1
|
15 const UInt32 kMask = (1 << kNumValueBits) - 1;
|
rlm@1
|
16
|
rlm@1
|
17 extern Byte kInvertTable[256];
|
rlm@1
|
18
|
rlm@1
|
19 template<class TInByte>
|
rlm@1
|
20 class CBaseDecoder
|
rlm@1
|
21 {
|
rlm@1
|
22 protected:
|
rlm@1
|
23 int m_BitPos;
|
rlm@1
|
24 UInt32 m_Value;
|
rlm@1
|
25 TInByte m_Stream;
|
rlm@1
|
26 public:
|
rlm@1
|
27 UInt32 NumExtraBytes;
|
rlm@1
|
28 bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
rlm@1
|
29 void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream); }
|
rlm@1
|
30 void ReleaseStream() { m_Stream.ReleaseStream(); }
|
rlm@1
|
31 void Init()
|
rlm@1
|
32 {
|
rlm@1
|
33 m_Stream.Init();
|
rlm@1
|
34 m_BitPos = kNumBigValueBits;
|
rlm@1
|
35 m_Value = 0;
|
rlm@1
|
36 NumExtraBytes = 0;
|
rlm@1
|
37 }
|
rlm@1
|
38 UInt64 GetProcessedSize() const
|
rlm@1
|
39 { return m_Stream.GetProcessedSize() - (kNumBigValueBits - m_BitPos) / 8; }
|
rlm@1
|
40 UInt64 GetProcessedBitsSize() const
|
rlm@1
|
41 { return (m_Stream.GetProcessedSize() << 3) - (kNumBigValueBits - m_BitPos); }
|
rlm@1
|
42 int GetBitPosition() const { return (m_BitPos & 7); }
|
rlm@1
|
43
|
rlm@1
|
44 void Normalize()
|
rlm@1
|
45 {
|
rlm@1
|
46 for (;m_BitPos >= 8; m_BitPos -= 8)
|
rlm@1
|
47 {
|
rlm@1
|
48 Byte b = 0;
|
rlm@1
|
49 if (!m_Stream.ReadByte(b))
|
rlm@1
|
50 {
|
rlm@1
|
51 b = 0xFF; // check it
|
rlm@1
|
52 NumExtraBytes++;
|
rlm@1
|
53 }
|
rlm@1
|
54 m_Value = (b << (kNumBigValueBits - m_BitPos)) | m_Value;
|
rlm@1
|
55 }
|
rlm@1
|
56 }
|
rlm@1
|
57
|
rlm@1
|
58 UInt32 ReadBits(int numBits)
|
rlm@1
|
59 {
|
rlm@1
|
60 Normalize();
|
rlm@1
|
61 UInt32 res = m_Value & ((1 << numBits) - 1);
|
rlm@1
|
62 m_BitPos += numBits;
|
rlm@1
|
63 m_Value >>= numBits;
|
rlm@1
|
64 return res;
|
rlm@1
|
65 }
|
rlm@1
|
66
|
rlm@1
|
67 bool ExtraBitsWereRead() const
|
rlm@1
|
68 {
|
rlm@1
|
69 if (NumExtraBytes == 0)
|
rlm@1
|
70 return false;
|
rlm@1
|
71 return ((UInt32)(kNumBigValueBits - m_BitPos) < (NumExtraBytes << 3));
|
rlm@1
|
72 }
|
rlm@1
|
73 };
|
rlm@1
|
74
|
rlm@1
|
75 template<class TInByte>
|
rlm@1
|
76 class CDecoder: public CBaseDecoder<TInByte>
|
rlm@1
|
77 {
|
rlm@1
|
78 UInt32 m_NormalValue;
|
rlm@1
|
79
|
rlm@1
|
80 public:
|
rlm@1
|
81 void Init()
|
rlm@1
|
82 {
|
rlm@1
|
83 CBaseDecoder<TInByte>::Init();
|
rlm@1
|
84 m_NormalValue = 0;
|
rlm@1
|
85 }
|
rlm@1
|
86
|
rlm@1
|
87 void Normalize()
|
rlm@1
|
88 {
|
rlm@1
|
89 for (; this->m_BitPos >= 8; this->m_BitPos -= 8)
|
rlm@1
|
90 {
|
rlm@1
|
91 Byte b = 0;
|
rlm@1
|
92 if (!this->m_Stream.ReadByte(b))
|
rlm@1
|
93 {
|
rlm@1
|
94 b = 0xFF; // check it
|
rlm@1
|
95 this->NumExtraBytes++;
|
rlm@1
|
96 }
|
rlm@1
|
97 m_NormalValue = (b << (kNumBigValueBits - this->m_BitPos)) | m_NormalValue;
|
rlm@1
|
98 this->m_Value = (this->m_Value << 8) | kInvertTable[b];
|
rlm@1
|
99 }
|
rlm@1
|
100 }
|
rlm@1
|
101
|
rlm@1
|
102 UInt32 GetValue(int numBits)
|
rlm@1
|
103 {
|
rlm@1
|
104 Normalize();
|
rlm@1
|
105 return ((this->m_Value >> (8 - this->m_BitPos)) & kMask) >> (kNumValueBits - numBits);
|
rlm@1
|
106 }
|
rlm@1
|
107
|
rlm@1
|
108 void MovePos(int numBits)
|
rlm@1
|
109 {
|
rlm@1
|
110 this->m_BitPos += numBits;
|
rlm@1
|
111 m_NormalValue >>= numBits;
|
rlm@1
|
112 }
|
rlm@1
|
113
|
rlm@1
|
114 UInt32 ReadBits(int numBits)
|
rlm@1
|
115 {
|
rlm@1
|
116 Normalize();
|
rlm@1
|
117 UInt32 res = m_NormalValue & ( (1 << numBits) - 1);
|
rlm@1
|
118 MovePos(numBits);
|
rlm@1
|
119 return res;
|
rlm@1
|
120 }
|
rlm@1
|
121 };
|
rlm@1
|
122
|
rlm@1
|
123 }
|
rlm@1
|
124
|
rlm@1
|
125 #endif
|