xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/LzmaDecoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // LzmaDecoder.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 
7*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker #include "LzmaDecoder.h"
10*f6dc9357SAndroid Build Coastguard Worker 
SResToHRESULT(SRes res)11*f6dc9357SAndroid Build Coastguard Worker static HRESULT SResToHRESULT(SRes res)
12*f6dc9357SAndroid Build Coastguard Worker {
13*f6dc9357SAndroid Build Coastguard Worker   switch (res)
14*f6dc9357SAndroid Build Coastguard Worker   {
15*f6dc9357SAndroid Build Coastguard Worker     case SZ_OK: return S_OK;
16*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_MEM: return E_OUTOFMEMORY;
17*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_PARAM: return E_INVALIDARG;
18*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
19*f6dc9357SAndroid Build Coastguard Worker     case SZ_ERROR_DATA: return S_FALSE;
20*f6dc9357SAndroid Build Coastguard Worker     default: break;
21*f6dc9357SAndroid Build Coastguard Worker   }
22*f6dc9357SAndroid Build Coastguard Worker   return E_FAIL;
23*f6dc9357SAndroid Build Coastguard Worker }
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker namespace NCompress {
26*f6dc9357SAndroid Build Coastguard Worker namespace NLzma {
27*f6dc9357SAndroid Build Coastguard Worker 
CDecoder()28*f6dc9357SAndroid Build Coastguard Worker CDecoder::CDecoder():
29*f6dc9357SAndroid Build Coastguard Worker     FinishStream(false),
30*f6dc9357SAndroid Build Coastguard Worker     _propsWereSet(false),
31*f6dc9357SAndroid Build Coastguard Worker     _outSizeDefined(false),
32*f6dc9357SAndroid Build Coastguard Worker     _outStep(1 << 20),
33*f6dc9357SAndroid Build Coastguard Worker     _inBufSize(0),
34*f6dc9357SAndroid Build Coastguard Worker     _inBufSizeNew(1 << 20),
35*f6dc9357SAndroid Build Coastguard Worker     _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED),
36*f6dc9357SAndroid Build Coastguard Worker     _inBuf(NULL)
37*f6dc9357SAndroid Build Coastguard Worker {
38*f6dc9357SAndroid Build Coastguard Worker   _inProcessed = 0;
39*f6dc9357SAndroid Build Coastguard Worker   _inPos = _inLim = 0;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker   /*
42*f6dc9357SAndroid Build Coastguard Worker   AlignOffsetAlloc_CreateVTable(&_alloc);
43*f6dc9357SAndroid Build Coastguard Worker   _alloc.numAlignBits = 7;
44*f6dc9357SAndroid Build Coastguard Worker   _alloc.offset = 0;
45*f6dc9357SAndroid Build Coastguard Worker   */
46*f6dc9357SAndroid Build Coastguard Worker   LzmaDec_CONSTRUCT(&_state)
47*f6dc9357SAndroid Build Coastguard Worker }
48*f6dc9357SAndroid Build Coastguard Worker 
~CDecoder()49*f6dc9357SAndroid Build Coastguard Worker CDecoder::~CDecoder()
50*f6dc9357SAndroid Build Coastguard Worker {
51*f6dc9357SAndroid Build Coastguard Worker   LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt
52*f6dc9357SAndroid Build Coastguard Worker   MyFree(_inBuf);
53*f6dc9357SAndroid Build Coastguard Worker }
54*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetInBufSize (UInt32,UInt32 size))55*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size))
56*f6dc9357SAndroid Build Coastguard Worker   { _inBufSizeNew = size; return S_OK; }
Z7_COM7F_IMF(CDecoder::SetOutBufSize (UInt32,UInt32 size))57*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size))
58*f6dc9357SAndroid Build Coastguard Worker   { _outStep = size; return S_OK; }
59*f6dc9357SAndroid Build Coastguard Worker 
CreateInputBuffer()60*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CreateInputBuffer()
61*f6dc9357SAndroid Build Coastguard Worker {
62*f6dc9357SAndroid Build Coastguard Worker   if (!_inBuf || _inBufSizeNew != _inBufSize)
63*f6dc9357SAndroid Build Coastguard Worker   {
64*f6dc9357SAndroid Build Coastguard Worker     MyFree(_inBuf);
65*f6dc9357SAndroid Build Coastguard Worker     _inBufSize = 0;
66*f6dc9357SAndroid Build Coastguard Worker     _inBuf = (Byte *)MyAlloc(_inBufSizeNew);
67*f6dc9357SAndroid Build Coastguard Worker     if (!_inBuf)
68*f6dc9357SAndroid Build Coastguard Worker       return E_OUTOFMEMORY;
69*f6dc9357SAndroid Build Coastguard Worker     _inBufSize = _inBufSizeNew;
70*f6dc9357SAndroid Build Coastguard Worker   }
71*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * prop,UInt32 size))75*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size))
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker   RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt
78*f6dc9357SAndroid Build Coastguard Worker   _propsWereSet = true;
79*f6dc9357SAndroid Build Coastguard Worker   return CreateInputBuffer();
80*f6dc9357SAndroid Build Coastguard Worker }
81*f6dc9357SAndroid Build Coastguard Worker 
82*f6dc9357SAndroid Build Coastguard Worker 
SetOutStreamSizeResume(const UInt64 * outSize)83*f6dc9357SAndroid Build Coastguard Worker void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker   _outSizeDefined = (outSize != NULL);
86*f6dc9357SAndroid Build Coastguard Worker   _outSize = 0;
87*f6dc9357SAndroid Build Coastguard Worker   if (_outSizeDefined)
88*f6dc9357SAndroid Build Coastguard Worker     _outSize = *outSize;
89*f6dc9357SAndroid Build Coastguard Worker   _outProcessed = 0;
90*f6dc9357SAndroid Build Coastguard Worker   _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED;
91*f6dc9357SAndroid Build Coastguard Worker 
92*f6dc9357SAndroid Build Coastguard Worker   LzmaDec_Init(&_state);
93*f6dc9357SAndroid Build Coastguard Worker }
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetOutStreamSize (const UInt64 * outSize))96*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize))
97*f6dc9357SAndroid Build Coastguard Worker {
98*f6dc9357SAndroid Build Coastguard Worker   _inProcessed = 0;
99*f6dc9357SAndroid Build Coastguard Worker   _inPos = _inLim = 0;
100*f6dc9357SAndroid Build Coastguard Worker   SetOutStreamSizeResume(outSize);
101*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
102*f6dc9357SAndroid Build Coastguard Worker }
103*f6dc9357SAndroid Build Coastguard Worker 
104*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetFinishMode (UInt32 finishMode))105*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode))
106*f6dc9357SAndroid Build Coastguard Worker {
107*f6dc9357SAndroid Build Coastguard Worker   FinishStream = (finishMode != 0);
108*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
109*f6dc9357SAndroid Build Coastguard Worker }
110*f6dc9357SAndroid Build Coastguard Worker 
111*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize (UInt64 * value))112*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value))
113*f6dc9357SAndroid Build Coastguard Worker {
114*f6dc9357SAndroid Build Coastguard Worker   *value = _inProcessed;
115*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
116*f6dc9357SAndroid Build Coastguard Worker }
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker 
CodeSpec(ISequentialInStream * inStream,ISequentialOutStream * outStream,ICompressProgressInfo * progress)119*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
120*f6dc9357SAndroid Build Coastguard Worker {
121*f6dc9357SAndroid Build Coastguard Worker   if (!_inBuf || !_propsWereSet)
122*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker   const UInt64 startInProgress = _inProcessed;
125*f6dc9357SAndroid Build Coastguard Worker   SizeT wrPos = _state.dicPos;
126*f6dc9357SAndroid Build Coastguard Worker   HRESULT readRes = S_OK;
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker   for (;;)
129*f6dc9357SAndroid Build Coastguard Worker   {
130*f6dc9357SAndroid Build Coastguard Worker     if (_inPos == _inLim && readRes == S_OK)
131*f6dc9357SAndroid Build Coastguard Worker     {
132*f6dc9357SAndroid Build Coastguard Worker       _inPos = _inLim = 0;
133*f6dc9357SAndroid Build Coastguard Worker       readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
134*f6dc9357SAndroid Build Coastguard Worker     }
135*f6dc9357SAndroid Build Coastguard Worker 
136*f6dc9357SAndroid Build Coastguard Worker     const SizeT dicPos = _state.dicPos;
137*f6dc9357SAndroid Build Coastguard Worker     SizeT size;
138*f6dc9357SAndroid Build Coastguard Worker     {
139*f6dc9357SAndroid Build Coastguard Worker       SizeT next = _state.dicBufSize;
140*f6dc9357SAndroid Build Coastguard Worker       if (next - wrPos > _outStep)
141*f6dc9357SAndroid Build Coastguard Worker         next = wrPos + _outStep;
142*f6dc9357SAndroid Build Coastguard Worker       size = next - dicPos;
143*f6dc9357SAndroid Build Coastguard Worker     }
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker     ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
146*f6dc9357SAndroid Build Coastguard Worker     if (_outSizeDefined)
147*f6dc9357SAndroid Build Coastguard Worker     {
148*f6dc9357SAndroid Build Coastguard Worker       const UInt64 rem = _outSize - _outProcessed;
149*f6dc9357SAndroid Build Coastguard Worker       if (size >= rem)
150*f6dc9357SAndroid Build Coastguard Worker       {
151*f6dc9357SAndroid Build Coastguard Worker         size = (SizeT)rem;
152*f6dc9357SAndroid Build Coastguard Worker         if (FinishStream)
153*f6dc9357SAndroid Build Coastguard Worker           finishMode = LZMA_FINISH_END;
154*f6dc9357SAndroid Build Coastguard Worker       }
155*f6dc9357SAndroid Build Coastguard Worker     }
156*f6dc9357SAndroid Build Coastguard Worker 
157*f6dc9357SAndroid Build Coastguard Worker     SizeT inProcessed = _inLim - _inPos;
158*f6dc9357SAndroid Build Coastguard Worker     ELzmaStatus status;
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker     const SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
161*f6dc9357SAndroid Build Coastguard Worker 
162*f6dc9357SAndroid Build Coastguard Worker     _lzmaStatus = status;
163*f6dc9357SAndroid Build Coastguard Worker     _inPos += (UInt32)inProcessed;
164*f6dc9357SAndroid Build Coastguard Worker     _inProcessed += inProcessed;
165*f6dc9357SAndroid Build Coastguard Worker     const SizeT outProcessed = _state.dicPos - dicPos;
166*f6dc9357SAndroid Build Coastguard Worker     _outProcessed += outProcessed;
167*f6dc9357SAndroid Build Coastguard Worker 
168*f6dc9357SAndroid Build Coastguard Worker     // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0)
169*f6dc9357SAndroid Build Coastguard Worker     const bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
170*f6dc9357SAndroid Build Coastguard Worker 
171*f6dc9357SAndroid Build Coastguard Worker     const bool needStop = (res != 0
172*f6dc9357SAndroid Build Coastguard Worker         || (inProcessed == 0 && outProcessed == 0)
173*f6dc9357SAndroid Build Coastguard Worker         || status == LZMA_STATUS_FINISHED_WITH_MARK
174*f6dc9357SAndroid Build Coastguard Worker         || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT));
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker     if (needStop || outProcessed >= size)
177*f6dc9357SAndroid Build Coastguard Worker     {
178*f6dc9357SAndroid Build Coastguard Worker       const HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos);
179*f6dc9357SAndroid Build Coastguard Worker 
180*f6dc9357SAndroid Build Coastguard Worker       if (_state.dicPos == _state.dicBufSize)
181*f6dc9357SAndroid Build Coastguard Worker         _state.dicPos = 0;
182*f6dc9357SAndroid Build Coastguard Worker       wrPos = _state.dicPos;
183*f6dc9357SAndroid Build Coastguard Worker 
184*f6dc9357SAndroid Build Coastguard Worker       RINOK(res2)
185*f6dc9357SAndroid Build Coastguard Worker 
186*f6dc9357SAndroid Build Coastguard Worker       if (needStop)
187*f6dc9357SAndroid Build Coastguard Worker       {
188*f6dc9357SAndroid Build Coastguard Worker         if (res != 0)
189*f6dc9357SAndroid Build Coastguard Worker         {
190*f6dc9357SAndroid Build Coastguard Worker           // return SResToHRESULT(res);
191*f6dc9357SAndroid Build Coastguard Worker           return S_FALSE;
192*f6dc9357SAndroid Build Coastguard Worker         }
193*f6dc9357SAndroid Build Coastguard Worker 
194*f6dc9357SAndroid Build Coastguard Worker         if (status == LZMA_STATUS_FINISHED_WITH_MARK)
195*f6dc9357SAndroid Build Coastguard Worker         {
196*f6dc9357SAndroid Build Coastguard Worker           if (FinishStream)
197*f6dc9357SAndroid Build Coastguard Worker             if (_outSizeDefined && _outSize != _outProcessed)
198*f6dc9357SAndroid Build Coastguard Worker               return S_FALSE;
199*f6dc9357SAndroid Build Coastguard Worker           return readRes;
200*f6dc9357SAndroid Build Coastguard Worker         }
201*f6dc9357SAndroid Build Coastguard Worker 
202*f6dc9357SAndroid Build Coastguard Worker         if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)
203*f6dc9357SAndroid Build Coastguard Worker           if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
204*f6dc9357SAndroid Build Coastguard Worker             return readRes;
205*f6dc9357SAndroid Build Coastguard Worker 
206*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
207*f6dc9357SAndroid Build Coastguard Worker       }
208*f6dc9357SAndroid Build Coastguard Worker     }
209*f6dc9357SAndroid Build Coastguard Worker 
210*f6dc9357SAndroid Build Coastguard Worker     if (progress)
211*f6dc9357SAndroid Build Coastguard Worker     {
212*f6dc9357SAndroid Build Coastguard Worker       const UInt64 inSize = _inProcessed - startInProgress;
213*f6dc9357SAndroid Build Coastguard Worker       RINOK(progress->SetRatioInfo(&inSize, &_outProcessed))
214*f6dc9357SAndroid Build Coastguard Worker     }
215*f6dc9357SAndroid Build Coastguard Worker   }
216*f6dc9357SAndroid Build Coastguard Worker }
217*f6dc9357SAndroid Build Coastguard Worker 
218*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))219*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
220*f6dc9357SAndroid Build Coastguard Worker     const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
221*f6dc9357SAndroid Build Coastguard Worker {
222*f6dc9357SAndroid Build Coastguard Worker   if (!_inBuf)
223*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
224*f6dc9357SAndroid Build Coastguard Worker   SetOutStreamSize(outSize);
225*f6dc9357SAndroid Build Coastguard Worker   HRESULT res = CodeSpec(inStream, outStream, progress);
226*f6dc9357SAndroid Build Coastguard Worker   if (res == S_OK)
227*f6dc9357SAndroid Build Coastguard Worker     if (FinishStream && inSize && *inSize != _inProcessed)
228*f6dc9357SAndroid Build Coastguard Worker       res = S_FALSE;
229*f6dc9357SAndroid Build Coastguard Worker   return res;
230*f6dc9357SAndroid Build Coastguard Worker }
231*f6dc9357SAndroid Build Coastguard Worker 
232*f6dc9357SAndroid Build Coastguard Worker 
233*f6dc9357SAndroid Build Coastguard Worker #ifndef Z7_NO_READ_FROM_CODER
234*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::SetInStream (ISequentialInStream * inStream))235*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream))
236*f6dc9357SAndroid Build Coastguard Worker   { _inStream = inStream; return S_OK; }
Z7_COM7F_IMF(CDecoder::ReleaseInStream ())237*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::ReleaseInStream())
238*f6dc9357SAndroid Build Coastguard Worker   { _inStream.Release(); return S_OK; }
239*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CDecoder::Read (void * data,UInt32 size,UInt32 * processedSize))240*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize))
241*f6dc9357SAndroid Build Coastguard Worker {
242*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
243*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
244*f6dc9357SAndroid Build Coastguard Worker 
245*f6dc9357SAndroid Build Coastguard Worker   ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
246*f6dc9357SAndroid Build Coastguard Worker   if (_outSizeDefined)
247*f6dc9357SAndroid Build Coastguard Worker   {
248*f6dc9357SAndroid Build Coastguard Worker     const UInt64 rem = _outSize - _outProcessed;
249*f6dc9357SAndroid Build Coastguard Worker     if (size >= rem)
250*f6dc9357SAndroid Build Coastguard Worker     {
251*f6dc9357SAndroid Build Coastguard Worker       size = (UInt32)rem;
252*f6dc9357SAndroid Build Coastguard Worker       if (FinishStream)
253*f6dc9357SAndroid Build Coastguard Worker         finishMode = LZMA_FINISH_END;
254*f6dc9357SAndroid Build Coastguard Worker     }
255*f6dc9357SAndroid Build Coastguard Worker   }
256*f6dc9357SAndroid Build Coastguard Worker 
257*f6dc9357SAndroid Build Coastguard Worker   HRESULT readRes = S_OK;
258*f6dc9357SAndroid Build Coastguard Worker 
259*f6dc9357SAndroid Build Coastguard Worker   for (;;)
260*f6dc9357SAndroid Build Coastguard Worker   {
261*f6dc9357SAndroid Build Coastguard Worker     if (_inPos == _inLim && readRes == S_OK)
262*f6dc9357SAndroid Build Coastguard Worker     {
263*f6dc9357SAndroid Build Coastguard Worker       _inPos = _inLim = 0;
264*f6dc9357SAndroid Build Coastguard Worker       readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
265*f6dc9357SAndroid Build Coastguard Worker     }
266*f6dc9357SAndroid Build Coastguard Worker 
267*f6dc9357SAndroid Build Coastguard Worker     SizeT inProcessed = _inLim - _inPos;
268*f6dc9357SAndroid Build Coastguard Worker     SizeT outProcessed = size;
269*f6dc9357SAndroid Build Coastguard Worker     ELzmaStatus status;
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker     const SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
272*f6dc9357SAndroid Build Coastguard Worker         _inBuf + _inPos, &inProcessed, finishMode, &status);
273*f6dc9357SAndroid Build Coastguard Worker 
274*f6dc9357SAndroid Build Coastguard Worker     _lzmaStatus = status;
275*f6dc9357SAndroid Build Coastguard Worker     _inPos += (UInt32)inProcessed;
276*f6dc9357SAndroid Build Coastguard Worker     _inProcessed += inProcessed;
277*f6dc9357SAndroid Build Coastguard Worker     _outProcessed += outProcessed;
278*f6dc9357SAndroid Build Coastguard Worker     size -= (UInt32)outProcessed;
279*f6dc9357SAndroid Build Coastguard Worker     data = (Byte *)data + outProcessed;
280*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
281*f6dc9357SAndroid Build Coastguard Worker       *processedSize += (UInt32)outProcessed;
282*f6dc9357SAndroid Build Coastguard Worker 
283*f6dc9357SAndroid Build Coastguard Worker     if (res != 0)
284*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
285*f6dc9357SAndroid Build Coastguard Worker 
286*f6dc9357SAndroid Build Coastguard Worker     /*
287*f6dc9357SAndroid Build Coastguard Worker     if (status == LZMA_STATUS_FINISHED_WITH_MARK)
288*f6dc9357SAndroid Build Coastguard Worker       return readRes;
289*f6dc9357SAndroid Build Coastguard Worker 
290*f6dc9357SAndroid Build Coastguard Worker     if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
291*f6dc9357SAndroid Build Coastguard Worker     {
292*f6dc9357SAndroid Build Coastguard Worker       if (FinishStream
293*f6dc9357SAndroid Build Coastguard Worker           && _outSizeDefined && _outProcessed >= _outSize
294*f6dc9357SAndroid Build Coastguard Worker           && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
295*f6dc9357SAndroid Build Coastguard Worker         return S_FALSE;
296*f6dc9357SAndroid Build Coastguard Worker       return readRes;
297*f6dc9357SAndroid Build Coastguard Worker     }
298*f6dc9357SAndroid Build Coastguard Worker     */
299*f6dc9357SAndroid Build Coastguard Worker 
300*f6dc9357SAndroid Build Coastguard Worker     if (inProcessed == 0 && outProcessed == 0)
301*f6dc9357SAndroid Build Coastguard Worker       return readRes;
302*f6dc9357SAndroid Build Coastguard Worker   }
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker 
CodeResume(ISequentialOutStream * outStream,const UInt64 * outSize,ICompressProgressInfo * progress)306*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
307*f6dc9357SAndroid Build Coastguard Worker {
308*f6dc9357SAndroid Build Coastguard Worker   SetOutStreamSizeResume(outSize);
309*f6dc9357SAndroid Build Coastguard Worker   return CodeSpec(_inStream, outStream, progress);
310*f6dc9357SAndroid Build Coastguard Worker }
311*f6dc9357SAndroid Build Coastguard Worker 
312*f6dc9357SAndroid Build Coastguard Worker 
ReadFromInputStream(void * data,UInt32 size,UInt32 * processedSize)313*f6dc9357SAndroid Build Coastguard Worker HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)
314*f6dc9357SAndroid Build Coastguard Worker {
315*f6dc9357SAndroid Build Coastguard Worker   RINOK(CreateInputBuffer())
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
318*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
319*f6dc9357SAndroid Build Coastguard Worker 
320*f6dc9357SAndroid Build Coastguard Worker   HRESULT readRes = S_OK;
321*f6dc9357SAndroid Build Coastguard Worker 
322*f6dc9357SAndroid Build Coastguard Worker   while (size != 0)
323*f6dc9357SAndroid Build Coastguard Worker   {
324*f6dc9357SAndroid Build Coastguard Worker     if (_inPos == _inLim)
325*f6dc9357SAndroid Build Coastguard Worker     {
326*f6dc9357SAndroid Build Coastguard Worker       _inPos = _inLim = 0;
327*f6dc9357SAndroid Build Coastguard Worker       if (readRes == S_OK)
328*f6dc9357SAndroid Build Coastguard Worker         readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
329*f6dc9357SAndroid Build Coastguard Worker       if (_inLim == 0)
330*f6dc9357SAndroid Build Coastguard Worker         break;
331*f6dc9357SAndroid Build Coastguard Worker     }
332*f6dc9357SAndroid Build Coastguard Worker 
333*f6dc9357SAndroid Build Coastguard Worker     UInt32 cur = _inLim - _inPos;
334*f6dc9357SAndroid Build Coastguard Worker     if (cur > size)
335*f6dc9357SAndroid Build Coastguard Worker       cur = size;
336*f6dc9357SAndroid Build Coastguard Worker     memcpy(data, _inBuf + _inPos, cur);
337*f6dc9357SAndroid Build Coastguard Worker     _inPos += cur;
338*f6dc9357SAndroid Build Coastguard Worker     _inProcessed += cur;
339*f6dc9357SAndroid Build Coastguard Worker     size -= cur;
340*f6dc9357SAndroid Build Coastguard Worker     data = (Byte *)data + cur;
341*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
342*f6dc9357SAndroid Build Coastguard Worker       *processedSize += cur;
343*f6dc9357SAndroid Build Coastguard Worker   }
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker   return readRes;
346*f6dc9357SAndroid Build Coastguard Worker }
347*f6dc9357SAndroid Build Coastguard Worker 
348*f6dc9357SAndroid Build Coastguard Worker #endif
349*f6dc9357SAndroid Build Coastguard Worker 
350*f6dc9357SAndroid Build Coastguard Worker }}
351