Merge pull request #511 from negativeExponent/updates
[pcsx_rearmed.git] / deps / lzma-16.04 / C / Lzma2Dec.c
CommitLineData
ce188d4d 1/* Lzma2Dec.c -- LZMA2 Decoder\r
22015-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
1700000000 - EOS\r
1800000001 U U - Uncompressed Reset Dic\r
1900000010 U U - Uncompressed No Reset\r
20100uuuuu U U P P - LZMA no reset\r
21101uuuuu U U P P - LZMA reset state\r
22110uuuuu U U P P S - LZMA reset state + new prop\r
23111uuuuu 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
49typedef 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
63static 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
77SRes 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
84SRes 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
91void 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
100static 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
161static 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
170void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);\r
171\r
172SRes 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
319SRes 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
358SRes 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