1370b324cSopenharmony_ci/* Lzma2Dec.c -- LZMA2 Decoder
2370b324cSopenharmony_ci2023-03-03 : Igor Pavlov : Public domain */
3370b324cSopenharmony_ci
4370b324cSopenharmony_ci/* #define SHOW_DEBUG_INFO */
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include "Precomp.h"
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO
9370b324cSopenharmony_ci#include <stdio.h>
10370b324cSopenharmony_ci#endif
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#include <string.h>
13370b324cSopenharmony_ci
14370b324cSopenharmony_ci#include "Lzma2Dec.h"
15370b324cSopenharmony_ci
16370b324cSopenharmony_ci/*
17370b324cSopenharmony_ci00000000  -  End of data
18370b324cSopenharmony_ci00000001 U U  -  Uncompressed, reset dic, need reset state and set new prop
19370b324cSopenharmony_ci00000010 U U  -  Uncompressed, no reset
20370b324cSopenharmony_ci100uuuuu U U P P  -  LZMA, no reset
21370b324cSopenharmony_ci101uuuuu U U P P  -  LZMA, reset state
22370b324cSopenharmony_ci110uuuuu U U P P S  -  LZMA, reset state + set new prop
23370b324cSopenharmony_ci111uuuuu U U P P S  -  LZMA, reset state + set new prop, reset dic
24370b324cSopenharmony_ci
25370b324cSopenharmony_ci  u, U - Unpack Size
26370b324cSopenharmony_ci  P - Pack Size
27370b324cSopenharmony_ci  S - Props
28370b324cSopenharmony_ci*/
29370b324cSopenharmony_ci
30370b324cSopenharmony_ci#define LZMA2_CONTROL_COPY_RESET_DIC 1
31370b324cSopenharmony_ci
32370b324cSopenharmony_ci#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
33370b324cSopenharmony_ci
34370b324cSopenharmony_ci#define LZMA2_LCLP_MAX 4
35370b324cSopenharmony_ci#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
36370b324cSopenharmony_ci
37370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO
38370b324cSopenharmony_ci#define PRF(x) x
39370b324cSopenharmony_ci#else
40370b324cSopenharmony_ci#define PRF(x)
41370b324cSopenharmony_ci#endif
42370b324cSopenharmony_ci
43370b324cSopenharmony_citypedef enum
44370b324cSopenharmony_ci{
45370b324cSopenharmony_ci  LZMA2_STATE_CONTROL,
46370b324cSopenharmony_ci  LZMA2_STATE_UNPACK0,
47370b324cSopenharmony_ci  LZMA2_STATE_UNPACK1,
48370b324cSopenharmony_ci  LZMA2_STATE_PACK0,
49370b324cSopenharmony_ci  LZMA2_STATE_PACK1,
50370b324cSopenharmony_ci  LZMA2_STATE_PROP,
51370b324cSopenharmony_ci  LZMA2_STATE_DATA,
52370b324cSopenharmony_ci  LZMA2_STATE_DATA_CONT,
53370b324cSopenharmony_ci  LZMA2_STATE_FINISHED,
54370b324cSopenharmony_ci  LZMA2_STATE_ERROR
55370b324cSopenharmony_ci} ELzma2State;
56370b324cSopenharmony_ci
57370b324cSopenharmony_cistatic SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
58370b324cSopenharmony_ci{
59370b324cSopenharmony_ci  UInt32 dicSize;
60370b324cSopenharmony_ci  if (prop > 40)
61370b324cSopenharmony_ci    return SZ_ERROR_UNSUPPORTED;
62370b324cSopenharmony_ci  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
63370b324cSopenharmony_ci  props[0] = (Byte)LZMA2_LCLP_MAX;
64370b324cSopenharmony_ci  props[1] = (Byte)(dicSize);
65370b324cSopenharmony_ci  props[2] = (Byte)(dicSize >> 8);
66370b324cSopenharmony_ci  props[3] = (Byte)(dicSize >> 16);
67370b324cSopenharmony_ci  props[4] = (Byte)(dicSize >> 24);
68370b324cSopenharmony_ci  return SZ_OK;
69370b324cSopenharmony_ci}
70370b324cSopenharmony_ci
71370b324cSopenharmony_ciSRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
72370b324cSopenharmony_ci{
73370b324cSopenharmony_ci  Byte props[LZMA_PROPS_SIZE];
74370b324cSopenharmony_ci  RINOK(Lzma2Dec_GetOldProps(prop, props))
75370b324cSopenharmony_ci  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
76370b324cSopenharmony_ci}
77370b324cSopenharmony_ci
78370b324cSopenharmony_ciSRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
79370b324cSopenharmony_ci{
80370b324cSopenharmony_ci  Byte props[LZMA_PROPS_SIZE];
81370b324cSopenharmony_ci  RINOK(Lzma2Dec_GetOldProps(prop, props))
82370b324cSopenharmony_ci  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
83370b324cSopenharmony_ci}
84370b324cSopenharmony_ci
85370b324cSopenharmony_civoid Lzma2Dec_Init(CLzma2Dec *p)
86370b324cSopenharmony_ci{
87370b324cSopenharmony_ci  p->state = LZMA2_STATE_CONTROL;
88370b324cSopenharmony_ci  p->needInitLevel = 0xE0;
89370b324cSopenharmony_ci  p->isExtraMode = False;
90370b324cSopenharmony_ci  p->unpackSize = 0;
91370b324cSopenharmony_ci
92370b324cSopenharmony_ci  // p->decoder.dicPos = 0; // we can use it instead of full init
93370b324cSopenharmony_ci  LzmaDec_Init(&p->decoder);
94370b324cSopenharmony_ci}
95370b324cSopenharmony_ci
96370b324cSopenharmony_ci// ELzma2State
97370b324cSopenharmony_cistatic unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
98370b324cSopenharmony_ci{
99370b324cSopenharmony_ci  switch (p->state)
100370b324cSopenharmony_ci  {
101370b324cSopenharmony_ci    case LZMA2_STATE_CONTROL:
102370b324cSopenharmony_ci      p->isExtraMode = False;
103370b324cSopenharmony_ci      p->control = b;
104370b324cSopenharmony_ci      PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
105370b324cSopenharmony_ci      PRF(printf(" %02X", (unsigned)b));
106370b324cSopenharmony_ci      if (b == 0)
107370b324cSopenharmony_ci        return LZMA2_STATE_FINISHED;
108370b324cSopenharmony_ci      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109370b324cSopenharmony_ci      {
110370b324cSopenharmony_ci        if (b == LZMA2_CONTROL_COPY_RESET_DIC)
111370b324cSopenharmony_ci          p->needInitLevel = 0xC0;
112370b324cSopenharmony_ci        else if (b > 2 || p->needInitLevel == 0xE0)
113370b324cSopenharmony_ci          return LZMA2_STATE_ERROR;
114370b324cSopenharmony_ci      }
115370b324cSopenharmony_ci      else
116370b324cSopenharmony_ci      {
117370b324cSopenharmony_ci        if (b < p->needInitLevel)
118370b324cSopenharmony_ci          return LZMA2_STATE_ERROR;
119370b324cSopenharmony_ci        p->needInitLevel = 0;
120370b324cSopenharmony_ci        p->unpackSize = (UInt32)(b & 0x1F) << 16;
121370b324cSopenharmony_ci      }
122370b324cSopenharmony_ci      return LZMA2_STATE_UNPACK0;
123370b324cSopenharmony_ci
124370b324cSopenharmony_ci    case LZMA2_STATE_UNPACK0:
125370b324cSopenharmony_ci      p->unpackSize |= (UInt32)b << 8;
126370b324cSopenharmony_ci      return LZMA2_STATE_UNPACK1;
127370b324cSopenharmony_ci
128370b324cSopenharmony_ci    case LZMA2_STATE_UNPACK1:
129370b324cSopenharmony_ci      p->unpackSize |= (UInt32)b;
130370b324cSopenharmony_ci      p->unpackSize++;
131370b324cSopenharmony_ci      PRF(printf(" %7u", (unsigned)p->unpackSize));
132370b324cSopenharmony_ci      return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
133370b324cSopenharmony_ci
134370b324cSopenharmony_ci    case LZMA2_STATE_PACK0:
135370b324cSopenharmony_ci      p->packSize = (UInt32)b << 8;
136370b324cSopenharmony_ci      return LZMA2_STATE_PACK1;
137370b324cSopenharmony_ci
138370b324cSopenharmony_ci    case LZMA2_STATE_PACK1:
139370b324cSopenharmony_ci      p->packSize |= (UInt32)b;
140370b324cSopenharmony_ci      p->packSize++;
141370b324cSopenharmony_ci      // if (p->packSize < 5) return LZMA2_STATE_ERROR;
142370b324cSopenharmony_ci      PRF(printf(" %5u", (unsigned)p->packSize));
143370b324cSopenharmony_ci      return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
144370b324cSopenharmony_ci
145370b324cSopenharmony_ci    case LZMA2_STATE_PROP:
146370b324cSopenharmony_ci    {
147370b324cSopenharmony_ci      unsigned lc, lp;
148370b324cSopenharmony_ci      if (b >= (9 * 5 * 5))
149370b324cSopenharmony_ci        return LZMA2_STATE_ERROR;
150370b324cSopenharmony_ci      lc = b % 9;
151370b324cSopenharmony_ci      b /= 9;
152370b324cSopenharmony_ci      p->decoder.prop.pb = (Byte)(b / 5);
153370b324cSopenharmony_ci      lp = b % 5;
154370b324cSopenharmony_ci      if (lc + lp > LZMA2_LCLP_MAX)
155370b324cSopenharmony_ci        return LZMA2_STATE_ERROR;
156370b324cSopenharmony_ci      p->decoder.prop.lc = (Byte)lc;
157370b324cSopenharmony_ci      p->decoder.prop.lp = (Byte)lp;
158370b324cSopenharmony_ci      return LZMA2_STATE_DATA;
159370b324cSopenharmony_ci    }
160370b324cSopenharmony_ci  }
161370b324cSopenharmony_ci  return LZMA2_STATE_ERROR;
162370b324cSopenharmony_ci}
163370b324cSopenharmony_ci
164370b324cSopenharmony_cistatic void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
165370b324cSopenharmony_ci{
166370b324cSopenharmony_ci  memcpy(p->dic + p->dicPos, src, size);
167370b324cSopenharmony_ci  p->dicPos += size;
168370b324cSopenharmony_ci  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
169370b324cSopenharmony_ci    p->checkDicSize = p->prop.dicSize;
170370b324cSopenharmony_ci  p->processedPos += (UInt32)size;
171370b324cSopenharmony_ci}
172370b324cSopenharmony_ci
173370b324cSopenharmony_civoid LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
174370b324cSopenharmony_ci
175370b324cSopenharmony_ci
176370b324cSopenharmony_ciSRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
177370b324cSopenharmony_ci    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
178370b324cSopenharmony_ci{
179370b324cSopenharmony_ci  SizeT inSize = *srcLen;
180370b324cSopenharmony_ci  *srcLen = 0;
181370b324cSopenharmony_ci  *status = LZMA_STATUS_NOT_SPECIFIED;
182370b324cSopenharmony_ci
183370b324cSopenharmony_ci  while (p->state != LZMA2_STATE_ERROR)
184370b324cSopenharmony_ci  {
185370b324cSopenharmony_ci    SizeT dicPos;
186370b324cSopenharmony_ci
187370b324cSopenharmony_ci    if (p->state == LZMA2_STATE_FINISHED)
188370b324cSopenharmony_ci    {
189370b324cSopenharmony_ci      *status = LZMA_STATUS_FINISHED_WITH_MARK;
190370b324cSopenharmony_ci      return SZ_OK;
191370b324cSopenharmony_ci    }
192370b324cSopenharmony_ci
193370b324cSopenharmony_ci    dicPos = p->decoder.dicPos;
194370b324cSopenharmony_ci
195370b324cSopenharmony_ci    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
196370b324cSopenharmony_ci    {
197370b324cSopenharmony_ci      *status = LZMA_STATUS_NOT_FINISHED;
198370b324cSopenharmony_ci      return SZ_OK;
199370b324cSopenharmony_ci    }
200370b324cSopenharmony_ci
201370b324cSopenharmony_ci    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
202370b324cSopenharmony_ci    {
203370b324cSopenharmony_ci      if (*srcLen == inSize)
204370b324cSopenharmony_ci      {
205370b324cSopenharmony_ci        *status = LZMA_STATUS_NEEDS_MORE_INPUT;
206370b324cSopenharmony_ci        return SZ_OK;
207370b324cSopenharmony_ci      }
208370b324cSopenharmony_ci      (*srcLen)++;
209370b324cSopenharmony_ci      p->state = Lzma2Dec_UpdateState(p, *src++);
210370b324cSopenharmony_ci      if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
211370b324cSopenharmony_ci        break;
212370b324cSopenharmony_ci      continue;
213370b324cSopenharmony_ci    }
214370b324cSopenharmony_ci
215370b324cSopenharmony_ci    {
216370b324cSopenharmony_ci      SizeT inCur = inSize - *srcLen;
217370b324cSopenharmony_ci      SizeT outCur = dicLimit - dicPos;
218370b324cSopenharmony_ci      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
219370b324cSopenharmony_ci
220370b324cSopenharmony_ci      if (outCur >= p->unpackSize)
221370b324cSopenharmony_ci      {
222370b324cSopenharmony_ci        outCur = (SizeT)p->unpackSize;
223370b324cSopenharmony_ci        curFinishMode = LZMA_FINISH_END;
224370b324cSopenharmony_ci      }
225370b324cSopenharmony_ci
226370b324cSopenharmony_ci      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
227370b324cSopenharmony_ci      {
228370b324cSopenharmony_ci        if (inCur == 0)
229370b324cSopenharmony_ci        {
230370b324cSopenharmony_ci          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
231370b324cSopenharmony_ci          return SZ_OK;
232370b324cSopenharmony_ci        }
233370b324cSopenharmony_ci
234370b324cSopenharmony_ci        if (p->state == LZMA2_STATE_DATA)
235370b324cSopenharmony_ci        {
236370b324cSopenharmony_ci          BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
237370b324cSopenharmony_ci          LzmaDec_InitDicAndState(&p->decoder, initDic, False);
238370b324cSopenharmony_ci        }
239370b324cSopenharmony_ci
240370b324cSopenharmony_ci        if (inCur > outCur)
241370b324cSopenharmony_ci          inCur = outCur;
242370b324cSopenharmony_ci        if (inCur == 0)
243370b324cSopenharmony_ci          break;
244370b324cSopenharmony_ci
245370b324cSopenharmony_ci        LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
246370b324cSopenharmony_ci
247370b324cSopenharmony_ci        src += inCur;
248370b324cSopenharmony_ci        *srcLen += inCur;
249370b324cSopenharmony_ci        p->unpackSize -= (UInt32)inCur;
250370b324cSopenharmony_ci        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
251370b324cSopenharmony_ci      }
252370b324cSopenharmony_ci      else
253370b324cSopenharmony_ci      {
254370b324cSopenharmony_ci        SRes res;
255370b324cSopenharmony_ci
256370b324cSopenharmony_ci        if (p->state == LZMA2_STATE_DATA)
257370b324cSopenharmony_ci        {
258370b324cSopenharmony_ci          BoolInt initDic = (p->control >= 0xE0);
259370b324cSopenharmony_ci          BoolInt initState = (p->control >= 0xA0);
260370b324cSopenharmony_ci          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
261370b324cSopenharmony_ci          p->state = LZMA2_STATE_DATA_CONT;
262370b324cSopenharmony_ci        }
263370b324cSopenharmony_ci
264370b324cSopenharmony_ci        if (inCur > p->packSize)
265370b324cSopenharmony_ci          inCur = (SizeT)p->packSize;
266370b324cSopenharmony_ci
267370b324cSopenharmony_ci        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
268370b324cSopenharmony_ci
269370b324cSopenharmony_ci        src += inCur;
270370b324cSopenharmony_ci        *srcLen += inCur;
271370b324cSopenharmony_ci        p->packSize -= (UInt32)inCur;
272370b324cSopenharmony_ci        outCur = p->decoder.dicPos - dicPos;
273370b324cSopenharmony_ci        p->unpackSize -= (UInt32)outCur;
274370b324cSopenharmony_ci
275370b324cSopenharmony_ci        if (res != 0)
276370b324cSopenharmony_ci          break;
277370b324cSopenharmony_ci
278370b324cSopenharmony_ci        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
279370b324cSopenharmony_ci        {
280370b324cSopenharmony_ci          if (p->packSize == 0)
281370b324cSopenharmony_ci            break;
282370b324cSopenharmony_ci          return SZ_OK;
283370b324cSopenharmony_ci        }
284370b324cSopenharmony_ci
285370b324cSopenharmony_ci        if (inCur == 0 && outCur == 0)
286370b324cSopenharmony_ci        {
287370b324cSopenharmony_ci          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
288370b324cSopenharmony_ci              || p->unpackSize != 0
289370b324cSopenharmony_ci              || p->packSize != 0)
290370b324cSopenharmony_ci            break;
291370b324cSopenharmony_ci          p->state = LZMA2_STATE_CONTROL;
292370b324cSopenharmony_ci        }
293370b324cSopenharmony_ci
294370b324cSopenharmony_ci        *status = LZMA_STATUS_NOT_SPECIFIED;
295370b324cSopenharmony_ci      }
296370b324cSopenharmony_ci    }
297370b324cSopenharmony_ci  }
298370b324cSopenharmony_ci
299370b324cSopenharmony_ci  *status = LZMA_STATUS_NOT_SPECIFIED;
300370b324cSopenharmony_ci  p->state = LZMA2_STATE_ERROR;
301370b324cSopenharmony_ci  return SZ_ERROR_DATA;
302370b324cSopenharmony_ci}
303370b324cSopenharmony_ci
304370b324cSopenharmony_ci
305370b324cSopenharmony_ci
306370b324cSopenharmony_ci
307370b324cSopenharmony_ciELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
308370b324cSopenharmony_ci    SizeT outSize,
309370b324cSopenharmony_ci    const Byte *src, SizeT *srcLen,
310370b324cSopenharmony_ci    int checkFinishBlock)
311370b324cSopenharmony_ci{
312370b324cSopenharmony_ci  SizeT inSize = *srcLen;
313370b324cSopenharmony_ci  *srcLen = 0;
314370b324cSopenharmony_ci
315370b324cSopenharmony_ci  while (p->state != LZMA2_STATE_ERROR)
316370b324cSopenharmony_ci  {
317370b324cSopenharmony_ci    if (p->state == LZMA2_STATE_FINISHED)
318370b324cSopenharmony_ci      return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
319370b324cSopenharmony_ci
320370b324cSopenharmony_ci    if (outSize == 0 && !checkFinishBlock)
321370b324cSopenharmony_ci      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
322370b324cSopenharmony_ci
323370b324cSopenharmony_ci    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
324370b324cSopenharmony_ci    {
325370b324cSopenharmony_ci      if (*srcLen == inSize)
326370b324cSopenharmony_ci        return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
327370b324cSopenharmony_ci      (*srcLen)++;
328370b324cSopenharmony_ci
329370b324cSopenharmony_ci      p->state = Lzma2Dec_UpdateState(p, *src++);
330370b324cSopenharmony_ci
331370b324cSopenharmony_ci      if (p->state == LZMA2_STATE_UNPACK0)
332370b324cSopenharmony_ci      {
333370b324cSopenharmony_ci        // if (p->decoder.dicPos != 0)
334370b324cSopenharmony_ci        if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
335370b324cSopenharmony_ci          return LZMA2_PARSE_STATUS_NEW_BLOCK;
336370b324cSopenharmony_ci        // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
337370b324cSopenharmony_ci      }
338370b324cSopenharmony_ci
339370b324cSopenharmony_ci      // The following code can be commented.
340370b324cSopenharmony_ci      // It's not big problem, if we read additional input bytes.
341370b324cSopenharmony_ci      // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
342370b324cSopenharmony_ci
343370b324cSopenharmony_ci      if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
344370b324cSopenharmony_ci      {
345370b324cSopenharmony_ci        // checkFinishBlock is true. So we expect that block must be finished,
346370b324cSopenharmony_ci        // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
347370b324cSopenharmony_ci        // break;
348370b324cSopenharmony_ci        return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
349370b324cSopenharmony_ci      }
350370b324cSopenharmony_ci
351370b324cSopenharmony_ci      if (p->state == LZMA2_STATE_DATA)
352370b324cSopenharmony_ci        return LZMA2_PARSE_STATUS_NEW_CHUNK;
353370b324cSopenharmony_ci
354370b324cSopenharmony_ci      continue;
355370b324cSopenharmony_ci    }
356370b324cSopenharmony_ci
357370b324cSopenharmony_ci    if (outSize == 0)
358370b324cSopenharmony_ci      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
359370b324cSopenharmony_ci
360370b324cSopenharmony_ci    {
361370b324cSopenharmony_ci      SizeT inCur = inSize - *srcLen;
362370b324cSopenharmony_ci
363370b324cSopenharmony_ci      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
364370b324cSopenharmony_ci      {
365370b324cSopenharmony_ci        if (inCur == 0)
366370b324cSopenharmony_ci          return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
367370b324cSopenharmony_ci        if (inCur > p->unpackSize)
368370b324cSopenharmony_ci          inCur = p->unpackSize;
369370b324cSopenharmony_ci        if (inCur > outSize)
370370b324cSopenharmony_ci          inCur = outSize;
371370b324cSopenharmony_ci        p->decoder.dicPos += inCur;
372370b324cSopenharmony_ci        src += inCur;
373370b324cSopenharmony_ci        *srcLen += inCur;
374370b324cSopenharmony_ci        outSize -= inCur;
375370b324cSopenharmony_ci        p->unpackSize -= (UInt32)inCur;
376370b324cSopenharmony_ci        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
377370b324cSopenharmony_ci      }
378370b324cSopenharmony_ci      else
379370b324cSopenharmony_ci      {
380370b324cSopenharmony_ci        p->isExtraMode = True;
381370b324cSopenharmony_ci
382370b324cSopenharmony_ci        if (inCur == 0)
383370b324cSopenharmony_ci        {
384370b324cSopenharmony_ci          if (p->packSize != 0)
385370b324cSopenharmony_ci            return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
386370b324cSopenharmony_ci        }
387370b324cSopenharmony_ci        else if (p->state == LZMA2_STATE_DATA)
388370b324cSopenharmony_ci        {
389370b324cSopenharmony_ci          p->state = LZMA2_STATE_DATA_CONT;
390370b324cSopenharmony_ci          if (*src != 0)
391370b324cSopenharmony_ci          {
392370b324cSopenharmony_ci            // first byte of lzma chunk must be Zero
393370b324cSopenharmony_ci            *srcLen += 1;
394370b324cSopenharmony_ci            p->packSize--;
395370b324cSopenharmony_ci            break;
396370b324cSopenharmony_ci          }
397370b324cSopenharmony_ci        }
398370b324cSopenharmony_ci
399370b324cSopenharmony_ci        if (inCur > p->packSize)
400370b324cSopenharmony_ci          inCur = (SizeT)p->packSize;
401370b324cSopenharmony_ci
402370b324cSopenharmony_ci        src += inCur;
403370b324cSopenharmony_ci        *srcLen += inCur;
404370b324cSopenharmony_ci        p->packSize -= (UInt32)inCur;
405370b324cSopenharmony_ci
406370b324cSopenharmony_ci        if (p->packSize == 0)
407370b324cSopenharmony_ci        {
408370b324cSopenharmony_ci          SizeT rem = outSize;
409370b324cSopenharmony_ci          if (rem > p->unpackSize)
410370b324cSopenharmony_ci            rem = p->unpackSize;
411370b324cSopenharmony_ci          p->decoder.dicPos += rem;
412370b324cSopenharmony_ci          p->unpackSize -= (UInt32)rem;
413370b324cSopenharmony_ci          outSize -= rem;
414370b324cSopenharmony_ci          if (p->unpackSize == 0)
415370b324cSopenharmony_ci            p->state = LZMA2_STATE_CONTROL;
416370b324cSopenharmony_ci        }
417370b324cSopenharmony_ci      }
418370b324cSopenharmony_ci    }
419370b324cSopenharmony_ci  }
420370b324cSopenharmony_ci
421370b324cSopenharmony_ci  p->state = LZMA2_STATE_ERROR;
422370b324cSopenharmony_ci  return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
423370b324cSopenharmony_ci}
424370b324cSopenharmony_ci
425370b324cSopenharmony_ci
426370b324cSopenharmony_ci
427370b324cSopenharmony_ci
428370b324cSopenharmony_ciSRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
429370b324cSopenharmony_ci{
430370b324cSopenharmony_ci  SizeT outSize = *destLen, inSize = *srcLen;
431370b324cSopenharmony_ci  *srcLen = *destLen = 0;
432370b324cSopenharmony_ci
433370b324cSopenharmony_ci  for (;;)
434370b324cSopenharmony_ci  {
435370b324cSopenharmony_ci    SizeT inCur = inSize, outCur, dicPos;
436370b324cSopenharmony_ci    ELzmaFinishMode curFinishMode;
437370b324cSopenharmony_ci    SRes res;
438370b324cSopenharmony_ci
439370b324cSopenharmony_ci    if (p->decoder.dicPos == p->decoder.dicBufSize)
440370b324cSopenharmony_ci      p->decoder.dicPos = 0;
441370b324cSopenharmony_ci    dicPos = p->decoder.dicPos;
442370b324cSopenharmony_ci    curFinishMode = LZMA_FINISH_ANY;
443370b324cSopenharmony_ci    outCur = p->decoder.dicBufSize - dicPos;
444370b324cSopenharmony_ci
445370b324cSopenharmony_ci    if (outCur >= outSize)
446370b324cSopenharmony_ci    {
447370b324cSopenharmony_ci      outCur = outSize;
448370b324cSopenharmony_ci      curFinishMode = finishMode;
449370b324cSopenharmony_ci    }
450370b324cSopenharmony_ci
451370b324cSopenharmony_ci    res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
452370b324cSopenharmony_ci
453370b324cSopenharmony_ci    src += inCur;
454370b324cSopenharmony_ci    inSize -= inCur;
455370b324cSopenharmony_ci    *srcLen += inCur;
456370b324cSopenharmony_ci    outCur = p->decoder.dicPos - dicPos;
457370b324cSopenharmony_ci    memcpy(dest, p->decoder.dic + dicPos, outCur);
458370b324cSopenharmony_ci    dest += outCur;
459370b324cSopenharmony_ci    outSize -= outCur;
460370b324cSopenharmony_ci    *destLen += outCur;
461370b324cSopenharmony_ci    if (res != 0)
462370b324cSopenharmony_ci      return res;
463370b324cSopenharmony_ci    if (outCur == 0 || outSize == 0)
464370b324cSopenharmony_ci      return SZ_OK;
465370b324cSopenharmony_ci  }
466370b324cSopenharmony_ci}
467370b324cSopenharmony_ci
468370b324cSopenharmony_ci
469370b324cSopenharmony_ciSRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
470370b324cSopenharmony_ci    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
471370b324cSopenharmony_ci{
472370b324cSopenharmony_ci  CLzma2Dec p;
473370b324cSopenharmony_ci  SRes res;
474370b324cSopenharmony_ci  SizeT outSize = *destLen, inSize = *srcLen;
475370b324cSopenharmony_ci  *destLen = *srcLen = 0;
476370b324cSopenharmony_ci  *status = LZMA_STATUS_NOT_SPECIFIED;
477370b324cSopenharmony_ci  Lzma2Dec_CONSTRUCT(&p)
478370b324cSopenharmony_ci  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
479370b324cSopenharmony_ci  p.decoder.dic = dest;
480370b324cSopenharmony_ci  p.decoder.dicBufSize = outSize;
481370b324cSopenharmony_ci  Lzma2Dec_Init(&p);
482370b324cSopenharmony_ci  *srcLen = inSize;
483370b324cSopenharmony_ci  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
484370b324cSopenharmony_ci  *destLen = p.decoder.dicPos;
485370b324cSopenharmony_ci  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
486370b324cSopenharmony_ci    res = SZ_ERROR_INPUT_EOF;
487370b324cSopenharmony_ci  Lzma2Dec_FreeProbs(&p, alloc);
488370b324cSopenharmony_ci  return res;
489370b324cSopenharmony_ci}
490370b324cSopenharmony_ci
491370b324cSopenharmony_ci#undef PRF
492