xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/LzmsDecoder.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // LzmsDecoder.h
2*f6dc9357SAndroid Build Coastguard Worker // The code is based on LZMS description from wimlib code
3*f6dc9357SAndroid Build Coastguard Worker 
4*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_LZMS_DECODER_H
5*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_LZMS_DECODER_H
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/HuffEnc.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "HuffmanDecoder.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
13*f6dc9357SAndroid Build Coastguard Worker namespace NLzms {
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumLitSyms = 256;
16*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumLenSyms = 54;
17*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumPosSyms = 799;
18*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumPowerSyms = 8;
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumProbBits = 6;
21*f6dc9357SAndroid Build Coastguard Worker const unsigned k_ProbLimit = 1 << k_NumProbBits;
22*f6dc9357SAndroid Build Coastguard Worker const unsigned k_InitialProb = 48;
23*f6dc9357SAndroid Build Coastguard Worker const UInt32 k_InitialHist = 0x55555555;
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumReps = 3;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumMainProbs  = 16;
28*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumMatchProbs = 32;
29*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumRepProbs   = 64;
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker const unsigned k_NumHuffmanBits = 15;
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker template <UInt32 m_NumSyms, UInt32 m_RebuildFreq, unsigned numTableBits>
34*f6dc9357SAndroid Build Coastguard Worker class CHuffDecoder: public NCompress::NHuffman::CDecoder<k_NumHuffmanBits, m_NumSyms, numTableBits>
35*f6dc9357SAndroid Build Coastguard Worker {
36*f6dc9357SAndroid Build Coastguard Worker public:
37*f6dc9357SAndroid Build Coastguard Worker   UInt32 RebuildRem;
38*f6dc9357SAndroid Build Coastguard Worker   UInt32 NumSyms;
39*f6dc9357SAndroid Build Coastguard Worker   UInt32 Freqs[m_NumSyms];
40*f6dc9357SAndroid Build Coastguard Worker 
Generate()41*f6dc9357SAndroid Build Coastguard Worker   void Generate() throw()
42*f6dc9357SAndroid Build Coastguard Worker   {
43*f6dc9357SAndroid Build Coastguard Worker     UInt32 vals[m_NumSyms];
44*f6dc9357SAndroid Build Coastguard Worker     Byte levels[m_NumSyms];
45*f6dc9357SAndroid Build Coastguard Worker 
46*f6dc9357SAndroid Build Coastguard Worker     // We need to check that our algorithm is OK, when optimal Huffman tree uses more than 15 levels !!!
47*f6dc9357SAndroid Build Coastguard Worker     Huffman_Generate(Freqs, vals, levels, NumSyms, k_NumHuffmanBits);
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = NumSyms; i < m_NumSyms; i++)
50*f6dc9357SAndroid Build Coastguard Worker       levels[i] = 0;
51*f6dc9357SAndroid Build Coastguard Worker 
52*f6dc9357SAndroid Build Coastguard Worker     this->Build(levels, /* NumSyms, */ NHuffman::k_BuildMode_Full);
53*f6dc9357SAndroid Build Coastguard Worker   }
54*f6dc9357SAndroid Build Coastguard Worker 
Rebuild()55*f6dc9357SAndroid Build Coastguard Worker   void Rebuild() throw()
56*f6dc9357SAndroid Build Coastguard Worker   {
57*f6dc9357SAndroid Build Coastguard Worker     Generate();
58*f6dc9357SAndroid Build Coastguard Worker     RebuildRem = m_RebuildFreq;
59*f6dc9357SAndroid Build Coastguard Worker     const UInt32 num = NumSyms;
60*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < num; i++)
61*f6dc9357SAndroid Build Coastguard Worker       Freqs[i] = (Freqs[i] >> 1) + 1;
62*f6dc9357SAndroid Build Coastguard Worker   }
63*f6dc9357SAndroid Build Coastguard Worker 
64*f6dc9357SAndroid Build Coastguard Worker public:
throw()65*f6dc9357SAndroid Build Coastguard Worker   void Init(UInt32 numSyms = m_NumSyms) throw()
66*f6dc9357SAndroid Build Coastguard Worker   {
67*f6dc9357SAndroid Build Coastguard Worker     RebuildRem = m_RebuildFreq;
68*f6dc9357SAndroid Build Coastguard Worker     NumSyms = numSyms;
69*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < numSyms; i++)
70*f6dc9357SAndroid Build Coastguard Worker       Freqs[i] = 1;
71*f6dc9357SAndroid Build Coastguard Worker     // for (; i < m_NumSyms; i++) Freqs[i] = 0;
72*f6dc9357SAndroid Build Coastguard Worker     Generate();
73*f6dc9357SAndroid Build Coastguard Worker   }
74*f6dc9357SAndroid Build Coastguard Worker };
75*f6dc9357SAndroid Build Coastguard Worker 
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker struct CProbEntry
78*f6dc9357SAndroid Build Coastguard Worker {
79*f6dc9357SAndroid Build Coastguard Worker   UInt32 Prob;
80*f6dc9357SAndroid Build Coastguard Worker   UInt64 Hist;
81*f6dc9357SAndroid Build Coastguard Worker 
InitCProbEntry82*f6dc9357SAndroid Build Coastguard Worker   void Init()
83*f6dc9357SAndroid Build Coastguard Worker   {
84*f6dc9357SAndroid Build Coastguard Worker     Prob = k_InitialProb;
85*f6dc9357SAndroid Build Coastguard Worker     Hist = k_InitialHist;
86*f6dc9357SAndroid Build Coastguard Worker   }
87*f6dc9357SAndroid Build Coastguard Worker 
GetProbCProbEntry88*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetProb() const throw()
89*f6dc9357SAndroid Build Coastguard Worker   {
90*f6dc9357SAndroid Build Coastguard Worker     UInt32 prob = Prob;
91*f6dc9357SAndroid Build Coastguard Worker     if (prob == 0)
92*f6dc9357SAndroid Build Coastguard Worker       prob = 1;
93*f6dc9357SAndroid Build Coastguard Worker     else if (prob == k_ProbLimit)
94*f6dc9357SAndroid Build Coastguard Worker       prob = k_ProbLimit - 1;
95*f6dc9357SAndroid Build Coastguard Worker     return prob;
96*f6dc9357SAndroid Build Coastguard Worker   }
97*f6dc9357SAndroid Build Coastguard Worker 
UpdateCProbEntry98*f6dc9357SAndroid Build Coastguard Worker   void Update(unsigned bit) throw()
99*f6dc9357SAndroid Build Coastguard Worker   {
100*f6dc9357SAndroid Build Coastguard Worker     Prob += (UInt32)((Int32)(Hist >> (k_ProbLimit - 1)) - (Int32)bit);
101*f6dc9357SAndroid Build Coastguard Worker     Hist = (Hist << 1) | bit;
102*f6dc9357SAndroid Build Coastguard Worker   }
103*f6dc9357SAndroid Build Coastguard Worker };
104*f6dc9357SAndroid Build Coastguard Worker 
105*f6dc9357SAndroid Build Coastguard Worker 
106*f6dc9357SAndroid Build Coastguard Worker struct CRangeDecoder
107*f6dc9357SAndroid Build Coastguard Worker {
108*f6dc9357SAndroid Build Coastguard Worker   UInt32 range;
109*f6dc9357SAndroid Build Coastguard Worker   UInt32 code;
110*f6dc9357SAndroid Build Coastguard Worker   const Byte *cur;
111*f6dc9357SAndroid Build Coastguard Worker   // const Byte *end;
112*f6dc9357SAndroid Build Coastguard Worker 
InitCRangeDecoder113*f6dc9357SAndroid Build Coastguard Worker   void Init(const Byte *data, size_t /* size */) throw()
114*f6dc9357SAndroid Build Coastguard Worker   {
115*f6dc9357SAndroid Build Coastguard Worker     range = 0xFFFFFFFF;
116*f6dc9357SAndroid Build Coastguard Worker     code = (((UInt32)GetUi16(data)) << 16) | GetUi16(data + 2);
117*f6dc9357SAndroid Build Coastguard Worker     cur = data + 4;
118*f6dc9357SAndroid Build Coastguard Worker     // end = data + size;
119*f6dc9357SAndroid Build Coastguard Worker   }
120*f6dc9357SAndroid Build Coastguard Worker 
NormalizeCRangeDecoder121*f6dc9357SAndroid Build Coastguard Worker   void Normalize()
122*f6dc9357SAndroid Build Coastguard Worker   {
123*f6dc9357SAndroid Build Coastguard Worker     if (range <= 0xFFFF)
124*f6dc9357SAndroid Build Coastguard Worker     {
125*f6dc9357SAndroid Build Coastguard Worker       range <<= 16;
126*f6dc9357SAndroid Build Coastguard Worker       code <<= 16;
127*f6dc9357SAndroid Build Coastguard Worker       // if (cur >= end) throw 1;
128*f6dc9357SAndroid Build Coastguard Worker       code |= GetUi16(cur);
129*f6dc9357SAndroid Build Coastguard Worker       cur += 2;
130*f6dc9357SAndroid Build Coastguard Worker     }
131*f6dc9357SAndroid Build Coastguard Worker   }
132*f6dc9357SAndroid Build Coastguard Worker 
DecodeCRangeDecoder133*f6dc9357SAndroid Build Coastguard Worker   unsigned Decode(UInt32 *state, UInt32 numStates, struct CProbEntry *probs)
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     UInt32 st = *state;
136*f6dc9357SAndroid Build Coastguard Worker     CProbEntry *entry = &probs[st];
137*f6dc9357SAndroid Build Coastguard Worker     st = (st << 1) & (numStates - 1);
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker     const UInt32 prob = entry->GetProb();
140*f6dc9357SAndroid Build Coastguard Worker 
141*f6dc9357SAndroid Build Coastguard Worker     if (range <= 0xFFFF)
142*f6dc9357SAndroid Build Coastguard Worker     {
143*f6dc9357SAndroid Build Coastguard Worker       range <<= 16;
144*f6dc9357SAndroid Build Coastguard Worker       code <<= 16;
145*f6dc9357SAndroid Build Coastguard Worker       // if (cur >= end) throw 1;
146*f6dc9357SAndroid Build Coastguard Worker       code |= GetUi16(cur);
147*f6dc9357SAndroid Build Coastguard Worker       cur += 2;
148*f6dc9357SAndroid Build Coastguard Worker     }
149*f6dc9357SAndroid Build Coastguard Worker 
150*f6dc9357SAndroid Build Coastguard Worker     const UInt32 bound = (range >> k_NumProbBits) * prob;
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker     if (code < bound)
153*f6dc9357SAndroid Build Coastguard Worker     {
154*f6dc9357SAndroid Build Coastguard Worker       range = bound;
155*f6dc9357SAndroid Build Coastguard Worker       *state = st;
156*f6dc9357SAndroid Build Coastguard Worker       entry->Update(0);
157*f6dc9357SAndroid Build Coastguard Worker       return 0;
158*f6dc9357SAndroid Build Coastguard Worker     }
159*f6dc9357SAndroid Build Coastguard Worker     else
160*f6dc9357SAndroid Build Coastguard Worker     {
161*f6dc9357SAndroid Build Coastguard Worker       range -= bound;
162*f6dc9357SAndroid Build Coastguard Worker       code -= bound;
163*f6dc9357SAndroid Build Coastguard Worker       *state = st | 1;
164*f6dc9357SAndroid Build Coastguard Worker       entry->Update(1);
165*f6dc9357SAndroid Build Coastguard Worker       return 1;
166*f6dc9357SAndroid Build Coastguard Worker     }
167*f6dc9357SAndroid Build Coastguard Worker   }
168*f6dc9357SAndroid Build Coastguard Worker };
169*f6dc9357SAndroid Build Coastguard Worker 
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker class CDecoder
172*f6dc9357SAndroid Build Coastguard Worker {
173*f6dc9357SAndroid Build Coastguard Worker   // CRangeDecoder _rc;
174*f6dc9357SAndroid Build Coastguard Worker   size_t _pos;
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   UInt32 _reps[k_NumReps + 1];
177*f6dc9357SAndroid Build Coastguard Worker   UInt64 _deltaReps[k_NumReps + 1];
178*f6dc9357SAndroid Build Coastguard Worker 
179*f6dc9357SAndroid Build Coastguard Worker   UInt32 mainState;
180*f6dc9357SAndroid Build Coastguard Worker   UInt32 matchState;
181*f6dc9357SAndroid Build Coastguard Worker   UInt32 lzRepStates[k_NumReps];
182*f6dc9357SAndroid Build Coastguard Worker   UInt32 deltaRepStates[k_NumReps];
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker   struct CProbEntry mainProbs[k_NumMainProbs];
185*f6dc9357SAndroid Build Coastguard Worker   struct CProbEntry matchProbs[k_NumMatchProbs];
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker   struct CProbEntry lzRepProbs[k_NumReps][k_NumRepProbs];
188*f6dc9357SAndroid Build Coastguard Worker   struct CProbEntry deltaRepProbs[k_NumReps][k_NumRepProbs];
189*f6dc9357SAndroid Build Coastguard Worker 
190*f6dc9357SAndroid Build Coastguard Worker   CHuffDecoder<k_NumLitSyms, 1024, 9> m_LitDecoder;
191*f6dc9357SAndroid Build Coastguard Worker   CHuffDecoder<k_NumPosSyms, 1024, 9> m_PosDecoder;
192*f6dc9357SAndroid Build Coastguard Worker   CHuffDecoder<k_NumLenSyms, 512, 8> m_LenDecoder;
193*f6dc9357SAndroid Build Coastguard Worker   CHuffDecoder<k_NumPowerSyms, 512, 6> m_PowerDecoder;
194*f6dc9357SAndroid Build Coastguard Worker   CHuffDecoder<k_NumPosSyms, 1024, 9> m_DeltaDecoder;
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   Int32 *_x86_history;
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker   HRESULT CodeReal(const Byte *in, size_t inSize, Byte *out, size_t outSize);
199*f6dc9357SAndroid Build Coastguard Worker public:
200*f6dc9357SAndroid Build Coastguard Worker   CDecoder();
201*f6dc9357SAndroid Build Coastguard Worker   ~CDecoder();
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker   HRESULT Code(const Byte *in, size_t inSize, Byte *out, size_t outSize);
GetUnpackSize()204*f6dc9357SAndroid Build Coastguard Worker   size_t GetUnpackSize() const { return _pos; }
205*f6dc9357SAndroid Build Coastguard Worker };
206*f6dc9357SAndroid Build Coastguard Worker 
207*f6dc9357SAndroid Build Coastguard Worker }}
208*f6dc9357SAndroid Build Coastguard Worker 
209*f6dc9357SAndroid Build Coastguard Worker #endif
210