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