xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/QuantumDecoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // QuantumDecoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker // #include <stdio.h>
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
9*f6dc9357SAndroid Build Coastguard Worker 
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/Defs.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "QuantumDecoder.h"
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
15*f6dc9357SAndroid Build Coastguard Worker namespace NQuantum {
16*f6dc9357SAndroid Build Coastguard Worker 
17*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumLenSymbols = 27;
18*f6dc9357SAndroid Build Coastguard Worker static const unsigned kMatchMinLen = 3;
19*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumSimpleLenSlots = 6;
20*f6dc9357SAndroid Build Coastguard Worker 
21*f6dc9357SAndroid Build Coastguard Worker static const unsigned kUpdateStep = 8;
22*f6dc9357SAndroid Build Coastguard Worker static const unsigned kFreqSumMax = 3800;
23*f6dc9357SAndroid Build Coastguard Worker static const unsigned kReorderCount_Start = 4;
24*f6dc9357SAndroid Build Coastguard Worker static const unsigned kReorderCount = 50;
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker class CRangeDecoder
28*f6dc9357SAndroid Build Coastguard Worker {
29*f6dc9357SAndroid Build Coastguard Worker   UInt32 Low;
30*f6dc9357SAndroid Build Coastguard Worker   UInt32 Range;
31*f6dc9357SAndroid Build Coastguard Worker   UInt32 Code;
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker   unsigned _bitOffset;
34*f6dc9357SAndroid Build Coastguard Worker   const Byte *_buf;
35*f6dc9357SAndroid Build Coastguard Worker   const Byte *_bufLim;
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker public:
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
Init(const Byte * inData,size_t inSize)40*f6dc9357SAndroid Build Coastguard Worker   void Init(const Byte *inData, size_t inSize)
41*f6dc9357SAndroid Build Coastguard Worker   {
42*f6dc9357SAndroid Build Coastguard Worker     Code = ((UInt32)*inData << 8) | inData[1];
43*f6dc9357SAndroid Build Coastguard Worker     _buf = inData + 2;
44*f6dc9357SAndroid Build Coastguard Worker     _bufLim = inData + inSize;
45*f6dc9357SAndroid Build Coastguard Worker     _bitOffset = 0;
46*f6dc9357SAndroid Build Coastguard Worker     Low = 0;
47*f6dc9357SAndroid Build Coastguard Worker     Range = 0x10000;
48*f6dc9357SAndroid Build Coastguard Worker   }
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
WasExtraRead() const51*f6dc9357SAndroid Build Coastguard Worker   bool WasExtraRead() const
52*f6dc9357SAndroid Build Coastguard Worker   {
53*f6dc9357SAndroid Build Coastguard Worker     return _buf > _bufLim;
54*f6dc9357SAndroid Build Coastguard Worker   }
55*f6dc9357SAndroid Build Coastguard Worker 
56*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
ReadBits(unsigned numBits)57*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadBits(unsigned numBits) // numBits > 0
58*f6dc9357SAndroid Build Coastguard Worker   {
59*f6dc9357SAndroid Build Coastguard Worker     unsigned bitOffset = _bitOffset;
60*f6dc9357SAndroid Build Coastguard Worker     const Byte *buf = _buf;
61*f6dc9357SAndroid Build Coastguard Worker     const UInt32 res = GetBe32(buf) << bitOffset;
62*f6dc9357SAndroid Build Coastguard Worker     bitOffset += numBits;
63*f6dc9357SAndroid Build Coastguard Worker     _buf = buf + (bitOffset >> 3);
64*f6dc9357SAndroid Build Coastguard Worker     _bitOffset = bitOffset & 7;
65*f6dc9357SAndroid Build Coastguard Worker     return res >> (32 - numBits);
66*f6dc9357SAndroid Build Coastguard Worker   }
67*f6dc9357SAndroid Build Coastguard Worker 
68*f6dc9357SAndroid Build Coastguard Worker   // ---------- Range Decoder functions ----------
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
Finish()71*f6dc9357SAndroid Build Coastguard Worker   bool Finish()
72*f6dc9357SAndroid Build Coastguard Worker   {
73*f6dc9357SAndroid Build Coastguard Worker     const unsigned numBits = 2 + ((16 - 2 - _bitOffset) & 7);
74*f6dc9357SAndroid Build Coastguard Worker     if (ReadBits(numBits) != 0)
75*f6dc9357SAndroid Build Coastguard Worker       return false;
76*f6dc9357SAndroid Build Coastguard Worker     return _buf == _bufLim;
77*f6dc9357SAndroid Build Coastguard Worker   }
78*f6dc9357SAndroid Build Coastguard Worker 
79*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
GetThreshold(UInt32 total) const80*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetThreshold(UInt32 total) const
81*f6dc9357SAndroid Build Coastguard Worker   {
82*f6dc9357SAndroid Build Coastguard Worker     return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;
83*f6dc9357SAndroid Build Coastguard Worker   }
84*f6dc9357SAndroid Build Coastguard Worker 
85*f6dc9357SAndroid Build Coastguard Worker   Z7_FORCE_INLINE
Decode(UInt32 start,UInt32 end,UInt32 total)86*f6dc9357SAndroid Build Coastguard Worker   void Decode(UInt32 start, UInt32 end, UInt32 total)
87*f6dc9357SAndroid Build Coastguard Worker   {
88*f6dc9357SAndroid Build Coastguard Worker     // UInt32 hi = ~(Low + end * Range / total - 1);
89*f6dc9357SAndroid Build Coastguard Worker     UInt32 hi = 0 - (Low + end * Range / total);
90*f6dc9357SAndroid Build Coastguard Worker     const UInt32 offset = start * Range / total;
91*f6dc9357SAndroid Build Coastguard Worker     UInt32 lo = Low + offset;
92*f6dc9357SAndroid Build Coastguard Worker     Code -= offset;
93*f6dc9357SAndroid Build Coastguard Worker     UInt32 numBits = 0;
94*f6dc9357SAndroid Build Coastguard Worker     lo ^= hi;
95*f6dc9357SAndroid Build Coastguard Worker     while (lo & (1u << 15))
96*f6dc9357SAndroid Build Coastguard Worker     {
97*f6dc9357SAndroid Build Coastguard Worker       lo <<= 1;
98*f6dc9357SAndroid Build Coastguard Worker       hi <<= 1;
99*f6dc9357SAndroid Build Coastguard Worker       numBits++;
100*f6dc9357SAndroid Build Coastguard Worker     }
101*f6dc9357SAndroid Build Coastguard Worker     lo ^= hi;
102*f6dc9357SAndroid Build Coastguard Worker     UInt32 an = lo & hi;
103*f6dc9357SAndroid Build Coastguard Worker     while (an & (1u << 14))
104*f6dc9357SAndroid Build Coastguard Worker     {
105*f6dc9357SAndroid Build Coastguard Worker       an <<= 1;
106*f6dc9357SAndroid Build Coastguard Worker       lo <<= 1;
107*f6dc9357SAndroid Build Coastguard Worker       hi <<= 1;
108*f6dc9357SAndroid Build Coastguard Worker       numBits++;
109*f6dc9357SAndroid Build Coastguard Worker     }
110*f6dc9357SAndroid Build Coastguard Worker     Low = lo;
111*f6dc9357SAndroid Build Coastguard Worker     Range = ((~hi - lo) & 0xffff) + 1;
112*f6dc9357SAndroid Build Coastguard Worker     if (numBits)
113*f6dc9357SAndroid Build Coastguard Worker       Code = (Code << numBits) + ReadBits(numBits);
114*f6dc9357SAndroid Build Coastguard Worker   }
115*f6dc9357SAndroid Build Coastguard Worker };
116*f6dc9357SAndroid Build Coastguard Worker 
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker // Z7_FORCE_INLINE
119*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Decode(CRangeDecoder * rc)120*f6dc9357SAndroid Build Coastguard Worker unsigned CModelDecoder::Decode(CRangeDecoder *rc)
121*f6dc9357SAndroid Build Coastguard Worker // Z7_NO_INLINE void CModelDecoder::Normalize()
122*f6dc9357SAndroid Build Coastguard Worker {
123*f6dc9357SAndroid Build Coastguard Worker   if (Freqs[0] > kFreqSumMax)
124*f6dc9357SAndroid Build Coastguard Worker   {
125*f6dc9357SAndroid Build Coastguard Worker     if (--ReorderCount == 0)
126*f6dc9357SAndroid Build Coastguard Worker     {
127*f6dc9357SAndroid Build Coastguard Worker       ReorderCount = kReorderCount;
128*f6dc9357SAndroid Build Coastguard Worker       {
129*f6dc9357SAndroid Build Coastguard Worker         unsigned i = NumItems;
130*f6dc9357SAndroid Build Coastguard Worker         unsigned next = 0;
131*f6dc9357SAndroid Build Coastguard Worker         UInt16 *freqs = &Freqs[i];
132*f6dc9357SAndroid Build Coastguard Worker         do
133*f6dc9357SAndroid Build Coastguard Worker         {
134*f6dc9357SAndroid Build Coastguard Worker           const unsigned freq = *--freqs;
135*f6dc9357SAndroid Build Coastguard Worker           *freqs = (UInt16)((freq - next + 1) >> 1);
136*f6dc9357SAndroid Build Coastguard Worker           next = freq;
137*f6dc9357SAndroid Build Coastguard Worker         }
138*f6dc9357SAndroid Build Coastguard Worker         while (--i);
139*f6dc9357SAndroid Build Coastguard Worker       }
140*f6dc9357SAndroid Build Coastguard Worker       {
141*f6dc9357SAndroid Build Coastguard Worker         for (unsigned i = 0; i < NumItems - 1; i++)
142*f6dc9357SAndroid Build Coastguard Worker         {
143*f6dc9357SAndroid Build Coastguard Worker           UInt16 freq = Freqs[i];
144*f6dc9357SAndroid Build Coastguard Worker           for (unsigned k = i + 1; k < NumItems; k++)
145*f6dc9357SAndroid Build Coastguard Worker             if (freq < Freqs[k])
146*f6dc9357SAndroid Build Coastguard Worker             {
147*f6dc9357SAndroid Build Coastguard Worker               const UInt16 freq2 = Freqs[k];
148*f6dc9357SAndroid Build Coastguard Worker               Freqs[k] = freq;
149*f6dc9357SAndroid Build Coastguard Worker               Freqs[i] = freq2;
150*f6dc9357SAndroid Build Coastguard Worker               freq = freq2;
151*f6dc9357SAndroid Build Coastguard Worker               const Byte val = Vals[i];
152*f6dc9357SAndroid Build Coastguard Worker               Vals[i] = Vals[k];
153*f6dc9357SAndroid Build Coastguard Worker               Vals[k] = val;
154*f6dc9357SAndroid Build Coastguard Worker             }
155*f6dc9357SAndroid Build Coastguard Worker         }
156*f6dc9357SAndroid Build Coastguard Worker       }
157*f6dc9357SAndroid Build Coastguard Worker       unsigned i = NumItems;
158*f6dc9357SAndroid Build Coastguard Worker       unsigned freq = 0;
159*f6dc9357SAndroid Build Coastguard Worker       UInt16 *freqs = &Freqs[i];
160*f6dc9357SAndroid Build Coastguard Worker       do
161*f6dc9357SAndroid Build Coastguard Worker       {
162*f6dc9357SAndroid Build Coastguard Worker         freq += *--freqs;
163*f6dc9357SAndroid Build Coastguard Worker         *freqs = (UInt16)freq;
164*f6dc9357SAndroid Build Coastguard Worker       }
165*f6dc9357SAndroid Build Coastguard Worker       while (--i);
166*f6dc9357SAndroid Build Coastguard Worker     }
167*f6dc9357SAndroid Build Coastguard Worker     else
168*f6dc9357SAndroid Build Coastguard Worker     {
169*f6dc9357SAndroid Build Coastguard Worker       unsigned i = NumItems;
170*f6dc9357SAndroid Build Coastguard Worker       unsigned next = 1;
171*f6dc9357SAndroid Build Coastguard Worker       UInt16 *freqs = &Freqs[i];
172*f6dc9357SAndroid Build Coastguard Worker       do
173*f6dc9357SAndroid Build Coastguard Worker       {
174*f6dc9357SAndroid Build Coastguard Worker         unsigned freq = *--freqs >> 1;
175*f6dc9357SAndroid Build Coastguard Worker         if (freq < next)
176*f6dc9357SAndroid Build Coastguard Worker           freq = next;
177*f6dc9357SAndroid Build Coastguard Worker         *freqs = (UInt16)freq;
178*f6dc9357SAndroid Build Coastguard Worker         next = freq + 1;
179*f6dc9357SAndroid Build Coastguard Worker       }
180*f6dc9357SAndroid Build Coastguard Worker       while (--i);
181*f6dc9357SAndroid Build Coastguard Worker     }
182*f6dc9357SAndroid Build Coastguard Worker   }
183*f6dc9357SAndroid Build Coastguard Worker   unsigned res;
184*f6dc9357SAndroid Build Coastguard Worker   {
185*f6dc9357SAndroid Build Coastguard Worker     const unsigned freq0 = Freqs[0];
186*f6dc9357SAndroid Build Coastguard Worker     Freqs[0] = (UInt16)(freq0 + kUpdateStep);
187*f6dc9357SAndroid Build Coastguard Worker     const unsigned threshold = rc->GetThreshold(freq0);
188*f6dc9357SAndroid Build Coastguard Worker     UInt16 *freqs = &Freqs[1];
189*f6dc9357SAndroid Build Coastguard Worker     unsigned freq = *freqs;
190*f6dc9357SAndroid Build Coastguard Worker     while (freq > threshold)
191*f6dc9357SAndroid Build Coastguard Worker     {
192*f6dc9357SAndroid Build Coastguard Worker       *freqs++ = (UInt16)(freq + kUpdateStep);
193*f6dc9357SAndroid Build Coastguard Worker       freq = *freqs;
194*f6dc9357SAndroid Build Coastguard Worker     }
195*f6dc9357SAndroid Build Coastguard Worker     res = Vals[freqs - Freqs - 1];
196*f6dc9357SAndroid Build Coastguard Worker     rc->Decode(freq, freqs[-1] - kUpdateStep, freq0);
197*f6dc9357SAndroid Build Coastguard Worker   }
198*f6dc9357SAndroid Build Coastguard Worker   return res;
199*f6dc9357SAndroid Build Coastguard Worker }
200*f6dc9357SAndroid Build Coastguard Worker 
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker Z7_NO_INLINE
Init(unsigned numItems,unsigned startVal)203*f6dc9357SAndroid Build Coastguard Worker void CModelDecoder::Init(unsigned numItems, unsigned startVal)
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker   NumItems = numItems;
206*f6dc9357SAndroid Build Coastguard Worker   ReorderCount = kReorderCount_Start;
207*f6dc9357SAndroid Build Coastguard Worker   UInt16 *freqs = Freqs;
208*f6dc9357SAndroid Build Coastguard Worker   freqs[numItems] = 0;
209*f6dc9357SAndroid Build Coastguard Worker   Byte *vals = Vals;
210*f6dc9357SAndroid Build Coastguard Worker   do
211*f6dc9357SAndroid Build Coastguard Worker   {
212*f6dc9357SAndroid Build Coastguard Worker     *freqs++ = (UInt16)numItems;
213*f6dc9357SAndroid Build Coastguard Worker     *vals++ = (Byte)startVal;
214*f6dc9357SAndroid Build Coastguard Worker     startVal++;
215*f6dc9357SAndroid Build Coastguard Worker   }
216*f6dc9357SAndroid Build Coastguard Worker   while (--numItems);
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker 
219*f6dc9357SAndroid Build Coastguard Worker 
Code(const Byte * inData,size_t inSize,UInt32 outSize,bool keepHistory)220*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::Code(const Byte *inData, size_t inSize, UInt32 outSize, bool keepHistory)
221*f6dc9357SAndroid Build Coastguard Worker {
222*f6dc9357SAndroid Build Coastguard Worker   if (inSize < 2)
223*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
224*f6dc9357SAndroid Build Coastguard Worker   if (!keepHistory)
225*f6dc9357SAndroid Build Coastguard Worker   {
226*f6dc9357SAndroid Build Coastguard Worker     _winPos = 0;
227*f6dc9357SAndroid Build Coastguard Worker     m_Selector.Init(kNumSelectors, 0);
228*f6dc9357SAndroid Build Coastguard Worker     unsigned i;
229*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < kNumLitSelectors; i++)
230*f6dc9357SAndroid Build Coastguard Worker       m_Literals[i].Init(kNumLitSymbols, i * kNumLitSymbols);
231*f6dc9357SAndroid Build Coastguard Worker     const unsigned numItems = (_numDictBits == 0 ? 1 : (_numDictBits << 1));
232*f6dc9357SAndroid Build Coastguard Worker     // const unsigned kNumPosSymbolsMax[kNumMatchSelectors] = { 24, 36, 42 };
233*f6dc9357SAndroid Build Coastguard Worker     for (i = 0; i < kNumMatchSelectors; i++)
234*f6dc9357SAndroid Build Coastguard Worker     {
235*f6dc9357SAndroid Build Coastguard Worker       const unsigned num = 24 + i * 6 + ((i + 1) & 2) * 3;
236*f6dc9357SAndroid Build Coastguard Worker       m_PosSlot[i].Init(MyMin(numItems, num), 0);
237*f6dc9357SAndroid Build Coastguard Worker     }
238*f6dc9357SAndroid Build Coastguard Worker     m_LenSlot.Init(kNumLenSymbols, kMatchMinLen + kNumMatchSelectors - 1);
239*f6dc9357SAndroid Build Coastguard Worker   }
240*f6dc9357SAndroid Build Coastguard Worker 
241*f6dc9357SAndroid Build Coastguard Worker   CRangeDecoder rc;
242*f6dc9357SAndroid Build Coastguard Worker   rc.Init(inData, inSize);
243*f6dc9357SAndroid Build Coastguard Worker   const UInt32 winSize = _winSize;
244*f6dc9357SAndroid Build Coastguard Worker   Byte *pos;
245*f6dc9357SAndroid Build Coastguard Worker   {
246*f6dc9357SAndroid Build Coastguard Worker     UInt32 winPos = _winPos;
247*f6dc9357SAndroid Build Coastguard Worker     if (winPos == winSize)
248*f6dc9357SAndroid Build Coastguard Worker     {
249*f6dc9357SAndroid Build Coastguard Worker       winPos = 0;
250*f6dc9357SAndroid Build Coastguard Worker       _winPos = winPos;
251*f6dc9357SAndroid Build Coastguard Worker       _overWin = true;
252*f6dc9357SAndroid Build Coastguard Worker     }
253*f6dc9357SAndroid Build Coastguard Worker     if (outSize > winSize - winPos)
254*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
255*f6dc9357SAndroid Build Coastguard Worker     pos = _win + winPos;
256*f6dc9357SAndroid Build Coastguard Worker   }
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker   while (outSize != 0)
259*f6dc9357SAndroid Build Coastguard Worker   {
260*f6dc9357SAndroid Build Coastguard Worker     if (rc.WasExtraRead())
261*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
262*f6dc9357SAndroid Build Coastguard Worker 
263*f6dc9357SAndroid Build Coastguard Worker     const unsigned selector = m_Selector.Decode(&rc);
264*f6dc9357SAndroid Build Coastguard Worker 
265*f6dc9357SAndroid Build Coastguard Worker     if (selector < kNumLitSelectors)
266*f6dc9357SAndroid Build Coastguard Worker     {
267*f6dc9357SAndroid Build Coastguard Worker       const unsigned b = m_Literals[selector].Decode(&rc);
268*f6dc9357SAndroid Build Coastguard Worker       *pos++ = (Byte)b;
269*f6dc9357SAndroid Build Coastguard Worker       --outSize;
270*f6dc9357SAndroid Build Coastguard Worker       // if (--outSize == 0) break;
271*f6dc9357SAndroid Build Coastguard Worker     }
272*f6dc9357SAndroid Build Coastguard Worker     else
273*f6dc9357SAndroid Build Coastguard Worker     {
274*f6dc9357SAndroid Build Coastguard Worker       unsigned len = selector - kNumLitSelectors + kMatchMinLen;
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker       if (selector == kNumLitSelectors + kNumMatchSelectors - 1)
277*f6dc9357SAndroid Build Coastguard Worker       {
278*f6dc9357SAndroid Build Coastguard Worker         len = m_LenSlot.Decode(&rc);
279*f6dc9357SAndroid Build Coastguard Worker         if (len >= kNumSimpleLenSlots + kMatchMinLen + kNumMatchSelectors - 1)
280*f6dc9357SAndroid Build Coastguard Worker         {
281*f6dc9357SAndroid Build Coastguard Worker           len -= kNumSimpleLenSlots - 4 + kMatchMinLen + kNumMatchSelectors - 1;
282*f6dc9357SAndroid Build Coastguard Worker           const unsigned numDirectBits = (unsigned)(len >> 2);
283*f6dc9357SAndroid Build Coastguard Worker           len = ((4 | (len & 3)) << numDirectBits) - (4 << 1)
284*f6dc9357SAndroid Build Coastguard Worker               + kNumSimpleLenSlots
285*f6dc9357SAndroid Build Coastguard Worker               + kMatchMinLen + kNumMatchSelectors - 1;
286*f6dc9357SAndroid Build Coastguard Worker           if (numDirectBits < 6)
287*f6dc9357SAndroid Build Coastguard Worker             len += rc.ReadBits(numDirectBits);
288*f6dc9357SAndroid Build Coastguard Worker         }
289*f6dc9357SAndroid Build Coastguard Worker       }
290*f6dc9357SAndroid Build Coastguard Worker 
291*f6dc9357SAndroid Build Coastguard Worker       UInt32 dist = m_PosSlot[(size_t)selector - kNumLitSelectors].Decode(&rc);
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker       if (dist >= 4)
294*f6dc9357SAndroid Build Coastguard Worker       {
295*f6dc9357SAndroid Build Coastguard Worker         const unsigned numDirectBits = (unsigned)((dist >> 1) - 1);
296*f6dc9357SAndroid Build Coastguard Worker         dist = ((2 | (dist & 1)) << numDirectBits) + rc.ReadBits(numDirectBits);
297*f6dc9357SAndroid Build Coastguard Worker       }
298*f6dc9357SAndroid Build Coastguard Worker 
299*f6dc9357SAndroid Build Coastguard Worker       if ((Int32)(outSize -= len) < 0)
300*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
301*f6dc9357SAndroid Build Coastguard Worker 
302*f6dc9357SAndroid Build Coastguard Worker       ptrdiff_t srcPos = (ptrdiff_t)(Int32)((pos - _win) - (ptrdiff_t)dist - 1);
303*f6dc9357SAndroid Build Coastguard Worker       if (srcPos < 0)
304*f6dc9357SAndroid Build Coastguard Worker       {
305*f6dc9357SAndroid Build Coastguard Worker         if (!_overWin)
306*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
307*f6dc9357SAndroid Build Coastguard Worker         UInt32 rem = (UInt32)-srcPos;
308*f6dc9357SAndroid Build Coastguard Worker         srcPos += winSize;
309*f6dc9357SAndroid Build Coastguard Worker         if (rem < len)
310*f6dc9357SAndroid Build Coastguard Worker         {
311*f6dc9357SAndroid Build Coastguard Worker           const Byte *src = _win + srcPos;
312*f6dc9357SAndroid Build Coastguard Worker           len -= rem;
313*f6dc9357SAndroid Build Coastguard Worker           do
314*f6dc9357SAndroid Build Coastguard Worker             *pos++ = *src++;
315*f6dc9357SAndroid Build Coastguard Worker           while (--rem);
316*f6dc9357SAndroid Build Coastguard Worker           srcPos = 0;
317*f6dc9357SAndroid Build Coastguard Worker         }
318*f6dc9357SAndroid Build Coastguard Worker       }
319*f6dc9357SAndroid Build Coastguard Worker       const Byte *src = _win + srcPos;
320*f6dc9357SAndroid Build Coastguard Worker       do
321*f6dc9357SAndroid Build Coastguard Worker         *pos++ = *src++;
322*f6dc9357SAndroid Build Coastguard Worker       while (--len);
323*f6dc9357SAndroid Build Coastguard Worker       // if (outSize == 0) break;
324*f6dc9357SAndroid Build Coastguard Worker     }
325*f6dc9357SAndroid Build Coastguard Worker   }
326*f6dc9357SAndroid Build Coastguard Worker 
327*f6dc9357SAndroid Build Coastguard Worker   _winPos = (UInt32)(size_t)(pos - _win);
328*f6dc9357SAndroid Build Coastguard Worker   return rc.Finish() ? S_OK : S_FALSE;
329*f6dc9357SAndroid Build Coastguard Worker }
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker 
SetParams(unsigned numDictBits)332*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::SetParams(unsigned numDictBits)
333*f6dc9357SAndroid Build Coastguard Worker {
334*f6dc9357SAndroid Build Coastguard Worker   if (numDictBits > 21)
335*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
336*f6dc9357SAndroid Build Coastguard Worker   _numDictBits = numDictBits;
337*f6dc9357SAndroid Build Coastguard Worker   _winPos = 0;
338*f6dc9357SAndroid Build Coastguard Worker   _overWin = false;
339*f6dc9357SAndroid Build Coastguard Worker 
340*f6dc9357SAndroid Build Coastguard Worker   if (numDictBits < 15)
341*f6dc9357SAndroid Build Coastguard Worker       numDictBits = 15;
342*f6dc9357SAndroid Build Coastguard Worker   _winSize = (UInt32)1 << numDictBits;
343*f6dc9357SAndroid Build Coastguard Worker   if (!_win || _winSize > _winSize_allocated)
344*f6dc9357SAndroid Build Coastguard Worker   {
345*f6dc9357SAndroid Build Coastguard Worker     MidFree(_win);
346*f6dc9357SAndroid Build Coastguard Worker     _win = NULL;
347*f6dc9357SAndroid Build Coastguard Worker     _win = (Byte *)MidAlloc(_winSize);
348*f6dc9357SAndroid Build Coastguard Worker     if (!_win)
349*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
350*f6dc9357SAndroid Build Coastguard Worker     _winSize_allocated = _winSize;
351*f6dc9357SAndroid Build Coastguard Worker   }
352*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
353*f6dc9357SAndroid Build Coastguard Worker }
354*f6dc9357SAndroid Build Coastguard Worker 
355*f6dc9357SAndroid Build Coastguard Worker }}
356