xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Rar3Decoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // Rar3Decoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker // According to unRAR license, this code may not be used to develop
3*f6dc9357SAndroid Build Coastguard Worker // a program that creates RAR archives
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "Rar3Decoder.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
16*f6dc9357SAndroid Build Coastguard Worker namespace NRar3 {
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNumAlignReps = 15;
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSymbolReadTable = 256;
21*f6dc9357SAndroid Build Coastguard Worker static const unsigned kSymbolRep = 259;
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker static const Byte kDistDirectBits[kDistTableSize] =
24*f6dc9357SAndroid Build Coastguard Worker   {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,
25*f6dc9357SAndroid Build Coastguard Worker   16,16,16,16,16,16,16,16,16,16,16,16,16,16,
26*f6dc9357SAndroid Build Coastguard Worker   18,18,18,18,18,18,18,18,18,18,18,18};
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker static const Byte kLen2DistStarts[kNumLen2Symbols] = {0,4,8,16,32,64,128,192};
29*f6dc9357SAndroid Build Coastguard Worker static const Byte kLen2DistDirectBits[kNumLen2Symbols] = {2,2,3, 4, 5, 6,  6,  6};
30*f6dc9357SAndroid Build Coastguard Worker 
31*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDistLimit3 = 0x2000 - 2;
32*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kDistLimit4 = 0x40000 - 2;
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kNormalMatchMinLen = 3;
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kVmDataSizeMax = 1 << 16;
37*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kVmCodeSizeMax = 1 << 16;
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker extern "C" {
40*f6dc9357SAndroid Build Coastguard Worker 
Wrap_ReadByte(IByteInPtr pp)41*f6dc9357SAndroid Build Coastguard Worker static Byte Wrap_ReadByte(IByteInPtr pp) throw()
42*f6dc9357SAndroid Build Coastguard Worker {
43*f6dc9357SAndroid Build Coastguard Worker   CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
44*f6dc9357SAndroid Build Coastguard Worker   return p->BitDecoder.Stream.ReadByte();
45*f6dc9357SAndroid Build Coastguard Worker }
46*f6dc9357SAndroid Build Coastguard Worker 
Wrap_ReadBits8(IByteInPtr pp)47*f6dc9357SAndroid Build Coastguard Worker static Byte Wrap_ReadBits8(IByteInPtr pp) throw()
48*f6dc9357SAndroid Build Coastguard Worker {
49*f6dc9357SAndroid Build Coastguard Worker   CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
50*f6dc9357SAndroid Build Coastguard Worker   return (Byte)p->BitDecoder.ReadByteFromAligned();
51*f6dc9357SAndroid Build Coastguard Worker }
52*f6dc9357SAndroid Build Coastguard Worker 
53*f6dc9357SAndroid Build Coastguard Worker }
54*f6dc9357SAndroid Build Coastguard Worker 
55*f6dc9357SAndroid Build Coastguard Worker 
CDecoder()56*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder():
57*f6dc9357SAndroid Build Coastguard Worker   _isSolid(false),
58*f6dc9357SAndroid Build Coastguard Worker   _solidAllowed(false),
59*f6dc9357SAndroid Build Coastguard Worker   _window(NULL),
60*f6dc9357SAndroid Build Coastguard Worker   _winPos(0),
61*f6dc9357SAndroid Build Coastguard Worker   _wrPtr(0),
62*f6dc9357SAndroid Build Coastguard Worker   _lzSize(0),
63*f6dc9357SAndroid Build Coastguard Worker   _writtenFileSize(0),
64*f6dc9357SAndroid Build Coastguard Worker   _vmData(NULL),
65*f6dc9357SAndroid Build Coastguard Worker   _vmCode(NULL)
66*f6dc9357SAndroid Build Coastguard Worker {
67*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_Construct(&_ppmd);
68*f6dc9357SAndroid Build Coastguard Worker 
69*f6dc9357SAndroid Build Coastguard Worker   UInt32 start = 0;
70*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < kDistTableSize; i++)
71*f6dc9357SAndroid Build Coastguard Worker   {
72*f6dc9357SAndroid Build Coastguard Worker     kDistStart[i] = start;
73*f6dc9357SAndroid Build Coastguard Worker     start += ((UInt32)1 << kDistDirectBits[i]);
74*f6dc9357SAndroid Build Coastguard Worker   }
75*f6dc9357SAndroid Build Coastguard Worker }
76*f6dc9357SAndroid Build Coastguard Worker 
~CDecoder()77*f6dc9357SAndroid Build Coastguard Worker CDecoder::~CDecoder()
78*f6dc9357SAndroid Build Coastguard Worker {
79*f6dc9357SAndroid Build Coastguard Worker   InitFilters();
80*f6dc9357SAndroid Build Coastguard Worker   ::MidFree(_vmData);
81*f6dc9357SAndroid Build Coastguard Worker   ::MidFree(_window);
82*f6dc9357SAndroid Build Coastguard Worker   Ppmd7_Free(&_ppmd, &g_BigAlloc);
83*f6dc9357SAndroid Build Coastguard Worker }
84*f6dc9357SAndroid Build Coastguard Worker 
WriteDataToStream(const Byte * data,UInt32 size)85*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker   return WriteStream(_outStream, data, size);
88*f6dc9357SAndroid Build Coastguard Worker }
89*f6dc9357SAndroid Build Coastguard Worker 
WriteData(const Byte * data,UInt32 size)90*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)
91*f6dc9357SAndroid Build Coastguard Worker {
92*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = S_OK;
93*f6dc9357SAndroid Build Coastguard Worker   if (_writtenFileSize < _unpackSize)
94*f6dc9357SAndroid Build Coastguard Worker   {
95*f6dc9357SAndroid Build Coastguard Worker     UInt32 curSize = size;
96*f6dc9357SAndroid Build Coastguard Worker     UInt64 remain = _unpackSize - _writtenFileSize;
97*f6dc9357SAndroid Build Coastguard Worker     if (remain < curSize)
98*f6dc9357SAndroid Build Coastguard Worker       curSize = (UInt32)remain;
99*f6dc9357SAndroid Build Coastguard Worker     res = WriteDataToStream(data, curSize);
100*f6dc9357SAndroid Build Coastguard Worker   }
101*f6dc9357SAndroid Build Coastguard Worker   _writtenFileSize += size;
102*f6dc9357SAndroid Build Coastguard Worker   return res;
103*f6dc9357SAndroid Build Coastguard Worker }
104*f6dc9357SAndroid Build Coastguard Worker 
WriteArea(UInt32 startPtr,UInt32 endPtr)105*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker   if (startPtr <= endPtr)
108*f6dc9357SAndroid Build Coastguard Worker     return WriteData(_window + startPtr, endPtr - startPtr);
109*f6dc9357SAndroid Build Coastguard Worker   RINOK(WriteData(_window + startPtr, kWindowSize - startPtr))
110*f6dc9357SAndroid Build Coastguard Worker   return WriteData(_window, endPtr);
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker 
ExecuteFilter(unsigned tempFilterIndex,NVm::CBlockRef & outBlockRef)113*f6dc9357SAndroid Build Coastguard Worker void CDecoder::ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef)
114*f6dc9357SAndroid Build Coastguard Worker {
115*f6dc9357SAndroid Build Coastguard Worker   CTempFilter *tempFilter = _tempFilters[tempFilterIndex];
116*f6dc9357SAndroid Build Coastguard Worker   tempFilter->InitR[6] = (UInt32)_writtenFileSize;
117*f6dc9357SAndroid Build Coastguard Worker   NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
118*f6dc9357SAndroid Build Coastguard Worker   NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
119*f6dc9357SAndroid Build Coastguard Worker   CFilter *filter = _filters[tempFilter->FilterIndex];
120*f6dc9357SAndroid Build Coastguard Worker   if (!filter->IsSupported)
121*f6dc9357SAndroid Build Coastguard Worker     _unsupportedFilter = true;
122*f6dc9357SAndroid Build Coastguard Worker   if (!_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData))
123*f6dc9357SAndroid Build Coastguard Worker     _unsupportedFilter = true;
124*f6dc9357SAndroid Build Coastguard Worker   delete tempFilter;
125*f6dc9357SAndroid Build Coastguard Worker   _tempFilters[tempFilterIndex] = NULL;
126*f6dc9357SAndroid Build Coastguard Worker   _numEmptyTempFilters++;
127*f6dc9357SAndroid Build Coastguard Worker }
128*f6dc9357SAndroid Build Coastguard Worker 
WriteBuf()129*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::WriteBuf()
130*f6dc9357SAndroid Build Coastguard Worker {
131*f6dc9357SAndroid Build Coastguard Worker   UInt32 writtenBorder = _wrPtr;
132*f6dc9357SAndroid Build Coastguard Worker   UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;
133*f6dc9357SAndroid Build Coastguard Worker   FOR_VECTOR (i, _tempFilters)
134*f6dc9357SAndroid Build Coastguard Worker   {
135*f6dc9357SAndroid Build Coastguard Worker     CTempFilter *filter = _tempFilters[i];
136*f6dc9357SAndroid Build Coastguard Worker     if (!filter)
137*f6dc9357SAndroid Build Coastguard Worker       continue;
138*f6dc9357SAndroid Build Coastguard Worker     if (filter->NextWindow)
139*f6dc9357SAndroid Build Coastguard Worker     {
140*f6dc9357SAndroid Build Coastguard Worker       filter->NextWindow = false;
141*f6dc9357SAndroid Build Coastguard Worker       continue;
142*f6dc9357SAndroid Build Coastguard Worker     }
143*f6dc9357SAndroid Build Coastguard Worker     UInt32 blockStart = filter->BlockStart;
144*f6dc9357SAndroid Build Coastguard Worker     UInt32 blockSize = filter->BlockSize;
145*f6dc9357SAndroid Build Coastguard Worker     if (((blockStart - writtenBorder) & kWindowMask) < writeSize)
146*f6dc9357SAndroid Build Coastguard Worker     {
147*f6dc9357SAndroid Build Coastguard Worker       if (writtenBorder != blockStart)
148*f6dc9357SAndroid Build Coastguard Worker       {
149*f6dc9357SAndroid Build Coastguard Worker         RINOK(WriteArea(writtenBorder, blockStart))
150*f6dc9357SAndroid Build Coastguard Worker         writtenBorder = blockStart;
151*f6dc9357SAndroid Build Coastguard Worker         writeSize = (_winPos - writtenBorder) & kWindowMask;
152*f6dc9357SAndroid Build Coastguard Worker       }
153*f6dc9357SAndroid Build Coastguard Worker       if (blockSize <= writeSize)
154*f6dc9357SAndroid Build Coastguard Worker       {
155*f6dc9357SAndroid Build Coastguard Worker         UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;
156*f6dc9357SAndroid Build Coastguard Worker         if (blockStart < blockEnd || blockEnd == 0)
157*f6dc9357SAndroid Build Coastguard Worker           _vm.SetMemory(0, _window + blockStart, blockSize);
158*f6dc9357SAndroid Build Coastguard Worker         else
159*f6dc9357SAndroid Build Coastguard Worker         {
160*f6dc9357SAndroid Build Coastguard Worker           UInt32 tailSize = kWindowSize - blockStart;
161*f6dc9357SAndroid Build Coastguard Worker           _vm.SetMemory(0, _window + blockStart, tailSize);
162*f6dc9357SAndroid Build Coastguard Worker           _vm.SetMemory(tailSize, _window, blockEnd);
163*f6dc9357SAndroid Build Coastguard Worker         }
164*f6dc9357SAndroid Build Coastguard Worker         NVm::CBlockRef outBlockRef;
165*f6dc9357SAndroid Build Coastguard Worker         ExecuteFilter(i, outBlockRef);
166*f6dc9357SAndroid Build Coastguard Worker         while (i + 1 < _tempFilters.Size())
167*f6dc9357SAndroid Build Coastguard Worker         {
168*f6dc9357SAndroid Build Coastguard Worker           CTempFilter *nextFilter = _tempFilters[i + 1];
169*f6dc9357SAndroid Build Coastguard Worker           if (!nextFilter
170*f6dc9357SAndroid Build Coastguard Worker               || nextFilter->BlockStart != blockStart
171*f6dc9357SAndroid Build Coastguard Worker               || nextFilter->BlockSize != outBlockRef.Size
172*f6dc9357SAndroid Build Coastguard Worker               || nextFilter->NextWindow)
173*f6dc9357SAndroid Build Coastguard Worker             break;
174*f6dc9357SAndroid Build Coastguard Worker           _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
175*f6dc9357SAndroid Build Coastguard Worker           ExecuteFilter(++i, outBlockRef);
176*f6dc9357SAndroid Build Coastguard Worker         }
177*f6dc9357SAndroid Build Coastguard Worker         WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
178*f6dc9357SAndroid Build Coastguard Worker         _writtenFileSize += outBlockRef.Size;
179*f6dc9357SAndroid Build Coastguard Worker         writtenBorder = blockEnd;
180*f6dc9357SAndroid Build Coastguard Worker         writeSize = (_winPos - writtenBorder) & kWindowMask;
181*f6dc9357SAndroid Build Coastguard Worker       }
182*f6dc9357SAndroid Build Coastguard Worker       else
183*f6dc9357SAndroid Build Coastguard Worker       {
184*f6dc9357SAndroid Build Coastguard Worker         for (unsigned j = i; j < _tempFilters.Size(); j++)
185*f6dc9357SAndroid Build Coastguard Worker         {
186*f6dc9357SAndroid Build Coastguard Worker           CTempFilter *filter2 = _tempFilters[j];
187*f6dc9357SAndroid Build Coastguard Worker           if (filter2 && filter2->NextWindow)
188*f6dc9357SAndroid Build Coastguard Worker             filter2->NextWindow = false;
189*f6dc9357SAndroid Build Coastguard Worker         }
190*f6dc9357SAndroid Build Coastguard Worker         _wrPtr = writtenBorder;
191*f6dc9357SAndroid Build Coastguard Worker         return S_OK; // check it
192*f6dc9357SAndroid Build Coastguard Worker       }
193*f6dc9357SAndroid Build Coastguard Worker     }
194*f6dc9357SAndroid Build Coastguard Worker   }
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   _wrPtr = _winPos;
197*f6dc9357SAndroid Build Coastguard Worker   return WriteArea(writtenBorder, _winPos);
198*f6dc9357SAndroid Build Coastguard Worker }
199*f6dc9357SAndroid Build Coastguard Worker 
InitFilters()200*f6dc9357SAndroid Build Coastguard Worker void CDecoder::InitFilters()
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker   _lastFilter = 0;
203*f6dc9357SAndroid Build Coastguard Worker   _numEmptyTempFilters = 0;
204*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
205*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _tempFilters.Size(); i++)
206*f6dc9357SAndroid Build Coastguard Worker     delete _tempFilters[i];
207*f6dc9357SAndroid Build Coastguard Worker   _tempFilters.Clear();
208*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < _filters.Size(); i++)
209*f6dc9357SAndroid Build Coastguard Worker     delete _filters[i];
210*f6dc9357SAndroid Build Coastguard Worker   _filters.Clear();
211*f6dc9357SAndroid Build Coastguard Worker }
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker static const unsigned MAX_UNPACK_FILTERS = 8192;
214*f6dc9357SAndroid Build Coastguard Worker 
AddVmCode(UInt32 firstByte,UInt32 codeSize)215*f6dc9357SAndroid Build Coastguard Worker bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker   CMemBitDecoder inp;
218*f6dc9357SAndroid Build Coastguard Worker   inp.Init(_vmData, codeSize);
219*f6dc9357SAndroid Build Coastguard Worker 
220*f6dc9357SAndroid Build Coastguard Worker   UInt32 filterIndex;
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker   if (firstByte & 0x80)
223*f6dc9357SAndroid Build Coastguard Worker   {
224*f6dc9357SAndroid Build Coastguard Worker     filterIndex = inp.ReadEncodedUInt32();
225*f6dc9357SAndroid Build Coastguard Worker     if (filterIndex == 0)
226*f6dc9357SAndroid Build Coastguard Worker       InitFilters();
227*f6dc9357SAndroid Build Coastguard Worker     else
228*f6dc9357SAndroid Build Coastguard Worker       filterIndex--;
229*f6dc9357SAndroid Build Coastguard Worker   }
230*f6dc9357SAndroid Build Coastguard Worker   else
231*f6dc9357SAndroid Build Coastguard Worker     filterIndex = _lastFilter;
232*f6dc9357SAndroid Build Coastguard Worker 
233*f6dc9357SAndroid Build Coastguard Worker   if (filterIndex > (UInt32)_filters.Size())
234*f6dc9357SAndroid Build Coastguard Worker     return false;
235*f6dc9357SAndroid Build Coastguard Worker   _lastFilter = filterIndex;
236*f6dc9357SAndroid Build Coastguard Worker   bool newFilter = (filterIndex == (UInt32)_filters.Size());
237*f6dc9357SAndroid Build Coastguard Worker 
238*f6dc9357SAndroid Build Coastguard Worker   CFilter *filter;
239*f6dc9357SAndroid Build Coastguard Worker   if (newFilter)
240*f6dc9357SAndroid Build Coastguard Worker   {
241*f6dc9357SAndroid Build Coastguard Worker     // check if too many filters
242*f6dc9357SAndroid Build Coastguard Worker     if (filterIndex > MAX_UNPACK_FILTERS)
243*f6dc9357SAndroid Build Coastguard Worker       return false;
244*f6dc9357SAndroid Build Coastguard Worker     filter = new CFilter;
245*f6dc9357SAndroid Build Coastguard Worker     _filters.Add(filter);
246*f6dc9357SAndroid Build Coastguard Worker   }
247*f6dc9357SAndroid Build Coastguard Worker   else
248*f6dc9357SAndroid Build Coastguard Worker   {
249*f6dc9357SAndroid Build Coastguard Worker     filter = _filters[filterIndex];
250*f6dc9357SAndroid Build Coastguard Worker     filter->ExecCount++;
251*f6dc9357SAndroid Build Coastguard Worker   }
252*f6dc9357SAndroid Build Coastguard Worker 
253*f6dc9357SAndroid Build Coastguard Worker   if (_numEmptyTempFilters != 0)
254*f6dc9357SAndroid Build Coastguard Worker   {
255*f6dc9357SAndroid Build Coastguard Worker     const unsigned num = _tempFilters.Size();
256*f6dc9357SAndroid Build Coastguard Worker     CTempFilter **tempFilters = _tempFilters.NonConstData();
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker     unsigned w = 0;
259*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < num; i++)
260*f6dc9357SAndroid Build Coastguard Worker     {
261*f6dc9357SAndroid Build Coastguard Worker       CTempFilter *tf = tempFilters[i];
262*f6dc9357SAndroid Build Coastguard Worker       if (tf)
263*f6dc9357SAndroid Build Coastguard Worker         tempFilters[w++] = tf;
264*f6dc9357SAndroid Build Coastguard Worker     }
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker     _tempFilters.DeleteFrom(w);
267*f6dc9357SAndroid Build Coastguard Worker     _numEmptyTempFilters = 0;
268*f6dc9357SAndroid Build Coastguard Worker   }
269*f6dc9357SAndroid Build Coastguard Worker 
270*f6dc9357SAndroid Build Coastguard Worker   if (_tempFilters.Size() > MAX_UNPACK_FILTERS)
271*f6dc9357SAndroid Build Coastguard Worker     return false;
272*f6dc9357SAndroid Build Coastguard Worker   CTempFilter *tempFilter = new CTempFilter;
273*f6dc9357SAndroid Build Coastguard Worker   _tempFilters.Add(tempFilter);
274*f6dc9357SAndroid Build Coastguard Worker   tempFilter->FilterIndex = filterIndex;
275*f6dc9357SAndroid Build Coastguard Worker 
276*f6dc9357SAndroid Build Coastguard Worker   UInt32 blockStart = inp.ReadEncodedUInt32();
277*f6dc9357SAndroid Build Coastguard Worker   if (firstByte & 0x40)
278*f6dc9357SAndroid Build Coastguard Worker     blockStart += 258;
279*f6dc9357SAndroid Build Coastguard Worker   tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;
280*f6dc9357SAndroid Build Coastguard Worker   if (firstByte & 0x20)
281*f6dc9357SAndroid Build Coastguard Worker     filter->BlockSize = inp.ReadEncodedUInt32();
282*f6dc9357SAndroid Build Coastguard Worker   tempFilter->BlockSize = filter->BlockSize;
283*f6dc9357SAndroid Build Coastguard Worker   tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;
284*f6dc9357SAndroid Build Coastguard Worker 
285*f6dc9357SAndroid Build Coastguard Worker   memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));
286*f6dc9357SAndroid Build Coastguard Worker   tempFilter->InitR[3] = NVm::kGlobalOffset;
287*f6dc9357SAndroid Build Coastguard Worker   tempFilter->InitR[4] = tempFilter->BlockSize;
288*f6dc9357SAndroid Build Coastguard Worker   tempFilter->InitR[5] = filter->ExecCount;
289*f6dc9357SAndroid Build Coastguard Worker   if (firstByte & 0x10)
290*f6dc9357SAndroid Build Coastguard Worker   {
291*f6dc9357SAndroid Build Coastguard Worker     UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);
292*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
293*f6dc9357SAndroid Build Coastguard Worker       if (initMask & (1 << i))
294*f6dc9357SAndroid Build Coastguard Worker         tempFilter->InitR[i] = inp.ReadEncodedUInt32();
295*f6dc9357SAndroid Build Coastguard Worker   }
296*f6dc9357SAndroid Build Coastguard Worker 
297*f6dc9357SAndroid Build Coastguard Worker   bool isOK = true;
298*f6dc9357SAndroid Build Coastguard Worker   if (newFilter)
299*f6dc9357SAndroid Build Coastguard Worker   {
300*f6dc9357SAndroid Build Coastguard Worker     UInt32 vmCodeSize = inp.ReadEncodedUInt32();
301*f6dc9357SAndroid Build Coastguard Worker     if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)
302*f6dc9357SAndroid Build Coastguard Worker       return false;
303*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < vmCodeSize; i++)
304*f6dc9357SAndroid Build Coastguard Worker       _vmCode[i] = (Byte)inp.ReadBits(8);
305*f6dc9357SAndroid Build Coastguard Worker     isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
306*f6dc9357SAndroid Build Coastguard Worker   }
307*f6dc9357SAndroid Build Coastguard Worker 
308*f6dc9357SAndroid Build Coastguard Worker   {
309*f6dc9357SAndroid Build Coastguard Worker     Byte *globalData = &tempFilter->GlobalData[0];
310*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
311*f6dc9357SAndroid Build Coastguard Worker       NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);
312*f6dc9357SAndroid Build Coastguard Worker     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);
313*f6dc9357SAndroid Build Coastguard Worker     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?
314*f6dc9357SAndroid Build Coastguard Worker     NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], filter->ExecCount);
315*f6dc9357SAndroid Build Coastguard Worker   }
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   if (firstByte & 8)
318*f6dc9357SAndroid Build Coastguard Worker   {
319*f6dc9357SAndroid Build Coastguard Worker     UInt32 dataSize = inp.ReadEncodedUInt32();
320*f6dc9357SAndroid Build Coastguard Worker     if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)
321*f6dc9357SAndroid Build Coastguard Worker       return false;
322*f6dc9357SAndroid Build Coastguard Worker     CRecordVector<Byte> &globalData = tempFilter->GlobalData;
323*f6dc9357SAndroid Build Coastguard Worker     unsigned requiredSize = (unsigned)(dataSize + NVm::kFixedGlobalSize);
324*f6dc9357SAndroid Build Coastguard Worker     if (globalData.Size() < requiredSize)
325*f6dc9357SAndroid Build Coastguard Worker       globalData.ChangeSize_KeepData(requiredSize);
326*f6dc9357SAndroid Build Coastguard Worker     Byte *dest = &globalData[NVm::kFixedGlobalSize];
327*f6dc9357SAndroid Build Coastguard Worker     for (UInt32 i = 0; i < dataSize; i++)
328*f6dc9357SAndroid Build Coastguard Worker       dest[i] = (Byte)inp.ReadBits(8);
329*f6dc9357SAndroid Build Coastguard Worker   }
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker   return isOK;
332*f6dc9357SAndroid Build Coastguard Worker }
333*f6dc9357SAndroid Build Coastguard Worker 
ReadVmCodeLZ()334*f6dc9357SAndroid Build Coastguard Worker bool CDecoder::ReadVmCodeLZ()
335*f6dc9357SAndroid Build Coastguard Worker {
336*f6dc9357SAndroid Build Coastguard Worker   UInt32 firstByte = ReadBits(8);
337*f6dc9357SAndroid Build Coastguard Worker   UInt32 len = (firstByte & 7) + 1;
338*f6dc9357SAndroid Build Coastguard Worker   if (len == 7)
339*f6dc9357SAndroid Build Coastguard Worker     len = ReadBits(8) + 7;
340*f6dc9357SAndroid Build Coastguard Worker   else if (len == 8)
341*f6dc9357SAndroid Build Coastguard Worker     len = ReadBits(16);
342*f6dc9357SAndroid Build Coastguard Worker   if (len > kVmDataSizeMax)
343*f6dc9357SAndroid Build Coastguard Worker     return false;
344*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < len; i++)
345*f6dc9357SAndroid Build Coastguard Worker     _vmData[i] = (Byte)ReadBits(8);
346*f6dc9357SAndroid Build Coastguard Worker   return AddVmCode(firstByte, len);
347*f6dc9357SAndroid Build Coastguard Worker }
348*f6dc9357SAndroid Build Coastguard Worker 
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker // int CDecoder::DecodePpmSymbol() { return Ppmd7a_DecodeSymbol(&_ppmd); }
351*f6dc9357SAndroid Build Coastguard Worker #define DecodePpmSymbol() Ppmd7a_DecodeSymbol(&_ppmd)
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker 
ReadVmCodePPM()354*f6dc9357SAndroid Build Coastguard Worker bool CDecoder::ReadVmCodePPM()
355*f6dc9357SAndroid Build Coastguard Worker {
356*f6dc9357SAndroid Build Coastguard Worker   const int firstByte = DecodePpmSymbol();
357*f6dc9357SAndroid Build Coastguard Worker   if (firstByte < 0)
358*f6dc9357SAndroid Build Coastguard Worker     return false;
359*f6dc9357SAndroid Build Coastguard Worker   UInt32 len = (firstByte & 7) + 1;
360*f6dc9357SAndroid Build Coastguard Worker   if (len == 7)
361*f6dc9357SAndroid Build Coastguard Worker   {
362*f6dc9357SAndroid Build Coastguard Worker     const int b1 = DecodePpmSymbol();
363*f6dc9357SAndroid Build Coastguard Worker     if (b1 < 0)
364*f6dc9357SAndroid Build Coastguard Worker       return false;
365*f6dc9357SAndroid Build Coastguard Worker     len = (unsigned)b1 + 7;
366*f6dc9357SAndroid Build Coastguard Worker   }
367*f6dc9357SAndroid Build Coastguard Worker   else if (len == 8)
368*f6dc9357SAndroid Build Coastguard Worker   {
369*f6dc9357SAndroid Build Coastguard Worker     const int b1 = DecodePpmSymbol();
370*f6dc9357SAndroid Build Coastguard Worker     if (b1 < 0)
371*f6dc9357SAndroid Build Coastguard Worker       return false;
372*f6dc9357SAndroid Build Coastguard Worker     const int b2 = DecodePpmSymbol();
373*f6dc9357SAndroid Build Coastguard Worker     if (b2 < 0)
374*f6dc9357SAndroid Build Coastguard Worker       return false;
375*f6dc9357SAndroid Build Coastguard Worker     len = (unsigned)b1 * 256 + (unsigned)b2;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker   if (len > kVmDataSizeMax)
378*f6dc9357SAndroid Build Coastguard Worker     return false;
379*f6dc9357SAndroid Build Coastguard Worker   if (InputEofError_Fast())
380*f6dc9357SAndroid Build Coastguard Worker     return false;
381*f6dc9357SAndroid Build Coastguard Worker   for (UInt32 i = 0; i < len; i++)
382*f6dc9357SAndroid Build Coastguard Worker   {
383*f6dc9357SAndroid Build Coastguard Worker     const int b = DecodePpmSymbol();
384*f6dc9357SAndroid Build Coastguard Worker     if (b < 0)
385*f6dc9357SAndroid Build Coastguard Worker       return false;
386*f6dc9357SAndroid Build Coastguard Worker     _vmData[i] = (Byte)b;
387*f6dc9357SAndroid Build Coastguard Worker   }
388*f6dc9357SAndroid Build Coastguard Worker   return AddVmCode((unsigned)firstByte, len);
389*f6dc9357SAndroid Build Coastguard Worker }
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker #define RIF(x) { if (!(x)) return S_FALSE; }
392*f6dc9357SAndroid Build Coastguard Worker 
ReadBits(unsigned numBits)393*f6dc9357SAndroid Build Coastguard Worker UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); }
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker // ---------- PPM ----------
396*f6dc9357SAndroid Build Coastguard Worker 
InitPPM()397*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::InitPPM()
398*f6dc9357SAndroid Build Coastguard Worker {
399*f6dc9357SAndroid Build Coastguard Worker   unsigned maxOrder = (unsigned)ReadBits(7);
400*f6dc9357SAndroid Build Coastguard Worker 
401*f6dc9357SAndroid Build Coastguard Worker   const bool reset = ((maxOrder & 0x20) != 0);
402*f6dc9357SAndroid Build Coastguard Worker   UInt32 maxMB = 0;
403*f6dc9357SAndroid Build Coastguard Worker   if (reset)
404*f6dc9357SAndroid Build Coastguard Worker     maxMB = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
405*f6dc9357SAndroid Build Coastguard Worker   else
406*f6dc9357SAndroid Build Coastguard Worker   {
407*f6dc9357SAndroid Build Coastguard Worker     if (PpmError || !Ppmd7_WasAllocated(&_ppmd))
408*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
409*f6dc9357SAndroid Build Coastguard Worker   }
410*f6dc9357SAndroid Build Coastguard Worker   if (maxOrder & 0x40)
411*f6dc9357SAndroid Build Coastguard Worker     PpmEscChar = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
412*f6dc9357SAndroid Build Coastguard Worker 
413*f6dc9357SAndroid Build Coastguard Worker   _ppmd.rc.dec.Stream = &m_InBitStream.IByteIn_obj;
414*f6dc9357SAndroid Build Coastguard Worker   m_InBitStream.IByteIn_obj.Read = Wrap_ReadBits8;
415*f6dc9357SAndroid Build Coastguard Worker 
416*f6dc9357SAndroid Build Coastguard Worker   Ppmd7a_RangeDec_Init(&_ppmd.rc.dec);
417*f6dc9357SAndroid Build Coastguard Worker 
418*f6dc9357SAndroid Build Coastguard Worker   m_InBitStream.IByteIn_obj.Read = Wrap_ReadByte;
419*f6dc9357SAndroid Build Coastguard Worker 
420*f6dc9357SAndroid Build Coastguard Worker   if (reset)
421*f6dc9357SAndroid Build Coastguard Worker   {
422*f6dc9357SAndroid Build Coastguard Worker     PpmError = true;
423*f6dc9357SAndroid Build Coastguard Worker     maxOrder = (maxOrder & 0x1F) + 1;
424*f6dc9357SAndroid Build Coastguard Worker     if (maxOrder > 16)
425*f6dc9357SAndroid Build Coastguard Worker       maxOrder = 16 + (maxOrder - 16) * 3;
426*f6dc9357SAndroid Build Coastguard Worker     if (maxOrder == 1)
427*f6dc9357SAndroid Build Coastguard Worker     {
428*f6dc9357SAndroid Build Coastguard Worker       Ppmd7_Free(&_ppmd, &g_BigAlloc);
429*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
430*f6dc9357SAndroid Build Coastguard Worker     }
431*f6dc9357SAndroid Build Coastguard Worker     if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))
432*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
433*f6dc9357SAndroid Build Coastguard Worker     Ppmd7_Init(&_ppmd, maxOrder);
434*f6dc9357SAndroid Build Coastguard Worker     PpmError = false;
435*f6dc9357SAndroid Build Coastguard Worker   }
436*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
437*f6dc9357SAndroid Build Coastguard Worker }
438*f6dc9357SAndroid Build Coastguard Worker 
439*f6dc9357SAndroid Build Coastguard Worker 
DecodePPM(Int32 num,bool & keepDecompressing)440*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
441*f6dc9357SAndroid Build Coastguard Worker {
442*f6dc9357SAndroid Build Coastguard Worker   keepDecompressing = false;
443*f6dc9357SAndroid Build Coastguard Worker   if (PpmError)
444*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
445*f6dc9357SAndroid Build Coastguard Worker   do
446*f6dc9357SAndroid Build Coastguard Worker   {
447*f6dc9357SAndroid Build Coastguard Worker     if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
448*f6dc9357SAndroid Build Coastguard Worker     {
449*f6dc9357SAndroid Build Coastguard Worker       RINOK(WriteBuf())
450*f6dc9357SAndroid Build Coastguard Worker       if (_writtenFileSize > _unpackSize)
451*f6dc9357SAndroid Build Coastguard Worker       {
452*f6dc9357SAndroid Build Coastguard Worker         keepDecompressing = false;
453*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
454*f6dc9357SAndroid Build Coastguard Worker       }
455*f6dc9357SAndroid Build Coastguard Worker     }
456*f6dc9357SAndroid Build Coastguard Worker     if (InputEofError_Fast())
457*f6dc9357SAndroid Build Coastguard Worker       return false;
458*f6dc9357SAndroid Build Coastguard Worker     const int c = DecodePpmSymbol();
459*f6dc9357SAndroid Build Coastguard Worker     if (c < 0)
460*f6dc9357SAndroid Build Coastguard Worker     {
461*f6dc9357SAndroid Build Coastguard Worker       PpmError = true;
462*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
463*f6dc9357SAndroid Build Coastguard Worker     }
464*f6dc9357SAndroid Build Coastguard Worker     if (c == PpmEscChar)
465*f6dc9357SAndroid Build Coastguard Worker     {
466*f6dc9357SAndroid Build Coastguard Worker       const int nextCh = DecodePpmSymbol();
467*f6dc9357SAndroid Build Coastguard Worker       if (nextCh < 0)
468*f6dc9357SAndroid Build Coastguard Worker       {
469*f6dc9357SAndroid Build Coastguard Worker         PpmError = true;
470*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
471*f6dc9357SAndroid Build Coastguard Worker       }
472*f6dc9357SAndroid Build Coastguard Worker       if (nextCh == 0)
473*f6dc9357SAndroid Build Coastguard Worker         return ReadTables(keepDecompressing);
474*f6dc9357SAndroid Build Coastguard Worker       if (nextCh == 2 || nextCh == -1)
475*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
476*f6dc9357SAndroid Build Coastguard Worker       if (nextCh == 3)
477*f6dc9357SAndroid Build Coastguard Worker       {
478*f6dc9357SAndroid Build Coastguard Worker         if (!ReadVmCodePPM())
479*f6dc9357SAndroid Build Coastguard Worker         {
480*f6dc9357SAndroid Build Coastguard Worker           PpmError = true;
481*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
482*f6dc9357SAndroid Build Coastguard Worker         }
483*f6dc9357SAndroid Build Coastguard Worker         continue;
484*f6dc9357SAndroid Build Coastguard Worker       }
485*f6dc9357SAndroid Build Coastguard Worker       if (nextCh == 4 || nextCh == 5)
486*f6dc9357SAndroid Build Coastguard Worker       {
487*f6dc9357SAndroid Build Coastguard Worker         UInt32 dist = 0;
488*f6dc9357SAndroid Build Coastguard Worker         UInt32 len = 4;
489*f6dc9357SAndroid Build Coastguard Worker         if (nextCh == 4)
490*f6dc9357SAndroid Build Coastguard Worker         {
491*f6dc9357SAndroid Build Coastguard Worker           for (int i = 0; i < 3; i++)
492*f6dc9357SAndroid Build Coastguard Worker           {
493*f6dc9357SAndroid Build Coastguard Worker             const int c2 = DecodePpmSymbol();
494*f6dc9357SAndroid Build Coastguard Worker             if (c2 < 0)
495*f6dc9357SAndroid Build Coastguard Worker             {
496*f6dc9357SAndroid Build Coastguard Worker               PpmError = true;
497*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
498*f6dc9357SAndroid Build Coastguard Worker             }
499*f6dc9357SAndroid Build Coastguard Worker             dist = (dist << 8) + (Byte)c2;
500*f6dc9357SAndroid Build Coastguard Worker           }
501*f6dc9357SAndroid Build Coastguard Worker           dist++;
502*f6dc9357SAndroid Build Coastguard Worker           len += 28;
503*f6dc9357SAndroid Build Coastguard Worker         }
504*f6dc9357SAndroid Build Coastguard Worker         const int c2 = DecodePpmSymbol();
505*f6dc9357SAndroid Build Coastguard Worker         if (c2 < 0)
506*f6dc9357SAndroid Build Coastguard Worker         {
507*f6dc9357SAndroid Build Coastguard Worker           PpmError = true;
508*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
509*f6dc9357SAndroid Build Coastguard Worker         }
510*f6dc9357SAndroid Build Coastguard Worker         len += (unsigned)c2;
511*f6dc9357SAndroid Build Coastguard Worker         if (dist >= _lzSize)
512*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
513*f6dc9357SAndroid Build Coastguard Worker         CopyBlock(dist, len);
514*f6dc9357SAndroid Build Coastguard Worker         num -= (Int32)len;
515*f6dc9357SAndroid Build Coastguard Worker         continue;
516*f6dc9357SAndroid Build Coastguard Worker       }
517*f6dc9357SAndroid Build Coastguard Worker     }
518*f6dc9357SAndroid Build Coastguard Worker     PutByte((Byte)c);
519*f6dc9357SAndroid Build Coastguard Worker     num--;
520*f6dc9357SAndroid Build Coastguard Worker   }
521*f6dc9357SAndroid Build Coastguard Worker   while (num >= 0);
522*f6dc9357SAndroid Build Coastguard Worker   keepDecompressing = true;
523*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
524*f6dc9357SAndroid Build Coastguard Worker }
525*f6dc9357SAndroid Build Coastguard Worker 
526*f6dc9357SAndroid Build Coastguard Worker // ---------- LZ ----------
527*f6dc9357SAndroid Build Coastguard Worker 
ReadTables(bool & keepDecompressing)528*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::ReadTables(bool &keepDecompressing)
529*f6dc9357SAndroid Build Coastguard Worker {
530*f6dc9357SAndroid Build Coastguard Worker   keepDecompressing = true;
531*f6dc9357SAndroid Build Coastguard Worker   m_InBitStream.BitDecoder.AlignToByte();
532*f6dc9357SAndroid Build Coastguard Worker   if (ReadBits(1) != 0)
533*f6dc9357SAndroid Build Coastguard Worker   {
534*f6dc9357SAndroid Build Coastguard Worker     _lzMode = false;
535*f6dc9357SAndroid Build Coastguard Worker     return InitPPM();
536*f6dc9357SAndroid Build Coastguard Worker   }
537*f6dc9357SAndroid Build Coastguard Worker 
538*f6dc9357SAndroid Build Coastguard Worker   TablesRead = false;
539*f6dc9357SAndroid Build Coastguard Worker   TablesOK = false;
540*f6dc9357SAndroid Build Coastguard Worker 
541*f6dc9357SAndroid Build Coastguard Worker   _lzMode = true;
542*f6dc9357SAndroid Build Coastguard Worker   PrevAlignBits = 0;
543*f6dc9357SAndroid Build Coastguard Worker   PrevAlignCount = 0;
544*f6dc9357SAndroid Build Coastguard Worker 
545*f6dc9357SAndroid Build Coastguard Worker   const unsigned kLevelTableSize = 20;
546*f6dc9357SAndroid Build Coastguard Worker   Byte levelLevels[kLevelTableSize];
547*f6dc9357SAndroid Build Coastguard Worker   Byte lens[kTablesSizesSum];
548*f6dc9357SAndroid Build Coastguard Worker 
549*f6dc9357SAndroid Build Coastguard Worker   if (ReadBits(1) == 0)
550*f6dc9357SAndroid Build Coastguard Worker     memset(m_LastLevels, 0, kTablesSizesSum);
551*f6dc9357SAndroid Build Coastguard Worker 
552*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
553*f6dc9357SAndroid Build Coastguard Worker 
554*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < kLevelTableSize; i++)
555*f6dc9357SAndroid Build Coastguard Worker   {
556*f6dc9357SAndroid Build Coastguard Worker     const UInt32 len = ReadBits(4);
557*f6dc9357SAndroid Build Coastguard Worker     if (len == 15)
558*f6dc9357SAndroid Build Coastguard Worker     {
559*f6dc9357SAndroid Build Coastguard Worker       UInt32 zeroCount = ReadBits(4);
560*f6dc9357SAndroid Build Coastguard Worker       if (zeroCount != 0)
561*f6dc9357SAndroid Build Coastguard Worker       {
562*f6dc9357SAndroid Build Coastguard Worker         zeroCount += 2;
563*f6dc9357SAndroid Build Coastguard Worker         while (zeroCount-- > 0 && i < kLevelTableSize)
564*f6dc9357SAndroid Build Coastguard Worker           levelLevels[i++]=0;
565*f6dc9357SAndroid Build Coastguard Worker         i--;
566*f6dc9357SAndroid Build Coastguard Worker         continue;
567*f6dc9357SAndroid Build Coastguard Worker       }
568*f6dc9357SAndroid Build Coastguard Worker     }
569*f6dc9357SAndroid Build Coastguard Worker     levelLevels[i] = (Byte)len;
570*f6dc9357SAndroid Build Coastguard Worker   }
571*f6dc9357SAndroid Build Coastguard Worker 
572*f6dc9357SAndroid Build Coastguard Worker   NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, 6> m_LevelDecoder;
573*f6dc9357SAndroid Build Coastguard Worker   RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))
574*f6dc9357SAndroid Build Coastguard Worker 
575*f6dc9357SAndroid Build Coastguard Worker   i = 0;
576*f6dc9357SAndroid Build Coastguard Worker 
577*f6dc9357SAndroid Build Coastguard Worker   do
578*f6dc9357SAndroid Build Coastguard Worker   {
579*f6dc9357SAndroid Build Coastguard Worker     const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream.BitDecoder);
580*f6dc9357SAndroid Build Coastguard Worker     if (sym < 16)
581*f6dc9357SAndroid Build Coastguard Worker     {
582*f6dc9357SAndroid Build Coastguard Worker       lens[i] = Byte((sym + m_LastLevels[i]) & 15);
583*f6dc9357SAndroid Build Coastguard Worker       i++;
584*f6dc9357SAndroid Build Coastguard Worker     }
585*f6dc9357SAndroid Build Coastguard Worker #if 0
586*f6dc9357SAndroid Build Coastguard Worker     else if (sym > kLevelTableSize)
587*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
588*f6dc9357SAndroid Build Coastguard Worker #endif
589*f6dc9357SAndroid Build Coastguard Worker     else
590*f6dc9357SAndroid Build Coastguard Worker     {
591*f6dc9357SAndroid Build Coastguard Worker       unsigned num = ((sym /* - 16 */) & 1) * 4;
592*f6dc9357SAndroid Build Coastguard Worker       num += num + 3 + (unsigned)ReadBits(num + 3);
593*f6dc9357SAndroid Build Coastguard Worker       num += i;
594*f6dc9357SAndroid Build Coastguard Worker       if (num > kTablesSizesSum)
595*f6dc9357SAndroid Build Coastguard Worker         num = kTablesSizesSum;
596*f6dc9357SAndroid Build Coastguard Worker       Byte v = 0;
597*f6dc9357SAndroid Build Coastguard Worker       if (sym < 16 + 2)
598*f6dc9357SAndroid Build Coastguard Worker       {
599*f6dc9357SAndroid Build Coastguard Worker         if (i == 0)
600*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
601*f6dc9357SAndroid Build Coastguard Worker         v = lens[(size_t)i - 1];
602*f6dc9357SAndroid Build Coastguard Worker       }
603*f6dc9357SAndroid Build Coastguard Worker       do
604*f6dc9357SAndroid Build Coastguard Worker         lens[i++] = v;
605*f6dc9357SAndroid Build Coastguard Worker       while (i < num);
606*f6dc9357SAndroid Build Coastguard Worker     }
607*f6dc9357SAndroid Build Coastguard Worker   }
608*f6dc9357SAndroid Build Coastguard Worker   while (i < kTablesSizesSum);
609*f6dc9357SAndroid Build Coastguard Worker 
610*f6dc9357SAndroid Build Coastguard Worker   if (InputEofError())
611*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
612*f6dc9357SAndroid Build Coastguard Worker 
613*f6dc9357SAndroid Build Coastguard Worker   TablesRead = true;
614*f6dc9357SAndroid Build Coastguard Worker 
615*f6dc9357SAndroid Build Coastguard Worker   // original code has check here:
616*f6dc9357SAndroid Build Coastguard Worker   /*
617*f6dc9357SAndroid Build Coastguard Worker   if (InAddr > ReadTop)
618*f6dc9357SAndroid Build Coastguard Worker   {
619*f6dc9357SAndroid Build Coastguard Worker     keepDecompressing = false;
620*f6dc9357SAndroid Build Coastguard Worker     return true;
621*f6dc9357SAndroid Build Coastguard Worker   }
622*f6dc9357SAndroid Build Coastguard Worker   */
623*f6dc9357SAndroid Build Coastguard Worker 
624*f6dc9357SAndroid Build Coastguard Worker   RIF(m_MainDecoder.Build(&lens[0]))
625*f6dc9357SAndroid Build Coastguard Worker   RIF(m_DistDecoder.Build(&lens[kMainTableSize]))
626*f6dc9357SAndroid Build Coastguard Worker   RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize]))
627*f6dc9357SAndroid Build Coastguard Worker   RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]))
628*f6dc9357SAndroid Build Coastguard Worker 
629*f6dc9357SAndroid Build Coastguard Worker   memcpy(m_LastLevels, lens, kTablesSizesSum);
630*f6dc9357SAndroid Build Coastguard Worker 
631*f6dc9357SAndroid Build Coastguard Worker   TablesOK = true;
632*f6dc9357SAndroid Build Coastguard Worker 
633*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
634*f6dc9357SAndroid Build Coastguard Worker }
635*f6dc9357SAndroid Build Coastguard Worker 
636*f6dc9357SAndroid Build Coastguard Worker /*
637*f6dc9357SAndroid Build Coastguard Worker class CCoderReleaser
638*f6dc9357SAndroid Build Coastguard Worker {
639*f6dc9357SAndroid Build Coastguard Worker   CDecoder *m_Coder;
640*f6dc9357SAndroid Build Coastguard Worker public:
641*f6dc9357SAndroid Build Coastguard Worker   CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
642*f6dc9357SAndroid Build Coastguard Worker   ~CCoderReleaser()
643*f6dc9357SAndroid Build Coastguard Worker   {
644*f6dc9357SAndroid Build Coastguard Worker     m_Coder->ReleaseStreams();
645*f6dc9357SAndroid Build Coastguard Worker   }
646*f6dc9357SAndroid Build Coastguard Worker };
647*f6dc9357SAndroid Build Coastguard Worker */
648*f6dc9357SAndroid Build Coastguard Worker 
ReadEndOfBlock(bool & keepDecompressing)649*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)
650*f6dc9357SAndroid Build Coastguard Worker {
651*f6dc9357SAndroid Build Coastguard Worker   if (ReadBits(1) == 0)
652*f6dc9357SAndroid Build Coastguard Worker   {
653*f6dc9357SAndroid Build Coastguard Worker     // new file
654*f6dc9357SAndroid Build Coastguard Worker     keepDecompressing = false;
655*f6dc9357SAndroid Build Coastguard Worker     TablesRead = (ReadBits(1) == 0);
656*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
657*f6dc9357SAndroid Build Coastguard Worker   }
658*f6dc9357SAndroid Build Coastguard Worker   TablesRead = false;
659*f6dc9357SAndroid Build Coastguard Worker   return ReadTables(keepDecompressing);
660*f6dc9357SAndroid Build Coastguard Worker }
661*f6dc9357SAndroid Build Coastguard Worker 
662*f6dc9357SAndroid Build Coastguard Worker 
DecodeLZ(bool & keepDecompressing)663*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
664*f6dc9357SAndroid Build Coastguard Worker {
665*f6dc9357SAndroid Build Coastguard Worker   UInt32 rep0 = _reps[0];
666*f6dc9357SAndroid Build Coastguard Worker   UInt32 rep1 = _reps[1];
667*f6dc9357SAndroid Build Coastguard Worker   UInt32 rep2 = _reps[2];
668*f6dc9357SAndroid Build Coastguard Worker   UInt32 rep3 = _reps[3];
669*f6dc9357SAndroid Build Coastguard Worker   UInt32 len = _lastLength;
670*f6dc9357SAndroid Build Coastguard Worker   for (;;)
671*f6dc9357SAndroid Build Coastguard Worker   {
672*f6dc9357SAndroid Build Coastguard Worker     if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
673*f6dc9357SAndroid Build Coastguard Worker     {
674*f6dc9357SAndroid Build Coastguard Worker       RINOK(WriteBuf())
675*f6dc9357SAndroid Build Coastguard Worker       if (_writtenFileSize > _unpackSize)
676*f6dc9357SAndroid Build Coastguard Worker       {
677*f6dc9357SAndroid Build Coastguard Worker         keepDecompressing = false;
678*f6dc9357SAndroid Build Coastguard Worker         return S_OK;
679*f6dc9357SAndroid Build Coastguard Worker       }
680*f6dc9357SAndroid Build Coastguard Worker     }
681*f6dc9357SAndroid Build Coastguard Worker 
682*f6dc9357SAndroid Build Coastguard Worker     if (InputEofError_Fast())
683*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
684*f6dc9357SAndroid Build Coastguard Worker 
685*f6dc9357SAndroid Build Coastguard Worker     unsigned sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder);
686*f6dc9357SAndroid Build Coastguard Worker     if (sym < 256)
687*f6dc9357SAndroid Build Coastguard Worker     {
688*f6dc9357SAndroid Build Coastguard Worker       PutByte((Byte)sym);
689*f6dc9357SAndroid Build Coastguard Worker       continue;
690*f6dc9357SAndroid Build Coastguard Worker     }
691*f6dc9357SAndroid Build Coastguard Worker     else if (sym == kSymbolReadTable)
692*f6dc9357SAndroid Build Coastguard Worker     {
693*f6dc9357SAndroid Build Coastguard Worker       RINOK(ReadEndOfBlock(keepDecompressing))
694*f6dc9357SAndroid Build Coastguard Worker       break;
695*f6dc9357SAndroid Build Coastguard Worker     }
696*f6dc9357SAndroid Build Coastguard Worker     else if (sym == 257)
697*f6dc9357SAndroid Build Coastguard Worker     {
698*f6dc9357SAndroid Build Coastguard Worker       if (!ReadVmCodeLZ())
699*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
700*f6dc9357SAndroid Build Coastguard Worker       continue;
701*f6dc9357SAndroid Build Coastguard Worker     }
702*f6dc9357SAndroid Build Coastguard Worker     else if (sym == 258)
703*f6dc9357SAndroid Build Coastguard Worker     {
704*f6dc9357SAndroid Build Coastguard Worker       if (len == 0)
705*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
706*f6dc9357SAndroid Build Coastguard Worker     }
707*f6dc9357SAndroid Build Coastguard Worker     else if (sym < kSymbolRep + 4)
708*f6dc9357SAndroid Build Coastguard Worker     {
709*f6dc9357SAndroid Build Coastguard Worker       if (sym != kSymbolRep)
710*f6dc9357SAndroid Build Coastguard Worker       {
711*f6dc9357SAndroid Build Coastguard Worker         UInt32 dist;
712*f6dc9357SAndroid Build Coastguard Worker         if (sym == kSymbolRep + 1)
713*f6dc9357SAndroid Build Coastguard Worker           dist = rep1;
714*f6dc9357SAndroid Build Coastguard Worker         else
715*f6dc9357SAndroid Build Coastguard Worker         {
716*f6dc9357SAndroid Build Coastguard Worker           if (sym == kSymbolRep + 2)
717*f6dc9357SAndroid Build Coastguard Worker             dist = rep2;
718*f6dc9357SAndroid Build Coastguard Worker           else
719*f6dc9357SAndroid Build Coastguard Worker           {
720*f6dc9357SAndroid Build Coastguard Worker             dist = rep3;
721*f6dc9357SAndroid Build Coastguard Worker             rep3 = rep2;
722*f6dc9357SAndroid Build Coastguard Worker           }
723*f6dc9357SAndroid Build Coastguard Worker           rep2 = rep1;
724*f6dc9357SAndroid Build Coastguard Worker         }
725*f6dc9357SAndroid Build Coastguard Worker         rep1 = rep0;
726*f6dc9357SAndroid Build Coastguard Worker         rep0 = dist;
727*f6dc9357SAndroid Build Coastguard Worker       }
728*f6dc9357SAndroid Build Coastguard Worker 
729*f6dc9357SAndroid Build Coastguard Worker       const unsigned sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder);
730*f6dc9357SAndroid Build Coastguard Worker       if (sym2 >= kLenTableSize)
731*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
732*f6dc9357SAndroid Build Coastguard Worker       len = 2 + sym2;
733*f6dc9357SAndroid Build Coastguard Worker       if (sym2 >= 8)
734*f6dc9357SAndroid Build Coastguard Worker       {
735*f6dc9357SAndroid Build Coastguard Worker         const unsigned num = (sym2 >> 2) - 1;
736*f6dc9357SAndroid Build Coastguard Worker         len = 2 + (UInt32)((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
737*f6dc9357SAndroid Build Coastguard Worker       }
738*f6dc9357SAndroid Build Coastguard Worker     }
739*f6dc9357SAndroid Build Coastguard Worker     else
740*f6dc9357SAndroid Build Coastguard Worker     {
741*f6dc9357SAndroid Build Coastguard Worker       rep3 = rep2;
742*f6dc9357SAndroid Build Coastguard Worker       rep2 = rep1;
743*f6dc9357SAndroid Build Coastguard Worker       rep1 = rep0;
744*f6dc9357SAndroid Build Coastguard Worker       if (sym < 271)
745*f6dc9357SAndroid Build Coastguard Worker       {
746*f6dc9357SAndroid Build Coastguard Worker         sym -= 263;
747*f6dc9357SAndroid Build Coastguard Worker         rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits_upto8(kLen2DistDirectBits[sym]);
748*f6dc9357SAndroid Build Coastguard Worker         len = 2;
749*f6dc9357SAndroid Build Coastguard Worker       }
750*f6dc9357SAndroid Build Coastguard Worker       else if (sym < 299)
751*f6dc9357SAndroid Build Coastguard Worker       {
752*f6dc9357SAndroid Build Coastguard Worker         sym -= 271;
753*f6dc9357SAndroid Build Coastguard Worker         len = kNormalMatchMinLen + sym;
754*f6dc9357SAndroid Build Coastguard Worker         if (sym >= 8)
755*f6dc9357SAndroid Build Coastguard Worker         {
756*f6dc9357SAndroid Build Coastguard Worker           const unsigned num = (sym >> 2) - 1;
757*f6dc9357SAndroid Build Coastguard Worker           len = kNormalMatchMinLen + (UInt32)((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
758*f6dc9357SAndroid Build Coastguard Worker         }
759*f6dc9357SAndroid Build Coastguard Worker         const unsigned sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder);
760*f6dc9357SAndroid Build Coastguard Worker         if (sym2 >= kDistTableSize)
761*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
762*f6dc9357SAndroid Build Coastguard Worker         rep0 = kDistStart[sym2];
763*f6dc9357SAndroid Build Coastguard Worker         unsigned numBits = kDistDirectBits[sym2];
764*f6dc9357SAndroid Build Coastguard Worker         if (sym2 >= (kNumAlignBits * 2) + 2)
765*f6dc9357SAndroid Build Coastguard Worker         {
766*f6dc9357SAndroid Build Coastguard Worker           if (numBits > kNumAlignBits)
767*f6dc9357SAndroid Build Coastguard Worker             rep0 += (m_InBitStream.BitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
768*f6dc9357SAndroid Build Coastguard Worker           if (PrevAlignCount > 0)
769*f6dc9357SAndroid Build Coastguard Worker           {
770*f6dc9357SAndroid Build Coastguard Worker             PrevAlignCount--;
771*f6dc9357SAndroid Build Coastguard Worker             rep0 += PrevAlignBits;
772*f6dc9357SAndroid Build Coastguard Worker           }
773*f6dc9357SAndroid Build Coastguard Worker           else
774*f6dc9357SAndroid Build Coastguard Worker           {
775*f6dc9357SAndroid Build Coastguard Worker             const unsigned sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder);
776*f6dc9357SAndroid Build Coastguard Worker             if (sym3 < (1 << kNumAlignBits))
777*f6dc9357SAndroid Build Coastguard Worker             {
778*f6dc9357SAndroid Build Coastguard Worker               rep0 += sym3;
779*f6dc9357SAndroid Build Coastguard Worker               PrevAlignBits = sym3;
780*f6dc9357SAndroid Build Coastguard Worker             }
781*f6dc9357SAndroid Build Coastguard Worker             else if (sym3 == (1 << kNumAlignBits))
782*f6dc9357SAndroid Build Coastguard Worker             {
783*f6dc9357SAndroid Build Coastguard Worker               PrevAlignCount = kNumAlignReps;
784*f6dc9357SAndroid Build Coastguard Worker               rep0 += PrevAlignBits;
785*f6dc9357SAndroid Build Coastguard Worker             }
786*f6dc9357SAndroid Build Coastguard Worker             else
787*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
788*f6dc9357SAndroid Build Coastguard Worker           }
789*f6dc9357SAndroid Build Coastguard Worker         }
790*f6dc9357SAndroid Build Coastguard Worker         else
791*f6dc9357SAndroid Build Coastguard Worker           rep0 += m_InBitStream.BitDecoder.ReadBits_upto8(numBits);
792*f6dc9357SAndroid Build Coastguard Worker         len += ((UInt32)(kDistLimit4 - rep0) >> 31) + ((UInt32)(kDistLimit3 - rep0) >> 31);
793*f6dc9357SAndroid Build Coastguard Worker       }
794*f6dc9357SAndroid Build Coastguard Worker       else
795*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
796*f6dc9357SAndroid Build Coastguard Worker     }
797*f6dc9357SAndroid Build Coastguard Worker     if (rep0 >= _lzSize)
798*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
799*f6dc9357SAndroid Build Coastguard Worker     CopyBlock(rep0, len);
800*f6dc9357SAndroid Build Coastguard Worker   }
801*f6dc9357SAndroid Build Coastguard Worker   _reps[0] = rep0;
802*f6dc9357SAndroid Build Coastguard Worker   _reps[1] = rep1;
803*f6dc9357SAndroid Build Coastguard Worker   _reps[2] = rep2;
804*f6dc9357SAndroid Build Coastguard Worker   _reps[3] = rep3;
805*f6dc9357SAndroid Build Coastguard Worker   _lastLength = len;
806*f6dc9357SAndroid Build Coastguard Worker 
807*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
808*f6dc9357SAndroid Build Coastguard Worker }
809*f6dc9357SAndroid Build Coastguard Worker 
810*f6dc9357SAndroid Build Coastguard Worker 
CodeReal(ICompressProgressInfo * progress)811*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
812*f6dc9357SAndroid Build Coastguard Worker {
813*f6dc9357SAndroid Build Coastguard Worker   _writtenFileSize = 0;
814*f6dc9357SAndroid Build Coastguard Worker   _unsupportedFilter = false;
815*f6dc9357SAndroid Build Coastguard Worker 
816*f6dc9357SAndroid Build Coastguard Worker   if (!_isSolid)
817*f6dc9357SAndroid Build Coastguard Worker   {
818*f6dc9357SAndroid Build Coastguard Worker     _lzSize = 0;
819*f6dc9357SAndroid Build Coastguard Worker     _winPos = 0;
820*f6dc9357SAndroid Build Coastguard Worker     _wrPtr = 0;
821*f6dc9357SAndroid Build Coastguard Worker     for (unsigned i = 0; i < kNumReps; i++)
822*f6dc9357SAndroid Build Coastguard Worker       _reps[i] = 0;
823*f6dc9357SAndroid Build Coastguard Worker     _lastLength = 0;
824*f6dc9357SAndroid Build Coastguard Worker     memset(m_LastLevels, 0, kTablesSizesSum);
825*f6dc9357SAndroid Build Coastguard Worker     TablesRead = false;
826*f6dc9357SAndroid Build Coastguard Worker     PpmEscChar = 2;
827*f6dc9357SAndroid Build Coastguard Worker     PpmError = true;
828*f6dc9357SAndroid Build Coastguard Worker     InitFilters();
829*f6dc9357SAndroid Build Coastguard Worker     // _errorMode = false;
830*f6dc9357SAndroid Build Coastguard Worker   }
831*f6dc9357SAndroid Build Coastguard Worker 
832*f6dc9357SAndroid Build Coastguard Worker   /*
833*f6dc9357SAndroid Build Coastguard Worker   if (_errorMode)
834*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
835*f6dc9357SAndroid Build Coastguard Worker   */
836*f6dc9357SAndroid Build Coastguard Worker 
837*f6dc9357SAndroid Build Coastguard Worker   if (!_isSolid || !TablesRead)
838*f6dc9357SAndroid Build Coastguard Worker   {
839*f6dc9357SAndroid Build Coastguard Worker     bool keepDecompressing;
840*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadTables(keepDecompressing))
841*f6dc9357SAndroid Build Coastguard Worker     if (!keepDecompressing)
842*f6dc9357SAndroid Build Coastguard Worker     {
843*f6dc9357SAndroid Build Coastguard Worker       _solidAllowed = true;
844*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
845*f6dc9357SAndroid Build Coastguard Worker     }
846*f6dc9357SAndroid Build Coastguard Worker   }
847*f6dc9357SAndroid Build Coastguard Worker 
848*f6dc9357SAndroid Build Coastguard Worker   for (;;)
849*f6dc9357SAndroid Build Coastguard Worker   {
850*f6dc9357SAndroid Build Coastguard Worker     bool keepDecompressing;
851*f6dc9357SAndroid Build Coastguard Worker     if (_lzMode)
852*f6dc9357SAndroid Build Coastguard Worker     {
853*f6dc9357SAndroid Build Coastguard Worker       if (!TablesOK)
854*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
855*f6dc9357SAndroid Build Coastguard Worker       RINOK(DecodeLZ(keepDecompressing))
856*f6dc9357SAndroid Build Coastguard Worker     }
857*f6dc9357SAndroid Build Coastguard Worker     else
858*f6dc9357SAndroid Build Coastguard Worker     {
859*f6dc9357SAndroid Build Coastguard Worker       RINOK(DecodePPM(1 << 18, keepDecompressing))
860*f6dc9357SAndroid Build Coastguard Worker     }
861*f6dc9357SAndroid Build Coastguard Worker 
862*f6dc9357SAndroid Build Coastguard Worker     if (InputEofError())
863*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
864*f6dc9357SAndroid Build Coastguard Worker 
865*f6dc9357SAndroid Build Coastguard Worker     const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
866*f6dc9357SAndroid Build Coastguard Worker     RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
867*f6dc9357SAndroid Build Coastguard Worker     if (!keepDecompressing)
868*f6dc9357SAndroid Build Coastguard Worker       break;
869*f6dc9357SAndroid Build Coastguard Worker   }
870*f6dc9357SAndroid Build Coastguard Worker 
871*f6dc9357SAndroid Build Coastguard Worker   _solidAllowed = true;
872*f6dc9357SAndroid Build Coastguard Worker 
873*f6dc9357SAndroid Build Coastguard Worker   RINOK(WriteBuf())
874*f6dc9357SAndroid Build Coastguard Worker   const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
875*f6dc9357SAndroid Build Coastguard Worker   RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
876*f6dc9357SAndroid Build Coastguard Worker   if (_writtenFileSize < _unpackSize)
877*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
878*f6dc9357SAndroid Build Coastguard Worker 
879*f6dc9357SAndroid Build Coastguard Worker   if (_unsupportedFilter)
880*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
881*f6dc9357SAndroid Build Coastguard Worker 
882*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
883*f6dc9357SAndroid Build Coastguard Worker }
884*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))885*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
886*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
887*f6dc9357SAndroid Build Coastguard Worker {
888*f6dc9357SAndroid Build Coastguard Worker   try
889*f6dc9357SAndroid Build Coastguard Worker   {
890*f6dc9357SAndroid Build Coastguard Worker     if (!inSize)
891*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
892*f6dc9357SAndroid Build Coastguard Worker 
893*f6dc9357SAndroid Build Coastguard Worker     if (_isSolid && !_solidAllowed)
894*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
895*f6dc9357SAndroid Build Coastguard Worker     _solidAllowed = false;
896*f6dc9357SAndroid Build Coastguard Worker 
897*f6dc9357SAndroid Build Coastguard Worker     if (!_vmData)
898*f6dc9357SAndroid Build Coastguard Worker     {
899*f6dc9357SAndroid Build Coastguard Worker       _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
900*f6dc9357SAndroid Build Coastguard Worker       if (!_vmData)
901*f6dc9357SAndroid Build Coastguard Worker         return E_OUTOFMEMORY;
902*f6dc9357SAndroid Build Coastguard Worker       _vmCode = _vmData + kVmDataSizeMax;
903*f6dc9357SAndroid Build Coastguard Worker     }
904*f6dc9357SAndroid Build Coastguard Worker 
905*f6dc9357SAndroid Build Coastguard Worker     if (!_window)
906*f6dc9357SAndroid Build Coastguard Worker     {
907*f6dc9357SAndroid Build Coastguard Worker       _window = (Byte *)::MidAlloc(kWindowSize);
908*f6dc9357SAndroid Build Coastguard Worker       if (!_window)
909*f6dc9357SAndroid Build Coastguard Worker         return E_OUTOFMEMORY;
910*f6dc9357SAndroid Build Coastguard Worker     }
911*f6dc9357SAndroid Build Coastguard Worker     if (!m_InBitStream.BitDecoder.Create(1 << 20))
912*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
913*f6dc9357SAndroid Build Coastguard Worker     if (!_vm.Create())
914*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
915*f6dc9357SAndroid Build Coastguard Worker 
916*f6dc9357SAndroid Build Coastguard Worker 
917*f6dc9357SAndroid Build Coastguard Worker     m_InBitStream.BitDecoder.SetStream(inStream);
918*f6dc9357SAndroid Build Coastguard Worker     m_InBitStream.BitDecoder.Init();
919*f6dc9357SAndroid Build Coastguard Worker     _outStream = outStream;
920*f6dc9357SAndroid Build Coastguard Worker 
921*f6dc9357SAndroid Build Coastguard Worker     // CCoderReleaser coderReleaser(this);
922*f6dc9357SAndroid Build Coastguard Worker     _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
923*f6dc9357SAndroid Build Coastguard Worker     return CodeReal(progress);
924*f6dc9357SAndroid Build Coastguard Worker   }
925*f6dc9357SAndroid Build Coastguard Worker   catch(const CInBufferException &e)  { /* _errorMode = true; */ return e.ErrorCode; }
926*f6dc9357SAndroid Build Coastguard Worker   catch(...) { /* _errorMode = true; */ return S_FALSE; }
927*f6dc9357SAndroid Build Coastguard Worker   // CNewException is possible here. But probably CNewException is caused
928*f6dc9357SAndroid Build Coastguard Worker   // by error in data stream.
929*f6dc9357SAndroid Build Coastguard Worker }
930*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * data,UInt32 size))931*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
932*f6dc9357SAndroid Build Coastguard Worker {
933*f6dc9357SAndroid Build Coastguard Worker   if (size < 1)
934*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
935*f6dc9357SAndroid Build Coastguard Worker   _isSolid = ((data[0] & 1) != 0);
936*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
937*f6dc9357SAndroid Build Coastguard Worker }
938*f6dc9357SAndroid Build Coastguard Worker 
939*f6dc9357SAndroid Build Coastguard Worker }}
940