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