xref: /openbmc/u-boot/lib/lzma/LzmaDec.c (revision 96764df1b47ddebfb50fadf5af72530b07b5fc89)
178acc472SPeter Tyser /* LzmaDec.c -- LZMA Decoder
2*5fe8380dSStefan Reinauer 2009-09-20 : Igor Pavlov : Public domain */
378acc472SPeter Tyser 
478acc472SPeter Tyser #include <config.h>
578acc472SPeter Tyser #include <common.h>
678acc472SPeter Tyser #include <watchdog.h>
778acc472SPeter Tyser #include "LzmaDec.h"
878acc472SPeter Tyser 
978acc472SPeter Tyser #include <linux/string.h>
1078acc472SPeter Tyser 
1178acc472SPeter Tyser #define kNumTopBits 24
1278acc472SPeter Tyser #define kTopValue ((UInt32)1 << kNumTopBits)
1378acc472SPeter Tyser 
1478acc472SPeter Tyser #define kNumBitModelTotalBits 11
1578acc472SPeter Tyser #define kBitModelTotal (1 << kNumBitModelTotalBits)
1678acc472SPeter Tyser #define kNumMoveBits 5
1778acc472SPeter Tyser 
1878acc472SPeter Tyser #define RC_INIT_SIZE 5
1978acc472SPeter Tyser 
2078acc472SPeter Tyser #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
2178acc472SPeter Tyser 
2278acc472SPeter Tyser #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
2378acc472SPeter Tyser #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
2478acc472SPeter Tyser #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
2578acc472SPeter Tyser #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
2678acc472SPeter Tyser   { UPDATE_0(p); i = (i + i); A0; } else \
2778acc472SPeter Tyser   { UPDATE_1(p); i = (i + i) + 1; A1; }
2878acc472SPeter Tyser #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
2978acc472SPeter Tyser 
3078acc472SPeter Tyser #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
3178acc472SPeter Tyser #define TREE_DECODE(probs, limit, i) \
3278acc472SPeter Tyser   { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
3378acc472SPeter Tyser 
3478acc472SPeter Tyser /* #define _LZMA_SIZE_OPT */
3578acc472SPeter Tyser 
3678acc472SPeter Tyser #ifdef _LZMA_SIZE_OPT
3778acc472SPeter Tyser #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
3878acc472SPeter Tyser #else
3978acc472SPeter Tyser #define TREE_6_DECODE(probs, i) \
4078acc472SPeter Tyser   { i = 1; \
4178acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4278acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4378acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4478acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4578acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4678acc472SPeter Tyser   TREE_GET_BIT(probs, i); \
4778acc472SPeter Tyser   i -= 0x40; }
4878acc472SPeter Tyser #endif
4978acc472SPeter Tyser 
5078acc472SPeter Tyser #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
5178acc472SPeter Tyser 
5278acc472SPeter Tyser #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
5378acc472SPeter Tyser #define UPDATE_0_CHECK range = bound;
5478acc472SPeter Tyser #define UPDATE_1_CHECK range -= bound; code -= bound;
5578acc472SPeter Tyser #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
5678acc472SPeter Tyser   { UPDATE_0_CHECK; i = (i + i); A0; } else \
5778acc472SPeter Tyser   { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
5878acc472SPeter Tyser #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
5978acc472SPeter Tyser #define TREE_DECODE_CHECK(probs, limit, i) \
6078acc472SPeter Tyser   { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
6178acc472SPeter Tyser 
6278acc472SPeter Tyser 
6378acc472SPeter Tyser #define kNumPosBitsMax 4
6478acc472SPeter Tyser #define kNumPosStatesMax (1 << kNumPosBitsMax)
6578acc472SPeter Tyser 
6678acc472SPeter Tyser #define kLenNumLowBits 3
6778acc472SPeter Tyser #define kLenNumLowSymbols (1 << kLenNumLowBits)
6878acc472SPeter Tyser #define kLenNumMidBits 3
6978acc472SPeter Tyser #define kLenNumMidSymbols (1 << kLenNumMidBits)
7078acc472SPeter Tyser #define kLenNumHighBits 8
7178acc472SPeter Tyser #define kLenNumHighSymbols (1 << kLenNumHighBits)
7278acc472SPeter Tyser 
7378acc472SPeter Tyser #define LenChoice 0
7478acc472SPeter Tyser #define LenChoice2 (LenChoice + 1)
7578acc472SPeter Tyser #define LenLow (LenChoice2 + 1)
7678acc472SPeter Tyser #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
7778acc472SPeter Tyser #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
7878acc472SPeter Tyser #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
7978acc472SPeter Tyser 
8078acc472SPeter Tyser 
8178acc472SPeter Tyser #define kNumStates 12
8278acc472SPeter Tyser #define kNumLitStates 7
8378acc472SPeter Tyser 
8478acc472SPeter Tyser #define kStartPosModelIndex 4
8578acc472SPeter Tyser #define kEndPosModelIndex 14
8678acc472SPeter Tyser #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
8778acc472SPeter Tyser 
8878acc472SPeter Tyser #define kNumPosSlotBits 6
8978acc472SPeter Tyser #define kNumLenToPosStates 4
9078acc472SPeter Tyser 
9178acc472SPeter Tyser #define kNumAlignBits 4
9278acc472SPeter Tyser #define kAlignTableSize (1 << kNumAlignBits)
9378acc472SPeter Tyser 
9478acc472SPeter Tyser #define kMatchMinLen 2
9578acc472SPeter Tyser #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
9678acc472SPeter Tyser 
9778acc472SPeter Tyser #define IsMatch 0
9878acc472SPeter Tyser #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
9978acc472SPeter Tyser #define IsRepG0 (IsRep + kNumStates)
10078acc472SPeter Tyser #define IsRepG1 (IsRepG0 + kNumStates)
10178acc472SPeter Tyser #define IsRepG2 (IsRepG1 + kNumStates)
10278acc472SPeter Tyser #define IsRep0Long (IsRepG2 + kNumStates)
10378acc472SPeter Tyser #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
10478acc472SPeter Tyser #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
10578acc472SPeter Tyser #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
10678acc472SPeter Tyser #define LenCoder (Align + kAlignTableSize)
10778acc472SPeter Tyser #define RepLenCoder (LenCoder + kNumLenProbs)
10878acc472SPeter Tyser #define Literal (RepLenCoder + kNumLenProbs)
10978acc472SPeter Tyser 
11078acc472SPeter Tyser #define LZMA_BASE_SIZE 1846
11178acc472SPeter Tyser #define LZMA_LIT_SIZE 768
11278acc472SPeter Tyser 
11378acc472SPeter Tyser #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
11478acc472SPeter Tyser 
11578acc472SPeter Tyser #if Literal != LZMA_BASE_SIZE
11678acc472SPeter Tyser StopCompilingDueBUG
11778acc472SPeter Tyser #endif
11878acc472SPeter Tyser 
11978acc472SPeter Tyser #define LZMA_DIC_MIN (1 << 12)
12078acc472SPeter Tyser 
12178acc472SPeter Tyser /* First LZMA-symbol is always decoded.
12278acc472SPeter Tyser And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
12378acc472SPeter Tyser Out:
12478acc472SPeter Tyser   Result:
12578acc472SPeter Tyser     SZ_OK - OK
12678acc472SPeter Tyser     SZ_ERROR_DATA - Error
12778acc472SPeter Tyser   p->remainLen:
12878acc472SPeter Tyser     < kMatchSpecLenStart : normal remain
12978acc472SPeter Tyser     = kMatchSpecLenStart : finished
13078acc472SPeter Tyser     = kMatchSpecLenStart + 1 : Flush marker
13178acc472SPeter Tyser     = kMatchSpecLenStart + 2 : State Init Marker
13278acc472SPeter Tyser */
13378acc472SPeter Tyser 
LzmaDec_DecodeReal(CLzmaDec * p,SizeT limit,const Byte * bufLimit)13478acc472SPeter Tyser static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
13578acc472SPeter Tyser {
13678acc472SPeter Tyser   CLzmaProb *probs = p->probs;
13778acc472SPeter Tyser 
13878acc472SPeter Tyser   unsigned state = p->state;
13978acc472SPeter Tyser   UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
14078acc472SPeter Tyser   unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
14178acc472SPeter Tyser   unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
14278acc472SPeter Tyser   unsigned lc = p->prop.lc;
14378acc472SPeter Tyser 
14478acc472SPeter Tyser   Byte *dic = p->dic;
14578acc472SPeter Tyser   SizeT dicBufSize = p->dicBufSize;
14678acc472SPeter Tyser   SizeT dicPos = p->dicPos;
14778acc472SPeter Tyser 
14878acc472SPeter Tyser   UInt32 processedPos = p->processedPos;
14978acc472SPeter Tyser   UInt32 checkDicSize = p->checkDicSize;
15078acc472SPeter Tyser   unsigned len = 0;
15178acc472SPeter Tyser 
15278acc472SPeter Tyser   const Byte *buf = p->buf;
15378acc472SPeter Tyser   UInt32 range = p->range;
15478acc472SPeter Tyser   UInt32 code = p->code;
15578acc472SPeter Tyser 
15678acc472SPeter Tyser   WATCHDOG_RESET();
15778acc472SPeter Tyser 
15878acc472SPeter Tyser   do
15978acc472SPeter Tyser   {
16078acc472SPeter Tyser     CLzmaProb *prob;
16178acc472SPeter Tyser     UInt32 bound;
16278acc472SPeter Tyser     unsigned ttt;
16378acc472SPeter Tyser     unsigned posState = processedPos & pbMask;
16478acc472SPeter Tyser 
16578acc472SPeter Tyser     prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
16678acc472SPeter Tyser     IF_BIT_0(prob)
16778acc472SPeter Tyser     {
16878acc472SPeter Tyser       unsigned symbol;
16978acc472SPeter Tyser       UPDATE_0(prob);
17078acc472SPeter Tyser       prob = probs + Literal;
17178acc472SPeter Tyser       if (checkDicSize != 0 || processedPos != 0)
17278acc472SPeter Tyser         prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
17378acc472SPeter Tyser         (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
17478acc472SPeter Tyser 
17578acc472SPeter Tyser       if (state < kNumLitStates)
17678acc472SPeter Tyser       {
177*5fe8380dSStefan Reinauer         state -= (state < 4) ? state : 3;
17878acc472SPeter Tyser         symbol = 1;
17978acc472SPeter Tyser 
18078acc472SPeter Tyser         WATCHDOG_RESET();
18178acc472SPeter Tyser 
18278acc472SPeter Tyser         do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
18378acc472SPeter Tyser       }
18478acc472SPeter Tyser       else
18578acc472SPeter Tyser       {
18678acc472SPeter Tyser         unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
18778acc472SPeter Tyser         unsigned offs = 0x100;
188*5fe8380dSStefan Reinauer         state -= (state < 10) ? 3 : 6;
18978acc472SPeter Tyser         symbol = 1;
19078acc472SPeter Tyser 
19178acc472SPeter Tyser         WATCHDOG_RESET();
19278acc472SPeter Tyser 
19378acc472SPeter Tyser         do
19478acc472SPeter Tyser         {
19578acc472SPeter Tyser           unsigned bit;
19678acc472SPeter Tyser           CLzmaProb *probLit;
19778acc472SPeter Tyser           matchByte <<= 1;
19878acc472SPeter Tyser           bit = (matchByte & offs);
19978acc472SPeter Tyser           probLit = prob + offs + bit + symbol;
20078acc472SPeter Tyser           GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
20178acc472SPeter Tyser         }
20278acc472SPeter Tyser         while (symbol < 0x100);
20378acc472SPeter Tyser       }
20478acc472SPeter Tyser       dic[dicPos++] = (Byte)symbol;
20578acc472SPeter Tyser       processedPos++;
20678acc472SPeter Tyser       continue;
20778acc472SPeter Tyser     }
20878acc472SPeter Tyser     else
20978acc472SPeter Tyser     {
21078acc472SPeter Tyser       UPDATE_1(prob);
21178acc472SPeter Tyser       prob = probs + IsRep + state;
21278acc472SPeter Tyser       IF_BIT_0(prob)
21378acc472SPeter Tyser       {
21478acc472SPeter Tyser         UPDATE_0(prob);
21578acc472SPeter Tyser         state += kNumStates;
21678acc472SPeter Tyser         prob = probs + LenCoder;
21778acc472SPeter Tyser       }
21878acc472SPeter Tyser       else
21978acc472SPeter Tyser       {
22078acc472SPeter Tyser         UPDATE_1(prob);
22178acc472SPeter Tyser         if (checkDicSize == 0 && processedPos == 0)
22278acc472SPeter Tyser           return SZ_ERROR_DATA;
22378acc472SPeter Tyser         prob = probs + IsRepG0 + state;
22478acc472SPeter Tyser         IF_BIT_0(prob)
22578acc472SPeter Tyser         {
22678acc472SPeter Tyser           UPDATE_0(prob);
22778acc472SPeter Tyser           prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
22878acc472SPeter Tyser           IF_BIT_0(prob)
22978acc472SPeter Tyser           {
23078acc472SPeter Tyser             UPDATE_0(prob);
23178acc472SPeter Tyser             dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
23278acc472SPeter Tyser             dicPos++;
23378acc472SPeter Tyser             processedPos++;
23478acc472SPeter Tyser             state = state < kNumLitStates ? 9 : 11;
23578acc472SPeter Tyser             continue;
23678acc472SPeter Tyser           }
23778acc472SPeter Tyser           UPDATE_1(prob);
23878acc472SPeter Tyser         }
23978acc472SPeter Tyser         else
24078acc472SPeter Tyser         {
24178acc472SPeter Tyser           UInt32 distance;
24278acc472SPeter Tyser           UPDATE_1(prob);
24378acc472SPeter Tyser           prob = probs + IsRepG1 + state;
24478acc472SPeter Tyser           IF_BIT_0(prob)
24578acc472SPeter Tyser           {
24678acc472SPeter Tyser             UPDATE_0(prob);
24778acc472SPeter Tyser             distance = rep1;
24878acc472SPeter Tyser           }
24978acc472SPeter Tyser           else
25078acc472SPeter Tyser           {
25178acc472SPeter Tyser             UPDATE_1(prob);
25278acc472SPeter Tyser             prob = probs + IsRepG2 + state;
25378acc472SPeter Tyser             IF_BIT_0(prob)
25478acc472SPeter Tyser             {
25578acc472SPeter Tyser               UPDATE_0(prob);
25678acc472SPeter Tyser               distance = rep2;
25778acc472SPeter Tyser             }
25878acc472SPeter Tyser             else
25978acc472SPeter Tyser             {
26078acc472SPeter Tyser               UPDATE_1(prob);
26178acc472SPeter Tyser               distance = rep3;
26278acc472SPeter Tyser               rep3 = rep2;
26378acc472SPeter Tyser             }
26478acc472SPeter Tyser             rep2 = rep1;
26578acc472SPeter Tyser           }
26678acc472SPeter Tyser           rep1 = rep0;
26778acc472SPeter Tyser           rep0 = distance;
26878acc472SPeter Tyser         }
26978acc472SPeter Tyser         state = state < kNumLitStates ? 8 : 11;
27078acc472SPeter Tyser         prob = probs + RepLenCoder;
27178acc472SPeter Tyser       }
27278acc472SPeter Tyser       {
27378acc472SPeter Tyser         unsigned limit, offset;
27478acc472SPeter Tyser         CLzmaProb *probLen = prob + LenChoice;
27578acc472SPeter Tyser         IF_BIT_0(probLen)
27678acc472SPeter Tyser         {
27778acc472SPeter Tyser           UPDATE_0(probLen);
27878acc472SPeter Tyser           probLen = prob + LenLow + (posState << kLenNumLowBits);
27978acc472SPeter Tyser           offset = 0;
28078acc472SPeter Tyser           limit = (1 << kLenNumLowBits);
28178acc472SPeter Tyser         }
28278acc472SPeter Tyser         else
28378acc472SPeter Tyser         {
28478acc472SPeter Tyser           UPDATE_1(probLen);
28578acc472SPeter Tyser           probLen = prob + LenChoice2;
28678acc472SPeter Tyser           IF_BIT_0(probLen)
28778acc472SPeter Tyser           {
28878acc472SPeter Tyser             UPDATE_0(probLen);
28978acc472SPeter Tyser             probLen = prob + LenMid + (posState << kLenNumMidBits);
29078acc472SPeter Tyser             offset = kLenNumLowSymbols;
29178acc472SPeter Tyser             limit = (1 << kLenNumMidBits);
29278acc472SPeter Tyser           }
29378acc472SPeter Tyser           else
29478acc472SPeter Tyser           {
29578acc472SPeter Tyser             UPDATE_1(probLen);
29678acc472SPeter Tyser             probLen = prob + LenHigh;
29778acc472SPeter Tyser             offset = kLenNumLowSymbols + kLenNumMidSymbols;
29878acc472SPeter Tyser             limit = (1 << kLenNumHighBits);
29978acc472SPeter Tyser           }
30078acc472SPeter Tyser         }
30178acc472SPeter Tyser         TREE_DECODE(probLen, limit, len);
30278acc472SPeter Tyser         len += offset;
30378acc472SPeter Tyser       }
30478acc472SPeter Tyser 
30578acc472SPeter Tyser       if (state >= kNumStates)
30678acc472SPeter Tyser       {
30778acc472SPeter Tyser         UInt32 distance;
30878acc472SPeter Tyser         prob = probs + PosSlot +
30978acc472SPeter Tyser             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
31078acc472SPeter Tyser         TREE_6_DECODE(prob, distance);
31178acc472SPeter Tyser         if (distance >= kStartPosModelIndex)
31278acc472SPeter Tyser         {
31378acc472SPeter Tyser           unsigned posSlot = (unsigned)distance;
31478acc472SPeter Tyser           int numDirectBits = (int)(((distance >> 1) - 1));
31578acc472SPeter Tyser           distance = (2 | (distance & 1));
31678acc472SPeter Tyser           if (posSlot < kEndPosModelIndex)
31778acc472SPeter Tyser           {
31878acc472SPeter Tyser             distance <<= numDirectBits;
31978acc472SPeter Tyser             prob = probs + SpecPos + distance - posSlot - 1;
32078acc472SPeter Tyser             {
32178acc472SPeter Tyser               UInt32 mask = 1;
32278acc472SPeter Tyser               unsigned i = 1;
32378acc472SPeter Tyser 
32478acc472SPeter Tyser               WATCHDOG_RESET();
32578acc472SPeter Tyser 
32678acc472SPeter Tyser               do
32778acc472SPeter Tyser               {
32878acc472SPeter Tyser                 GET_BIT2(prob + i, i, ; , distance |= mask);
32978acc472SPeter Tyser                 mask <<= 1;
33078acc472SPeter Tyser               }
33178acc472SPeter Tyser               while (--numDirectBits != 0);
33278acc472SPeter Tyser             }
33378acc472SPeter Tyser           }
33478acc472SPeter Tyser           else
33578acc472SPeter Tyser           {
33678acc472SPeter Tyser             numDirectBits -= kNumAlignBits;
33778acc472SPeter Tyser 
33878acc472SPeter Tyser             WATCHDOG_RESET();
33978acc472SPeter Tyser 
34078acc472SPeter Tyser             do
34178acc472SPeter Tyser             {
34278acc472SPeter Tyser               NORMALIZE
34378acc472SPeter Tyser               range >>= 1;
34478acc472SPeter Tyser 
34578acc472SPeter Tyser               {
34678acc472SPeter Tyser                 UInt32 t;
34778acc472SPeter Tyser                 code -= range;
34878acc472SPeter Tyser                 t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
34978acc472SPeter Tyser                 distance = (distance << 1) + (t + 1);
35078acc472SPeter Tyser                 code += range & t;
35178acc472SPeter Tyser               }
35278acc472SPeter Tyser               /*
35378acc472SPeter Tyser               distance <<= 1;
35478acc472SPeter Tyser               if (code >= range)
35578acc472SPeter Tyser               {
35678acc472SPeter Tyser                 code -= range;
35778acc472SPeter Tyser                 distance |= 1;
35878acc472SPeter Tyser               }
35978acc472SPeter Tyser               */
36078acc472SPeter Tyser             }
36178acc472SPeter Tyser             while (--numDirectBits != 0);
36278acc472SPeter Tyser             prob = probs + Align;
36378acc472SPeter Tyser             distance <<= kNumAlignBits;
36478acc472SPeter Tyser             {
36578acc472SPeter Tyser               unsigned i = 1;
36678acc472SPeter Tyser               GET_BIT2(prob + i, i, ; , distance |= 1);
36778acc472SPeter Tyser               GET_BIT2(prob + i, i, ; , distance |= 2);
36878acc472SPeter Tyser               GET_BIT2(prob + i, i, ; , distance |= 4);
36978acc472SPeter Tyser               GET_BIT2(prob + i, i, ; , distance |= 8);
37078acc472SPeter Tyser             }
37178acc472SPeter Tyser             if (distance == (UInt32)0xFFFFFFFF)
37278acc472SPeter Tyser             {
37378acc472SPeter Tyser               len += kMatchSpecLenStart;
37478acc472SPeter Tyser               state -= kNumStates;
37578acc472SPeter Tyser               break;
37678acc472SPeter Tyser             }
37778acc472SPeter Tyser           }
37878acc472SPeter Tyser         }
37978acc472SPeter Tyser         rep3 = rep2;
38078acc472SPeter Tyser         rep2 = rep1;
38178acc472SPeter Tyser         rep1 = rep0;
38278acc472SPeter Tyser         rep0 = distance + 1;
38378acc472SPeter Tyser         if (checkDicSize == 0)
38478acc472SPeter Tyser         {
38578acc472SPeter Tyser           if (distance >= processedPos)
38678acc472SPeter Tyser             return SZ_ERROR_DATA;
38778acc472SPeter Tyser         }
38878acc472SPeter Tyser         else if (distance >= checkDicSize)
38978acc472SPeter Tyser           return SZ_ERROR_DATA;
39078acc472SPeter Tyser         state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
39178acc472SPeter Tyser       }
39278acc472SPeter Tyser 
39378acc472SPeter Tyser       len += kMatchMinLen;
39478acc472SPeter Tyser 
39578acc472SPeter Tyser       if (limit == dicPos)
39678acc472SPeter Tyser         return SZ_ERROR_DATA;
39778acc472SPeter Tyser       {
39878acc472SPeter Tyser         SizeT rem = limit - dicPos;
39978acc472SPeter Tyser         unsigned curLen = ((rem < len) ? (unsigned)rem : len);
40078acc472SPeter Tyser         SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
40178acc472SPeter Tyser 
40278acc472SPeter Tyser         processedPos += curLen;
40378acc472SPeter Tyser 
40478acc472SPeter Tyser         len -= curLen;
40578acc472SPeter Tyser         if (pos + curLen <= dicBufSize)
40678acc472SPeter Tyser         {
40778acc472SPeter Tyser           Byte *dest = dic + dicPos;
40878acc472SPeter Tyser           ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
40978acc472SPeter Tyser           const Byte *lim = dest + curLen;
41078acc472SPeter Tyser           dicPos += curLen;
41178acc472SPeter Tyser 
41278acc472SPeter Tyser           WATCHDOG_RESET();
41378acc472SPeter Tyser 
41478acc472SPeter Tyser           do
41578acc472SPeter Tyser             *(dest) = (Byte)*(dest + src);
41678acc472SPeter Tyser           while (++dest != lim);
41778acc472SPeter Tyser         }
41878acc472SPeter Tyser         else
41978acc472SPeter Tyser         {
42078acc472SPeter Tyser 
42178acc472SPeter Tyser           WATCHDOG_RESET();
42278acc472SPeter Tyser 
42378acc472SPeter Tyser           do
42478acc472SPeter Tyser           {
42578acc472SPeter Tyser             dic[dicPos++] = dic[pos];
42678acc472SPeter Tyser             if (++pos == dicBufSize)
42778acc472SPeter Tyser               pos = 0;
42878acc472SPeter Tyser           }
42978acc472SPeter Tyser           while (--curLen != 0);
43078acc472SPeter Tyser         }
43178acc472SPeter Tyser       }
43278acc472SPeter Tyser     }
43378acc472SPeter Tyser   }
43478acc472SPeter Tyser   while (dicPos < limit && buf < bufLimit);
43578acc472SPeter Tyser 
43678acc472SPeter Tyser   WATCHDOG_RESET();
43778acc472SPeter Tyser 
43878acc472SPeter Tyser   NORMALIZE;
43978acc472SPeter Tyser   p->buf = buf;
44078acc472SPeter Tyser   p->range = range;
44178acc472SPeter Tyser   p->code = code;
44278acc472SPeter Tyser   p->remainLen = len;
44378acc472SPeter Tyser   p->dicPos = dicPos;
44478acc472SPeter Tyser   p->processedPos = processedPos;
44578acc472SPeter Tyser   p->reps[0] = rep0;
44678acc472SPeter Tyser   p->reps[1] = rep1;
44778acc472SPeter Tyser   p->reps[2] = rep2;
44878acc472SPeter Tyser   p->reps[3] = rep3;
44978acc472SPeter Tyser   p->state = state;
45078acc472SPeter Tyser 
45178acc472SPeter Tyser   return SZ_OK;
45278acc472SPeter Tyser }
45378acc472SPeter Tyser 
LzmaDec_WriteRem(CLzmaDec * p,SizeT limit)45478acc472SPeter Tyser static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
45578acc472SPeter Tyser {
45678acc472SPeter Tyser   if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
45778acc472SPeter Tyser   {
45878acc472SPeter Tyser     Byte *dic = p->dic;
45978acc472SPeter Tyser     SizeT dicPos = p->dicPos;
46078acc472SPeter Tyser     SizeT dicBufSize = p->dicBufSize;
46178acc472SPeter Tyser     unsigned len = p->remainLen;
46278acc472SPeter Tyser     UInt32 rep0 = p->reps[0];
46378acc472SPeter Tyser     if (limit - dicPos < len)
46478acc472SPeter Tyser       len = (unsigned)(limit - dicPos);
46578acc472SPeter Tyser 
46678acc472SPeter Tyser     if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
46778acc472SPeter Tyser       p->checkDicSize = p->prop.dicSize;
46878acc472SPeter Tyser 
46978acc472SPeter Tyser     p->processedPos += len;
47078acc472SPeter Tyser     p->remainLen -= len;
47178acc472SPeter Tyser     while (len-- != 0)
47278acc472SPeter Tyser     {
47378acc472SPeter Tyser       dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
47478acc472SPeter Tyser       dicPos++;
47578acc472SPeter Tyser     }
47678acc472SPeter Tyser     p->dicPos = dicPos;
47778acc472SPeter Tyser   }
47878acc472SPeter Tyser }
47978acc472SPeter Tyser 
LzmaDec_DecodeReal2(CLzmaDec * p,SizeT limit,const Byte * bufLimit)48078acc472SPeter Tyser static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
48178acc472SPeter Tyser {
48278acc472SPeter Tyser   do
48378acc472SPeter Tyser   {
48478acc472SPeter Tyser     SizeT limit2 = limit;
48578acc472SPeter Tyser     if (p->checkDicSize == 0)
48678acc472SPeter Tyser     {
48778acc472SPeter Tyser       UInt32 rem = p->prop.dicSize - p->processedPos;
48878acc472SPeter Tyser       if (limit - p->dicPos > rem)
48978acc472SPeter Tyser         limit2 = p->dicPos + rem;
49078acc472SPeter Tyser     }
49178acc472SPeter Tyser     RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
49278acc472SPeter Tyser     if (p->processedPos >= p->prop.dicSize)
49378acc472SPeter Tyser       p->checkDicSize = p->prop.dicSize;
49478acc472SPeter Tyser     LzmaDec_WriteRem(p, limit);
49578acc472SPeter Tyser   }
49678acc472SPeter Tyser   while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
49778acc472SPeter Tyser 
49878acc472SPeter Tyser   if (p->remainLen > kMatchSpecLenStart)
49978acc472SPeter Tyser   {
50078acc472SPeter Tyser     p->remainLen = kMatchSpecLenStart;
50178acc472SPeter Tyser   }
50278acc472SPeter Tyser   return 0;
50378acc472SPeter Tyser }
50478acc472SPeter Tyser 
50578acc472SPeter Tyser typedef enum
50678acc472SPeter Tyser {
50778acc472SPeter Tyser   DUMMY_ERROR, /* unexpected end of input stream */
50878acc472SPeter Tyser   DUMMY_LIT,
50978acc472SPeter Tyser   DUMMY_MATCH,
51078acc472SPeter Tyser   DUMMY_REP
51178acc472SPeter Tyser } ELzmaDummy;
51278acc472SPeter Tyser 
LzmaDec_TryDummy(const CLzmaDec * p,const Byte * buf,SizeT inSize)51378acc472SPeter Tyser static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
51478acc472SPeter Tyser {
51578acc472SPeter Tyser   UInt32 range = p->range;
51678acc472SPeter Tyser   UInt32 code = p->code;
51778acc472SPeter Tyser   const Byte *bufLimit = buf + inSize;
51878acc472SPeter Tyser   CLzmaProb *probs = p->probs;
51978acc472SPeter Tyser   unsigned state = p->state;
52078acc472SPeter Tyser   ELzmaDummy res;
52178acc472SPeter Tyser 
52278acc472SPeter Tyser   {
52378acc472SPeter Tyser     CLzmaProb *prob;
52478acc472SPeter Tyser     UInt32 bound;
52578acc472SPeter Tyser     unsigned ttt;
52678acc472SPeter Tyser     unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
52778acc472SPeter Tyser 
52878acc472SPeter Tyser     prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
52978acc472SPeter Tyser     IF_BIT_0_CHECK(prob)
53078acc472SPeter Tyser     {
53178acc472SPeter Tyser       UPDATE_0_CHECK
53278acc472SPeter Tyser 
53378acc472SPeter Tyser       /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
53478acc472SPeter Tyser 
53578acc472SPeter Tyser       prob = probs + Literal;
53678acc472SPeter Tyser       if (p->checkDicSize != 0 || p->processedPos != 0)
53778acc472SPeter Tyser         prob += (LZMA_LIT_SIZE *
53878acc472SPeter Tyser           ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
53978acc472SPeter Tyser           (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
54078acc472SPeter Tyser 
54178acc472SPeter Tyser       if (state < kNumLitStates)
54278acc472SPeter Tyser       {
54378acc472SPeter Tyser         unsigned symbol = 1;
54478acc472SPeter Tyser         do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
54578acc472SPeter Tyser       }
54678acc472SPeter Tyser       else
54778acc472SPeter Tyser       {
54878acc472SPeter Tyser         unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
54978acc472SPeter Tyser             ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
55078acc472SPeter Tyser         unsigned offs = 0x100;
55178acc472SPeter Tyser         unsigned symbol = 1;
55278acc472SPeter Tyser         do
55378acc472SPeter Tyser         {
55478acc472SPeter Tyser           unsigned bit;
55578acc472SPeter Tyser           CLzmaProb *probLit;
55678acc472SPeter Tyser           matchByte <<= 1;
55778acc472SPeter Tyser           bit = (matchByte & offs);
55878acc472SPeter Tyser           probLit = prob + offs + bit + symbol;
55978acc472SPeter Tyser           GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
56078acc472SPeter Tyser         }
56178acc472SPeter Tyser         while (symbol < 0x100);
56278acc472SPeter Tyser       }
56378acc472SPeter Tyser       res = DUMMY_LIT;
56478acc472SPeter Tyser     }
56578acc472SPeter Tyser     else
56678acc472SPeter Tyser     {
56778acc472SPeter Tyser       unsigned len;
56878acc472SPeter Tyser       UPDATE_1_CHECK;
56978acc472SPeter Tyser 
57078acc472SPeter Tyser       prob = probs + IsRep + state;
57178acc472SPeter Tyser       IF_BIT_0_CHECK(prob)
57278acc472SPeter Tyser       {
57378acc472SPeter Tyser         UPDATE_0_CHECK;
57478acc472SPeter Tyser         state = 0;
57578acc472SPeter Tyser         prob = probs + LenCoder;
57678acc472SPeter Tyser         res = DUMMY_MATCH;
57778acc472SPeter Tyser       }
57878acc472SPeter Tyser       else
57978acc472SPeter Tyser       {
58078acc472SPeter Tyser         UPDATE_1_CHECK;
58178acc472SPeter Tyser         res = DUMMY_REP;
58278acc472SPeter Tyser         prob = probs + IsRepG0 + state;
58378acc472SPeter Tyser         IF_BIT_0_CHECK(prob)
58478acc472SPeter Tyser         {
58578acc472SPeter Tyser           UPDATE_0_CHECK;
58678acc472SPeter Tyser           prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
58778acc472SPeter Tyser           IF_BIT_0_CHECK(prob)
58878acc472SPeter Tyser           {
58978acc472SPeter Tyser             UPDATE_0_CHECK;
59078acc472SPeter Tyser             NORMALIZE_CHECK;
59178acc472SPeter Tyser             return DUMMY_REP;
59278acc472SPeter Tyser           }
59378acc472SPeter Tyser           else
59478acc472SPeter Tyser           {
59578acc472SPeter Tyser             UPDATE_1_CHECK;
59678acc472SPeter Tyser           }
59778acc472SPeter Tyser         }
59878acc472SPeter Tyser         else
59978acc472SPeter Tyser         {
60078acc472SPeter Tyser           UPDATE_1_CHECK;
60178acc472SPeter Tyser           prob = probs + IsRepG1 + state;
60278acc472SPeter Tyser           IF_BIT_0_CHECK(prob)
60378acc472SPeter Tyser           {
60478acc472SPeter Tyser             UPDATE_0_CHECK;
60578acc472SPeter Tyser           }
60678acc472SPeter Tyser           else
60778acc472SPeter Tyser           {
60878acc472SPeter Tyser             UPDATE_1_CHECK;
60978acc472SPeter Tyser             prob = probs + IsRepG2 + state;
61078acc472SPeter Tyser             IF_BIT_0_CHECK(prob)
61178acc472SPeter Tyser             {
61278acc472SPeter Tyser               UPDATE_0_CHECK;
61378acc472SPeter Tyser             }
61478acc472SPeter Tyser             else
61578acc472SPeter Tyser             {
61678acc472SPeter Tyser               UPDATE_1_CHECK;
61778acc472SPeter Tyser             }
61878acc472SPeter Tyser           }
61978acc472SPeter Tyser         }
62078acc472SPeter Tyser         state = kNumStates;
62178acc472SPeter Tyser         prob = probs + RepLenCoder;
62278acc472SPeter Tyser       }
62378acc472SPeter Tyser       {
62478acc472SPeter Tyser         unsigned limit, offset;
62578acc472SPeter Tyser         CLzmaProb *probLen = prob + LenChoice;
62678acc472SPeter Tyser         IF_BIT_0_CHECK(probLen)
62778acc472SPeter Tyser         {
62878acc472SPeter Tyser           UPDATE_0_CHECK;
62978acc472SPeter Tyser           probLen = prob + LenLow + (posState << kLenNumLowBits);
63078acc472SPeter Tyser           offset = 0;
63178acc472SPeter Tyser           limit = 1 << kLenNumLowBits;
63278acc472SPeter Tyser         }
63378acc472SPeter Tyser         else
63478acc472SPeter Tyser         {
63578acc472SPeter Tyser           UPDATE_1_CHECK;
63678acc472SPeter Tyser           probLen = prob + LenChoice2;
63778acc472SPeter Tyser           IF_BIT_0_CHECK(probLen)
63878acc472SPeter Tyser           {
63978acc472SPeter Tyser             UPDATE_0_CHECK;
64078acc472SPeter Tyser             probLen = prob + LenMid + (posState << kLenNumMidBits);
64178acc472SPeter Tyser             offset = kLenNumLowSymbols;
64278acc472SPeter Tyser             limit = 1 << kLenNumMidBits;
64378acc472SPeter Tyser           }
64478acc472SPeter Tyser           else
64578acc472SPeter Tyser           {
64678acc472SPeter Tyser             UPDATE_1_CHECK;
64778acc472SPeter Tyser             probLen = prob + LenHigh;
64878acc472SPeter Tyser             offset = kLenNumLowSymbols + kLenNumMidSymbols;
64978acc472SPeter Tyser             limit = 1 << kLenNumHighBits;
65078acc472SPeter Tyser           }
65178acc472SPeter Tyser         }
65278acc472SPeter Tyser         TREE_DECODE_CHECK(probLen, limit, len);
65378acc472SPeter Tyser         len += offset;
65478acc472SPeter Tyser       }
65578acc472SPeter Tyser 
65678acc472SPeter Tyser       if (state < 4)
65778acc472SPeter Tyser       {
65878acc472SPeter Tyser         unsigned posSlot;
65978acc472SPeter Tyser         prob = probs + PosSlot +
66078acc472SPeter Tyser             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
66178acc472SPeter Tyser             kNumPosSlotBits);
66278acc472SPeter Tyser         TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
66378acc472SPeter Tyser         if (posSlot >= kStartPosModelIndex)
66478acc472SPeter Tyser         {
66578acc472SPeter Tyser           int numDirectBits = ((posSlot >> 1) - 1);
66678acc472SPeter Tyser 
66778acc472SPeter Tyser           /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
66878acc472SPeter Tyser 
66978acc472SPeter Tyser           if (posSlot < kEndPosModelIndex)
67078acc472SPeter Tyser           {
67178acc472SPeter Tyser             prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
67278acc472SPeter Tyser           }
67378acc472SPeter Tyser           else
67478acc472SPeter Tyser           {
67578acc472SPeter Tyser             numDirectBits -= kNumAlignBits;
67678acc472SPeter Tyser             do
67778acc472SPeter Tyser             {
67878acc472SPeter Tyser               NORMALIZE_CHECK
67978acc472SPeter Tyser               range >>= 1;
68078acc472SPeter Tyser               code -= range & (((code - range) >> 31) - 1);
68178acc472SPeter Tyser               /* if (code >= range) code -= range; */
68278acc472SPeter Tyser             }
68378acc472SPeter Tyser             while (--numDirectBits != 0);
68478acc472SPeter Tyser             prob = probs + Align;
68578acc472SPeter Tyser             numDirectBits = kNumAlignBits;
68678acc472SPeter Tyser           }
68778acc472SPeter Tyser           {
68878acc472SPeter Tyser             unsigned i = 1;
68978acc472SPeter Tyser             do
69078acc472SPeter Tyser             {
69178acc472SPeter Tyser               GET_BIT_CHECK(prob + i, i);
69278acc472SPeter Tyser             }
69378acc472SPeter Tyser             while (--numDirectBits != 0);
69478acc472SPeter Tyser           }
69578acc472SPeter Tyser         }
69678acc472SPeter Tyser       }
69778acc472SPeter Tyser     }
69878acc472SPeter Tyser   }
69978acc472SPeter Tyser   NORMALIZE_CHECK;
70078acc472SPeter Tyser   return res;
70178acc472SPeter Tyser }
70278acc472SPeter Tyser 
70378acc472SPeter Tyser 
LzmaDec_InitRc(CLzmaDec * p,const Byte * data)70478acc472SPeter Tyser static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
70578acc472SPeter Tyser {
70678acc472SPeter Tyser   p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
70778acc472SPeter Tyser   p->range = 0xFFFFFFFF;
70878acc472SPeter Tyser   p->needFlush = 0;
70978acc472SPeter Tyser }
71078acc472SPeter Tyser 
LzmaDec_InitDicAndState(CLzmaDec * p,Bool initDic,Bool initState)71178acc472SPeter Tyser void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
71278acc472SPeter Tyser {
71378acc472SPeter Tyser   p->needFlush = 1;
71478acc472SPeter Tyser   p->remainLen = 0;
71578acc472SPeter Tyser   p->tempBufSize = 0;
71678acc472SPeter Tyser 
71778acc472SPeter Tyser   if (initDic)
71878acc472SPeter Tyser   {
71978acc472SPeter Tyser     p->processedPos = 0;
72078acc472SPeter Tyser     p->checkDicSize = 0;
72178acc472SPeter Tyser     p->needInitState = 1;
72278acc472SPeter Tyser   }
72378acc472SPeter Tyser   if (initState)
72478acc472SPeter Tyser     p->needInitState = 1;
72578acc472SPeter Tyser }
72678acc472SPeter Tyser 
LzmaDec_Init(CLzmaDec * p)72778acc472SPeter Tyser void LzmaDec_Init(CLzmaDec *p)
72878acc472SPeter Tyser {
72978acc472SPeter Tyser   p->dicPos = 0;
73078acc472SPeter Tyser   LzmaDec_InitDicAndState(p, True, True);
73178acc472SPeter Tyser }
73278acc472SPeter Tyser 
LzmaDec_InitStateReal(CLzmaDec * p)73378acc472SPeter Tyser static void LzmaDec_InitStateReal(CLzmaDec *p)
73478acc472SPeter Tyser {
73578acc472SPeter Tyser   UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
73678acc472SPeter Tyser   UInt32 i;
73778acc472SPeter Tyser   CLzmaProb *probs = p->probs;
73878acc472SPeter Tyser   for (i = 0; i < numProbs; i++)
73978acc472SPeter Tyser     probs[i] = kBitModelTotal >> 1;
74078acc472SPeter Tyser   p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
74178acc472SPeter Tyser   p->state = 0;
74278acc472SPeter Tyser   p->needInitState = 0;
74378acc472SPeter Tyser }
74478acc472SPeter Tyser 
LzmaDec_DecodeToDic(CLzmaDec * p,SizeT dicLimit,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)74578acc472SPeter Tyser SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
74678acc472SPeter Tyser     ELzmaFinishMode finishMode, ELzmaStatus *status)
74778acc472SPeter Tyser {
74878acc472SPeter Tyser   SizeT inSize = *srcLen;
74978acc472SPeter Tyser   (*srcLen) = 0;
75078acc472SPeter Tyser   LzmaDec_WriteRem(p, dicLimit);
75178acc472SPeter Tyser 
75278acc472SPeter Tyser   *status = LZMA_STATUS_NOT_SPECIFIED;
75378acc472SPeter Tyser 
75478acc472SPeter Tyser   while (p->remainLen != kMatchSpecLenStart)
75578acc472SPeter Tyser   {
75678acc472SPeter Tyser       int checkEndMarkNow;
75778acc472SPeter Tyser 
75878acc472SPeter Tyser       if (p->needFlush != 0)
75978acc472SPeter Tyser       {
76078acc472SPeter Tyser         for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
76178acc472SPeter Tyser           p->tempBuf[p->tempBufSize++] = *src++;
76278acc472SPeter Tyser         if (p->tempBufSize < RC_INIT_SIZE)
76378acc472SPeter Tyser         {
76478acc472SPeter Tyser           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
76578acc472SPeter Tyser           return SZ_OK;
76678acc472SPeter Tyser         }
76778acc472SPeter Tyser         if (p->tempBuf[0] != 0)
76878acc472SPeter Tyser           return SZ_ERROR_DATA;
76978acc472SPeter Tyser 
77078acc472SPeter Tyser         LzmaDec_InitRc(p, p->tempBuf);
77178acc472SPeter Tyser         p->tempBufSize = 0;
77278acc472SPeter Tyser       }
77378acc472SPeter Tyser 
77478acc472SPeter Tyser       checkEndMarkNow = 0;
77578acc472SPeter Tyser       if (p->dicPos >= dicLimit)
77678acc472SPeter Tyser       {
77778acc472SPeter Tyser         if (p->remainLen == 0 && p->code == 0)
77878acc472SPeter Tyser         {
77978acc472SPeter Tyser           *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
78078acc472SPeter Tyser           return SZ_OK;
78178acc472SPeter Tyser         }
78278acc472SPeter Tyser         if (finishMode == LZMA_FINISH_ANY)
78378acc472SPeter Tyser         {
78478acc472SPeter Tyser           *status = LZMA_STATUS_NOT_FINISHED;
78578acc472SPeter Tyser           return SZ_OK;
78678acc472SPeter Tyser         }
78778acc472SPeter Tyser         if (p->remainLen != 0)
78878acc472SPeter Tyser         {
78978acc472SPeter Tyser           *status = LZMA_STATUS_NOT_FINISHED;
79078acc472SPeter Tyser           return SZ_ERROR_DATA;
79178acc472SPeter Tyser         }
79278acc472SPeter Tyser         checkEndMarkNow = 1;
79378acc472SPeter Tyser       }
79478acc472SPeter Tyser 
79578acc472SPeter Tyser       if (p->needInitState)
79678acc472SPeter Tyser         LzmaDec_InitStateReal(p);
79778acc472SPeter Tyser 
79878acc472SPeter Tyser       if (p->tempBufSize == 0)
79978acc472SPeter Tyser       {
80078acc472SPeter Tyser         SizeT processed;
80178acc472SPeter Tyser         const Byte *bufLimit;
80278acc472SPeter Tyser         if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
80378acc472SPeter Tyser         {
80478acc472SPeter Tyser           int dummyRes = LzmaDec_TryDummy(p, src, inSize);
80578acc472SPeter Tyser           if (dummyRes == DUMMY_ERROR)
80678acc472SPeter Tyser           {
80778acc472SPeter Tyser             memcpy(p->tempBuf, src, inSize);
80878acc472SPeter Tyser             p->tempBufSize = (unsigned)inSize;
80978acc472SPeter Tyser             (*srcLen) += inSize;
81078acc472SPeter Tyser             *status = LZMA_STATUS_NEEDS_MORE_INPUT;
81178acc472SPeter Tyser             return SZ_OK;
81278acc472SPeter Tyser           }
81378acc472SPeter Tyser           if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
81478acc472SPeter Tyser           {
81578acc472SPeter Tyser             *status = LZMA_STATUS_NOT_FINISHED;
81678acc472SPeter Tyser             return SZ_ERROR_DATA;
81778acc472SPeter Tyser           }
81878acc472SPeter Tyser           bufLimit = src;
81978acc472SPeter Tyser         }
82078acc472SPeter Tyser         else
82178acc472SPeter Tyser           bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
82278acc472SPeter Tyser         p->buf = src;
82378acc472SPeter Tyser         if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
82478acc472SPeter Tyser           return SZ_ERROR_DATA;
82578acc472SPeter Tyser         processed = (SizeT)(p->buf - src);
82678acc472SPeter Tyser         (*srcLen) += processed;
82778acc472SPeter Tyser         src += processed;
82878acc472SPeter Tyser         inSize -= processed;
82978acc472SPeter Tyser       }
83078acc472SPeter Tyser       else
83178acc472SPeter Tyser       {
83278acc472SPeter Tyser         unsigned rem = p->tempBufSize, lookAhead = 0;
83378acc472SPeter Tyser         while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
83478acc472SPeter Tyser           p->tempBuf[rem++] = src[lookAhead++];
83578acc472SPeter Tyser         p->tempBufSize = rem;
83678acc472SPeter Tyser         if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
83778acc472SPeter Tyser         {
83878acc472SPeter Tyser           int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
83978acc472SPeter Tyser           if (dummyRes == DUMMY_ERROR)
84078acc472SPeter Tyser           {
84178acc472SPeter Tyser             (*srcLen) += lookAhead;
84278acc472SPeter Tyser             *status = LZMA_STATUS_NEEDS_MORE_INPUT;
84378acc472SPeter Tyser             return SZ_OK;
84478acc472SPeter Tyser           }
84578acc472SPeter Tyser           if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
84678acc472SPeter Tyser           {
84778acc472SPeter Tyser             *status = LZMA_STATUS_NOT_FINISHED;
84878acc472SPeter Tyser             return SZ_ERROR_DATA;
84978acc472SPeter Tyser           }
85078acc472SPeter Tyser         }
85178acc472SPeter Tyser         p->buf = p->tempBuf;
85278acc472SPeter Tyser         if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
85378acc472SPeter Tyser           return SZ_ERROR_DATA;
85478acc472SPeter Tyser         lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
85578acc472SPeter Tyser         (*srcLen) += lookAhead;
85678acc472SPeter Tyser         src += lookAhead;
85778acc472SPeter Tyser         inSize -= lookAhead;
85878acc472SPeter Tyser         p->tempBufSize = 0;
85978acc472SPeter Tyser       }
86078acc472SPeter Tyser   }
86178acc472SPeter Tyser   if (p->code == 0)
86278acc472SPeter Tyser     *status = LZMA_STATUS_FINISHED_WITH_MARK;
86378acc472SPeter Tyser   return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
86478acc472SPeter Tyser }
86578acc472SPeter Tyser 
LzmaDec_DecodeToBuf(CLzmaDec * p,Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,ELzmaFinishMode finishMode,ELzmaStatus * status)86678acc472SPeter Tyser SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
86778acc472SPeter Tyser {
86878acc472SPeter Tyser   SizeT outSize = *destLen;
86978acc472SPeter Tyser   SizeT inSize = *srcLen;
87078acc472SPeter Tyser   *srcLen = *destLen = 0;
87178acc472SPeter Tyser   for (;;)
87278acc472SPeter Tyser   {
87378acc472SPeter Tyser     SizeT inSizeCur = inSize, outSizeCur, dicPos;
87478acc472SPeter Tyser     ELzmaFinishMode curFinishMode;
87578acc472SPeter Tyser     SRes res;
87678acc472SPeter Tyser     if (p->dicPos == p->dicBufSize)
87778acc472SPeter Tyser       p->dicPos = 0;
87878acc472SPeter Tyser     dicPos = p->dicPos;
87978acc472SPeter Tyser     if (outSize > p->dicBufSize - dicPos)
88078acc472SPeter Tyser     {
88178acc472SPeter Tyser       outSizeCur = p->dicBufSize;
88278acc472SPeter Tyser       curFinishMode = LZMA_FINISH_ANY;
88378acc472SPeter Tyser     }
88478acc472SPeter Tyser     else
88578acc472SPeter Tyser     {
88678acc472SPeter Tyser       outSizeCur = dicPos + outSize;
88778acc472SPeter Tyser       curFinishMode = finishMode;
88878acc472SPeter Tyser     }
88978acc472SPeter Tyser 
89078acc472SPeter Tyser     res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
89178acc472SPeter Tyser     src += inSizeCur;
89278acc472SPeter Tyser     inSize -= inSizeCur;
89378acc472SPeter Tyser     *srcLen += inSizeCur;
89478acc472SPeter Tyser     outSizeCur = p->dicPos - dicPos;
89578acc472SPeter Tyser     memcpy(dest, p->dic + dicPos, outSizeCur);
89678acc472SPeter Tyser     dest += outSizeCur;
89778acc472SPeter Tyser     outSize -= outSizeCur;
89878acc472SPeter Tyser     *destLen += outSizeCur;
89978acc472SPeter Tyser     if (res != 0)
90078acc472SPeter Tyser       return res;
90178acc472SPeter Tyser     if (outSizeCur == 0 || outSize == 0)
90278acc472SPeter Tyser       return SZ_OK;
90378acc472SPeter Tyser   }
90478acc472SPeter Tyser }
90578acc472SPeter Tyser 
LzmaDec_FreeProbs(CLzmaDec * p,ISzAlloc * alloc)90678acc472SPeter Tyser void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
90778acc472SPeter Tyser {
90878acc472SPeter Tyser   alloc->Free(alloc, p->probs);
90978acc472SPeter Tyser   p->probs = 0;
91078acc472SPeter Tyser }
91178acc472SPeter Tyser 
LzmaDec_FreeDict(CLzmaDec * p,ISzAlloc * alloc)91278acc472SPeter Tyser static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
91378acc472SPeter Tyser {
91478acc472SPeter Tyser   alloc->Free(alloc, p->dic);
91578acc472SPeter Tyser   p->dic = 0;
91678acc472SPeter Tyser }
91778acc472SPeter Tyser 
LzmaDec_Free(CLzmaDec * p,ISzAlloc * alloc)91878acc472SPeter Tyser void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
91978acc472SPeter Tyser {
92078acc472SPeter Tyser   LzmaDec_FreeProbs(p, alloc);
92178acc472SPeter Tyser   LzmaDec_FreeDict(p, alloc);
92278acc472SPeter Tyser }
92378acc472SPeter Tyser 
LzmaProps_Decode(CLzmaProps * p,const Byte * data,unsigned size)92478acc472SPeter Tyser SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
92578acc472SPeter Tyser {
92678acc472SPeter Tyser   UInt32 dicSize;
92778acc472SPeter Tyser   Byte d;
92878acc472SPeter Tyser 
92978acc472SPeter Tyser   if (size < LZMA_PROPS_SIZE)
93078acc472SPeter Tyser     return SZ_ERROR_UNSUPPORTED;
93178acc472SPeter Tyser   else
93278acc472SPeter Tyser     dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
93378acc472SPeter Tyser 
93478acc472SPeter Tyser   if (dicSize < LZMA_DIC_MIN)
93578acc472SPeter Tyser     dicSize = LZMA_DIC_MIN;
93678acc472SPeter Tyser   p->dicSize = dicSize;
93778acc472SPeter Tyser 
93878acc472SPeter Tyser   d = data[0];
93978acc472SPeter Tyser   if (d >= (9 * 5 * 5))
94078acc472SPeter Tyser     return SZ_ERROR_UNSUPPORTED;
94178acc472SPeter Tyser 
94278acc472SPeter Tyser   p->lc = d % 9;
94378acc472SPeter Tyser   d /= 9;
94478acc472SPeter Tyser   p->pb = d / 5;
94578acc472SPeter Tyser   p->lp = d % 5;
94678acc472SPeter Tyser 
94778acc472SPeter Tyser   return SZ_OK;
94878acc472SPeter Tyser }
94978acc472SPeter Tyser 
LzmaDec_AllocateProbs2(CLzmaDec * p,const CLzmaProps * propNew,ISzAlloc * alloc)95078acc472SPeter Tyser static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
95178acc472SPeter Tyser {
95278acc472SPeter Tyser   UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
95378acc472SPeter Tyser   if (p->probs == 0 || numProbs != p->numProbs)
95478acc472SPeter Tyser   {
95578acc472SPeter Tyser     LzmaDec_FreeProbs(p, alloc);
95678acc472SPeter Tyser     p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
95778acc472SPeter Tyser     p->numProbs = numProbs;
95878acc472SPeter Tyser     if (p->probs == 0)
95978acc472SPeter Tyser       return SZ_ERROR_MEM;
96078acc472SPeter Tyser   }
96178acc472SPeter Tyser   return SZ_OK;
96278acc472SPeter Tyser }
96378acc472SPeter Tyser 
LzmaDec_AllocateProbs(CLzmaDec * p,const Byte * props,unsigned propsSize,ISzAlloc * alloc)96478acc472SPeter Tyser SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
96578acc472SPeter Tyser {
96678acc472SPeter Tyser   CLzmaProps propNew;
96778acc472SPeter Tyser   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
96878acc472SPeter Tyser   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
96978acc472SPeter Tyser   p->prop = propNew;
97078acc472SPeter Tyser   return SZ_OK;
97178acc472SPeter Tyser }
97278acc472SPeter Tyser 
LzmaDec_Allocate(CLzmaDec * p,const Byte * props,unsigned propsSize,ISzAlloc * alloc)97378acc472SPeter Tyser SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
97478acc472SPeter Tyser {
97578acc472SPeter Tyser   CLzmaProps propNew;
97678acc472SPeter Tyser   SizeT dicBufSize;
97778acc472SPeter Tyser   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
97878acc472SPeter Tyser   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
97978acc472SPeter Tyser   dicBufSize = propNew.dicSize;
98078acc472SPeter Tyser   if (p->dic == 0 || dicBufSize != p->dicBufSize)
98178acc472SPeter Tyser   {
98278acc472SPeter Tyser     LzmaDec_FreeDict(p, alloc);
98378acc472SPeter Tyser     p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
98478acc472SPeter Tyser     if (p->dic == 0)
98578acc472SPeter Tyser     {
98678acc472SPeter Tyser       LzmaDec_FreeProbs(p, alloc);
98778acc472SPeter Tyser       return SZ_ERROR_MEM;
98878acc472SPeter Tyser     }
98978acc472SPeter Tyser   }
99078acc472SPeter Tyser   p->dicBufSize = dicBufSize;
99178acc472SPeter Tyser   p->prop = propNew;
99278acc472SPeter Tyser   return SZ_OK;
99378acc472SPeter Tyser }
99478acc472SPeter Tyser 
LzmaDecode(Byte * dest,SizeT * destLen,const Byte * src,SizeT * srcLen,const Byte * propData,unsigned propSize,ELzmaFinishMode finishMode,ELzmaStatus * status,ISzAlloc * alloc)99578acc472SPeter Tyser SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
99678acc472SPeter Tyser     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
99778acc472SPeter Tyser     ELzmaStatus *status, ISzAlloc *alloc)
99878acc472SPeter Tyser {
99978acc472SPeter Tyser   CLzmaDec p;
100078acc472SPeter Tyser   SRes res;
100178acc472SPeter Tyser   SizeT inSize = *srcLen;
100278acc472SPeter Tyser   SizeT outSize = *destLen;
100378acc472SPeter Tyser   *srcLen = *destLen = 0;
100478acc472SPeter Tyser   if (inSize < RC_INIT_SIZE)
100578acc472SPeter Tyser     return SZ_ERROR_INPUT_EOF;
100678acc472SPeter Tyser 
100778acc472SPeter Tyser   LzmaDec_Construct(&p);
100878acc472SPeter Tyser   res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
100978acc472SPeter Tyser   if (res != 0)
101078acc472SPeter Tyser     return res;
101178acc472SPeter Tyser   p.dic = dest;
101278acc472SPeter Tyser   p.dicBufSize = outSize;
101378acc472SPeter Tyser 
101478acc472SPeter Tyser   LzmaDec_Init(&p);
101578acc472SPeter Tyser 
101678acc472SPeter Tyser   *srcLen = inSize;
101778acc472SPeter Tyser   res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
101878acc472SPeter Tyser 
101978acc472SPeter Tyser   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
102078acc472SPeter Tyser     res = SZ_ERROR_INPUT_EOF;
102178acc472SPeter Tyser 
102278acc472SPeter Tyser   (*destLen) = p.dicPos;
102378acc472SPeter Tyser   LzmaDec_FreeProbs(&p, alloc);
102478acc472SPeter Tyser   return res;
102578acc472SPeter Tyser }
1026