1 /* LzmaDec.c -- LZMA Decoder
\r
2 2016-05-16 : Igor Pavlov : Public domain */
\r
10 #define kNumTopBits 24
\r
11 #define kTopValue ((UInt32)1 << kNumTopBits)
\r
13 #define kNumBitModelTotalBits 11
\r
14 #define kBitModelTotal (1 << kNumBitModelTotalBits)
\r
15 #define kNumMoveBits 5
\r
17 #define RC_INIT_SIZE 5
\r
19 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
\r
21 #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
\r
22 #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
\r
23 #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
\r
24 #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
\r
25 { UPDATE_0(p); i = (i + i); A0; } else \
\r
26 { UPDATE_1(p); i = (i + i) + 1; A1; }
\r
27 #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
\r
29 #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
\r
30 #define TREE_DECODE(probs, limit, i) \
\r
31 { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
\r
33 /* #define _LZMA_SIZE_OPT */
\r
35 #ifdef _LZMA_SIZE_OPT
\r
36 #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
\r
38 #define TREE_6_DECODE(probs, i) \
\r
40 TREE_GET_BIT(probs, i); \
\r
41 TREE_GET_BIT(probs, i); \
\r
42 TREE_GET_BIT(probs, i); \
\r
43 TREE_GET_BIT(probs, i); \
\r
44 TREE_GET_BIT(probs, i); \
\r
45 TREE_GET_BIT(probs, i); \
\r
49 #define NORMAL_LITER_DEC GET_BIT(prob + symbol, symbol)
\r
50 #define MATCHED_LITER_DEC \
\r
52 bit = (matchByte & offs); \
\r
53 probLit = prob + offs + bit + symbol; \
\r
54 GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
\r
56 #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
\r
58 #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
\r
59 #define UPDATE_0_CHECK range = bound;
\r
60 #define UPDATE_1_CHECK range -= bound; code -= bound;
\r
61 #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
\r
62 { UPDATE_0_CHECK; i = (i + i); A0; } else \
\r
63 { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
\r
64 #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
\r
65 #define TREE_DECODE_CHECK(probs, limit, i) \
\r
66 { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
\r
69 #define kNumPosBitsMax 4
\r
70 #define kNumPosStatesMax (1 << kNumPosBitsMax)
\r
72 #define kLenNumLowBits 3
\r
73 #define kLenNumLowSymbols (1 << kLenNumLowBits)
\r
74 #define kLenNumMidBits 3
\r
75 #define kLenNumMidSymbols (1 << kLenNumMidBits)
\r
76 #define kLenNumHighBits 8
\r
77 #define kLenNumHighSymbols (1 << kLenNumHighBits)
\r
80 #define LenChoice2 (LenChoice + 1)
\r
81 #define LenLow (LenChoice2 + 1)
\r
82 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
\r
83 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
\r
84 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
\r
87 #define kNumStates 12
\r
88 #define kNumLitStates 7
\r
90 #define kStartPosModelIndex 4
\r
91 #define kEndPosModelIndex 14
\r
92 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
\r
94 #define kNumPosSlotBits 6
\r
95 #define kNumLenToPosStates 4
\r
97 #define kNumAlignBits 4
\r
98 #define kAlignTableSize (1 << kNumAlignBits)
\r
100 #define kMatchMinLen 2
\r
101 #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
\r
104 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
\r
105 #define IsRepG0 (IsRep + kNumStates)
\r
106 #define IsRepG1 (IsRepG0 + kNumStates)
\r
107 #define IsRepG2 (IsRepG1 + kNumStates)
\r
108 #define IsRep0Long (IsRepG2 + kNumStates)
\r
109 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
\r
110 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
\r
111 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
\r
112 #define LenCoder (Align + kAlignTableSize)
\r
113 #define RepLenCoder (LenCoder + kNumLenProbs)
\r
114 #define Literal (RepLenCoder + kNumLenProbs)
\r
116 #define LZMA_BASE_SIZE 1846
\r
117 #define LZMA_LIT_SIZE 0x300
\r
119 #if Literal != LZMA_BASE_SIZE
\r
120 StopCompilingDueBUG
\r
123 #define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
\r
125 #define LZMA_DIC_MIN (1 << 12)
\r
127 /* First LZMA-symbol is always decoded.
\r
128 And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
\r
132 SZ_ERROR_DATA - Error
\r
134 < kMatchSpecLenStart : normal remain
\r
135 = kMatchSpecLenStart : finished
\r
136 = kMatchSpecLenStart + 1 : Flush marker (unused now)
\r
137 = kMatchSpecLenStart + 2 : State Init Marker (unused now)
\r
140 static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
\r
142 CLzmaProb *probs = p->probs;
\r
144 unsigned state = p->state;
\r
145 UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
\r
146 unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
\r
147 unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
\r
148 unsigned lc = p->prop.lc;
\r
150 Byte *dic = p->dic;
\r
151 SizeT dicBufSize = p->dicBufSize;
\r
152 SizeT dicPos = p->dicPos;
\r
154 UInt32 processedPos = p->processedPos;
\r
155 UInt32 checkDicSize = p->checkDicSize;
\r
158 const Byte *buf = p->buf;
\r
159 UInt32 range = p->range;
\r
160 UInt32 code = p->code;
\r
167 unsigned posState = processedPos & pbMask;
\r
169 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
\r
174 prob = probs + Literal;
\r
175 if (processedPos != 0 || checkDicSize != 0)
\r
176 prob += ((UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
\r
177 (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
\r
180 if (state < kNumLitStates)
\r
182 state -= (state < 4) ? state : 3;
\r
184 #ifdef _LZMA_SIZE_OPT
\r
185 do { NORMAL_LITER_DEC } while (symbol < 0x100);
\r
199 unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
\r
200 unsigned offs = 0x100;
\r
201 state -= (state < 10) ? 3 : 6;
\r
203 #ifdef _LZMA_SIZE_OPT
\r
207 CLzmaProb *probLit;
\r
210 while (symbol < 0x100);
\r
214 CLzmaProb *probLit;
\r
227 dic[dicPos++] = (Byte)symbol;
\r
233 prob = probs + IsRep + state;
\r
237 state += kNumStates;
\r
238 prob = probs + LenCoder;
\r
243 if (checkDicSize == 0 && processedPos == 0)
\r
244 return SZ_ERROR_DATA;
\r
245 prob = probs + IsRepG0 + state;
\r
249 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
\r
253 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
\r
256 state = state < kNumLitStates ? 9 : 11;
\r
265 prob = probs + IsRepG1 + state;
\r
274 prob = probs + IsRepG2 + state;
\r
291 state = state < kNumLitStates ? 8 : 11;
\r
292 prob = probs + RepLenCoder;
\r
295 #ifdef _LZMA_SIZE_OPT
\r
297 unsigned lim, offset;
\r
298 CLzmaProb *probLen = prob + LenChoice;
\r
302 probLen = prob + LenLow + (posState << kLenNumLowBits);
\r
304 lim = (1 << kLenNumLowBits);
\r
309 probLen = prob + LenChoice2;
\r
313 probLen = prob + LenMid + (posState << kLenNumMidBits);
\r
314 offset = kLenNumLowSymbols;
\r
315 lim = (1 << kLenNumMidBits);
\r
320 probLen = prob + LenHigh;
\r
321 offset = kLenNumLowSymbols + kLenNumMidSymbols;
\r
322 lim = (1 << kLenNumHighBits);
\r
325 TREE_DECODE(probLen, lim, len);
\r
330 CLzmaProb *probLen = prob + LenChoice;
\r
334 probLen = prob + LenLow + (posState << kLenNumLowBits);
\r
336 TREE_GET_BIT(probLen, len);
\r
337 TREE_GET_BIT(probLen, len);
\r
338 TREE_GET_BIT(probLen, len);
\r
344 probLen = prob + LenChoice2;
\r
348 probLen = prob + LenMid + (posState << kLenNumMidBits);
\r
350 TREE_GET_BIT(probLen, len);
\r
351 TREE_GET_BIT(probLen, len);
\r
352 TREE_GET_BIT(probLen, len);
\r
357 probLen = prob + LenHigh;
\r
358 TREE_DECODE(probLen, (1 << kLenNumHighBits), len);
\r
359 len += kLenNumLowSymbols + kLenNumMidSymbols;
\r
365 if (state >= kNumStates)
\r
368 prob = probs + PosSlot +
\r
369 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
\r
370 TREE_6_DECODE(prob, distance);
\r
371 if (distance >= kStartPosModelIndex)
\r
373 unsigned posSlot = (unsigned)distance;
\r
374 unsigned numDirectBits = (unsigned)(((distance >> 1) - 1));
\r
375 distance = (2 | (distance & 1));
\r
376 if (posSlot < kEndPosModelIndex)
\r
378 distance <<= numDirectBits;
\r
379 prob = probs + SpecPos + distance - posSlot - 1;
\r
385 GET_BIT2(prob + i, i, ; , distance |= mask);
\r
388 while (--numDirectBits != 0);
\r
393 numDirectBits -= kNumAlignBits;
\r
402 t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
\r
403 distance = (distance << 1) + (t + 1);
\r
415 while (--numDirectBits != 0);
\r
416 prob = probs + Align;
\r
417 distance <<= kNumAlignBits;
\r
420 GET_BIT2(prob + i, i, ; , distance |= 1);
\r
421 GET_BIT2(prob + i, i, ; , distance |= 2);
\r
422 GET_BIT2(prob + i, i, ; , distance |= 4);
\r
423 GET_BIT2(prob + i, i, ; , distance |= 8);
\r
425 if (distance == (UInt32)0xFFFFFFFF)
\r
427 len += kMatchSpecLenStart;
\r
428 state -= kNumStates;
\r
437 rep0 = distance + 1;
\r
438 if (checkDicSize == 0)
\r
440 if (distance >= processedPos)
\r
442 p->dicPos = dicPos;
\r
443 return SZ_ERROR_DATA;
\r
446 else if (distance >= checkDicSize)
\r
448 p->dicPos = dicPos;
\r
449 return SZ_ERROR_DATA;
\r
451 state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
\r
454 len += kMatchMinLen;
\r
461 if ((rem = limit - dicPos) == 0)
\r
463 p->dicPos = dicPos;
\r
464 return SZ_ERROR_DATA;
\r
467 curLen = ((rem < len) ? (unsigned)rem : len);
\r
468 pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
\r
470 processedPos += curLen;
\r
473 if (curLen <= dicBufSize - pos)
\r
475 Byte *dest = dic + dicPos;
\r
476 ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
\r
477 const Byte *lim = dest + curLen;
\r
480 *(dest) = (Byte)*(dest + src);
\r
481 while (++dest != lim);
\r
487 dic[dicPos++] = dic[pos];
\r
488 if (++pos == dicBufSize)
\r
491 while (--curLen != 0);
\r
496 while (dicPos < limit && buf < bufLimit);
\r
503 p->remainLen = len;
\r
504 p->dicPos = dicPos;
\r
505 p->processedPos = processedPos;
\r
515 static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
\r
517 if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
\r
519 Byte *dic = p->dic;
\r
520 SizeT dicPos = p->dicPos;
\r
521 SizeT dicBufSize = p->dicBufSize;
\r
522 unsigned len = p->remainLen;
\r
523 SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
\r
524 SizeT rem = limit - dicPos;
\r
526 len = (unsigned)(rem);
\r
528 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
\r
529 p->checkDicSize = p->prop.dicSize;
\r
531 p->processedPos += len;
\r
532 p->remainLen -= len;
\r
536 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
\r
539 p->dicPos = dicPos;
\r
543 static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
\r
547 SizeT limit2 = limit;
\r
548 if (p->checkDicSize == 0)
\r
550 UInt32 rem = p->prop.dicSize - p->processedPos;
\r
551 if (limit - p->dicPos > rem)
\r
552 limit2 = p->dicPos + rem;
\r
555 RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
\r
557 if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize)
\r
558 p->checkDicSize = p->prop.dicSize;
\r
560 LzmaDec_WriteRem(p, limit);
\r
562 while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
\r
564 if (p->remainLen > kMatchSpecLenStart)
\r
565 p->remainLen = kMatchSpecLenStart;
\r
572 DUMMY_ERROR, /* unexpected end of input stream */
\r
578 static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
\r
580 UInt32 range = p->range;
\r
581 UInt32 code = p->code;
\r
582 const Byte *bufLimit = buf + inSize;
\r
583 const CLzmaProb *probs = p->probs;
\r
584 unsigned state = p->state;
\r
588 const CLzmaProb *prob;
\r
591 unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
\r
593 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
\r
594 IF_BIT_0_CHECK(prob)
\r
598 /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
\r
600 prob = probs + Literal;
\r
601 if (p->checkDicSize != 0 || p->processedPos != 0)
\r
602 prob += ((UInt32)LZMA_LIT_SIZE *
\r
603 ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
\r
604 (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
\r
606 if (state < kNumLitStates)
\r
608 unsigned symbol = 1;
\r
609 do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
\r
613 unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
\r
614 (p->dicPos < p->reps[0] ? p->dicBufSize : 0)];
\r
615 unsigned offs = 0x100;
\r
616 unsigned symbol = 1;
\r
620 const CLzmaProb *probLit;
\r
622 bit = (matchByte & offs);
\r
623 probLit = prob + offs + bit + symbol;
\r
624 GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
\r
626 while (symbol < 0x100);
\r
635 prob = probs + IsRep + state;
\r
636 IF_BIT_0_CHECK(prob)
\r
640 prob = probs + LenCoder;
\r
647 prob = probs + IsRepG0 + state;
\r
648 IF_BIT_0_CHECK(prob)
\r
651 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
\r
652 IF_BIT_0_CHECK(prob)
\r
666 prob = probs + IsRepG1 + state;
\r
667 IF_BIT_0_CHECK(prob)
\r
674 prob = probs + IsRepG2 + state;
\r
675 IF_BIT_0_CHECK(prob)
\r
685 state = kNumStates;
\r
686 prob = probs + RepLenCoder;
\r
689 unsigned limit, offset;
\r
690 const CLzmaProb *probLen = prob + LenChoice;
\r
691 IF_BIT_0_CHECK(probLen)
\r
694 probLen = prob + LenLow + (posState << kLenNumLowBits);
\r
696 limit = 1 << kLenNumLowBits;
\r
701 probLen = prob + LenChoice2;
\r
702 IF_BIT_0_CHECK(probLen)
\r
705 probLen = prob + LenMid + (posState << kLenNumMidBits);
\r
706 offset = kLenNumLowSymbols;
\r
707 limit = 1 << kLenNumMidBits;
\r
712 probLen = prob + LenHigh;
\r
713 offset = kLenNumLowSymbols + kLenNumMidSymbols;
\r
714 limit = 1 << kLenNumHighBits;
\r
717 TREE_DECODE_CHECK(probLen, limit, len);
\r
724 prob = probs + PosSlot +
\r
725 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
\r
727 TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
\r
728 if (posSlot >= kStartPosModelIndex)
\r
730 unsigned numDirectBits = ((posSlot >> 1) - 1);
\r
732 /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
\r
734 if (posSlot < kEndPosModelIndex)
\r
736 prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
\r
740 numDirectBits -= kNumAlignBits;
\r
745 code -= range & (((code - range) >> 31) - 1);
\r
746 /* if (code >= range) code -= range; */
\r
748 while (--numDirectBits != 0);
\r
749 prob = probs + Align;
\r
750 numDirectBits = kNumAlignBits;
\r
756 GET_BIT_CHECK(prob + i, i);
\r
758 while (--numDirectBits != 0);
\r
769 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
\r
773 p->tempBufSize = 0;
\r
777 p->processedPos = 0;
\r
778 p->checkDicSize = 0;
\r
779 p->needInitState = 1;
\r
782 p->needInitState = 1;
\r
785 void LzmaDec_Init(CLzmaDec *p)
\r
788 LzmaDec_InitDicAndState(p, True, True);
\r
791 static void LzmaDec_InitStateReal(CLzmaDec *p)
\r
793 SizeT numProbs = LzmaProps_GetNumProbs(&p->prop);
\r
795 CLzmaProb *probs = p->probs;
\r
796 for (i = 0; i < numProbs; i++)
\r
797 probs[i] = kBitModelTotal >> 1;
\r
798 p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
\r
800 p->needInitState = 0;
\r
803 SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
\r
804 ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
806 SizeT inSize = *srcLen;
\r
808 LzmaDec_WriteRem(p, dicLimit);
\r
810 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
812 while (p->remainLen != kMatchSpecLenStart)
\r
814 int checkEndMarkNow;
\r
818 for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
\r
819 p->tempBuf[p->tempBufSize++] = *src++;
\r
820 if (p->tempBufSize < RC_INIT_SIZE)
\r
822 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
825 if (p->tempBuf[0] != 0)
\r
826 return SZ_ERROR_DATA;
\r
828 ((UInt32)p->tempBuf[1] << 24)
\r
829 | ((UInt32)p->tempBuf[2] << 16)
\r
830 | ((UInt32)p->tempBuf[3] << 8)
\r
831 | ((UInt32)p->tempBuf[4]);
\r
832 p->range = 0xFFFFFFFF;
\r
834 p->tempBufSize = 0;
\r
837 checkEndMarkNow = 0;
\r
838 if (p->dicPos >= dicLimit)
\r
840 if (p->remainLen == 0 && p->code == 0)
\r
842 *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
\r
845 if (finishMode == LZMA_FINISH_ANY)
\r
847 *status = LZMA_STATUS_NOT_FINISHED;
\r
850 if (p->remainLen != 0)
\r
852 *status = LZMA_STATUS_NOT_FINISHED;
\r
853 return SZ_ERROR_DATA;
\r
855 checkEndMarkNow = 1;
\r
858 if (p->needInitState)
\r
859 LzmaDec_InitStateReal(p);
\r
861 if (p->tempBufSize == 0)
\r
864 const Byte *bufLimit;
\r
865 if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
\r
867 int dummyRes = LzmaDec_TryDummy(p, src, inSize);
\r
868 if (dummyRes == DUMMY_ERROR)
\r
870 memcpy(p->tempBuf, src, inSize);
\r
871 p->tempBufSize = (unsigned)inSize;
\r
872 (*srcLen) += inSize;
\r
873 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
876 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
\r
878 *status = LZMA_STATUS_NOT_FINISHED;
\r
879 return SZ_ERROR_DATA;
\r
884 bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
\r
886 if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
\r
887 return SZ_ERROR_DATA;
\r
888 processed = (SizeT)(p->buf - src);
\r
889 (*srcLen) += processed;
\r
891 inSize -= processed;
\r
895 unsigned rem = p->tempBufSize, lookAhead = 0;
\r
896 while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
\r
897 p->tempBuf[rem++] = src[lookAhead++];
\r
898 p->tempBufSize = rem;
\r
899 if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
\r
901 int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
\r
902 if (dummyRes == DUMMY_ERROR)
\r
904 (*srcLen) += lookAhead;
\r
905 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
908 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
\r
910 *status = LZMA_STATUS_NOT_FINISHED;
\r
911 return SZ_ERROR_DATA;
\r
914 p->buf = p->tempBuf;
\r
915 if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
\r
916 return SZ_ERROR_DATA;
\r
919 unsigned kkk = (unsigned)(p->buf - p->tempBuf);
\r
921 return SZ_ERROR_FAIL; /* some internal error */
\r
923 if (lookAhead < rem)
\r
924 return SZ_ERROR_FAIL; /* some internal error */
\r
927 (*srcLen) += lookAhead;
\r
929 inSize -= lookAhead;
\r
930 p->tempBufSize = 0;
\r
934 *status = LZMA_STATUS_FINISHED_WITH_MARK;
\r
935 return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
\r
938 SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
940 SizeT outSize = *destLen;
\r
941 SizeT inSize = *srcLen;
\r
942 *srcLen = *destLen = 0;
\r
945 SizeT inSizeCur = inSize, outSizeCur, dicPos;
\r
946 ELzmaFinishMode curFinishMode;
\r
948 if (p->dicPos == p->dicBufSize)
\r
950 dicPos = p->dicPos;
\r
951 if (outSize > p->dicBufSize - dicPos)
\r
953 outSizeCur = p->dicBufSize;
\r
954 curFinishMode = LZMA_FINISH_ANY;
\r
958 outSizeCur = dicPos + outSize;
\r
959 curFinishMode = finishMode;
\r
962 res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
\r
964 inSize -= inSizeCur;
\r
965 *srcLen += inSizeCur;
\r
966 outSizeCur = p->dicPos - dicPos;
\r
967 memcpy(dest, p->dic + dicPos, outSizeCur);
\r
968 dest += outSizeCur;
\r
969 outSize -= outSizeCur;
\r
970 *destLen += outSizeCur;
\r
973 if (outSizeCur == 0 || outSize == 0)
\r
978 void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
\r
980 alloc->Free(alloc, p->probs);
\r
984 static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
\r
986 alloc->Free(alloc, p->dic);
\r
990 void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
\r
992 LzmaDec_FreeProbs(p, alloc);
\r
993 LzmaDec_FreeDict(p, alloc);
\r
996 SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
\r
1001 if (size < LZMA_PROPS_SIZE)
\r
1002 return SZ_ERROR_UNSUPPORTED;
\r
1004 dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
\r
1006 if (dicSize < LZMA_DIC_MIN)
\r
1007 dicSize = LZMA_DIC_MIN;
\r
1008 p->dicSize = dicSize;
\r
1011 if (d >= (9 * 5 * 5))
\r
1012 return SZ_ERROR_UNSUPPORTED;
\r
1022 static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
\r
1024 UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
\r
1025 if (!p->probs || numProbs != p->numProbs)
\r
1027 LzmaDec_FreeProbs(p, alloc);
\r
1028 p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
\r
1029 p->numProbs = numProbs;
\r
1031 return SZ_ERROR_MEM;
\r
1036 SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
\r
1038 CLzmaProps propNew;
\r
1039 RINOK(LzmaProps_Decode(&propNew, props, propsSize));
\r
1040 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
\r
1041 p->prop = propNew;
\r
1045 SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
\r
1047 CLzmaProps propNew;
\r
1049 RINOK(LzmaProps_Decode(&propNew, props, propsSize));
\r
1050 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
\r
1053 UInt32 dictSize = propNew.dicSize;
\r
1054 SizeT mask = ((UInt32)1 << 12) - 1;
\r
1055 if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1;
\r
1056 else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;;
\r
1057 dicBufSize = ((SizeT)dictSize + mask) & ~mask;
\r
1058 if (dicBufSize < dictSize)
\r
1059 dicBufSize = dictSize;
\r
1062 if (!p->dic || dicBufSize != p->dicBufSize)
\r
1064 LzmaDec_FreeDict(p, alloc);
\r
1065 p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
\r
1068 LzmaDec_FreeProbs(p, alloc);
\r
1069 return SZ_ERROR_MEM;
\r
1072 p->dicBufSize = dicBufSize;
\r
1073 p->prop = propNew;
\r
1077 SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
1078 const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
\r
1079 ELzmaStatus *status, ISzAlloc *alloc)
\r
1083 SizeT outSize = *destLen, inSize = *srcLen;
\r
1084 *destLen = *srcLen = 0;
\r
1085 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
1086 if (inSize < RC_INIT_SIZE)
\r
1087 return SZ_ERROR_INPUT_EOF;
\r
1088 LzmaDec_Construct(&p);
\r
1089 RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc));
\r
1091 p.dicBufSize = outSize;
\r
1094 res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
\r
1095 *destLen = p.dicPos;
\r
1096 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
\r
1097 res = SZ_ERROR_INPUT_EOF;
\r
1098 LzmaDec_FreeProbs(&p, alloc);
\r