1 // LzmsDecoder.h
2 // The code is based on LZMS description from wimlib code
3 
4 #ifndef __LZMS_DECODER_H
5 #define __LZMS_DECODER_H
6 
7 // #define SHOW_DEBUG_INFO
8 
9 #ifdef SHOW_DEBUG_INFO
10 #include <stdio.h>
11 #define PRF(x) x
12 #else
13 // #define PRF(x)
14 #endif
15 
16 #include "../../../C/CpuArch.h"
17 #include "../../../C/HuffEnc.h"
18 
19 #include "../../Common/MyBuffer.h"
20 #include "../../Common/MyCom.h"
21 
22 #include "../ICoder.h"
23 
24 #include "HuffmanDecoder.h"
25 
26 namespace NCompress {
27 namespace NLzms {
28 
29 class CBitDecoder
30 {
31 public:
32   const Byte *_buf;
33   unsigned _bitPos;
34 
Init(const Byte * buf,size_t size)35   void Init(const Byte *buf, size_t size) throw()
36   {
37     _buf = buf + size;
38     _bitPos = 0;
39   }
40 
GetValue(unsigned numBits)41   UInt32 GetValue(unsigned numBits) const
42   {
43     UInt32 v = ((UInt32)_buf[-1] << 16) | ((UInt32)_buf[-2] << 8) | (UInt32)_buf[-3];
44     v >>= (24 - numBits - _bitPos);
45     return v & ((1 << numBits) - 1);
46   }
47 
MovePos(unsigned numBits)48   void MovePos(unsigned numBits)
49   {
50     _bitPos += numBits;
51     _buf -= (_bitPos >> 3);
52     _bitPos &= 7;
53   }
54 
ReadBits32(unsigned numBits)55   UInt32 ReadBits32(unsigned numBits)
56   {
57     UInt32 mask = (((UInt32)1 << numBits) - 1);
58     numBits += _bitPos;
59     const Byte *buf = _buf;
60     UInt32 v = GetUi32(buf - 4);
61     if (numBits > 32)
62     {
63       v <<= (numBits - 32);
64       v |= (UInt32)buf[-5] >> (40 - numBits);
65     }
66     else
67       v >>= (32 - numBits);
68     _buf = buf - (numBits >> 3);
69     _bitPos = numBits & 7;
70     return v & mask;
71   }
72 };
73 
74 
75 const unsigned k_NumLitSyms = 256;
76 const unsigned k_NumLenSyms = 54;
77 const unsigned k_NumPosSyms = 799;
78 const unsigned k_NumPowerSyms = 8;
79 
80 const unsigned k_NumProbBits = 6;
81 const unsigned k_ProbLimit = 1 << k_NumProbBits;
82 const unsigned k_InitialProb = 48;
83 const UInt32 k_InitialHist = 0x55555555;
84 
85 const unsigned k_NumReps = 3;
86 
87 const unsigned k_NumMainProbs  = 16;
88 const unsigned k_NumMatchProbs = 32;
89 const unsigned k_NumRepProbs   = 64;
90 
91 const unsigned k_NumHuffmanBits = 15;
92 
93 template <UInt32 m_NumSyms, UInt32 m_RebuildFreq, unsigned numTableBits>
94 class CHuffDecoder: public NCompress::NHuffman::CDecoder<k_NumHuffmanBits, m_NumSyms, numTableBits>
95 {
96 public:
97   UInt32 RebuildRem;
98   UInt32 NumSyms;
99   UInt32 Freqs[m_NumSyms];
100 
Generate()101   void Generate() throw()
102   {
103     UInt32 vals[m_NumSyms];
104     Byte levels[m_NumSyms];
105 
106     // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!!
107     Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits);
108 
109     /*
110     for (UInt32 i = NumSyms; i < m_NumSyms; i++)
111       levels[i] = 0;
112     */
113     this->BuildFull(levels, NumSyms);
114   }
115 
Rebuild()116   void Rebuild() throw()
117   {
118     Generate();
119     RebuildRem = m_RebuildFreq;
120     UInt32 num = NumSyms;
121     for (UInt32 i = 0; i < num; i++)
122       Freqs[i] = (Freqs[i] >> 1) + 1;
123   }
124 
125 public:
throw()126   void Init(UInt32 numSyms = m_NumSyms) throw()
127   {
128     RebuildRem = m_RebuildFreq;
129     NumSyms = numSyms;
130     for (UInt32 i = 0; i < numSyms; i++)
131       Freqs[i] = 1;
132     // for (; i < m_NumSyms; i++) Freqs[i] = 0;
133     Generate();
134   }
135 };
136 
137 
138 struct CProbEntry
139 {
140   UInt32 Prob;
141   UInt64 Hist;
142 
InitCProbEntry143   void Init()
144   {
145     Prob = k_InitialProb;
146     Hist = k_InitialHist;
147   }
148 
GetProbCProbEntry149   UInt32 GetProb() const throw()
150   {
151     UInt32 prob = Prob;
152     if (prob == 0)
153       prob = 1;
154     else if (prob == k_ProbLimit)
155       prob = k_ProbLimit - 1;
156     return prob;
157   }
158 
UpdateCProbEntry159   void Update(unsigned bit) throw()
160   {
161     Prob += (Int32)(Hist >> (k_ProbLimit - 1)) - (Int32)bit;
162     Hist = (Hist << 1) | bit;
163   }
164 };
165 
166 
167 struct CRangeDecoder
168 {
169   UInt32 range;
170   UInt32 code;
171   const Byte *cur;
172   // const Byte *end;
173 
InitCRangeDecoder174   void Init(const Byte *data, size_t /* size */) throw()
175   {
176     range = 0xFFFFFFFF;
177     code = (((UInt32)GetUi16(data)) << 16) | GetUi16(data + 2);
178     cur = data + 4;
179     // end = data + size;
180   }
181 
NormalizeCRangeDecoder182   void Normalize()
183   {
184     if (range <= 0xFFFF)
185     {
186       range <<= 16;
187       code <<= 16;
188       // if (cur >= end) throw 1;
189       code |= GetUi16(cur);
190       cur += 2;
191     }
192   }
193 
DecodeCRangeDecoder194   unsigned Decode(UInt32 *state, UInt32 numStates, struct CProbEntry *probs)
195   {
196     UInt32 st = *state;
197     CProbEntry *entry = &probs[st];
198     st = (st << 1) & (numStates - 1);
199 
200     UInt32 prob = entry->GetProb();
201 
202     if (range <= 0xFFFF)
203     {
204       range <<= 16;
205       code <<= 16;
206       // if (cur >= end) throw 1;
207       code |= GetUi16(cur);
208       cur += 2;
209     }
210 
211     UInt32 bound = (range >> k_NumProbBits) * prob;
212 
213     if (code < bound)
214     {
215       range = bound;
216       *state = st;
217       entry->Update(0);
218       return 0;
219     }
220     else
221     {
222       range -= bound;
223       code -= bound;
224       *state = st | 1;
225       entry->Update(1);
226       return 1;
227     }
228   }
229 };
230 
231 
232 class CDecoder
233 {
234   // CRangeDecoder _rc;
235   // CBitDecoder _bs;
236   size_t _pos;
237 
238   UInt32 _reps[k_NumReps + 1];
239   UInt64 _deltaReps[k_NumReps + 1];
240 
241   UInt32 mainState;
242   UInt32 matchState;
243   UInt32 lzRepStates[k_NumReps];
244   UInt32 deltaRepStates[k_NumReps];
245 
246   struct CProbEntry mainProbs[k_NumMainProbs];
247   struct CProbEntry matchProbs[k_NumMatchProbs];
248 
249   struct CProbEntry lzRepProbs[k_NumReps][k_NumRepProbs];
250   struct CProbEntry deltaRepProbs[k_NumReps][k_NumRepProbs];
251 
252   CHuffDecoder<k_NumLitSyms, 1024, 9> m_LitDecoder;
253   CHuffDecoder<k_NumPosSyms, 1024, 9> m_PosDecoder;
254   CHuffDecoder<k_NumLenSyms, 512, 8> m_LenDecoder;
255   CHuffDecoder<k_NumPowerSyms, 512, 6> m_PowerDecoder;
256   CHuffDecoder<k_NumPosSyms, 1024, 9> m_DeltaDecoder;
257 
258   Int32 *_x86_history;
259 
260   HRESULT CodeReal(const Byte *in, size_t inSize, Byte *out, size_t outSize);
261 public:
262   CDecoder();
263   ~CDecoder();
264 
265   HRESULT Code(const Byte *in, size_t inSize, Byte *out, size_t outSize);
GetUnpackSize()266   const size_t GetUnpackSize() const { return _pos; }
267 };
268 
269 }}
270 
271 #endif
272