xref: /aosp_15_r20/external/lzma/C/Lzma2Dec.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker /* Lzma2Dec.c -- LZMA2 Decoder
2*f6dc9357SAndroid Build Coastguard Worker 2024-03-01 : Igor Pavlov : Public domain */
3*f6dc9357SAndroid Build Coastguard Worker 
4*f6dc9357SAndroid Build Coastguard Worker /* #define SHOW_DEBUG_INFO */
5*f6dc9357SAndroid Build Coastguard Worker 
6*f6dc9357SAndroid Build Coastguard Worker #include "Precomp.h"
7*f6dc9357SAndroid Build Coastguard Worker 
8*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
9*f6dc9357SAndroid Build Coastguard Worker #include <stdio.h>
10*f6dc9357SAndroid Build Coastguard Worker #endif
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include <string.h>
13*f6dc9357SAndroid Build Coastguard Worker 
14*f6dc9357SAndroid Build Coastguard Worker #include "Lzma2Dec.h"
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker /*
17*f6dc9357SAndroid Build Coastguard Worker 00000000  -  End of data
18*f6dc9357SAndroid Build Coastguard Worker 00000001 U U  -  Uncompressed, reset dic, need reset state and set new prop
19*f6dc9357SAndroid Build Coastguard Worker 00000010 U U  -  Uncompressed, no reset
20*f6dc9357SAndroid Build Coastguard Worker 100uuuuu U U P P  -  LZMA, no reset
21*f6dc9357SAndroid Build Coastguard Worker 101uuuuu U U P P  -  LZMA, reset state
22*f6dc9357SAndroid Build Coastguard Worker 110uuuuu U U P P S  -  LZMA, reset state + set new prop
23*f6dc9357SAndroid Build Coastguard Worker 111uuuuu U U P P S  -  LZMA, reset state + set new prop, reset dic
24*f6dc9357SAndroid Build Coastguard Worker 
25*f6dc9357SAndroid Build Coastguard Worker   u, U - Unpack Size
26*f6dc9357SAndroid Build Coastguard Worker   P - Pack Size
27*f6dc9357SAndroid Build Coastguard Worker   S - Props
28*f6dc9357SAndroid Build Coastguard Worker */
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker #define LZMA2_CONTROL_COPY_RESET_DIC 1
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
33*f6dc9357SAndroid Build Coastguard Worker 
34*f6dc9357SAndroid Build Coastguard Worker #define LZMA2_LCLP_MAX 4
35*f6dc9357SAndroid Build Coastguard Worker #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker #ifdef SHOW_DEBUG_INFO
38*f6dc9357SAndroid Build Coastguard Worker #define PRF(x) x
39*f6dc9357SAndroid Build Coastguard Worker #else
40*f6dc9357SAndroid Build Coastguard Worker #define PRF(x)
41*f6dc9357SAndroid Build Coastguard Worker #endif
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker typedef enum
44*f6dc9357SAndroid Build Coastguard Worker {
45*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_CONTROL,
46*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_UNPACK0,
47*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_UNPACK1,
48*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_PACK0,
49*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_PACK1,
50*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_PROP,
51*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_DATA,
52*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_DATA_CONT,
53*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_FINISHED,
54*f6dc9357SAndroid Build Coastguard Worker   LZMA2_STATE_ERROR
55*f6dc9357SAndroid Build Coastguard Worker } ELzma2State;
56*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_GetOldProps(Byte prop,Byte * props)57*f6dc9357SAndroid Build Coastguard Worker static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
58*f6dc9357SAndroid Build Coastguard Worker {
59*f6dc9357SAndroid Build Coastguard Worker   UInt32 dicSize;
60*f6dc9357SAndroid Build Coastguard Worker   if (prop > 40)
61*f6dc9357SAndroid Build Coastguard Worker     return SZ_ERROR_UNSUPPORTED;
62*f6dc9357SAndroid Build Coastguard Worker   dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
63*f6dc9357SAndroid Build Coastguard Worker   props[0] = (Byte)LZMA2_LCLP_MAX;
64*f6dc9357SAndroid Build Coastguard Worker   props[1] = (Byte)(dicSize);
65*f6dc9357SAndroid Build Coastguard Worker   props[2] = (Byte)(dicSize >> 8);
66*f6dc9357SAndroid Build Coastguard Worker   props[3] = (Byte)(dicSize >> 16);
67*f6dc9357SAndroid Build Coastguard Worker   props[4] = (Byte)(dicSize >> 24);
68*f6dc9357SAndroid Build Coastguard Worker   return SZ_OK;
69*f6dc9357SAndroid Build Coastguard Worker }
70*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_AllocateProbs(CLzma2Dec * p,Byte prop,ISzAllocPtr alloc)71*f6dc9357SAndroid Build Coastguard Worker SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
72*f6dc9357SAndroid Build Coastguard Worker {
73*f6dc9357SAndroid Build Coastguard Worker   Byte props[LZMA_PROPS_SIZE];
74*f6dc9357SAndroid Build Coastguard Worker   RINOK(Lzma2Dec_GetOldProps(prop, props))
75*f6dc9357SAndroid Build Coastguard Worker   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
76*f6dc9357SAndroid Build Coastguard Worker }
77*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_Allocate(CLzma2Dec * p,Byte prop,ISzAllocPtr alloc)78*f6dc9357SAndroid Build Coastguard Worker SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
79*f6dc9357SAndroid Build Coastguard Worker {
80*f6dc9357SAndroid Build Coastguard Worker   Byte props[LZMA_PROPS_SIZE];
81*f6dc9357SAndroid Build Coastguard Worker   RINOK(Lzma2Dec_GetOldProps(prop, props))
82*f6dc9357SAndroid Build Coastguard Worker   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
83*f6dc9357SAndroid Build Coastguard Worker }
84*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_Init(CLzma2Dec * p)85*f6dc9357SAndroid Build Coastguard Worker void Lzma2Dec_Init(CLzma2Dec *p)
86*f6dc9357SAndroid Build Coastguard Worker {
87*f6dc9357SAndroid Build Coastguard Worker   p->state = LZMA2_STATE_CONTROL;
88*f6dc9357SAndroid Build Coastguard Worker   p->needInitLevel = 0xE0;
89*f6dc9357SAndroid Build Coastguard Worker   p->isExtraMode = False;
90*f6dc9357SAndroid Build Coastguard Worker   p->unpackSize = 0;
91*f6dc9357SAndroid Build Coastguard Worker 
92*f6dc9357SAndroid Build Coastguard Worker   // p->decoder.dicPos = 0; // we can use it instead of full init
93*f6dc9357SAndroid Build Coastguard Worker   LzmaDec_Init(&p->decoder);
94*f6dc9357SAndroid Build Coastguard Worker }
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker // ELzma2State
Lzma2Dec_UpdateState(CLzma2Dec * p,Byte b)97*f6dc9357SAndroid Build Coastguard Worker static unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
98*f6dc9357SAndroid Build Coastguard Worker {
99*f6dc9357SAndroid Build Coastguard Worker   switch (p->state)
100*f6dc9357SAndroid Build Coastguard Worker   {
101*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_CONTROL:
102*f6dc9357SAndroid Build Coastguard Worker       p->isExtraMode = False;
103*f6dc9357SAndroid Build Coastguard Worker       p->control = b;
104*f6dc9357SAndroid Build Coastguard Worker       PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
105*f6dc9357SAndroid Build Coastguard Worker       PRF(printf(" %02X", (unsigned)b));
106*f6dc9357SAndroid Build Coastguard Worker       if (b == 0)
107*f6dc9357SAndroid Build Coastguard Worker         return LZMA2_STATE_FINISHED;
108*f6dc9357SAndroid Build Coastguard Worker       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109*f6dc9357SAndroid Build Coastguard Worker       {
110*f6dc9357SAndroid Build Coastguard Worker         if (b == LZMA2_CONTROL_COPY_RESET_DIC)
111*f6dc9357SAndroid Build Coastguard Worker           p->needInitLevel = 0xC0;
112*f6dc9357SAndroid Build Coastguard Worker         else if (b > 2 || p->needInitLevel == 0xE0)
113*f6dc9357SAndroid Build Coastguard Worker           return LZMA2_STATE_ERROR;
114*f6dc9357SAndroid Build Coastguard Worker       }
115*f6dc9357SAndroid Build Coastguard Worker       else
116*f6dc9357SAndroid Build Coastguard Worker       {
117*f6dc9357SAndroid Build Coastguard Worker         if (b < p->needInitLevel)
118*f6dc9357SAndroid Build Coastguard Worker           return LZMA2_STATE_ERROR;
119*f6dc9357SAndroid Build Coastguard Worker         p->needInitLevel = 0;
120*f6dc9357SAndroid Build Coastguard Worker         p->unpackSize = (UInt32)(b & 0x1F) << 16;
121*f6dc9357SAndroid Build Coastguard Worker       }
122*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_STATE_UNPACK0;
123*f6dc9357SAndroid Build Coastguard Worker 
124*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_UNPACK0:
125*f6dc9357SAndroid Build Coastguard Worker       p->unpackSize |= (UInt32)b << 8;
126*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_STATE_UNPACK1;
127*f6dc9357SAndroid Build Coastguard Worker 
128*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_UNPACK1:
129*f6dc9357SAndroid Build Coastguard Worker       p->unpackSize |= (UInt32)b;
130*f6dc9357SAndroid Build Coastguard Worker       p->unpackSize++;
131*f6dc9357SAndroid Build Coastguard Worker       PRF(printf(" %7u", (unsigned)p->unpackSize));
132*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
133*f6dc9357SAndroid Build Coastguard Worker 
134*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_PACK0:
135*f6dc9357SAndroid Build Coastguard Worker       p->packSize = (UInt32)b << 8;
136*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_STATE_PACK1;
137*f6dc9357SAndroid Build Coastguard Worker 
138*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_PACK1:
139*f6dc9357SAndroid Build Coastguard Worker       p->packSize |= (UInt32)b;
140*f6dc9357SAndroid Build Coastguard Worker       p->packSize++;
141*f6dc9357SAndroid Build Coastguard Worker       // if (p->packSize < 5) return LZMA2_STATE_ERROR;
142*f6dc9357SAndroid Build Coastguard Worker       PRF(printf(" %5u", (unsigned)p->packSize));
143*f6dc9357SAndroid Build Coastguard Worker       return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
144*f6dc9357SAndroid Build Coastguard Worker 
145*f6dc9357SAndroid Build Coastguard Worker     case LZMA2_STATE_PROP:
146*f6dc9357SAndroid Build Coastguard Worker     {
147*f6dc9357SAndroid Build Coastguard Worker       unsigned lc, lp;
148*f6dc9357SAndroid Build Coastguard Worker       if (b >= (9 * 5 * 5))
149*f6dc9357SAndroid Build Coastguard Worker         return LZMA2_STATE_ERROR;
150*f6dc9357SAndroid Build Coastguard Worker       lc = b % 9;
151*f6dc9357SAndroid Build Coastguard Worker       b /= 9;
152*f6dc9357SAndroid Build Coastguard Worker       p->decoder.prop.pb = (Byte)(b / 5);
153*f6dc9357SAndroid Build Coastguard Worker       lp = b % 5;
154*f6dc9357SAndroid Build Coastguard Worker       if (lc + lp > LZMA2_LCLP_MAX)
155*f6dc9357SAndroid Build Coastguard Worker         return LZMA2_STATE_ERROR;
156*f6dc9357SAndroid Build Coastguard Worker       p->decoder.prop.lc = (Byte)lc;
157*f6dc9357SAndroid Build Coastguard Worker       p->decoder.prop.lp = (Byte)lp;
158*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_STATE_DATA;
159*f6dc9357SAndroid Build Coastguard Worker     }
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker     default:
162*f6dc9357SAndroid Build Coastguard Worker       return LZMA2_STATE_ERROR;
163*f6dc9357SAndroid Build Coastguard Worker   }
164*f6dc9357SAndroid Build Coastguard Worker }
165*f6dc9357SAndroid Build Coastguard Worker 
LzmaDec_UpdateWithUncompressed(CLzmaDec * p,const Byte * src,SizeT size)166*f6dc9357SAndroid Build Coastguard Worker static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
167*f6dc9357SAndroid Build Coastguard Worker {
168*f6dc9357SAndroid Build Coastguard Worker   memcpy(p->dic + p->dicPos, src, size);
169*f6dc9357SAndroid Build Coastguard Worker   p->dicPos += size;
170*f6dc9357SAndroid Build Coastguard Worker   if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
171*f6dc9357SAndroid Build Coastguard Worker     p->checkDicSize = p->prop.dicSize;
172*f6dc9357SAndroid Build Coastguard Worker   p->processedPos += (UInt32)size;
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker 
175*f6dc9357SAndroid Build Coastguard Worker void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
176*f6dc9357SAndroid Build Coastguard Worker 
177*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_DecodeToDic(CLzma2Dec * p,SizeT dicLimit,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)178*f6dc9357SAndroid Build Coastguard Worker SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
179*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
180*f6dc9357SAndroid Build Coastguard Worker {
181*f6dc9357SAndroid Build Coastguard Worker   SizeT inSize = *srcLen;
182*f6dc9357SAndroid Build Coastguard Worker   *srcLen = 0;
183*f6dc9357SAndroid Build Coastguard Worker   *status = LZMA_STATUS_NOT_SPECIFIED;
184*f6dc9357SAndroid Build Coastguard Worker 
185*f6dc9357SAndroid Build Coastguard Worker   while (p->state != LZMA2_STATE_ERROR)
186*f6dc9357SAndroid Build Coastguard Worker   {
187*f6dc9357SAndroid Build Coastguard Worker     SizeT dicPos;
188*f6dc9357SAndroid Build Coastguard Worker 
189*f6dc9357SAndroid Build Coastguard Worker     if (p->state == LZMA2_STATE_FINISHED)
190*f6dc9357SAndroid Build Coastguard Worker     {
191*f6dc9357SAndroid Build Coastguard Worker       *status = LZMA_STATUS_FINISHED_WITH_MARK;
192*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
193*f6dc9357SAndroid Build Coastguard Worker     }
194*f6dc9357SAndroid Build Coastguard Worker 
195*f6dc9357SAndroid Build Coastguard Worker     dicPos = p->decoder.dicPos;
196*f6dc9357SAndroid Build Coastguard Worker 
197*f6dc9357SAndroid Build Coastguard Worker     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
198*f6dc9357SAndroid Build Coastguard Worker     {
199*f6dc9357SAndroid Build Coastguard Worker       *status = LZMA_STATUS_NOT_FINISHED;
200*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
201*f6dc9357SAndroid Build Coastguard Worker     }
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
204*f6dc9357SAndroid Build Coastguard Worker     {
205*f6dc9357SAndroid Build Coastguard Worker       if (*srcLen == inSize)
206*f6dc9357SAndroid Build Coastguard Worker       {
207*f6dc9357SAndroid Build Coastguard Worker         *status = LZMA_STATUS_NEEDS_MORE_INPUT;
208*f6dc9357SAndroid Build Coastguard Worker         return SZ_OK;
209*f6dc9357SAndroid Build Coastguard Worker       }
210*f6dc9357SAndroid Build Coastguard Worker       (*srcLen)++;
211*f6dc9357SAndroid Build Coastguard Worker       p->state = Lzma2Dec_UpdateState(p, *src++);
212*f6dc9357SAndroid Build Coastguard Worker       if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
213*f6dc9357SAndroid Build Coastguard Worker         break;
214*f6dc9357SAndroid Build Coastguard Worker       continue;
215*f6dc9357SAndroid Build Coastguard Worker     }
216*f6dc9357SAndroid Build Coastguard Worker 
217*f6dc9357SAndroid Build Coastguard Worker     {
218*f6dc9357SAndroid Build Coastguard Worker       SizeT inCur = inSize - *srcLen;
219*f6dc9357SAndroid Build Coastguard Worker       SizeT outCur = dicLimit - dicPos;
220*f6dc9357SAndroid Build Coastguard Worker       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
221*f6dc9357SAndroid Build Coastguard Worker 
222*f6dc9357SAndroid Build Coastguard Worker       if (outCur >= p->unpackSize)
223*f6dc9357SAndroid Build Coastguard Worker       {
224*f6dc9357SAndroid Build Coastguard Worker         outCur = (SizeT)p->unpackSize;
225*f6dc9357SAndroid Build Coastguard Worker         curFinishMode = LZMA_FINISH_END;
226*f6dc9357SAndroid Build Coastguard Worker       }
227*f6dc9357SAndroid Build Coastguard Worker 
228*f6dc9357SAndroid Build Coastguard Worker       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
229*f6dc9357SAndroid Build Coastguard Worker       {
230*f6dc9357SAndroid Build Coastguard Worker         if (inCur == 0)
231*f6dc9357SAndroid Build Coastguard Worker         {
232*f6dc9357SAndroid Build Coastguard Worker           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
233*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
234*f6dc9357SAndroid Build Coastguard Worker         }
235*f6dc9357SAndroid Build Coastguard Worker 
236*f6dc9357SAndroid Build Coastguard Worker         if (p->state == LZMA2_STATE_DATA)
237*f6dc9357SAndroid Build Coastguard Worker         {
238*f6dc9357SAndroid Build Coastguard Worker           BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
239*f6dc9357SAndroid Build Coastguard Worker           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
240*f6dc9357SAndroid Build Coastguard Worker         }
241*f6dc9357SAndroid Build Coastguard Worker 
242*f6dc9357SAndroid Build Coastguard Worker         if (inCur > outCur)
243*f6dc9357SAndroid Build Coastguard Worker           inCur = outCur;
244*f6dc9357SAndroid Build Coastguard Worker         if (inCur == 0)
245*f6dc9357SAndroid Build Coastguard Worker           break;
246*f6dc9357SAndroid Build Coastguard Worker 
247*f6dc9357SAndroid Build Coastguard Worker         LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
248*f6dc9357SAndroid Build Coastguard Worker 
249*f6dc9357SAndroid Build Coastguard Worker         src += inCur;
250*f6dc9357SAndroid Build Coastguard Worker         *srcLen += inCur;
251*f6dc9357SAndroid Build Coastguard Worker         p->unpackSize -= (UInt32)inCur;
252*f6dc9357SAndroid Build Coastguard Worker         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
253*f6dc9357SAndroid Build Coastguard Worker       }
254*f6dc9357SAndroid Build Coastguard Worker       else
255*f6dc9357SAndroid Build Coastguard Worker       {
256*f6dc9357SAndroid Build Coastguard Worker         SRes res;
257*f6dc9357SAndroid Build Coastguard Worker 
258*f6dc9357SAndroid Build Coastguard Worker         if (p->state == LZMA2_STATE_DATA)
259*f6dc9357SAndroid Build Coastguard Worker         {
260*f6dc9357SAndroid Build Coastguard Worker           BoolInt initDic = (p->control >= 0xE0);
261*f6dc9357SAndroid Build Coastguard Worker           BoolInt initState = (p->control >= 0xA0);
262*f6dc9357SAndroid Build Coastguard Worker           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
263*f6dc9357SAndroid Build Coastguard Worker           p->state = LZMA2_STATE_DATA_CONT;
264*f6dc9357SAndroid Build Coastguard Worker         }
265*f6dc9357SAndroid Build Coastguard Worker 
266*f6dc9357SAndroid Build Coastguard Worker         if (inCur > p->packSize)
267*f6dc9357SAndroid Build Coastguard Worker           inCur = (SizeT)p->packSize;
268*f6dc9357SAndroid Build Coastguard Worker 
269*f6dc9357SAndroid Build Coastguard Worker         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
270*f6dc9357SAndroid Build Coastguard Worker 
271*f6dc9357SAndroid Build Coastguard Worker         src += inCur;
272*f6dc9357SAndroid Build Coastguard Worker         *srcLen += inCur;
273*f6dc9357SAndroid Build Coastguard Worker         p->packSize -= (UInt32)inCur;
274*f6dc9357SAndroid Build Coastguard Worker         outCur = p->decoder.dicPos - dicPos;
275*f6dc9357SAndroid Build Coastguard Worker         p->unpackSize -= (UInt32)outCur;
276*f6dc9357SAndroid Build Coastguard Worker 
277*f6dc9357SAndroid Build Coastguard Worker         if (res != 0)
278*f6dc9357SAndroid Build Coastguard Worker           break;
279*f6dc9357SAndroid Build Coastguard Worker 
280*f6dc9357SAndroid Build Coastguard Worker         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
281*f6dc9357SAndroid Build Coastguard Worker         {
282*f6dc9357SAndroid Build Coastguard Worker           if (p->packSize == 0)
283*f6dc9357SAndroid Build Coastguard Worker             break;
284*f6dc9357SAndroid Build Coastguard Worker           return SZ_OK;
285*f6dc9357SAndroid Build Coastguard Worker         }
286*f6dc9357SAndroid Build Coastguard Worker 
287*f6dc9357SAndroid Build Coastguard Worker         if (inCur == 0 && outCur == 0)
288*f6dc9357SAndroid Build Coastguard Worker         {
289*f6dc9357SAndroid Build Coastguard Worker           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
290*f6dc9357SAndroid Build Coastguard Worker               || p->unpackSize != 0
291*f6dc9357SAndroid Build Coastguard Worker               || p->packSize != 0)
292*f6dc9357SAndroid Build Coastguard Worker             break;
293*f6dc9357SAndroid Build Coastguard Worker           p->state = LZMA2_STATE_CONTROL;
294*f6dc9357SAndroid Build Coastguard Worker         }
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker         *status = LZMA_STATUS_NOT_SPECIFIED;
297*f6dc9357SAndroid Build Coastguard Worker       }
298*f6dc9357SAndroid Build Coastguard Worker     }
299*f6dc9357SAndroid Build Coastguard Worker   }
300*f6dc9357SAndroid Build Coastguard Worker 
301*f6dc9357SAndroid Build Coastguard Worker   *status = LZMA_STATUS_NOT_SPECIFIED;
302*f6dc9357SAndroid Build Coastguard Worker   p->state = LZMA2_STATE_ERROR;
303*f6dc9357SAndroid Build Coastguard Worker   return SZ_ERROR_DATA;
304*f6dc9357SAndroid Build Coastguard Worker }
305*f6dc9357SAndroid Build Coastguard Worker 
306*f6dc9357SAndroid Build Coastguard Worker 
307*f6dc9357SAndroid Build Coastguard Worker 
308*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_Parse(CLzma2Dec * p,SizeT outSize,const Byte * src,SizeT * srcLen,int checkFinishBlock)309*f6dc9357SAndroid Build Coastguard Worker ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
310*f6dc9357SAndroid Build Coastguard Worker     SizeT outSize,
311*f6dc9357SAndroid Build Coastguard Worker     const Byte *src, SizeT *srcLen,
312*f6dc9357SAndroid Build Coastguard Worker     int checkFinishBlock)
313*f6dc9357SAndroid Build Coastguard Worker {
314*f6dc9357SAndroid Build Coastguard Worker   SizeT inSize = *srcLen;
315*f6dc9357SAndroid Build Coastguard Worker   *srcLen = 0;
316*f6dc9357SAndroid Build Coastguard Worker 
317*f6dc9357SAndroid Build Coastguard Worker   while (p->state != LZMA2_STATE_ERROR)
318*f6dc9357SAndroid Build Coastguard Worker   {
319*f6dc9357SAndroid Build Coastguard Worker     if (p->state == LZMA2_STATE_FINISHED)
320*f6dc9357SAndroid Build Coastguard Worker       return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
321*f6dc9357SAndroid Build Coastguard Worker 
322*f6dc9357SAndroid Build Coastguard Worker     if (outSize == 0 && !checkFinishBlock)
323*f6dc9357SAndroid Build Coastguard Worker       return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
324*f6dc9357SAndroid Build Coastguard Worker 
325*f6dc9357SAndroid Build Coastguard Worker     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
326*f6dc9357SAndroid Build Coastguard Worker     {
327*f6dc9357SAndroid Build Coastguard Worker       if (*srcLen == inSize)
328*f6dc9357SAndroid Build Coastguard Worker         return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
329*f6dc9357SAndroid Build Coastguard Worker       (*srcLen)++;
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker       p->state = Lzma2Dec_UpdateState(p, *src++);
332*f6dc9357SAndroid Build Coastguard Worker 
333*f6dc9357SAndroid Build Coastguard Worker       if (p->state == LZMA2_STATE_UNPACK0)
334*f6dc9357SAndroid Build Coastguard Worker       {
335*f6dc9357SAndroid Build Coastguard Worker         // if (p->decoder.dicPos != 0)
336*f6dc9357SAndroid Build Coastguard Worker         if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
337*f6dc9357SAndroid Build Coastguard Worker           return LZMA2_PARSE_STATUS_NEW_BLOCK;
338*f6dc9357SAndroid Build Coastguard Worker         // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
339*f6dc9357SAndroid Build Coastguard Worker       }
340*f6dc9357SAndroid Build Coastguard Worker 
341*f6dc9357SAndroid Build Coastguard Worker       // The following code can be commented.
342*f6dc9357SAndroid Build Coastguard Worker       // It's not big problem, if we read additional input bytes.
343*f6dc9357SAndroid Build Coastguard Worker       // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
344*f6dc9357SAndroid Build Coastguard Worker 
345*f6dc9357SAndroid Build Coastguard Worker       if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
346*f6dc9357SAndroid Build Coastguard Worker       {
347*f6dc9357SAndroid Build Coastguard Worker         // checkFinishBlock is true. So we expect that block must be finished,
348*f6dc9357SAndroid Build Coastguard Worker         // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
349*f6dc9357SAndroid Build Coastguard Worker         // break;
350*f6dc9357SAndroid Build Coastguard Worker         return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
351*f6dc9357SAndroid Build Coastguard Worker       }
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker       if (p->state == LZMA2_STATE_DATA)
354*f6dc9357SAndroid Build Coastguard Worker         return LZMA2_PARSE_STATUS_NEW_CHUNK;
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker       continue;
357*f6dc9357SAndroid Build Coastguard Worker     }
358*f6dc9357SAndroid Build Coastguard Worker 
359*f6dc9357SAndroid Build Coastguard Worker     if (outSize == 0)
360*f6dc9357SAndroid Build Coastguard Worker       return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
361*f6dc9357SAndroid Build Coastguard Worker 
362*f6dc9357SAndroid Build Coastguard Worker     {
363*f6dc9357SAndroid Build Coastguard Worker       SizeT inCur = inSize - *srcLen;
364*f6dc9357SAndroid Build Coastguard Worker 
365*f6dc9357SAndroid Build Coastguard Worker       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
366*f6dc9357SAndroid Build Coastguard Worker       {
367*f6dc9357SAndroid Build Coastguard Worker         if (inCur == 0)
368*f6dc9357SAndroid Build Coastguard Worker           return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
369*f6dc9357SAndroid Build Coastguard Worker         if (inCur > p->unpackSize)
370*f6dc9357SAndroid Build Coastguard Worker           inCur = p->unpackSize;
371*f6dc9357SAndroid Build Coastguard Worker         if (inCur > outSize)
372*f6dc9357SAndroid Build Coastguard Worker           inCur = outSize;
373*f6dc9357SAndroid Build Coastguard Worker         p->decoder.dicPos += inCur;
374*f6dc9357SAndroid Build Coastguard Worker         src += inCur;
375*f6dc9357SAndroid Build Coastguard Worker         *srcLen += inCur;
376*f6dc9357SAndroid Build Coastguard Worker         outSize -= inCur;
377*f6dc9357SAndroid Build Coastguard Worker         p->unpackSize -= (UInt32)inCur;
378*f6dc9357SAndroid Build Coastguard Worker         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
379*f6dc9357SAndroid Build Coastguard Worker       }
380*f6dc9357SAndroid Build Coastguard Worker       else
381*f6dc9357SAndroid Build Coastguard Worker       {
382*f6dc9357SAndroid Build Coastguard Worker         p->isExtraMode = True;
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker         if (inCur == 0)
385*f6dc9357SAndroid Build Coastguard Worker         {
386*f6dc9357SAndroid Build Coastguard Worker           if (p->packSize != 0)
387*f6dc9357SAndroid Build Coastguard Worker             return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
388*f6dc9357SAndroid Build Coastguard Worker         }
389*f6dc9357SAndroid Build Coastguard Worker         else if (p->state == LZMA2_STATE_DATA)
390*f6dc9357SAndroid Build Coastguard Worker         {
391*f6dc9357SAndroid Build Coastguard Worker           p->state = LZMA2_STATE_DATA_CONT;
392*f6dc9357SAndroid Build Coastguard Worker           if (*src != 0)
393*f6dc9357SAndroid Build Coastguard Worker           {
394*f6dc9357SAndroid Build Coastguard Worker             // first byte of lzma chunk must be Zero
395*f6dc9357SAndroid Build Coastguard Worker             *srcLen += 1;
396*f6dc9357SAndroid Build Coastguard Worker             p->packSize--;
397*f6dc9357SAndroid Build Coastguard Worker             break;
398*f6dc9357SAndroid Build Coastguard Worker           }
399*f6dc9357SAndroid Build Coastguard Worker         }
400*f6dc9357SAndroid Build Coastguard Worker 
401*f6dc9357SAndroid Build Coastguard Worker         if (inCur > p->packSize)
402*f6dc9357SAndroid Build Coastguard Worker           inCur = (SizeT)p->packSize;
403*f6dc9357SAndroid Build Coastguard Worker 
404*f6dc9357SAndroid Build Coastguard Worker         src += inCur;
405*f6dc9357SAndroid Build Coastguard Worker         *srcLen += inCur;
406*f6dc9357SAndroid Build Coastguard Worker         p->packSize -= (UInt32)inCur;
407*f6dc9357SAndroid Build Coastguard Worker 
408*f6dc9357SAndroid Build Coastguard Worker         if (p->packSize == 0)
409*f6dc9357SAndroid Build Coastguard Worker         {
410*f6dc9357SAndroid Build Coastguard Worker           SizeT rem = outSize;
411*f6dc9357SAndroid Build Coastguard Worker           if (rem > p->unpackSize)
412*f6dc9357SAndroid Build Coastguard Worker             rem = p->unpackSize;
413*f6dc9357SAndroid Build Coastguard Worker           p->decoder.dicPos += rem;
414*f6dc9357SAndroid Build Coastguard Worker           p->unpackSize -= (UInt32)rem;
415*f6dc9357SAndroid Build Coastguard Worker           outSize -= rem;
416*f6dc9357SAndroid Build Coastguard Worker           if (p->unpackSize == 0)
417*f6dc9357SAndroid Build Coastguard Worker             p->state = LZMA2_STATE_CONTROL;
418*f6dc9357SAndroid Build Coastguard Worker         }
419*f6dc9357SAndroid Build Coastguard Worker       }
420*f6dc9357SAndroid Build Coastguard Worker     }
421*f6dc9357SAndroid Build Coastguard Worker   }
422*f6dc9357SAndroid Build Coastguard Worker 
423*f6dc9357SAndroid Build Coastguard Worker   p->state = LZMA2_STATE_ERROR;
424*f6dc9357SAndroid Build Coastguard Worker   return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
425*f6dc9357SAndroid Build Coastguard Worker }
426*f6dc9357SAndroid Build Coastguard Worker 
427*f6dc9357SAndroid Build Coastguard Worker 
428*f6dc9357SAndroid Build Coastguard Worker 
429*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Dec_DecodeToBuf(CLzma2Dec * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)430*f6dc9357SAndroid Build Coastguard Worker SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
431*f6dc9357SAndroid Build Coastguard Worker {
432*f6dc9357SAndroid Build Coastguard Worker   SizeT outSize = *destLen, inSize = *srcLen;
433*f6dc9357SAndroid Build Coastguard Worker   *srcLen = *destLen = 0;
434*f6dc9357SAndroid Build Coastguard Worker 
435*f6dc9357SAndroid Build Coastguard Worker   for (;;)
436*f6dc9357SAndroid Build Coastguard Worker   {
437*f6dc9357SAndroid Build Coastguard Worker     SizeT inCur = inSize, outCur, dicPos;
438*f6dc9357SAndroid Build Coastguard Worker     ELzmaFinishMode curFinishMode;
439*f6dc9357SAndroid Build Coastguard Worker     SRes res;
440*f6dc9357SAndroid Build Coastguard Worker 
441*f6dc9357SAndroid Build Coastguard Worker     if (p->decoder.dicPos == p->decoder.dicBufSize)
442*f6dc9357SAndroid Build Coastguard Worker       p->decoder.dicPos = 0;
443*f6dc9357SAndroid Build Coastguard Worker     dicPos = p->decoder.dicPos;
444*f6dc9357SAndroid Build Coastguard Worker     curFinishMode = LZMA_FINISH_ANY;
445*f6dc9357SAndroid Build Coastguard Worker     outCur = p->decoder.dicBufSize - dicPos;
446*f6dc9357SAndroid Build Coastguard Worker 
447*f6dc9357SAndroid Build Coastguard Worker     if (outCur >= outSize)
448*f6dc9357SAndroid Build Coastguard Worker     {
449*f6dc9357SAndroid Build Coastguard Worker       outCur = outSize;
450*f6dc9357SAndroid Build Coastguard Worker       curFinishMode = finishMode;
451*f6dc9357SAndroid Build Coastguard Worker     }
452*f6dc9357SAndroid Build Coastguard Worker 
453*f6dc9357SAndroid Build Coastguard Worker     res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
454*f6dc9357SAndroid Build Coastguard Worker 
455*f6dc9357SAndroid Build Coastguard Worker     src += inCur;
456*f6dc9357SAndroid Build Coastguard Worker     inSize -= inCur;
457*f6dc9357SAndroid Build Coastguard Worker     *srcLen += inCur;
458*f6dc9357SAndroid Build Coastguard Worker     outCur = p->decoder.dicPos - dicPos;
459*f6dc9357SAndroid Build Coastguard Worker     memcpy(dest, p->decoder.dic + dicPos, outCur);
460*f6dc9357SAndroid Build Coastguard Worker     dest += outCur;
461*f6dc9357SAndroid Build Coastguard Worker     outSize -= outCur;
462*f6dc9357SAndroid Build Coastguard Worker     *destLen += outCur;
463*f6dc9357SAndroid Build Coastguard Worker     if (res != 0)
464*f6dc9357SAndroid Build Coastguard Worker       return res;
465*f6dc9357SAndroid Build Coastguard Worker     if (outCur == 0 || outSize == 0)
466*f6dc9357SAndroid Build Coastguard Worker       return SZ_OK;
467*f6dc9357SAndroid Build Coastguard Worker   }
468*f6dc9357SAndroid Build Coastguard Worker }
469*f6dc9357SAndroid Build Coastguard Worker 
470*f6dc9357SAndroid Build Coastguard Worker 
Lzma2Decode(Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,Byte prop,ELzmaFinishMode finishMode,ELzmaStatus * status,ISzAllocPtr alloc)471*f6dc9357SAndroid Build Coastguard Worker SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
472*f6dc9357SAndroid Build Coastguard Worker     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
473*f6dc9357SAndroid Build Coastguard Worker {
474*f6dc9357SAndroid Build Coastguard Worker   CLzma2Dec p;
475*f6dc9357SAndroid Build Coastguard Worker   SRes res;
476*f6dc9357SAndroid Build Coastguard Worker   SizeT outSize = *destLen, inSize = *srcLen;
477*f6dc9357SAndroid Build Coastguard Worker   *destLen = *srcLen = 0;
478*f6dc9357SAndroid Build Coastguard Worker   *status = LZMA_STATUS_NOT_SPECIFIED;
479*f6dc9357SAndroid Build Coastguard Worker   Lzma2Dec_CONSTRUCT(&p)
480*f6dc9357SAndroid Build Coastguard Worker   RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc))
481*f6dc9357SAndroid Build Coastguard Worker   p.decoder.dic = dest;
482*f6dc9357SAndroid Build Coastguard Worker   p.decoder.dicBufSize = outSize;
483*f6dc9357SAndroid Build Coastguard Worker   Lzma2Dec_Init(&p);
484*f6dc9357SAndroid Build Coastguard Worker   *srcLen = inSize;
485*f6dc9357SAndroid Build Coastguard Worker   res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
486*f6dc9357SAndroid Build Coastguard Worker   *destLen = p.decoder.dicPos;
487*f6dc9357SAndroid Build Coastguard Worker   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
488*f6dc9357SAndroid Build Coastguard Worker     res = SZ_ERROR_INPUT_EOF;
489*f6dc9357SAndroid Build Coastguard Worker   Lzma2Dec_FreeProbs(&p, alloc);
490*f6dc9357SAndroid Build Coastguard Worker   return res;
491*f6dc9357SAndroid Build Coastguard Worker }
492*f6dc9357SAndroid Build Coastguard Worker 
493*f6dc9357SAndroid Build Coastguard Worker #undef PRF
494