1*f6dc9357SAndroid Build Coastguard Worker // PpmdDecoder.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Alloc.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
7*f6dc9357SAndroid Build Coastguard Worker
8*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
9*f6dc9357SAndroid Build Coastguard Worker
10*f6dc9357SAndroid Build Coastguard Worker #include "PpmdDecoder.h"
11*f6dc9357SAndroid Build Coastguard Worker
12*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
13*f6dc9357SAndroid Build Coastguard Worker namespace NPpmd {
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kBufSize = (1 << 16);
16*f6dc9357SAndroid Build Coastguard Worker
17*f6dc9357SAndroid Build Coastguard Worker enum
18*f6dc9357SAndroid Build Coastguard Worker {
19*f6dc9357SAndroid Build Coastguard Worker kStatus_NeedInit,
20*f6dc9357SAndroid Build Coastguard Worker kStatus_Normal,
21*f6dc9357SAndroid Build Coastguard Worker kStatus_Finished_With_Mark,
22*f6dc9357SAndroid Build Coastguard Worker kStatus_Error
23*f6dc9357SAndroid Build Coastguard Worker };
24*f6dc9357SAndroid Build Coastguard Worker
~CDecoder()25*f6dc9357SAndroid Build Coastguard Worker CDecoder::~CDecoder()
26*f6dc9357SAndroid Build Coastguard Worker {
27*f6dc9357SAndroid Build Coastguard Worker ::MidFree(_outBuf);
28*f6dc9357SAndroid Build Coastguard Worker Ppmd7_Free(&_ppmd, &g_BigAlloc);
29*f6dc9357SAndroid Build Coastguard Worker }
30*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * props,UInt32 size))31*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *props, UInt32 size))
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker if (size < 5)
34*f6dc9357SAndroid Build Coastguard Worker return E_INVALIDARG;
35*f6dc9357SAndroid Build Coastguard Worker _order = props[0];
36*f6dc9357SAndroid Build Coastguard Worker const UInt32 memSize = GetUi32(props + 1);
37*f6dc9357SAndroid Build Coastguard Worker if (_order < PPMD7_MIN_ORDER ||
38*f6dc9357SAndroid Build Coastguard Worker _order > PPMD7_MAX_ORDER ||
39*f6dc9357SAndroid Build Coastguard Worker memSize < PPMD7_MIN_MEM_SIZE ||
40*f6dc9357SAndroid Build Coastguard Worker memSize > PPMD7_MAX_MEM_SIZE)
41*f6dc9357SAndroid Build Coastguard Worker return E_NOTIMPL;
42*f6dc9357SAndroid Build Coastguard Worker if (!_inStream.Alloc(1 << 20))
43*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
44*f6dc9357SAndroid Build Coastguard Worker if (!Ppmd7_Alloc(&_ppmd, memSize, &g_BigAlloc))
45*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
46*f6dc9357SAndroid Build Coastguard Worker return S_OK;
47*f6dc9357SAndroid Build Coastguard Worker }
48*f6dc9357SAndroid Build Coastguard Worker
49*f6dc9357SAndroid Build Coastguard Worker #define MY_rangeDec _ppmd.rc.dec
50*f6dc9357SAndroid Build Coastguard Worker
51*f6dc9357SAndroid Build Coastguard Worker #define CHECK_EXTRA_ERROR \
52*f6dc9357SAndroid Build Coastguard Worker if (_inStream.Extra) { \
53*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_Error; \
54*f6dc9357SAndroid Build Coastguard Worker return (_res = (_inStream.Res != SZ_OK ? _inStream.Res: S_FALSE)); }
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker
CodeSpec(Byte * memStream,UInt32 size)57*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker if (_res != S_OK)
60*f6dc9357SAndroid Build Coastguard Worker return _res;
61*f6dc9357SAndroid Build Coastguard Worker
62*f6dc9357SAndroid Build Coastguard Worker switch (_status)
63*f6dc9357SAndroid Build Coastguard Worker {
64*f6dc9357SAndroid Build Coastguard Worker case kStatus_Finished_With_Mark: return S_OK;
65*f6dc9357SAndroid Build Coastguard Worker case kStatus_Error: return S_FALSE;
66*f6dc9357SAndroid Build Coastguard Worker case kStatus_NeedInit:
67*f6dc9357SAndroid Build Coastguard Worker _inStream.Init();
68*f6dc9357SAndroid Build Coastguard Worker if (!Ppmd7z_RangeDec_Init(&MY_rangeDec))
69*f6dc9357SAndroid Build Coastguard Worker {
70*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_Error;
71*f6dc9357SAndroid Build Coastguard Worker return (_res = S_FALSE);
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker CHECK_EXTRA_ERROR
74*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_Normal;
75*f6dc9357SAndroid Build Coastguard Worker Ppmd7_Init(&_ppmd, _order);
76*f6dc9357SAndroid Build Coastguard Worker break;
77*f6dc9357SAndroid Build Coastguard Worker default: break;
78*f6dc9357SAndroid Build Coastguard Worker }
79*f6dc9357SAndroid Build Coastguard Worker
80*f6dc9357SAndroid Build Coastguard Worker if (_outSizeDefined)
81*f6dc9357SAndroid Build Coastguard Worker {
82*f6dc9357SAndroid Build Coastguard Worker const UInt64 rem = _outSize - _processedSize;
83*f6dc9357SAndroid Build Coastguard Worker if (size > rem)
84*f6dc9357SAndroid Build Coastguard Worker size = (UInt32)rem;
85*f6dc9357SAndroid Build Coastguard Worker }
86*f6dc9357SAndroid Build Coastguard Worker
87*f6dc9357SAndroid Build Coastguard Worker int sym = 0;
88*f6dc9357SAndroid Build Coastguard Worker {
89*f6dc9357SAndroid Build Coastguard Worker Byte *buf = memStream;
90*f6dc9357SAndroid Build Coastguard Worker const Byte *lim = buf + size;
91*f6dc9357SAndroid Build Coastguard Worker for (; buf != lim; buf++)
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker sym = Ppmd7z_DecodeSymbol(&_ppmd);
94*f6dc9357SAndroid Build Coastguard Worker if (_inStream.Extra || sym < 0)
95*f6dc9357SAndroid Build Coastguard Worker break;
96*f6dc9357SAndroid Build Coastguard Worker *buf = (Byte)sym;
97*f6dc9357SAndroid Build Coastguard Worker }
98*f6dc9357SAndroid Build Coastguard Worker /*
99*f6dc9357SAndroid Build Coastguard Worker buf = Ppmd7z_DecodeSymbols(&_ppmd, buf, lim);
100*f6dc9357SAndroid Build Coastguard Worker sym = _ppmd.LastSymbol;
101*f6dc9357SAndroid Build Coastguard Worker */
102*f6dc9357SAndroid Build Coastguard Worker _processedSize += (size_t)(buf - memStream);
103*f6dc9357SAndroid Build Coastguard Worker }
104*f6dc9357SAndroid Build Coastguard Worker
105*f6dc9357SAndroid Build Coastguard Worker CHECK_EXTRA_ERROR
106*f6dc9357SAndroid Build Coastguard Worker
107*f6dc9357SAndroid Build Coastguard Worker if (sym >= 0)
108*f6dc9357SAndroid Build Coastguard Worker {
109*f6dc9357SAndroid Build Coastguard Worker if (!FinishStream
110*f6dc9357SAndroid Build Coastguard Worker || !_outSizeDefined
111*f6dc9357SAndroid Build Coastguard Worker || _outSize != _processedSize
112*f6dc9357SAndroid Build Coastguard Worker || MY_rangeDec.Code == 0)
113*f6dc9357SAndroid Build Coastguard Worker return S_OK;
114*f6dc9357SAndroid Build Coastguard Worker /*
115*f6dc9357SAndroid Build Coastguard Worker // We can decode additional End Marker here:
116*f6dc9357SAndroid Build Coastguard Worker sym = Ppmd7z_DecodeSymbol(&_ppmd);
117*f6dc9357SAndroid Build Coastguard Worker CHECK_EXTRA_ERROR
118*f6dc9357SAndroid Build Coastguard Worker */
119*f6dc9357SAndroid Build Coastguard Worker }
120*f6dc9357SAndroid Build Coastguard Worker
121*f6dc9357SAndroid Build Coastguard Worker if (sym != PPMD7_SYM_END || MY_rangeDec.Code != 0)
122*f6dc9357SAndroid Build Coastguard Worker {
123*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_Error;
124*f6dc9357SAndroid Build Coastguard Worker return (_res = S_FALSE);
125*f6dc9357SAndroid Build Coastguard Worker }
126*f6dc9357SAndroid Build Coastguard Worker
127*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_Finished_With_Mark;
128*f6dc9357SAndroid Build Coastguard Worker return S_OK;
129*f6dc9357SAndroid Build Coastguard Worker }
130*f6dc9357SAndroid Build Coastguard Worker
131*f6dc9357SAndroid Build Coastguard Worker
132*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))133*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
134*f6dc9357SAndroid Build Coastguard Worker const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
135*f6dc9357SAndroid Build Coastguard Worker {
136*f6dc9357SAndroid Build Coastguard Worker if (!_outBuf)
137*f6dc9357SAndroid Build Coastguard Worker {
138*f6dc9357SAndroid Build Coastguard Worker _outBuf = (Byte *)::MidAlloc(kBufSize);
139*f6dc9357SAndroid Build Coastguard Worker if (!_outBuf)
140*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY;
141*f6dc9357SAndroid Build Coastguard Worker }
142*f6dc9357SAndroid Build Coastguard Worker
143*f6dc9357SAndroid Build Coastguard Worker _inStream.Stream = inStream;
144*f6dc9357SAndroid Build Coastguard Worker SetOutStreamSize(outSize);
145*f6dc9357SAndroid Build Coastguard Worker
146*f6dc9357SAndroid Build Coastguard Worker do
147*f6dc9357SAndroid Build Coastguard Worker {
148*f6dc9357SAndroid Build Coastguard Worker const UInt64 startPos = _processedSize;
149*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = CodeSpec(_outBuf, kBufSize);
150*f6dc9357SAndroid Build Coastguard Worker const size_t processed = (size_t)(_processedSize - startPos);
151*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(outStream, _outBuf, processed))
152*f6dc9357SAndroid Build Coastguard Worker RINOK(res)
153*f6dc9357SAndroid Build Coastguard Worker if (_status == kStatus_Finished_With_Mark)
154*f6dc9357SAndroid Build Coastguard Worker break;
155*f6dc9357SAndroid Build Coastguard Worker if (progress)
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker const UInt64 inProcessed = _inStream.GetProcessed();
158*f6dc9357SAndroid Build Coastguard Worker RINOK(progress->SetRatioInfo(&inProcessed, &_processedSize))
159*f6dc9357SAndroid Build Coastguard Worker }
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker while (!_outSizeDefined || _processedSize < _outSize);
162*f6dc9357SAndroid Build Coastguard Worker
163*f6dc9357SAndroid Build Coastguard Worker if (FinishStream && inSize && *inSize != _inStream.GetProcessed())
164*f6dc9357SAndroid Build Coastguard Worker return S_FALSE;
165*f6dc9357SAndroid Build Coastguard Worker
166*f6dc9357SAndroid Build Coastguard Worker return S_OK;
167*f6dc9357SAndroid Build Coastguard Worker }
168*f6dc9357SAndroid Build Coastguard Worker
169*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetOutStreamSize (const UInt64 * outSize))170*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
171*f6dc9357SAndroid Build Coastguard Worker {
172*f6dc9357SAndroid Build Coastguard Worker _outSizeDefined = (outSize != NULL);
173*f6dc9357SAndroid Build Coastguard Worker if (_outSizeDefined)
174*f6dc9357SAndroid Build Coastguard Worker _outSize = *outSize;
175*f6dc9357SAndroid Build Coastguard Worker _processedSize = 0;
176*f6dc9357SAndroid Build Coastguard Worker _status = kStatus_NeedInit;
177*f6dc9357SAndroid Build Coastguard Worker _res = SZ_OK;
178*f6dc9357SAndroid Build Coastguard Worker return S_OK;
179*f6dc9357SAndroid Build Coastguard Worker }
180*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetFinishMode (UInt32 finishMode))181*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
182*f6dc9357SAndroid Build Coastguard Worker {
183*f6dc9357SAndroid Build Coastguard Worker FinishStream = (finishMode != 0);
184*f6dc9357SAndroid Build Coastguard Worker return S_OK;
185*f6dc9357SAndroid Build Coastguard Worker }
186*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize (UInt64 * value))187*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
188*f6dc9357SAndroid Build Coastguard Worker {
189*f6dc9357SAndroid Build Coastguard Worker *value = _inStream.GetProcessed();
190*f6dc9357SAndroid Build Coastguard Worker return S_OK;
191*f6dc9357SAndroid Build Coastguard Worker }
192*f6dc9357SAndroid Build Coastguard Worker
193*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_READ_FROM_CODER
194*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::SetInStream (ISequentialInStream * inStream))195*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
196*f6dc9357SAndroid Build Coastguard Worker {
197*f6dc9357SAndroid Build Coastguard Worker InSeqStream = inStream;
198*f6dc9357SAndroid Build Coastguard Worker _inStream.Stream = inStream;
199*f6dc9357SAndroid Build Coastguard Worker return S_OK;
200*f6dc9357SAndroid Build Coastguard Worker }
201*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::ReleaseInStream ())202*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::ReleaseInStream())
203*f6dc9357SAndroid Build Coastguard Worker {
204*f6dc9357SAndroid Build Coastguard Worker InSeqStream.Release();
205*f6dc9357SAndroid Build Coastguard Worker return S_OK;
206*f6dc9357SAndroid Build Coastguard Worker }
207*f6dc9357SAndroid Build Coastguard Worker
Z7_COM7F_IMF(CDecoder::Read (void * data,UInt32 size,UInt32 * processedSize))208*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker const UInt64 startPos = _processedSize;
211*f6dc9357SAndroid Build Coastguard Worker const HRESULT res = CodeSpec((Byte *)data, size);
212*f6dc9357SAndroid Build Coastguard Worker if (processedSize)
213*f6dc9357SAndroid Build Coastguard Worker *processedSize = (UInt32)(_processedSize - startPos);
214*f6dc9357SAndroid Build Coastguard Worker return res;
215*f6dc9357SAndroid Build Coastguard Worker }
216*f6dc9357SAndroid Build Coastguard Worker
217*f6dc9357SAndroid Build Coastguard Worker #endif
218*f6dc9357SAndroid Build Coastguard Worker
219*f6dc9357SAndroid Build Coastguard Worker }}
220