add CHD support.
[pcsx_rearmed.git] / deps / lzma-16.04 / C / Lzma2Dec.c
1 /* Lzma2Dec.c -- LZMA2 Decoder\r
2 2015-11-09 : Igor Pavlov : Public domain */\r
3 \r
4 /* #define SHOW_DEBUG_INFO */\r
5 \r
6 #include "Precomp.h"\r
7 \r
8 #ifdef SHOW_DEBUG_INFO\r
9 #include <stdio.h>\r
10 #endif\r
11 \r
12 #include <string.h>\r
13 \r
14 #include "Lzma2Dec.h"\r
15 \r
16 /*\r
17 00000000  -  EOS\r
18 00000001 U U  -  Uncompressed Reset Dic\r
19 00000010 U U  -  Uncompressed No Reset\r
20 100uuuuu U U P P  -  LZMA no reset\r
21 101uuuuu U U P P  -  LZMA reset state\r
22 110uuuuu U U P P S  -  LZMA reset state + new prop\r
23 111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic\r
24 \r
25   u, U - Unpack Size\r
26   P - Pack Size\r
27   S - Props\r
28 */\r
29 \r
30 #define LZMA2_CONTROL_LZMA (1 << 7)\r
31 #define LZMA2_CONTROL_COPY_NO_RESET 2\r
32 #define LZMA2_CONTROL_COPY_RESET_DIC 1\r
33 #define LZMA2_CONTROL_EOF 0\r
34 \r
35 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)\r
36 \r
37 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)\r
38 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)\r
39 \r
40 #define LZMA2_LCLP_MAX 4\r
41 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\r
42 \r
43 #ifdef SHOW_DEBUG_INFO\r
44 #define PRF(x) x\r
45 #else\r
46 #define PRF(x)\r
47 #endif\r
48 \r
49 typedef enum\r
50 {\r
51   LZMA2_STATE_CONTROL,\r
52   LZMA2_STATE_UNPACK0,\r
53   LZMA2_STATE_UNPACK1,\r
54   LZMA2_STATE_PACK0,\r
55   LZMA2_STATE_PACK1,\r
56   LZMA2_STATE_PROP,\r
57   LZMA2_STATE_DATA,\r
58   LZMA2_STATE_DATA_CONT,\r
59   LZMA2_STATE_FINISHED,\r
60   LZMA2_STATE_ERROR\r
61 } ELzma2State;\r
62 \r
63 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)\r
64 {\r
65   UInt32 dicSize;\r
66   if (prop > 40)\r
67     return SZ_ERROR_UNSUPPORTED;\r
68   dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);\r
69   props[0] = (Byte)LZMA2_LCLP_MAX;\r
70   props[1] = (Byte)(dicSize);\r
71   props[2] = (Byte)(dicSize >> 8);\r
72   props[3] = (Byte)(dicSize >> 16);\r
73   props[4] = (Byte)(dicSize >> 24);\r
74   return SZ_OK;\r
75 }\r
76 \r
77 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
78 {\r
79   Byte props[LZMA_PROPS_SIZE];\r
80   RINOK(Lzma2Dec_GetOldProps(prop, props));\r
81   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\r
82 }\r
83 \r
84 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
85 {\r
86   Byte props[LZMA_PROPS_SIZE];\r
87   RINOK(Lzma2Dec_GetOldProps(prop, props));\r
88   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);\r
89 }\r
90 \r
91 void Lzma2Dec_Init(CLzma2Dec *p)\r
92 {\r
93   p->state = LZMA2_STATE_CONTROL;\r
94   p->needInitDic = True;\r
95   p->needInitState = True;\r
96   p->needInitProp = True;\r
97   LzmaDec_Init(&p->decoder);\r
98 }\r
99 \r
100 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)\r
101 {\r
102   switch (p->state)\r
103   {\r
104     case LZMA2_STATE_CONTROL:\r
105       p->control = b;\r
106       PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));\r
107       PRF(printf(" %2X", (unsigned)b));\r
108       if (p->control == 0)\r
109         return LZMA2_STATE_FINISHED;\r
110       if (LZMA2_IS_UNCOMPRESSED_STATE(p))\r
111       {\r
112         if ((p->control & 0x7F) > 2)\r
113           return LZMA2_STATE_ERROR;\r
114         p->unpackSize = 0;\r
115       }\r
116       else\r
117         p->unpackSize = (UInt32)(p->control & 0x1F) << 16;\r
118       return LZMA2_STATE_UNPACK0;\r
119     \r
120     case LZMA2_STATE_UNPACK0:\r
121       p->unpackSize |= (UInt32)b << 8;\r
122       return LZMA2_STATE_UNPACK1;\r
123     \r
124     case LZMA2_STATE_UNPACK1:\r
125       p->unpackSize |= (UInt32)b;\r
126       p->unpackSize++;\r
127       PRF(printf(" %8u", (unsigned)p->unpackSize));\r
128       return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;\r
129     \r
130     case LZMA2_STATE_PACK0:\r
131       p->packSize = (UInt32)b << 8;\r
132       return LZMA2_STATE_PACK1;\r
133 \r
134     case LZMA2_STATE_PACK1:\r
135       p->packSize |= (UInt32)b;\r
136       p->packSize++;\r
137       PRF(printf(" %8u", (unsigned)p->packSize));\r
138       return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:\r
139         (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);\r
140 \r
141     case LZMA2_STATE_PROP:\r
142     {\r
143       unsigned lc, lp;\r
144       if (b >= (9 * 5 * 5))\r
145         return LZMA2_STATE_ERROR;\r
146       lc = b % 9;\r
147       b /= 9;\r
148       p->decoder.prop.pb = b / 5;\r
149       lp = b % 5;\r
150       if (lc + lp > LZMA2_LCLP_MAX)\r
151         return LZMA2_STATE_ERROR;\r
152       p->decoder.prop.lc = lc;\r
153       p->decoder.prop.lp = lp;\r
154       p->needInitProp = False;\r
155       return LZMA2_STATE_DATA;\r
156     }\r
157   }\r
158   return LZMA2_STATE_ERROR;\r
159 }\r
160 \r
161 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)\r
162 {\r
163   memcpy(p->dic + p->dicPos, src, size);\r
164   p->dicPos += size;\r
165   if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)\r
166     p->checkDicSize = p->prop.dicSize;\r
167   p->processedPos += (UInt32)size;\r
168 }\r
169 \r
170 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);\r
171 \r
172 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\r
173     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
174 {\r
175   SizeT inSize = *srcLen;\r
176   *srcLen = 0;\r
177   *status = LZMA_STATUS_NOT_SPECIFIED;\r
178 \r
179   while (p->state != LZMA2_STATE_FINISHED)\r
180   {\r
181     SizeT dicPos = p->decoder.dicPos;\r
182     \r
183     if (p->state == LZMA2_STATE_ERROR)\r
184       return SZ_ERROR_DATA;\r
185     \r
186     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)\r
187     {\r
188       *status = LZMA_STATUS_NOT_FINISHED;\r
189       return SZ_OK;\r
190     }\r
191 \r
192     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)\r
193     {\r
194       if (*srcLen == inSize)\r
195       {\r
196         *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
197         return SZ_OK;\r
198       }\r
199       (*srcLen)++;\r
200       p->state = Lzma2Dec_UpdateState(p, *src++);\r
201 \r
202       if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)\r
203       {\r
204         p->state = LZMA2_STATE_ERROR;\r
205         return SZ_ERROR_DATA;\r
206       }\r
207       continue;\r
208     }\r
209     \r
210     {\r
211       SizeT destSizeCur = dicLimit - dicPos;\r
212       SizeT srcSizeCur = inSize - *srcLen;\r
213       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;\r
214       \r
215       if (p->unpackSize <= destSizeCur)\r
216       {\r
217         destSizeCur = (SizeT)p->unpackSize;\r
218         curFinishMode = LZMA_FINISH_END;\r
219       }\r
220 \r
221       if (LZMA2_IS_UNCOMPRESSED_STATE(p))\r
222       {\r
223         if (*srcLen == inSize)\r
224         {\r
225           *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
226           return SZ_OK;\r
227         }\r
228 \r
229         if (p->state == LZMA2_STATE_DATA)\r
230         {\r
231           Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);\r
232           if (initDic)\r
233             p->needInitProp = p->needInitState = True;\r
234           else if (p->needInitDic)\r
235           {\r
236             p->state = LZMA2_STATE_ERROR;\r
237             return SZ_ERROR_DATA;\r
238           }\r
239           p->needInitDic = False;\r
240           LzmaDec_InitDicAndState(&p->decoder, initDic, False);\r
241         }\r
242 \r
243         if (srcSizeCur > destSizeCur)\r
244           srcSizeCur = destSizeCur;\r
245 \r
246         if (srcSizeCur == 0)\r
247         {\r
248           p->state = LZMA2_STATE_ERROR;\r
249           return SZ_ERROR_DATA;\r
250         }\r
251 \r
252         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);\r
253 \r
254         src += srcSizeCur;\r
255         *srcLen += srcSizeCur;\r
256         p->unpackSize -= (UInt32)srcSizeCur;\r
257         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;\r
258       }\r
259       else\r
260       {\r
261         SizeT outSizeProcessed;\r
262         SRes res;\r
263 \r
264         if (p->state == LZMA2_STATE_DATA)\r
265         {\r
266           unsigned mode = LZMA2_GET_LZMA_MODE(p);\r
267           Bool initDic = (mode == 3);\r
268           Bool initState = (mode != 0);\r
269           if ((!initDic && p->needInitDic) || (!initState && p->needInitState))\r
270           {\r
271             p->state = LZMA2_STATE_ERROR;\r
272             return SZ_ERROR_DATA;\r
273           }\r
274           \r
275           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);\r
276           p->needInitDic = False;\r
277           p->needInitState = False;\r
278           p->state = LZMA2_STATE_DATA_CONT;\r
279         }\r
280   \r
281         if (srcSizeCur > p->packSize)\r
282           srcSizeCur = (SizeT)p->packSize;\r
283           \r
284         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);\r
285         \r
286         src += srcSizeCur;\r
287         *srcLen += srcSizeCur;\r
288         p->packSize -= (UInt32)srcSizeCur;\r
289 \r
290         outSizeProcessed = p->decoder.dicPos - dicPos;\r
291         p->unpackSize -= (UInt32)outSizeProcessed;\r
292 \r
293         RINOK(res);\r
294         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
295           return res;\r
296 \r
297         if (srcSizeCur == 0 && outSizeProcessed == 0)\r
298         {\r
299           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK\r
300               || p->unpackSize != 0\r
301               || p->packSize != 0)\r
302           {\r
303             p->state = LZMA2_STATE_ERROR;\r
304             return SZ_ERROR_DATA;\r
305           }\r
306           p->state = LZMA2_STATE_CONTROL;\r
307         }\r
308         \r
309         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\r
310           *status = LZMA_STATUS_NOT_FINISHED;\r
311       }\r
312     }\r
313   }\r
314   \r
315   *status = LZMA_STATUS_FINISHED_WITH_MARK;\r
316   return SZ_OK;\r
317 }\r
318 \r
319 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
320 {\r
321   SizeT outSize = *destLen, inSize = *srcLen;\r
322   *srcLen = *destLen = 0;\r
323   for (;;)\r
324   {\r
325     SizeT srcSizeCur = inSize, outSizeCur, dicPos;\r
326     ELzmaFinishMode curFinishMode;\r
327     SRes res;\r
328     if (p->decoder.dicPos == p->decoder.dicBufSize)\r
329       p->decoder.dicPos = 0;\r
330     dicPos = p->decoder.dicPos;\r
331     if (outSize > p->decoder.dicBufSize - dicPos)\r
332     {\r
333       outSizeCur = p->decoder.dicBufSize;\r
334       curFinishMode = LZMA_FINISH_ANY;\r
335     }\r
336     else\r
337     {\r
338       outSizeCur = dicPos + outSize;\r
339       curFinishMode = finishMode;\r
340     }\r
341 \r
342     res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);\r
343     src += srcSizeCur;\r
344     inSize -= srcSizeCur;\r
345     *srcLen += srcSizeCur;\r
346     outSizeCur = p->decoder.dicPos - dicPos;\r
347     memcpy(dest, p->decoder.dic + dicPos, outSizeCur);\r
348     dest += outSizeCur;\r
349     outSize -= outSizeCur;\r
350     *destLen += outSizeCur;\r
351     if (res != 0)\r
352       return res;\r
353     if (outSizeCur == 0 || outSize == 0)\r
354       return SZ_OK;\r
355   }\r
356 }\r
357 \r
358 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
359     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)\r
360 {\r
361   CLzma2Dec p;\r
362   SRes res;\r
363   SizeT outSize = *destLen, inSize = *srcLen;\r
364   *destLen = *srcLen = 0;\r
365   *status = LZMA_STATUS_NOT_SPECIFIED;\r
366   Lzma2Dec_Construct(&p);\r
367   RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));\r
368   p.decoder.dic = dest;\r
369   p.decoder.dicBufSize = outSize;\r
370   Lzma2Dec_Init(&p);\r
371   *srcLen = inSize;\r
372   res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\r
373   *destLen = p.decoder.dicPos;\r
374   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
375     res = SZ_ERROR_INPUT_EOF;\r
376   Lzma2Dec_FreeProbs(&p, alloc);\r
377   return res;\r
378 }\r