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