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