update libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / lzma-22.01 / src / LzmaDec.c
CommitLineData
9e052883 1/* LzmaDec.c -- LZMA Decoder\r
22021-04-01 : Igor Pavlov : Public domain */\r
3\r
4#include "Precomp.h"\r
5\r
6#include <string.h>\r
7\r
8/* #include "CpuArch.h" */\r
9#include "LzmaDec.h"\r
10\r
11#define kNumTopBits 24\r
12#define kTopValue ((UInt32)1 << kNumTopBits)\r
13\r
14#define kNumBitModelTotalBits 11\r
15#define kBitModelTotal (1 << kNumBitModelTotalBits)\r
16\r
17#define RC_INIT_SIZE 5\r
18\r
19#ifndef _LZMA_DEC_OPT\r
20\r
21#define kNumMoveBits 5\r
22#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }\r
23\r
24#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)\r
25#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));\r
26#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));\r
27#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \\r
28 { UPDATE_0(p); i = (i + i); A0; } else \\r
29 { UPDATE_1(p); i = (i + i) + 1; A1; }\r
30\r
31#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); }\r
32\r
33#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \\r
34 { UPDATE_0(p + i); A0; } else \\r
35 { UPDATE_1(p + i); A1; }\r
36#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; )\r
37#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; )\r
38#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; )\r
39\r
40#define TREE_DECODE(probs, limit, i) \\r
41 { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }\r
42\r
43/* #define _LZMA_SIZE_OPT */\r
44\r
45#ifdef _LZMA_SIZE_OPT\r
46#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)\r
47#else\r
48#define TREE_6_DECODE(probs, i) \\r
49 { i = 1; \\r
50 TREE_GET_BIT(probs, i); \\r
51 TREE_GET_BIT(probs, i); \\r
52 TREE_GET_BIT(probs, i); \\r
53 TREE_GET_BIT(probs, i); \\r
54 TREE_GET_BIT(probs, i); \\r
55 TREE_GET_BIT(probs, i); \\r
56 i -= 0x40; }\r
57#endif\r
58\r
59#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol)\r
60#define MATCHED_LITER_DEC \\r
61 matchByte += matchByte; \\r
62 bit = offs; \\r
63 offs &= matchByte; \\r
64 probLit = prob + (offs + bit + symbol); \\r
65 GET_BIT2(probLit, symbol, offs ^= bit; , ;)\r
66\r
67#endif // _LZMA_DEC_OPT\r
68\r
69\r
70#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); }\r
71\r
72#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)\r
73#define UPDATE_0_CHECK range = bound;\r
74#define UPDATE_1_CHECK range -= bound; code -= bound;\r
75#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \\r
76 { UPDATE_0_CHECK; i = (i + i); A0; } else \\r
77 { UPDATE_1_CHECK; i = (i + i) + 1; A1; }\r
78#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)\r
79#define TREE_DECODE_CHECK(probs, limit, i) \\r
80 { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }\r
81\r
82\r
83#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \\r
84 { UPDATE_0_CHECK; i += m; m += m; } else \\r
85 { UPDATE_1_CHECK; m += m; i += m; }\r
86\r
87\r
88#define kNumPosBitsMax 4\r
89#define kNumPosStatesMax (1 << kNumPosBitsMax)\r
90\r
91#define kLenNumLowBits 3\r
92#define kLenNumLowSymbols (1 << kLenNumLowBits)\r
93#define kLenNumHighBits 8\r
94#define kLenNumHighSymbols (1 << kLenNumHighBits)\r
95\r
96#define LenLow 0\r
97#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits))\r
98#define kNumLenProbs (LenHigh + kLenNumHighSymbols)\r
99\r
100#define LenChoice LenLow\r
101#define LenChoice2 (LenLow + (1 << kLenNumLowBits))\r
102\r
103#define kNumStates 12\r
104#define kNumStates2 16\r
105#define kNumLitStates 7\r
106\r
107#define kStartPosModelIndex 4\r
108#define kEndPosModelIndex 14\r
109#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))\r
110\r
111#define kNumPosSlotBits 6\r
112#define kNumLenToPosStates 4\r
113\r
114#define kNumAlignBits 4\r
115#define kAlignTableSize (1 << kNumAlignBits)\r
116\r
117#define kMatchMinLen 2\r
118#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols)\r
119\r
120#define kMatchSpecLen_Error_Data (1 << 9)\r
121#define kMatchSpecLen_Error_Fail (kMatchSpecLen_Error_Data - 1)\r
122\r
123/* External ASM code needs same CLzmaProb array layout. So don't change it. */\r
124\r
125/* (probs_1664) is faster and better for code size at some platforms */\r
126/*\r
127#ifdef MY_CPU_X86_OR_AMD64\r
128*/\r
129#define kStartOffset 1664\r
130#define GET_PROBS p->probs_1664\r
131/*\r
132#define GET_PROBS p->probs + kStartOffset\r
133#else\r
134#define kStartOffset 0\r
135#define GET_PROBS p->probs\r
136#endif\r
137*/\r
138\r
139#define SpecPos (-kStartOffset)\r
140#define IsRep0Long (SpecPos + kNumFullDistances)\r
141#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax))\r
142#define LenCoder (RepLenCoder + kNumLenProbs)\r
143#define IsMatch (LenCoder + kNumLenProbs)\r
144#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax))\r
145#define IsRep (Align + kAlignTableSize)\r
146#define IsRepG0 (IsRep + kNumStates)\r
147#define IsRepG1 (IsRepG0 + kNumStates)\r
148#define IsRepG2 (IsRepG1 + kNumStates)\r
149#define PosSlot (IsRepG2 + kNumStates)\r
150#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))\r
151#define NUM_BASE_PROBS (Literal + kStartOffset)\r
152\r
153#if Align != 0 && kStartOffset != 0\r
154 #error Stop_Compiling_Bad_LZMA_kAlign\r
155#endif\r
156\r
157#if NUM_BASE_PROBS != 1984\r
158 #error Stop_Compiling_Bad_LZMA_PROBS\r
159#endif\r
160\r
161\r
162#define LZMA_LIT_SIZE 0x300\r
163\r
164#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))\r
165\r
166\r
167#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4)\r
168#define COMBINED_PS_STATE (posState + state)\r
169#define GET_LEN_STATE (posState)\r
170\r
171#define LZMA_DIC_MIN (1 << 12)\r
172\r
173/*\r
174p->remainLen : shows status of LZMA decoder:\r
175 < kMatchSpecLenStart : the number of bytes to be copied with (p->rep0) offset\r
176 = kMatchSpecLenStart : the LZMA stream was finished with end mark\r
177 = kMatchSpecLenStart + 1 : need init range coder\r
178 = kMatchSpecLenStart + 2 : need init range coder and state\r
179 = kMatchSpecLen_Error_Fail : Internal Code Failure\r
180 = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error\r
181*/\r
182\r
183/* ---------- LZMA_DECODE_REAL ---------- */\r
184/*\r
185LzmaDec_DecodeReal_3() can be implemented in external ASM file.\r
1863 - is the code compatibility version of that function for check at link time.\r
187*/\r
188\r
189#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3\r
190\r
191/*\r
192LZMA_DECODE_REAL()\r
193In:\r
194 RangeCoder is normalized\r
195 if (p->dicPos == limit)\r
196 {\r
197 LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.\r
198 So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol\r
199 is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary,\r
200 the function returns SZ_OK, and the caller can use (p->remainLen) and (p->reps[0]) later.\r
201 }\r
202\r
203Processing:\r
204 The first LZMA symbol will be decoded in any case.\r
205 All main checks for limits are at the end of main loop,\r
206 It decodes additional LZMA-symbols while (p->buf < bufLimit && dicPos < limit),\r
207 RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked.\r
208 But if (p->buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for\r
209 next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX),\r
210 that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit.\r
211 So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte.\r
212\r
213Out:\r
214 RangeCoder is normalized\r
215 Result:\r
216 SZ_OK - OK\r
217 p->remainLen:\r
218 < kMatchSpecLenStart : the number of bytes to be copied with (p->reps[0]) offset\r
219 = kMatchSpecLenStart : the LZMA stream was finished with end mark\r
220\r
221 SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary\r
222 p->remainLen : undefined\r
223 p->reps[*] : undefined\r
224*/\r
225\r
226\r
227#ifdef _LZMA_DEC_OPT\r
228\r
229int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit);\r
230\r
231#else\r
232\r
233static\r
234int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r
235{\r
236 CLzmaProb *probs = GET_PROBS;\r
237 unsigned state = (unsigned)p->state;\r
238 UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];\r
239 unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;\r
240 unsigned lc = p->prop.lc;\r
241 unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc);\r
242\r
243 Byte *dic = p->dic;\r
244 SizeT dicBufSize = p->dicBufSize;\r
245 SizeT dicPos = p->dicPos;\r
246 \r
247 UInt32 processedPos = p->processedPos;\r
248 UInt32 checkDicSize = p->checkDicSize;\r
249 unsigned len = 0;\r
250\r
251 const Byte *buf = p->buf;\r
252 UInt32 range = p->range;\r
253 UInt32 code = p->code;\r
254\r
255 do\r
256 {\r
257 CLzmaProb *prob;\r
258 UInt32 bound;\r
259 unsigned ttt;\r
260 unsigned posState = CALC_POS_STATE(processedPos, pbMask);\r
261\r
262 prob = probs + IsMatch + COMBINED_PS_STATE;\r
263 IF_BIT_0(prob)\r
264 {\r
265 unsigned symbol;\r
266 UPDATE_0(prob);\r
267 prob = probs + Literal;\r
268 if (processedPos != 0 || checkDicSize != 0)\r
269 prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);\r
270 processedPos++;\r
271\r
272 if (state < kNumLitStates)\r
273 {\r
274 state -= (state < 4) ? state : 3;\r
275 symbol = 1;\r
276 #ifdef _LZMA_SIZE_OPT\r
277 do { NORMAL_LITER_DEC } while (symbol < 0x100);\r
278 #else\r
279 NORMAL_LITER_DEC\r
280 NORMAL_LITER_DEC\r
281 NORMAL_LITER_DEC\r
282 NORMAL_LITER_DEC\r
283 NORMAL_LITER_DEC\r
284 NORMAL_LITER_DEC\r
285 NORMAL_LITER_DEC\r
286 NORMAL_LITER_DEC\r
287 #endif\r
288 }\r
289 else\r
290 {\r
291 unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r
292 unsigned offs = 0x100;\r
293 state -= (state < 10) ? 3 : 6;\r
294 symbol = 1;\r
295 #ifdef _LZMA_SIZE_OPT\r
296 do\r
297 {\r
298 unsigned bit;\r
299 CLzmaProb *probLit;\r
300 MATCHED_LITER_DEC\r
301 }\r
302 while (symbol < 0x100);\r
303 #else\r
304 {\r
305 unsigned bit;\r
306 CLzmaProb *probLit;\r
307 MATCHED_LITER_DEC\r
308 MATCHED_LITER_DEC\r
309 MATCHED_LITER_DEC\r
310 MATCHED_LITER_DEC\r
311 MATCHED_LITER_DEC\r
312 MATCHED_LITER_DEC\r
313 MATCHED_LITER_DEC\r
314 MATCHED_LITER_DEC\r
315 }\r
316 #endif\r
317 }\r
318\r
319 dic[dicPos++] = (Byte)symbol;\r
320 continue;\r
321 }\r
322 \r
323 {\r
324 UPDATE_1(prob);\r
325 prob = probs + IsRep + state;\r
326 IF_BIT_0(prob)\r
327 {\r
328 UPDATE_0(prob);\r
329 state += kNumStates;\r
330 prob = probs + LenCoder;\r
331 }\r
332 else\r
333 {\r
334 UPDATE_1(prob);\r
335 prob = probs + IsRepG0 + state;\r
336 IF_BIT_0(prob)\r
337 {\r
338 UPDATE_0(prob);\r
339 prob = probs + IsRep0Long + COMBINED_PS_STATE;\r
340 IF_BIT_0(prob)\r
341 {\r
342 UPDATE_0(prob);\r
343 \r
344 // that case was checked before with kBadRepCode\r
345 // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; }\r
346 // The caller doesn't allow (dicPos == limit) case here\r
347 // so we don't need the following check:\r
348 // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; }\r
349 \r
350 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r
351 dicPos++;\r
352 processedPos++;\r
353 state = state < kNumLitStates ? 9 : 11;\r
354 continue;\r
355 }\r
356 UPDATE_1(prob);\r
357 }\r
358 else\r
359 {\r
360 UInt32 distance;\r
361 UPDATE_1(prob);\r
362 prob = probs + IsRepG1 + state;\r
363 IF_BIT_0(prob)\r
364 {\r
365 UPDATE_0(prob);\r
366 distance = rep1;\r
367 }\r
368 else\r
369 {\r
370 UPDATE_1(prob);\r
371 prob = probs + IsRepG2 + state;\r
372 IF_BIT_0(prob)\r
373 {\r
374 UPDATE_0(prob);\r
375 distance = rep2;\r
376 }\r
377 else\r
378 {\r
379 UPDATE_1(prob);\r
380 distance = rep3;\r
381 rep3 = rep2;\r
382 }\r
383 rep2 = rep1;\r
384 }\r
385 rep1 = rep0;\r
386 rep0 = distance;\r
387 }\r
388 state = state < kNumLitStates ? 8 : 11;\r
389 prob = probs + RepLenCoder;\r
390 }\r
391 \r
392 #ifdef _LZMA_SIZE_OPT\r
393 {\r
394 unsigned lim, offset;\r
395 CLzmaProb *probLen = prob + LenChoice;\r
396 IF_BIT_0(probLen)\r
397 {\r
398 UPDATE_0(probLen);\r
399 probLen = prob + LenLow + GET_LEN_STATE;\r
400 offset = 0;\r
401 lim = (1 << kLenNumLowBits);\r
402 }\r
403 else\r
404 {\r
405 UPDATE_1(probLen);\r
406 probLen = prob + LenChoice2;\r
407 IF_BIT_0(probLen)\r
408 {\r
409 UPDATE_0(probLen);\r
410 probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\r
411 offset = kLenNumLowSymbols;\r
412 lim = (1 << kLenNumLowBits);\r
413 }\r
414 else\r
415 {\r
416 UPDATE_1(probLen);\r
417 probLen = prob + LenHigh;\r
418 offset = kLenNumLowSymbols * 2;\r
419 lim = (1 << kLenNumHighBits);\r
420 }\r
421 }\r
422 TREE_DECODE(probLen, lim, len);\r
423 len += offset;\r
424 }\r
425 #else\r
426 {\r
427 CLzmaProb *probLen = prob + LenChoice;\r
428 IF_BIT_0(probLen)\r
429 {\r
430 UPDATE_0(probLen);\r
431 probLen = prob + LenLow + GET_LEN_STATE;\r
432 len = 1;\r
433 TREE_GET_BIT(probLen, len);\r
434 TREE_GET_BIT(probLen, len);\r
435 TREE_GET_BIT(probLen, len);\r
436 len -= 8;\r
437 }\r
438 else\r
439 {\r
440 UPDATE_1(probLen);\r
441 probLen = prob + LenChoice2;\r
442 IF_BIT_0(probLen)\r
443 {\r
444 UPDATE_0(probLen);\r
445 probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\r
446 len = 1;\r
447 TREE_GET_BIT(probLen, len);\r
448 TREE_GET_BIT(probLen, len);\r
449 TREE_GET_BIT(probLen, len);\r
450 }\r
451 else\r
452 {\r
453 UPDATE_1(probLen);\r
454 probLen = prob + LenHigh;\r
455 TREE_DECODE(probLen, (1 << kLenNumHighBits), len);\r
456 len += kLenNumLowSymbols * 2;\r
457 }\r
458 }\r
459 }\r
460 #endif\r
461\r
462 if (state >= kNumStates)\r
463 {\r
464 UInt32 distance;\r
465 prob = probs + PosSlot +\r
466 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);\r
467 TREE_6_DECODE(prob, distance);\r
468 if (distance >= kStartPosModelIndex)\r
469 {\r
470 unsigned posSlot = (unsigned)distance;\r
471 unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));\r
472 distance = (2 | (distance & 1));\r
473 if (posSlot < kEndPosModelIndex)\r
474 {\r
475 distance <<= numDirectBits;\r
476 prob = probs + SpecPos;\r
477 {\r
478 UInt32 m = 1;\r
479 distance++;\r
480 do\r
481 {\r
482 REV_BIT_VAR(prob, distance, m);\r
483 }\r
484 while (--numDirectBits);\r
485 distance -= m;\r
486 }\r
487 }\r
488 else\r
489 {\r
490 numDirectBits -= kNumAlignBits;\r
491 do\r
492 {\r
493 NORMALIZE\r
494 range >>= 1;\r
495 \r
496 {\r
497 UInt32 t;\r
498 code -= range;\r
499 t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */\r
500 distance = (distance << 1) + (t + 1);\r
501 code += range & t;\r
502 }\r
503 /*\r
504 distance <<= 1;\r
505 if (code >= range)\r
506 {\r
507 code -= range;\r
508 distance |= 1;\r
509 }\r
510 */\r
511 }\r
512 while (--numDirectBits);\r
513 prob = probs + Align;\r
514 distance <<= kNumAlignBits;\r
515 {\r
516 unsigned i = 1;\r
517 REV_BIT_CONST(prob, i, 1);\r
518 REV_BIT_CONST(prob, i, 2);\r
519 REV_BIT_CONST(prob, i, 4);\r
520 REV_BIT_LAST (prob, i, 8);\r
521 distance |= i;\r
522 }\r
523 if (distance == (UInt32)0xFFFFFFFF)\r
524 {\r
525 len = kMatchSpecLenStart;\r
526 state -= kNumStates;\r
527 break;\r
528 }\r
529 }\r
530 }\r
531 \r
532 rep3 = rep2;\r
533 rep2 = rep1;\r
534 rep1 = rep0;\r
535 rep0 = distance + 1;\r
536 state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;\r
537 if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))\r
538 {\r
539 len += kMatchSpecLen_Error_Data + kMatchMinLen;\r
540 // len = kMatchSpecLen_Error_Data;\r
541 // len += kMatchMinLen;\r
542 break;\r
543 }\r
544 }\r
545\r
546 len += kMatchMinLen;\r
547\r
548 {\r
549 SizeT rem;\r
550 unsigned curLen;\r
551 SizeT pos;\r
552 \r
553 if ((rem = limit - dicPos) == 0)\r
554 {\r
555 /*\r
556 We stop decoding and return SZ_OK, and we can resume decoding later.\r
557 Any error conditions can be tested later in caller code.\r
558 For more strict mode we can stop decoding with error\r
559 // len += kMatchSpecLen_Error_Data;\r
560 */\r
561 break;\r
562 }\r
563 \r
564 curLen = ((rem < len) ? (unsigned)rem : len);\r
565 pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);\r
566\r
567 processedPos += (UInt32)curLen;\r
568\r
569 len -= curLen;\r
570 if (curLen <= dicBufSize - pos)\r
571 {\r
572 Byte *dest = dic + dicPos;\r
573 ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;\r
574 const Byte *lim = dest + curLen;\r
575 dicPos += (SizeT)curLen;\r
576 do\r
577 *(dest) = (Byte)*(dest + src);\r
578 while (++dest != lim);\r
579 }\r
580 else\r
581 {\r
582 do\r
583 {\r
584 dic[dicPos++] = dic[pos];\r
585 if (++pos == dicBufSize)\r
586 pos = 0;\r
587 }\r
588 while (--curLen != 0);\r
589 }\r
590 }\r
591 }\r
592 }\r
593 while (dicPos < limit && buf < bufLimit);\r
594\r
595 NORMALIZE;\r
596 \r
597 p->buf = buf;\r
598 p->range = range;\r
599 p->code = code;\r
600 p->remainLen = (UInt32)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too.\r
601 p->dicPos = dicPos;\r
602 p->processedPos = processedPos;\r
603 p->reps[0] = rep0;\r
604 p->reps[1] = rep1;\r
605 p->reps[2] = rep2;\r
606 p->reps[3] = rep3;\r
607 p->state = (UInt32)state;\r
608 if (len >= kMatchSpecLen_Error_Data)\r
609 return SZ_ERROR_DATA;\r
610 return SZ_OK;\r
611}\r
612#endif\r
613\r
614\r
615\r
616static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)\r
617{\r
618 unsigned len = (unsigned)p->remainLen;\r
619 if (len == 0 /* || len >= kMatchSpecLenStart */)\r
620 return;\r
621 {\r
622 SizeT dicPos = p->dicPos;\r
623 Byte *dic;\r
624 SizeT dicBufSize;\r
625 SizeT rep0; /* we use SizeT to avoid the BUG of VC14 for AMD64 */\r
626 {\r
627 SizeT rem = limit - dicPos;\r
628 if (rem < len)\r
629 {\r
630 len = (unsigned)(rem);\r
631 if (len == 0)\r
632 return;\r
633 }\r
634 }\r
635\r
636 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)\r
637 p->checkDicSize = p->prop.dicSize;\r
638\r
639 p->processedPos += (UInt32)len;\r
640 p->remainLen -= (UInt32)len;\r
641 dic = p->dic;\r
642 rep0 = p->reps[0];\r
643 dicBufSize = p->dicBufSize;\r
644 do\r
645 {\r
646 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];\r
647 dicPos++;\r
648 }\r
649 while (--len);\r
650 p->dicPos = dicPos;\r
651 }\r
652}\r
653\r
654\r
655/*\r
656At staring of new stream we have one of the following symbols:\r
657 - Literal - is allowed\r
658 - Non-Rep-Match - is allowed only if it's end marker symbol\r
659 - Rep-Match - is not allowed\r
660We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code\r
661*/\r
662\r
663#define kRange0 0xFFFFFFFF\r
664#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))\r
665#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)))\r
666#if kBadRepCode != (0xC0000000 - 0x400)\r
667 #error Stop_Compiling_Bad_LZMA_Check\r
668#endif\r
669\r
670\r
671/*\r
672LzmaDec_DecodeReal2():\r
673 It calls LZMA_DECODE_REAL() and it adjusts limit according (p->checkDicSize).\r
674\r
675We correct (p->checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(),\r
676and we support the following state of (p->checkDicSize):\r
677 if (total_processed < p->prop.dicSize) then\r
678 {\r
679 (total_processed == p->processedPos)\r
680 (p->checkDicSize == 0)\r
681 }\r
682 else\r
683 (p->checkDicSize == p->prop.dicSize)\r
684*/\r
685\r
686static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)\r
687{\r
688 if (p->checkDicSize == 0)\r
689 {\r
690 UInt32 rem = p->prop.dicSize - p->processedPos;\r
691 if (limit - p->dicPos > rem)\r
692 limit = p->dicPos + rem;\r
693 }\r
694 {\r
695 int res = LZMA_DECODE_REAL(p, limit, bufLimit);\r
696 if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)\r
697 p->checkDicSize = p->prop.dicSize;\r
698 return res;\r
699 }\r
700}\r
701\r
702\r
703\r
704typedef enum\r
705{\r
706 DUMMY_INPUT_EOF, /* need more input data */\r
707 DUMMY_LIT,\r
708 DUMMY_MATCH,\r
709 DUMMY_REP\r
710} ELzmaDummy;\r
711\r
712\r
713#define IS_DUMMY_END_MARKER_POSSIBLE(dummyRes) ((dummyRes) == DUMMY_MATCH)\r
714\r
715static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, const Byte **bufOut)\r
716{\r
717 UInt32 range = p->range;\r
718 UInt32 code = p->code;\r
719 const Byte *bufLimit = *bufOut;\r
720 const CLzmaProb *probs = GET_PROBS;\r
721 unsigned state = (unsigned)p->state;\r
722 ELzmaDummy res;\r
723\r
724 for (;;)\r
725 {\r
726 const CLzmaProb *prob;\r
727 UInt32 bound;\r
728 unsigned ttt;\r
729 unsigned posState = CALC_POS_STATE(p->processedPos, ((unsigned)1 << p->prop.pb) - 1);\r
730\r
731 prob = probs + IsMatch + COMBINED_PS_STATE;\r
732 IF_BIT_0_CHECK(prob)\r
733 {\r
734 UPDATE_0_CHECK\r
735\r
736 prob = probs + Literal;\r
737 if (p->checkDicSize != 0 || p->processedPos != 0)\r
738 prob += ((UInt32)LZMA_LIT_SIZE *\r
739 ((((p->processedPos) & (((unsigned)1 << (p->prop.lp)) - 1)) << p->prop.lc) +\r
740 ((unsigned)p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));\r
741\r
742 if (state < kNumLitStates)\r
743 {\r
744 unsigned symbol = 1;\r
745 do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);\r
746 }\r
747 else\r
748 {\r
749 unsigned matchByte = p->dic[p->dicPos - p->reps[0] +\r
750 (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];\r
751 unsigned offs = 0x100;\r
752 unsigned symbol = 1;\r
753 do\r
754 {\r
755 unsigned bit;\r
756 const CLzmaProb *probLit;\r
757 matchByte += matchByte;\r
758 bit = offs;\r
759 offs &= matchByte;\r
760 probLit = prob + (offs + bit + symbol);\r
761 GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; )\r
762 }\r
763 while (symbol < 0x100);\r
764 }\r
765 res = DUMMY_LIT;\r
766 }\r
767 else\r
768 {\r
769 unsigned len;\r
770 UPDATE_1_CHECK;\r
771\r
772 prob = probs + IsRep + state;\r
773 IF_BIT_0_CHECK(prob)\r
774 {\r
775 UPDATE_0_CHECK;\r
776 state = 0;\r
777 prob = probs + LenCoder;\r
778 res = DUMMY_MATCH;\r
779 }\r
780 else\r
781 {\r
782 UPDATE_1_CHECK;\r
783 res = DUMMY_REP;\r
784 prob = probs + IsRepG0 + state;\r
785 IF_BIT_0_CHECK(prob)\r
786 {\r
787 UPDATE_0_CHECK;\r
788 prob = probs + IsRep0Long + COMBINED_PS_STATE;\r
789 IF_BIT_0_CHECK(prob)\r
790 {\r
791 UPDATE_0_CHECK;\r
792 break;\r
793 }\r
794 else\r
795 {\r
796 UPDATE_1_CHECK;\r
797 }\r
798 }\r
799 else\r
800 {\r
801 UPDATE_1_CHECK;\r
802 prob = probs + IsRepG1 + state;\r
803 IF_BIT_0_CHECK(prob)\r
804 {\r
805 UPDATE_0_CHECK;\r
806 }\r
807 else\r
808 {\r
809 UPDATE_1_CHECK;\r
810 prob = probs + IsRepG2 + state;\r
811 IF_BIT_0_CHECK(prob)\r
812 {\r
813 UPDATE_0_CHECK;\r
814 }\r
815 else\r
816 {\r
817 UPDATE_1_CHECK;\r
818 }\r
819 }\r
820 }\r
821 state = kNumStates;\r
822 prob = probs + RepLenCoder;\r
823 }\r
824 {\r
825 unsigned limit, offset;\r
826 const CLzmaProb *probLen = prob + LenChoice;\r
827 IF_BIT_0_CHECK(probLen)\r
828 {\r
829 UPDATE_0_CHECK;\r
830 probLen = prob + LenLow + GET_LEN_STATE;\r
831 offset = 0;\r
832 limit = 1 << kLenNumLowBits;\r
833 }\r
834 else\r
835 {\r
836 UPDATE_1_CHECK;\r
837 probLen = prob + LenChoice2;\r
838 IF_BIT_0_CHECK(probLen)\r
839 {\r
840 UPDATE_0_CHECK;\r
841 probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits);\r
842 offset = kLenNumLowSymbols;\r
843 limit = 1 << kLenNumLowBits;\r
844 }\r
845 else\r
846 {\r
847 UPDATE_1_CHECK;\r
848 probLen = prob + LenHigh;\r
849 offset = kLenNumLowSymbols * 2;\r
850 limit = 1 << kLenNumHighBits;\r
851 }\r
852 }\r
853 TREE_DECODE_CHECK(probLen, limit, len);\r
854 len += offset;\r
855 }\r
856\r
857 if (state < 4)\r
858 {\r
859 unsigned posSlot;\r
860 prob = probs + PosSlot +\r
861 ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<\r
862 kNumPosSlotBits);\r
863 TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);\r
864 if (posSlot >= kStartPosModelIndex)\r
865 {\r
866 unsigned numDirectBits = ((posSlot >> 1) - 1);\r
867\r
868 if (posSlot < kEndPosModelIndex)\r
869 {\r
870 prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);\r
871 }\r
872 else\r
873 {\r
874 numDirectBits -= kNumAlignBits;\r
875 do\r
876 {\r
877 NORMALIZE_CHECK\r
878 range >>= 1;\r
879 code -= range & (((code - range) >> 31) - 1);\r
880 /* if (code >= range) code -= range; */\r
881 }\r
882 while (--numDirectBits);\r
883 prob = probs + Align;\r
884 numDirectBits = kNumAlignBits;\r
885 }\r
886 {\r
887 unsigned i = 1;\r
888 unsigned m = 1;\r
889 do\r
890 {\r
891 REV_BIT_CHECK(prob, i, m);\r
892 }\r
893 while (--numDirectBits);\r
894 }\r
895 }\r
896 }\r
897 }\r
898 break;\r
899 }\r
900 NORMALIZE_CHECK;\r
901\r
902 *bufOut = buf;\r
903 return res;\r
904}\r
905\r
906void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);\r
907void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)\r
908{\r
909 p->remainLen = kMatchSpecLenStart + 1;\r
910 p->tempBufSize = 0;\r
911\r
912 if (initDic)\r
913 {\r
914 p->processedPos = 0;\r
915 p->checkDicSize = 0;\r
916 p->remainLen = kMatchSpecLenStart + 2;\r
917 }\r
918 if (initState)\r
919 p->remainLen = kMatchSpecLenStart + 2;\r
920}\r
921\r
922void LzmaDec_Init(CLzmaDec *p)\r
923{\r
924 p->dicPos = 0;\r
925 LzmaDec_InitDicAndState(p, True, True);\r
926}\r
927\r
928\r
929/*\r
930LZMA supports optional end_marker.\r
931So the decoder can lookahead for one additional LZMA-Symbol to check end_marker.\r
932That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream.\r
933When the decoder reaches dicLimit, it looks (finishMode) parameter:\r
934 if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead\r
935 if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position\r
936\r
937When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways:\r
938 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA.\r
939 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller\r
940 must check (status) value. The caller can show the error,\r
941 if the end of stream is expected, and the (status) is noit\r
942 LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK.\r
943*/\r
944\r
945\r
946#define RETURN__NOT_FINISHED__FOR_FINISH \\r
947 *status = LZMA_STATUS_NOT_FINISHED; \\r
948 return SZ_ERROR_DATA; // for strict mode\r
949 // return SZ_OK; // for relaxed mode\r
950\r
951\r
952SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,\r
953 ELzmaFinishMode finishMode, ELzmaStatus *status)\r
954{\r
955 SizeT inSize = *srcLen;\r
956 (*srcLen) = 0;\r
957 *status = LZMA_STATUS_NOT_SPECIFIED;\r
958\r
959 if (p->remainLen > kMatchSpecLenStart)\r
960 {\r
961 if (p->remainLen > kMatchSpecLenStart + 2)\r
962 return p->remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA;\r
963\r
964 for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)\r
965 p->tempBuf[p->tempBufSize++] = *src++;\r
966 if (p->tempBufSize != 0 && p->tempBuf[0] != 0)\r
967 return SZ_ERROR_DATA;\r
968 if (p->tempBufSize < RC_INIT_SIZE)\r
969 {\r
970 *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
971 return SZ_OK;\r
972 }\r
973 p->code =\r
974 ((UInt32)p->tempBuf[1] << 24)\r
975 | ((UInt32)p->tempBuf[2] << 16)\r
976 | ((UInt32)p->tempBuf[3] << 8)\r
977 | ((UInt32)p->tempBuf[4]);\r
978\r
979 if (p->checkDicSize == 0\r
980 && p->processedPos == 0\r
981 && p->code >= kBadRepCode)\r
982 return SZ_ERROR_DATA;\r
983\r
984 p->range = 0xFFFFFFFF;\r
985 p->tempBufSize = 0;\r
986\r
987 if (p->remainLen > kMatchSpecLenStart + 1)\r
988 {\r
989 SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);\r
990 SizeT i;\r
991 CLzmaProb *probs = p->probs;\r
992 for (i = 0; i < numProbs; i++)\r
993 probs[i] = kBitModelTotal >> 1;\r
994 p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;\r
995 p->state = 0;\r
996 }\r
997\r
998 p->remainLen = 0;\r
999 }\r
1000\r
1001 for (;;)\r
1002 {\r
1003 if (p->remainLen == kMatchSpecLenStart)\r
1004 {\r
1005 if (p->code != 0)\r
1006 return SZ_ERROR_DATA;\r
1007 *status = LZMA_STATUS_FINISHED_WITH_MARK;\r
1008 return SZ_OK;\r
1009 }\r
1010\r
1011 LzmaDec_WriteRem(p, dicLimit);\r
1012\r
1013 {\r
1014 // (p->remainLen == 0 || p->dicPos == dicLimit)\r
1015\r
1016 int checkEndMarkNow = 0;\r
1017\r
1018 if (p->dicPos >= dicLimit)\r
1019 {\r
1020 if (p->remainLen == 0 && p->code == 0)\r
1021 {\r
1022 *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;\r
1023 return SZ_OK;\r
1024 }\r
1025 if (finishMode == LZMA_FINISH_ANY)\r
1026 {\r
1027 *status = LZMA_STATUS_NOT_FINISHED;\r
1028 return SZ_OK;\r
1029 }\r
1030 if (p->remainLen != 0)\r
1031 {\r
1032 RETURN__NOT_FINISHED__FOR_FINISH;\r
1033 }\r
1034 checkEndMarkNow = 1;\r
1035 }\r
1036\r
1037 // (p->remainLen == 0)\r
1038\r
1039 if (p->tempBufSize == 0)\r
1040 {\r
1041 const Byte *bufLimit;\r
1042 int dummyProcessed = -1;\r
1043 \r
1044 if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r
1045 {\r
1046 const Byte *bufOut = src + inSize;\r
1047 \r
1048 ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut);\r
1049 \r
1050 if (dummyRes == DUMMY_INPUT_EOF)\r
1051 {\r
1052 size_t i;\r
1053 if (inSize >= LZMA_REQUIRED_INPUT_MAX)\r
1054 break;\r
1055 (*srcLen) += inSize;\r
1056 p->tempBufSize = (unsigned)inSize;\r
1057 for (i = 0; i < inSize; i++)\r
1058 p->tempBuf[i] = src[i];\r
1059 *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
1060 return SZ_OK;\r
1061 }\r
1062 \r
1063 dummyProcessed = (int)(bufOut - src);\r
1064 if ((unsigned)dummyProcessed > LZMA_REQUIRED_INPUT_MAX)\r
1065 break;\r
1066 \r
1067 if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))\r
1068 {\r
1069 unsigned i;\r
1070 (*srcLen) += (unsigned)dummyProcessed;\r
1071 p->tempBufSize = (unsigned)dummyProcessed;\r
1072 for (i = 0; i < (unsigned)dummyProcessed; i++)\r
1073 p->tempBuf[i] = src[i];\r
1074 // p->remainLen = kMatchSpecLen_Error_Data;\r
1075 RETURN__NOT_FINISHED__FOR_FINISH;\r
1076 }\r
1077 \r
1078 bufLimit = src;\r
1079 // we will decode only one iteration\r
1080 }\r
1081 else\r
1082 bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;\r
1083\r
1084 p->buf = src;\r
1085 \r
1086 {\r
1087 int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit);\r
1088 \r
1089 SizeT processed = (SizeT)(p->buf - src);\r
1090\r
1091 if (dummyProcessed < 0)\r
1092 {\r
1093 if (processed > inSize)\r
1094 break;\r
1095 }\r
1096 else if ((unsigned)dummyProcessed != processed)\r
1097 break;\r
1098\r
1099 src += processed;\r
1100 inSize -= processed;\r
1101 (*srcLen) += processed;\r
1102\r
1103 if (res != SZ_OK)\r
1104 {\r
1105 p->remainLen = kMatchSpecLen_Error_Data;\r
1106 return SZ_ERROR_DATA;\r
1107 }\r
1108 }\r
1109 continue;\r
1110 }\r
1111\r
1112 {\r
1113 // we have some data in (p->tempBuf)\r
1114 // in strict mode: tempBufSize is not enough for one Symbol decoding.\r
1115 // in relaxed mode: tempBufSize not larger than required for one Symbol decoding.\r
1116\r
1117 unsigned rem = p->tempBufSize;\r
1118 unsigned ahead = 0;\r
1119 int dummyProcessed = -1;\r
1120 \r
1121 while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize)\r
1122 p->tempBuf[rem++] = src[ahead++];\r
1123 \r
1124 // ahead - the size of new data copied from (src) to (p->tempBuf)\r
1125 // rem - the size of temp buffer including new data from (src)\r
1126 \r
1127 if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)\r
1128 {\r
1129 const Byte *bufOut = p->tempBuf + rem;\r
1130 \r
1131 ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p->tempBuf, &bufOut);\r
1132 \r
1133 if (dummyRes == DUMMY_INPUT_EOF)\r
1134 {\r
1135 if (rem >= LZMA_REQUIRED_INPUT_MAX)\r
1136 break;\r
1137 p->tempBufSize = rem;\r
1138 (*srcLen) += (SizeT)ahead;\r
1139 *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
1140 return SZ_OK;\r
1141 }\r
1142 \r
1143 dummyProcessed = (int)(bufOut - p->tempBuf);\r
1144\r
1145 if ((unsigned)dummyProcessed < p->tempBufSize)\r
1146 break;\r
1147\r
1148 if (checkEndMarkNow && !IS_DUMMY_END_MARKER_POSSIBLE(dummyRes))\r
1149 {\r
1150 (*srcLen) += (unsigned)dummyProcessed - p->tempBufSize;\r
1151 p->tempBufSize = (unsigned)dummyProcessed;\r
1152 // p->remainLen = kMatchSpecLen_Error_Data;\r
1153 RETURN__NOT_FINISHED__FOR_FINISH;\r
1154 }\r
1155 }\r
1156\r
1157 p->buf = p->tempBuf;\r
1158 \r
1159 {\r
1160 // we decode one symbol from (p->tempBuf) here, so the (bufLimit) is equal to (p->buf)\r
1161 int res = LzmaDec_DecodeReal2(p, dicLimit, p->buf);\r
1162\r
1163 SizeT processed = (SizeT)(p->buf - p->tempBuf);\r
1164 rem = p->tempBufSize;\r
1165 \r
1166 if (dummyProcessed < 0)\r
1167 {\r
1168 if (processed > LZMA_REQUIRED_INPUT_MAX)\r
1169 break;\r
1170 if (processed < rem)\r
1171 break;\r
1172 }\r
1173 else if ((unsigned)dummyProcessed != processed)\r
1174 break;\r
1175 \r
1176 processed -= rem;\r
1177\r
1178 src += processed;\r
1179 inSize -= processed;\r
1180 (*srcLen) += processed;\r
1181 p->tempBufSize = 0;\r
1182 \r
1183 if (res != SZ_OK)\r
1184 {\r
1185 p->remainLen = kMatchSpecLen_Error_Data;\r
1186 return SZ_ERROR_DATA;\r
1187 }\r
1188 }\r
1189 }\r
1190 }\r
1191 }\r
1192\r
1193 /* Some unexpected error: internal error of code, memory corruption or hardware failure */\r
1194 p->remainLen = kMatchSpecLen_Error_Fail;\r
1195 return SZ_ERROR_FAIL;\r
1196}\r
1197\r
1198\r
1199\r
1200SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
1201{\r
1202 SizeT outSize = *destLen;\r
1203 SizeT inSize = *srcLen;\r
1204 *srcLen = *destLen = 0;\r
1205 for (;;)\r
1206 {\r
1207 SizeT inSizeCur = inSize, outSizeCur, dicPos;\r
1208 ELzmaFinishMode curFinishMode;\r
1209 SRes res;\r
1210 if (p->dicPos == p->dicBufSize)\r
1211 p->dicPos = 0;\r
1212 dicPos = p->dicPos;\r
1213 if (outSize > p->dicBufSize - dicPos)\r
1214 {\r
1215 outSizeCur = p->dicBufSize;\r
1216 curFinishMode = LZMA_FINISH_ANY;\r
1217 }\r
1218 else\r
1219 {\r
1220 outSizeCur = dicPos + outSize;\r
1221 curFinishMode = finishMode;\r
1222 }\r
1223\r
1224 res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);\r
1225 src += inSizeCur;\r
1226 inSize -= inSizeCur;\r
1227 *srcLen += inSizeCur;\r
1228 outSizeCur = p->dicPos - dicPos;\r
1229 memcpy(dest, p->dic + dicPos, outSizeCur);\r
1230 dest += outSizeCur;\r
1231 outSize -= outSizeCur;\r
1232 *destLen += outSizeCur;\r
1233 if (res != 0)\r
1234 return res;\r
1235 if (outSizeCur == 0 || outSize == 0)\r
1236 return SZ_OK;\r
1237 }\r
1238}\r
1239\r
1240void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc)\r
1241{\r
1242 ISzAlloc_Free(alloc, p->probs);\r
1243 p->probs = NULL;\r
1244}\r
1245\r
1246static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc)\r
1247{\r
1248 ISzAlloc_Free(alloc, p->dic);\r
1249 p->dic = NULL;\r
1250}\r
1251\r
1252void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc)\r
1253{\r
1254 LzmaDec_FreeProbs(p, alloc);\r
1255 LzmaDec_FreeDict(p, alloc);\r
1256}\r
1257\r
1258SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)\r
1259{\r
1260 UInt32 dicSize;\r
1261 Byte d;\r
1262 \r
1263 if (size < LZMA_PROPS_SIZE)\r
1264 return SZ_ERROR_UNSUPPORTED;\r
1265 else\r
1266 dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);\r
1267 \r
1268 if (dicSize < LZMA_DIC_MIN)\r
1269 dicSize = LZMA_DIC_MIN;\r
1270 p->dicSize = dicSize;\r
1271\r
1272 d = data[0];\r
1273 if (d >= (9 * 5 * 5))\r
1274 return SZ_ERROR_UNSUPPORTED;\r
1275\r
1276 p->lc = (Byte)(d % 9);\r
1277 d /= 9;\r
1278 p->pb = (Byte)(d / 5);\r
1279 p->lp = (Byte)(d % 5);\r
1280\r
1281 return SZ_OK;\r
1282}\r
1283\r
1284static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc)\r
1285{\r
1286 UInt32 numProbs = LzmaProps_GetNumProbs(propNew);\r
1287 if (!p->probs || numProbs != p->numProbs)\r
1288 {\r
1289 LzmaDec_FreeProbs(p, alloc);\r
1290 p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb));\r
1291 if (!p->probs)\r
1292 return SZ_ERROR_MEM;\r
1293 p->probs_1664 = p->probs + 1664;\r
1294 p->numProbs = numProbs;\r
1295 }\r
1296 return SZ_OK;\r
1297}\r
1298\r
1299SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)\r
1300{\r
1301 CLzmaProps propNew;\r
1302 RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r
1303 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r
1304 p->prop = propNew;\r
1305 return SZ_OK;\r
1306}\r
1307\r
1308SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc)\r
1309{\r
1310 CLzmaProps propNew;\r
1311 SizeT dicBufSize;\r
1312 RINOK(LzmaProps_Decode(&propNew, props, propsSize));\r
1313 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));\r
1314\r
1315 {\r
1316 UInt32 dictSize = propNew.dicSize;\r
1317 SizeT mask = ((UInt32)1 << 12) - 1;\r
1318 if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;\r
1319 else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;\r
1320 dicBufSize = ((SizeT)dictSize + mask) & ~mask;\r
1321 if (dicBufSize < dictSize)\r
1322 dicBufSize = dictSize;\r
1323 }\r
1324\r
1325 if (!p->dic || dicBufSize != p->dicBufSize)\r
1326 {\r
1327 LzmaDec_FreeDict(p, alloc);\r
1328 p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize);\r
1329 if (!p->dic)\r
1330 {\r
1331 LzmaDec_FreeProbs(p, alloc);\r
1332 return SZ_ERROR_MEM;\r
1333 }\r
1334 }\r
1335 p->dicBufSize = dicBufSize;\r
1336 p->prop = propNew;\r
1337 return SZ_OK;\r
1338}\r
1339\r
1340SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
1341 const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,\r
1342 ELzmaStatus *status, ISzAllocPtr alloc)\r
1343{\r
1344 CLzmaDec p;\r
1345 SRes res;\r
1346 SizeT outSize = *destLen, inSize = *srcLen;\r
1347 *destLen = *srcLen = 0;\r
1348 *status = LZMA_STATUS_NOT_SPECIFIED;\r
1349 if (inSize < RC_INIT_SIZE)\r
1350 return SZ_ERROR_INPUT_EOF;\r
1351 LzmaDec_Construct(&p);\r
1352 RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));\r
1353 p.dic = dest;\r
1354 p.dicBufSize = outSize;\r
1355 LzmaDec_Init(&p);\r
1356 *srcLen = inSize;\r
1357 res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);\r
1358 *destLen = p.dicPos;\r
1359 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
1360 res = SZ_ERROR_INPUT_EOF;\r
1361 LzmaDec_FreeProbs(&p, alloc);\r
1362 return res;\r
1363}\r