xref: /illumos-gate/usr/src/common/lzma/LzmaDec.c (revision b1efbcd6)
1*b1efbcd6SAlok Aggarwal /*
2*b1efbcd6SAlok Aggarwal  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3*b1efbcd6SAlok Aggarwal  * Use is subject to license terms.
4*b1efbcd6SAlok Aggarwal  */
5*b1efbcd6SAlok Aggarwal 
6*b1efbcd6SAlok Aggarwal /* LzmaDec.c -- LZMA Decoder
7*b1efbcd6SAlok Aggarwal 2008-11-06 : Igor Pavlov : Public domain */
8*b1efbcd6SAlok Aggarwal 
9*b1efbcd6SAlok Aggarwal #include "LzmaDec.h"
10*b1efbcd6SAlok Aggarwal 
11*b1efbcd6SAlok Aggarwal #ifndef _KERNEL
12*b1efbcd6SAlok Aggarwal #include <string.h>
13*b1efbcd6SAlok Aggarwal #endif /* _KERNEL */
14*b1efbcd6SAlok Aggarwal 
15*b1efbcd6SAlok Aggarwal #define kNumTopBits 24
16*b1efbcd6SAlok Aggarwal #define kTopValue ((UInt32)1 << kNumTopBits)
17*b1efbcd6SAlok Aggarwal 
18*b1efbcd6SAlok Aggarwal #define kNumBitModelTotalBits 11
19*b1efbcd6SAlok Aggarwal #define kBitModelTotal (1 << kNumBitModelTotalBits)
20*b1efbcd6SAlok Aggarwal #define kNumMoveBits 5
21*b1efbcd6SAlok Aggarwal 
22*b1efbcd6SAlok Aggarwal #define RC_INIT_SIZE 5
23*b1efbcd6SAlok Aggarwal 
24*b1efbcd6SAlok Aggarwal #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
25*b1efbcd6SAlok Aggarwal 
26*b1efbcd6SAlok Aggarwal #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
27*b1efbcd6SAlok Aggarwal #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
28*b1efbcd6SAlok Aggarwal #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
29*b1efbcd6SAlok Aggarwal #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
30*b1efbcd6SAlok Aggarwal   { UPDATE_0(p); i = (i + i); A0; } else \
31*b1efbcd6SAlok Aggarwal   { UPDATE_1(p); i = (i + i) + 1; A1; }
32*b1efbcd6SAlok Aggarwal #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
33*b1efbcd6SAlok Aggarwal 
34*b1efbcd6SAlok Aggarwal #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
35*b1efbcd6SAlok Aggarwal #define TREE_DECODE(probs, limit, i) \
36*b1efbcd6SAlok Aggarwal   { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
37*b1efbcd6SAlok Aggarwal 
38*b1efbcd6SAlok Aggarwal /* #define _LZMA_SIZE_OPT */
39*b1efbcd6SAlok Aggarwal 
40*b1efbcd6SAlok Aggarwal #ifdef _LZMA_SIZE_OPT
41*b1efbcd6SAlok Aggarwal #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
42*b1efbcd6SAlok Aggarwal #else
43*b1efbcd6SAlok Aggarwal #define TREE_6_DECODE(probs, i) \
44*b1efbcd6SAlok Aggarwal   { i = 1; \
45*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
46*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
47*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
48*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
49*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
50*b1efbcd6SAlok Aggarwal   TREE_GET_BIT(probs, i); \
51*b1efbcd6SAlok Aggarwal   i -= 0x40; }
52*b1efbcd6SAlok Aggarwal #endif
53*b1efbcd6SAlok Aggarwal 
54*b1efbcd6SAlok Aggarwal #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
55*b1efbcd6SAlok Aggarwal 
56*b1efbcd6SAlok Aggarwal #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
57*b1efbcd6SAlok Aggarwal #define UPDATE_0_CHECK range = bound;
58*b1efbcd6SAlok Aggarwal #define UPDATE_1_CHECK range -= bound; code -= bound;
59*b1efbcd6SAlok Aggarwal #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
60*b1efbcd6SAlok Aggarwal   { UPDATE_0_CHECK; i = (i + i); A0; } else \
61*b1efbcd6SAlok Aggarwal   { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
62*b1efbcd6SAlok Aggarwal #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
63*b1efbcd6SAlok Aggarwal #define TREE_DECODE_CHECK(probs, limit, i) \
64*b1efbcd6SAlok Aggarwal   { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
65*b1efbcd6SAlok Aggarwal 
66*b1efbcd6SAlok Aggarwal 
67*b1efbcd6SAlok Aggarwal #define kNumPosBitsMax 4
68*b1efbcd6SAlok Aggarwal #define kNumPosStatesMax (1 << kNumPosBitsMax)
69*b1efbcd6SAlok Aggarwal 
70*b1efbcd6SAlok Aggarwal #define kLenNumLowBits 3
71*b1efbcd6SAlok Aggarwal #define kLenNumLowSymbols (1 << kLenNumLowBits)
72*b1efbcd6SAlok Aggarwal #define kLenNumMidBits 3
73*b1efbcd6SAlok Aggarwal #define kLenNumMidSymbols (1 << kLenNumMidBits)
74*b1efbcd6SAlok Aggarwal #define kLenNumHighBits 8
75*b1efbcd6SAlok Aggarwal #define kLenNumHighSymbols (1 << kLenNumHighBits)
76*b1efbcd6SAlok Aggarwal 
77*b1efbcd6SAlok Aggarwal #define LenChoice 0
78*b1efbcd6SAlok Aggarwal #define LenChoice2 (LenChoice + 1)
79*b1efbcd6SAlok Aggarwal #define LenLow (LenChoice2 + 1)
80*b1efbcd6SAlok Aggarwal #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
81*b1efbcd6SAlok Aggarwal #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
82*b1efbcd6SAlok Aggarwal #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
83*b1efbcd6SAlok Aggarwal 
84*b1efbcd6SAlok Aggarwal 
85*b1efbcd6SAlok Aggarwal #define kNumStates 12
86*b1efbcd6SAlok Aggarwal #define kNumLitStates 7
87*b1efbcd6SAlok Aggarwal 
88*b1efbcd6SAlok Aggarwal #define kStartPosModelIndex 4
89*b1efbcd6SAlok Aggarwal #define kEndPosModelIndex 14
90*b1efbcd6SAlok Aggarwal #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
91*b1efbcd6SAlok Aggarwal 
92*b1efbcd6SAlok Aggarwal #define kNumPosSlotBits 6
93*b1efbcd6SAlok Aggarwal #define kNumLenToPosStates 4
94*b1efbcd6SAlok Aggarwal 
95*b1efbcd6SAlok Aggarwal #define kNumAlignBits 4
96*b1efbcd6SAlok Aggarwal #define kAlignTableSize (1 << kNumAlignBits)
97*b1efbcd6SAlok Aggarwal 
98*b1efbcd6SAlok Aggarwal #define kMatchMinLen 2
99*b1efbcd6SAlok Aggarwal #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
100*b1efbcd6SAlok Aggarwal 
101*b1efbcd6SAlok Aggarwal #define IsMatch 0
102*b1efbcd6SAlok Aggarwal #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
103*b1efbcd6SAlok Aggarwal #define IsRepG0 (IsRep + kNumStates)
104*b1efbcd6SAlok Aggarwal #define IsRepG1 (IsRepG0 + kNumStates)
105*b1efbcd6SAlok Aggarwal #define IsRepG2 (IsRepG1 + kNumStates)
106*b1efbcd6SAlok Aggarwal #define IsRep0Long (IsRepG2 + kNumStates)
107*b1efbcd6SAlok Aggarwal #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
108*b1efbcd6SAlok Aggarwal #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
109*b1efbcd6SAlok Aggarwal #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
110*b1efbcd6SAlok Aggarwal #define LenCoder (Align + kAlignTableSize)
111*b1efbcd6SAlok Aggarwal #define RepLenCoder (LenCoder + kNumLenProbs)
112*b1efbcd6SAlok Aggarwal #define Literal (RepLenCoder + kNumLenProbs)
113*b1efbcd6SAlok Aggarwal 
114*b1efbcd6SAlok Aggarwal #define LZMA_BASE_SIZE 1846
115*b1efbcd6SAlok Aggarwal #define LZMA_LIT_SIZE 768
116*b1efbcd6SAlok Aggarwal 
117*b1efbcd6SAlok Aggarwal #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
118*b1efbcd6SAlok Aggarwal 
119*b1efbcd6SAlok Aggarwal #if Literal != LZMA_BASE_SIZE
120*b1efbcd6SAlok Aggarwal StopCompilingDueBUG
121*b1efbcd6SAlok Aggarwal #endif
122*b1efbcd6SAlok Aggarwal 
123*b1efbcd6SAlok Aggarwal static const Byte kLiteralNextStates[kNumStates * 2] =
124*b1efbcd6SAlok Aggarwal {
125*b1efbcd6SAlok Aggarwal   0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5,
126*b1efbcd6SAlok Aggarwal   7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
127*b1efbcd6SAlok Aggarwal };
128*b1efbcd6SAlok Aggarwal 
129*b1efbcd6SAlok Aggarwal #ifdef _KERNEL
130*b1efbcd6SAlok Aggarwal extern void *memcpy(void *, const void *, size_t);
131*b1efbcd6SAlok Aggarwal #endif /* _KERNEL */
132*b1efbcd6SAlok Aggarwal 
133*b1efbcd6SAlok Aggarwal #define LZMA_DIC_MIN (1 << 12)
134*b1efbcd6SAlok Aggarwal 
135*b1efbcd6SAlok Aggarwal /* First LZMA-symbol is always decoded.
136*b1efbcd6SAlok Aggarwal And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
137*b1efbcd6SAlok Aggarwal Out:
138*b1efbcd6SAlok Aggarwal   Result:
139*b1efbcd6SAlok Aggarwal     SZ_OK - OK
140*b1efbcd6SAlok Aggarwal     SZ_ERROR_DATA - Error
141*b1efbcd6SAlok Aggarwal   p->remainLen:
142*b1efbcd6SAlok Aggarwal     < kMatchSpecLenStart : normal remain
143*b1efbcd6SAlok Aggarwal     = kMatchSpecLenStart : finished
144*b1efbcd6SAlok Aggarwal     = kMatchSpecLenStart + 1 : Flush marker
145*b1efbcd6SAlok Aggarwal     = kMatchSpecLenStart + 2 : State Init Marker
146*b1efbcd6SAlok Aggarwal */
147*b1efbcd6SAlok Aggarwal 
148*b1efbcd6SAlok Aggarwal static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
149*b1efbcd6SAlok Aggarwal {
150*b1efbcd6SAlok Aggarwal   CLzmaProb *probs = p->probs;
151*b1efbcd6SAlok Aggarwal 
152*b1efbcd6SAlok Aggarwal   unsigned state = p->state;
153*b1efbcd6SAlok Aggarwal   UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
154*b1efbcd6SAlok Aggarwal   unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
155*b1efbcd6SAlok Aggarwal   unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
156*b1efbcd6SAlok Aggarwal   unsigned lc = p->prop.lc;
157*b1efbcd6SAlok Aggarwal 
158*b1efbcd6SAlok Aggarwal   Byte *dic = p->dic;
159*b1efbcd6SAlok Aggarwal   SizeT dicBufSize = p->dicBufSize;
160*b1efbcd6SAlok Aggarwal   SizeT dicPos = p->dicPos;
161*b1efbcd6SAlok Aggarwal 
162*b1efbcd6SAlok Aggarwal   UInt32 processedPos = p->processedPos;
163*b1efbcd6SAlok Aggarwal   UInt32 checkDicSize = p->checkDicSize;
164*b1efbcd6SAlok Aggarwal   unsigned len = 0;
165*b1efbcd6SAlok Aggarwal 
166*b1efbcd6SAlok Aggarwal   const Byte *buf = p->buf;
167*b1efbcd6SAlok Aggarwal   UInt32 range = p->range;
168*b1efbcd6SAlok Aggarwal   UInt32 code = p->code;
169*b1efbcd6SAlok Aggarwal 
170*b1efbcd6SAlok Aggarwal   do
171*b1efbcd6SAlok Aggarwal   {
172*b1efbcd6SAlok Aggarwal     CLzmaProb *prob;
173*b1efbcd6SAlok Aggarwal     UInt32 bound;
174*b1efbcd6SAlok Aggarwal     unsigned ttt;
175*b1efbcd6SAlok Aggarwal     unsigned posState = processedPos & pbMask;
176*b1efbcd6SAlok Aggarwal 
177*b1efbcd6SAlok Aggarwal     prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
178*b1efbcd6SAlok Aggarwal     IF_BIT_0(prob)
179*b1efbcd6SAlok Aggarwal     {
180*b1efbcd6SAlok Aggarwal       unsigned symbol;
181*b1efbcd6SAlok Aggarwal       UPDATE_0(prob);
182*b1efbcd6SAlok Aggarwal       prob = probs + Literal;
183*b1efbcd6SAlok Aggarwal       if (checkDicSize != 0 || processedPos != 0)
184*b1efbcd6SAlok Aggarwal         prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
185*b1efbcd6SAlok Aggarwal         (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
186*b1efbcd6SAlok Aggarwal 
187*b1efbcd6SAlok Aggarwal       if (state < kNumLitStates)
188*b1efbcd6SAlok Aggarwal       {
189*b1efbcd6SAlok Aggarwal         symbol = 1;
190*b1efbcd6SAlok Aggarwal         do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
191*b1efbcd6SAlok Aggarwal       }
192*b1efbcd6SAlok Aggarwal       else
193*b1efbcd6SAlok Aggarwal       {
194*b1efbcd6SAlok Aggarwal         unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
195*b1efbcd6SAlok Aggarwal         unsigned offs = 0x100;
196*b1efbcd6SAlok Aggarwal         symbol = 1;
197*b1efbcd6SAlok Aggarwal         do
198*b1efbcd6SAlok Aggarwal         {
199*b1efbcd6SAlok Aggarwal           unsigned bit;
200*b1efbcd6SAlok Aggarwal           CLzmaProb *probLit;
201*b1efbcd6SAlok Aggarwal           matchByte <<= 1;
202*b1efbcd6SAlok Aggarwal           bit = (matchByte & offs);
203*b1efbcd6SAlok Aggarwal           probLit = prob + offs + bit + symbol;
204*b1efbcd6SAlok Aggarwal           GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
205*b1efbcd6SAlok Aggarwal         }
206*b1efbcd6SAlok Aggarwal         while (symbol < 0x100);
207*b1efbcd6SAlok Aggarwal       }
208*b1efbcd6SAlok Aggarwal       dic[dicPos++] = (Byte)symbol;
209*b1efbcd6SAlok Aggarwal       processedPos++;
210*b1efbcd6SAlok Aggarwal 
211*b1efbcd6SAlok Aggarwal       state = kLiteralNextStates[state];
212*b1efbcd6SAlok Aggarwal       /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
213*b1efbcd6SAlok Aggarwal       continue;
214*b1efbcd6SAlok Aggarwal     }
215*b1efbcd6SAlok Aggarwal     else
216*b1efbcd6SAlok Aggarwal     {
217*b1efbcd6SAlok Aggarwal       UPDATE_1(prob);
218*b1efbcd6SAlok Aggarwal       prob = probs + IsRep + state;
219*b1efbcd6SAlok Aggarwal       IF_BIT_0(prob)
220*b1efbcd6SAlok Aggarwal       {
221*b1efbcd6SAlok Aggarwal         UPDATE_0(prob);
222*b1efbcd6SAlok Aggarwal         state += kNumStates;
223*b1efbcd6SAlok Aggarwal         prob = probs + LenCoder;
224*b1efbcd6SAlok Aggarwal       }
225*b1efbcd6SAlok Aggarwal       else
226*b1efbcd6SAlok Aggarwal       {
227*b1efbcd6SAlok Aggarwal         UPDATE_1(prob);
228*b1efbcd6SAlok Aggarwal         if (checkDicSize == 0 && processedPos == 0)
229*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
230*b1efbcd6SAlok Aggarwal         prob = probs + IsRepG0 + state;
231*b1efbcd6SAlok Aggarwal         IF_BIT_0(prob)
232*b1efbcd6SAlok Aggarwal         {
233*b1efbcd6SAlok Aggarwal           UPDATE_0(prob);
234*b1efbcd6SAlok Aggarwal           prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
235*b1efbcd6SAlok Aggarwal           IF_BIT_0(prob)
236*b1efbcd6SAlok Aggarwal           {
237*b1efbcd6SAlok Aggarwal             UPDATE_0(prob);
238*b1efbcd6SAlok Aggarwal             dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
239*b1efbcd6SAlok Aggarwal             dicPos++;
240*b1efbcd6SAlok Aggarwal             processedPos++;
241*b1efbcd6SAlok Aggarwal             state = state < kNumLitStates ? 9 : 11;
242*b1efbcd6SAlok Aggarwal             continue;
243*b1efbcd6SAlok Aggarwal           }
244*b1efbcd6SAlok Aggarwal           UPDATE_1(prob);
245*b1efbcd6SAlok Aggarwal         }
246*b1efbcd6SAlok Aggarwal         else
247*b1efbcd6SAlok Aggarwal         {
248*b1efbcd6SAlok Aggarwal           UInt32 distance;
249*b1efbcd6SAlok Aggarwal           UPDATE_1(prob);
250*b1efbcd6SAlok Aggarwal           prob = probs + IsRepG1 + state;
251*b1efbcd6SAlok Aggarwal           IF_BIT_0(prob)
252*b1efbcd6SAlok Aggarwal           {
253*b1efbcd6SAlok Aggarwal             UPDATE_0(prob);
254*b1efbcd6SAlok Aggarwal             distance = rep1;
255*b1efbcd6SAlok Aggarwal           }
256*b1efbcd6SAlok Aggarwal           else
257*b1efbcd6SAlok Aggarwal           {
258*b1efbcd6SAlok Aggarwal             UPDATE_1(prob);
259*b1efbcd6SAlok Aggarwal             prob = probs + IsRepG2 + state;
260*b1efbcd6SAlok Aggarwal             IF_BIT_0(prob)
261*b1efbcd6SAlok Aggarwal             {
262*b1efbcd6SAlok Aggarwal               UPDATE_0(prob);
263*b1efbcd6SAlok Aggarwal               distance = rep2;
264*b1efbcd6SAlok Aggarwal             }
265*b1efbcd6SAlok Aggarwal             else
266*b1efbcd6SAlok Aggarwal             {
267*b1efbcd6SAlok Aggarwal               UPDATE_1(prob);
268*b1efbcd6SAlok Aggarwal               distance = rep3;
269*b1efbcd6SAlok Aggarwal               rep3 = rep2;
270*b1efbcd6SAlok Aggarwal             }
271*b1efbcd6SAlok Aggarwal             rep2 = rep1;
272*b1efbcd6SAlok Aggarwal           }
273*b1efbcd6SAlok Aggarwal           rep1 = rep0;
274*b1efbcd6SAlok Aggarwal           rep0 = distance;
275*b1efbcd6SAlok Aggarwal         }
276*b1efbcd6SAlok Aggarwal         state = state < kNumLitStates ? 8 : 11;
277*b1efbcd6SAlok Aggarwal         prob = probs + RepLenCoder;
278*b1efbcd6SAlok Aggarwal       }
279*b1efbcd6SAlok Aggarwal       {
280*b1efbcd6SAlok Aggarwal         unsigned limit, offset;
281*b1efbcd6SAlok Aggarwal         CLzmaProb *probLen = prob + LenChoice;
282*b1efbcd6SAlok Aggarwal         IF_BIT_0(probLen)
283*b1efbcd6SAlok Aggarwal         {
284*b1efbcd6SAlok Aggarwal           UPDATE_0(probLen);
285*b1efbcd6SAlok Aggarwal           probLen = prob + LenLow + (posState << kLenNumLowBits);
286*b1efbcd6SAlok Aggarwal           offset = 0;
287*b1efbcd6SAlok Aggarwal           limit = (1 << kLenNumLowBits);
288*b1efbcd6SAlok Aggarwal         }
289*b1efbcd6SAlok Aggarwal         else
290*b1efbcd6SAlok Aggarwal         {
291*b1efbcd6SAlok Aggarwal           UPDATE_1(probLen);
292*b1efbcd6SAlok Aggarwal           probLen = prob + LenChoice2;
293*b1efbcd6SAlok Aggarwal           IF_BIT_0(probLen)
294*b1efbcd6SAlok Aggarwal           {
295*b1efbcd6SAlok Aggarwal             UPDATE_0(probLen);
296*b1efbcd6SAlok Aggarwal             probLen = prob + LenMid + (posState << kLenNumMidBits);
297*b1efbcd6SAlok Aggarwal             offset = kLenNumLowSymbols;
298*b1efbcd6SAlok Aggarwal             limit = (1 << kLenNumMidBits);
299*b1efbcd6SAlok Aggarwal           }
300*b1efbcd6SAlok Aggarwal           else
301*b1efbcd6SAlok Aggarwal           {
302*b1efbcd6SAlok Aggarwal             UPDATE_1(probLen);
303*b1efbcd6SAlok Aggarwal             probLen = prob + LenHigh;
304*b1efbcd6SAlok Aggarwal             offset = kLenNumLowSymbols + kLenNumMidSymbols;
305*b1efbcd6SAlok Aggarwal             limit = (1 << kLenNumHighBits);
306*b1efbcd6SAlok Aggarwal           }
307*b1efbcd6SAlok Aggarwal         }
308*b1efbcd6SAlok Aggarwal         TREE_DECODE(probLen, limit, len);
309*b1efbcd6SAlok Aggarwal         len += offset;
310*b1efbcd6SAlok Aggarwal       }
311*b1efbcd6SAlok Aggarwal 
312*b1efbcd6SAlok Aggarwal       if (state >= kNumStates)
313*b1efbcd6SAlok Aggarwal       {
314*b1efbcd6SAlok Aggarwal         UInt32 distance;
315*b1efbcd6SAlok Aggarwal         prob = probs + PosSlot +
316*b1efbcd6SAlok Aggarwal             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
317*b1efbcd6SAlok Aggarwal         TREE_6_DECODE(prob, distance);
318*b1efbcd6SAlok Aggarwal         if (distance >= kStartPosModelIndex)
319*b1efbcd6SAlok Aggarwal         {
320*b1efbcd6SAlok Aggarwal           unsigned posSlot = (unsigned)distance;
321*b1efbcd6SAlok Aggarwal           int numDirectBits = (int)(((distance >> 1) - 1));
322*b1efbcd6SAlok Aggarwal           distance = (2 | (distance & 1));
323*b1efbcd6SAlok Aggarwal           if (posSlot < kEndPosModelIndex)
324*b1efbcd6SAlok Aggarwal           {
325*b1efbcd6SAlok Aggarwal             distance <<= numDirectBits;
326*b1efbcd6SAlok Aggarwal             prob = probs + SpecPos + distance - posSlot - 1;
327*b1efbcd6SAlok Aggarwal             {
328*b1efbcd6SAlok Aggarwal               UInt32 mask = 1;
329*b1efbcd6SAlok Aggarwal               unsigned i = 1;
330*b1efbcd6SAlok Aggarwal               do
331*b1efbcd6SAlok Aggarwal               {
332*b1efbcd6SAlok Aggarwal                 GET_BIT2(prob + i, i, ; , distance |= mask);
333*b1efbcd6SAlok Aggarwal                 mask <<= 1;
334*b1efbcd6SAlok Aggarwal               }
335*b1efbcd6SAlok Aggarwal               while (--numDirectBits != 0);
336*b1efbcd6SAlok Aggarwal             }
337*b1efbcd6SAlok Aggarwal           }
338*b1efbcd6SAlok Aggarwal           else
339*b1efbcd6SAlok Aggarwal           {
340*b1efbcd6SAlok Aggarwal             numDirectBits -= kNumAlignBits;
341*b1efbcd6SAlok Aggarwal             do
342*b1efbcd6SAlok Aggarwal             {
343*b1efbcd6SAlok Aggarwal               NORMALIZE
344*b1efbcd6SAlok Aggarwal               range >>= 1;
345*b1efbcd6SAlok Aggarwal 
346*b1efbcd6SAlok Aggarwal               {
347*b1efbcd6SAlok Aggarwal                 UInt32 t;
348*b1efbcd6SAlok Aggarwal                 code -= range;
349*b1efbcd6SAlok Aggarwal                 t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
350*b1efbcd6SAlok Aggarwal                 distance = (distance << 1) + (t + 1);
351*b1efbcd6SAlok Aggarwal                 code += range & t;
352*b1efbcd6SAlok Aggarwal               }
353*b1efbcd6SAlok Aggarwal               /*
354*b1efbcd6SAlok Aggarwal               distance <<= 1;
355*b1efbcd6SAlok Aggarwal               if (code >= range)
356*b1efbcd6SAlok Aggarwal               {
357*b1efbcd6SAlok Aggarwal                 code -= range;
358*b1efbcd6SAlok Aggarwal                 distance |= 1;
359*b1efbcd6SAlok Aggarwal               }
360*b1efbcd6SAlok Aggarwal               */
361*b1efbcd6SAlok Aggarwal             }
362*b1efbcd6SAlok Aggarwal             while (--numDirectBits != 0);
363*b1efbcd6SAlok Aggarwal             prob = probs + Align;
364*b1efbcd6SAlok Aggarwal             distance <<= kNumAlignBits;
365*b1efbcd6SAlok Aggarwal             {
366*b1efbcd6SAlok Aggarwal               unsigned i = 1;
367*b1efbcd6SAlok Aggarwal               GET_BIT2(prob + i, i, ; , distance |= 1);
368*b1efbcd6SAlok Aggarwal               GET_BIT2(prob + i, i, ; , distance |= 2);
369*b1efbcd6SAlok Aggarwal               GET_BIT2(prob + i, i, ; , distance |= 4);
370*b1efbcd6SAlok Aggarwal               GET_BIT2(prob + i, i, ; , distance |= 8);
371*b1efbcd6SAlok Aggarwal             }
372*b1efbcd6SAlok Aggarwal             if (distance == (UInt32)0xFFFFFFFF)
373*b1efbcd6SAlok Aggarwal             {
374*b1efbcd6SAlok Aggarwal               len += kMatchSpecLenStart;
375*b1efbcd6SAlok Aggarwal               state -= kNumStates;
376*b1efbcd6SAlok Aggarwal               break;
377*b1efbcd6SAlok Aggarwal             }
378*b1efbcd6SAlok Aggarwal           }
379*b1efbcd6SAlok Aggarwal         }
380*b1efbcd6SAlok Aggarwal         rep3 = rep2;
381*b1efbcd6SAlok Aggarwal         rep2 = rep1;
382*b1efbcd6SAlok Aggarwal         rep1 = rep0;
383*b1efbcd6SAlok Aggarwal         rep0 = distance + 1;
384*b1efbcd6SAlok Aggarwal         if (checkDicSize == 0)
385*b1efbcd6SAlok Aggarwal         {
386*b1efbcd6SAlok Aggarwal           if (distance >= processedPos)
387*b1efbcd6SAlok Aggarwal             return SZ_ERROR_DATA;
388*b1efbcd6SAlok Aggarwal         }
389*b1efbcd6SAlok Aggarwal         else if (distance >= checkDicSize)
390*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
391*b1efbcd6SAlok Aggarwal         state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
392*b1efbcd6SAlok Aggarwal         /* state = kLiteralNextStates[state]; */
393*b1efbcd6SAlok Aggarwal       }
394*b1efbcd6SAlok Aggarwal 
395*b1efbcd6SAlok Aggarwal       len += kMatchMinLen;
396*b1efbcd6SAlok Aggarwal 
397*b1efbcd6SAlok Aggarwal       if (limit == dicPos)
398*b1efbcd6SAlok Aggarwal         return SZ_ERROR_DATA;
399*b1efbcd6SAlok Aggarwal       {
400*b1efbcd6SAlok Aggarwal         SizeT rem = limit - dicPos;
401*b1efbcd6SAlok Aggarwal         unsigned curLen = ((rem < len) ? (unsigned)rem : len);
402*b1efbcd6SAlok Aggarwal         SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
403*b1efbcd6SAlok Aggarwal 
404*b1efbcd6SAlok Aggarwal         processedPos += curLen;
405*b1efbcd6SAlok Aggarwal 
406*b1efbcd6SAlok Aggarwal         len -= curLen;
407*b1efbcd6SAlok Aggarwal         if (pos + curLen <= dicBufSize)
408*b1efbcd6SAlok Aggarwal         {
409*b1efbcd6SAlok Aggarwal           Byte *dest = dic + dicPos;
410*b1efbcd6SAlok Aggarwal           ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
411*b1efbcd6SAlok Aggarwal           const Byte *lim = dest + curLen;
412*b1efbcd6SAlok Aggarwal           dicPos += curLen;
413*b1efbcd6SAlok Aggarwal           do
414*b1efbcd6SAlok Aggarwal             *(dest) = (Byte)*(dest + src);
415*b1efbcd6SAlok Aggarwal           while (++dest != lim);
416*b1efbcd6SAlok Aggarwal         }
417*b1efbcd6SAlok Aggarwal         else
418*b1efbcd6SAlok Aggarwal         {
419*b1efbcd6SAlok Aggarwal           do
420*b1efbcd6SAlok Aggarwal           {
421*b1efbcd6SAlok Aggarwal             dic[dicPos++] = dic[pos];
422*b1efbcd6SAlok Aggarwal             if (++pos == dicBufSize)
423*b1efbcd6SAlok Aggarwal               pos = 0;
424*b1efbcd6SAlok Aggarwal           }
425*b1efbcd6SAlok Aggarwal           while (--curLen != 0);
426*b1efbcd6SAlok Aggarwal         }
427*b1efbcd6SAlok Aggarwal       }
428*b1efbcd6SAlok Aggarwal     }
429*b1efbcd6SAlok Aggarwal   }
430*b1efbcd6SAlok Aggarwal   while (dicPos < limit && buf < bufLimit);
431*b1efbcd6SAlok Aggarwal   NORMALIZE;
432*b1efbcd6SAlok Aggarwal   p->buf = buf;
433*b1efbcd6SAlok Aggarwal   p->range = range;
434*b1efbcd6SAlok Aggarwal   p->code = code;
435*b1efbcd6SAlok Aggarwal   p->remainLen = len;
436*b1efbcd6SAlok Aggarwal   p->dicPos = dicPos;
437*b1efbcd6SAlok Aggarwal   p->processedPos = processedPos;
438*b1efbcd6SAlok Aggarwal   p->reps[0] = rep0;
439*b1efbcd6SAlok Aggarwal   p->reps[1] = rep1;
440*b1efbcd6SAlok Aggarwal   p->reps[2] = rep2;
441*b1efbcd6SAlok Aggarwal   p->reps[3] = rep3;
442*b1efbcd6SAlok Aggarwal   p->state = state;
443*b1efbcd6SAlok Aggarwal 
444*b1efbcd6SAlok Aggarwal   return SZ_OK;
445*b1efbcd6SAlok Aggarwal }
446*b1efbcd6SAlok Aggarwal 
447*b1efbcd6SAlok Aggarwal static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
448*b1efbcd6SAlok Aggarwal {
449*b1efbcd6SAlok Aggarwal   if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
450*b1efbcd6SAlok Aggarwal   {
451*b1efbcd6SAlok Aggarwal     Byte *dic = p->dic;
452*b1efbcd6SAlok Aggarwal     SizeT dicPos = p->dicPos;
453*b1efbcd6SAlok Aggarwal     SizeT dicBufSize = p->dicBufSize;
454*b1efbcd6SAlok Aggarwal     unsigned len = p->remainLen;
455*b1efbcd6SAlok Aggarwal     UInt32 rep0 = p->reps[0];
456*b1efbcd6SAlok Aggarwal     if (limit - dicPos < len)
457*b1efbcd6SAlok Aggarwal       len = (unsigned)(limit - dicPos);
458*b1efbcd6SAlok Aggarwal 
459*b1efbcd6SAlok Aggarwal     if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
460*b1efbcd6SAlok Aggarwal       p->checkDicSize = p->prop.dicSize;
461*b1efbcd6SAlok Aggarwal 
462*b1efbcd6SAlok Aggarwal     p->processedPos += len;
463*b1efbcd6SAlok Aggarwal     p->remainLen -= len;
464*b1efbcd6SAlok Aggarwal     while (len-- != 0)
465*b1efbcd6SAlok Aggarwal     {
466*b1efbcd6SAlok Aggarwal       dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
467*b1efbcd6SAlok Aggarwal       dicPos++;
468*b1efbcd6SAlok Aggarwal     }
469*b1efbcd6SAlok Aggarwal     p->dicPos = dicPos;
470*b1efbcd6SAlok Aggarwal   }
471*b1efbcd6SAlok Aggarwal }
472*b1efbcd6SAlok Aggarwal 
473*b1efbcd6SAlok Aggarwal static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
474*b1efbcd6SAlok Aggarwal {
475*b1efbcd6SAlok Aggarwal   do
476*b1efbcd6SAlok Aggarwal   {
477*b1efbcd6SAlok Aggarwal     SizeT limit2 = limit;
478*b1efbcd6SAlok Aggarwal     if (p->checkDicSize == 0)
479*b1efbcd6SAlok Aggarwal     {
480*b1efbcd6SAlok Aggarwal       UInt32 rem = p->prop.dicSize - p->processedPos;
481*b1efbcd6SAlok Aggarwal       if (limit - p->dicPos > rem)
482*b1efbcd6SAlok Aggarwal         limit2 = p->dicPos + rem;
483*b1efbcd6SAlok Aggarwal     }
484*b1efbcd6SAlok Aggarwal     RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
485*b1efbcd6SAlok Aggarwal     if (p->processedPos >= p->prop.dicSize)
486*b1efbcd6SAlok Aggarwal       p->checkDicSize = p->prop.dicSize;
487*b1efbcd6SAlok Aggarwal     LzmaDec_WriteRem(p, limit);
488*b1efbcd6SAlok Aggarwal   }
489*b1efbcd6SAlok Aggarwal   while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
490*b1efbcd6SAlok Aggarwal 
491*b1efbcd6SAlok Aggarwal   if (p->remainLen > kMatchSpecLenStart)
492*b1efbcd6SAlok Aggarwal   {
493*b1efbcd6SAlok Aggarwal     p->remainLen = kMatchSpecLenStart;
494*b1efbcd6SAlok Aggarwal   }
495*b1efbcd6SAlok Aggarwal   return 0;
496*b1efbcd6SAlok Aggarwal }
497*b1efbcd6SAlok Aggarwal 
498*b1efbcd6SAlok Aggarwal typedef enum
499*b1efbcd6SAlok Aggarwal {
500*b1efbcd6SAlok Aggarwal   DUMMY_ERROR, /* unexpected end of input stream */
501*b1efbcd6SAlok Aggarwal   DUMMY_LIT,
502*b1efbcd6SAlok Aggarwal   DUMMY_MATCH,
503*b1efbcd6SAlok Aggarwal   DUMMY_REP
504*b1efbcd6SAlok Aggarwal } ELzmaDummy;
505*b1efbcd6SAlok Aggarwal 
506*b1efbcd6SAlok Aggarwal static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
507*b1efbcd6SAlok Aggarwal {
508*b1efbcd6SAlok Aggarwal   UInt32 range = p->range;
509*b1efbcd6SAlok Aggarwal   UInt32 code = p->code;
510*b1efbcd6SAlok Aggarwal   const Byte *bufLimit = buf + inSize;
511*b1efbcd6SAlok Aggarwal   CLzmaProb *probs = p->probs;
512*b1efbcd6SAlok Aggarwal   unsigned state = p->state;
513*b1efbcd6SAlok Aggarwal   ELzmaDummy res;
514*b1efbcd6SAlok Aggarwal 
515*b1efbcd6SAlok Aggarwal   {
516*b1efbcd6SAlok Aggarwal     CLzmaProb *prob;
517*b1efbcd6SAlok Aggarwal     UInt32 bound;
518*b1efbcd6SAlok Aggarwal     unsigned ttt;
519*b1efbcd6SAlok Aggarwal     unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
520*b1efbcd6SAlok Aggarwal 
521*b1efbcd6SAlok Aggarwal     prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
522*b1efbcd6SAlok Aggarwal     IF_BIT_0_CHECK(prob)
523*b1efbcd6SAlok Aggarwal     {
524*b1efbcd6SAlok Aggarwal       UPDATE_0_CHECK
525*b1efbcd6SAlok Aggarwal 
526*b1efbcd6SAlok Aggarwal       /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
527*b1efbcd6SAlok Aggarwal 
528*b1efbcd6SAlok Aggarwal       prob = probs + Literal;
529*b1efbcd6SAlok Aggarwal       if (p->checkDicSize != 0 || p->processedPos != 0)
530*b1efbcd6SAlok Aggarwal         prob += (LZMA_LIT_SIZE *
531*b1efbcd6SAlok Aggarwal           ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
532*b1efbcd6SAlok Aggarwal           (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
533*b1efbcd6SAlok Aggarwal 
534*b1efbcd6SAlok Aggarwal       if (state < kNumLitStates)
535*b1efbcd6SAlok Aggarwal       {
536*b1efbcd6SAlok Aggarwal         unsigned symbol = 1;
537*b1efbcd6SAlok Aggarwal         do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
538*b1efbcd6SAlok Aggarwal       }
539*b1efbcd6SAlok Aggarwal       else
540*b1efbcd6SAlok Aggarwal       {
541*b1efbcd6SAlok Aggarwal         unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
542*b1efbcd6SAlok Aggarwal             ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
543*b1efbcd6SAlok Aggarwal         unsigned offs = 0x100;
544*b1efbcd6SAlok Aggarwal         unsigned symbol = 1;
545*b1efbcd6SAlok Aggarwal         do
546*b1efbcd6SAlok Aggarwal         {
547*b1efbcd6SAlok Aggarwal           unsigned bit;
548*b1efbcd6SAlok Aggarwal           CLzmaProb *probLit;
549*b1efbcd6SAlok Aggarwal           matchByte <<= 1;
550*b1efbcd6SAlok Aggarwal           bit = (matchByte & offs);
551*b1efbcd6SAlok Aggarwal           probLit = prob + offs + bit + symbol;
552*b1efbcd6SAlok Aggarwal           GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
553*b1efbcd6SAlok Aggarwal         }
554*b1efbcd6SAlok Aggarwal         while (symbol < 0x100);
555*b1efbcd6SAlok Aggarwal       }
556*b1efbcd6SAlok Aggarwal       res = DUMMY_LIT;
557*b1efbcd6SAlok Aggarwal     }
558*b1efbcd6SAlok Aggarwal     else
559*b1efbcd6SAlok Aggarwal     {
560*b1efbcd6SAlok Aggarwal       unsigned len;
561*b1efbcd6SAlok Aggarwal       UPDATE_1_CHECK;
562*b1efbcd6SAlok Aggarwal 
563*b1efbcd6SAlok Aggarwal       prob = probs + IsRep + state;
564*b1efbcd6SAlok Aggarwal       IF_BIT_0_CHECK(prob)
565*b1efbcd6SAlok Aggarwal       {
566*b1efbcd6SAlok Aggarwal         UPDATE_0_CHECK;
567*b1efbcd6SAlok Aggarwal         state = 0;
568*b1efbcd6SAlok Aggarwal         prob = probs + LenCoder;
569*b1efbcd6SAlok Aggarwal         res = DUMMY_MATCH;
570*b1efbcd6SAlok Aggarwal       }
571*b1efbcd6SAlok Aggarwal       else
572*b1efbcd6SAlok Aggarwal       {
573*b1efbcd6SAlok Aggarwal         UPDATE_1_CHECK;
574*b1efbcd6SAlok Aggarwal         res = DUMMY_REP;
575*b1efbcd6SAlok Aggarwal         prob = probs + IsRepG0 + state;
576*b1efbcd6SAlok Aggarwal         IF_BIT_0_CHECK(prob)
577*b1efbcd6SAlok Aggarwal         {
578*b1efbcd6SAlok Aggarwal           UPDATE_0_CHECK;
579*b1efbcd6SAlok Aggarwal           prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
580*b1efbcd6SAlok Aggarwal           IF_BIT_0_CHECK(prob)
581*b1efbcd6SAlok Aggarwal           {
582*b1efbcd6SAlok Aggarwal             UPDATE_0_CHECK;
583*b1efbcd6SAlok Aggarwal             NORMALIZE_CHECK;
584*b1efbcd6SAlok Aggarwal             return DUMMY_REP;
585*b1efbcd6SAlok Aggarwal           }
586*b1efbcd6SAlok Aggarwal           else
587*b1efbcd6SAlok Aggarwal           {
588*b1efbcd6SAlok Aggarwal             UPDATE_1_CHECK;
589*b1efbcd6SAlok Aggarwal           }
590*b1efbcd6SAlok Aggarwal         }
591*b1efbcd6SAlok Aggarwal         else
592*b1efbcd6SAlok Aggarwal         {
593*b1efbcd6SAlok Aggarwal           UPDATE_1_CHECK;
594*b1efbcd6SAlok Aggarwal           prob = probs + IsRepG1 + state;
595*b1efbcd6SAlok Aggarwal           IF_BIT_0_CHECK(prob)
596*b1efbcd6SAlok Aggarwal           {
597*b1efbcd6SAlok Aggarwal             UPDATE_0_CHECK;
598*b1efbcd6SAlok Aggarwal           }
599*b1efbcd6SAlok Aggarwal           else
600*b1efbcd6SAlok Aggarwal           {
601*b1efbcd6SAlok Aggarwal             UPDATE_1_CHECK;
602*b1efbcd6SAlok Aggarwal             prob = probs + IsRepG2 + state;
603*b1efbcd6SAlok Aggarwal             IF_BIT_0_CHECK(prob)
604*b1efbcd6SAlok Aggarwal             {
605*b1efbcd6SAlok Aggarwal               UPDATE_0_CHECK;
606*b1efbcd6SAlok Aggarwal             }
607*b1efbcd6SAlok Aggarwal             else
608*b1efbcd6SAlok Aggarwal             {
609*b1efbcd6SAlok Aggarwal               UPDATE_1_CHECK;
610*b1efbcd6SAlok Aggarwal             }
611*b1efbcd6SAlok Aggarwal           }
612*b1efbcd6SAlok Aggarwal         }
613*b1efbcd6SAlok Aggarwal         state = kNumStates;
614*b1efbcd6SAlok Aggarwal         prob = probs + RepLenCoder;
615*b1efbcd6SAlok Aggarwal       }
616*b1efbcd6SAlok Aggarwal       {
617*b1efbcd6SAlok Aggarwal         unsigned limit, offset;
618*b1efbcd6SAlok Aggarwal         CLzmaProb *probLen = prob + LenChoice;
619*b1efbcd6SAlok Aggarwal         IF_BIT_0_CHECK(probLen)
620*b1efbcd6SAlok Aggarwal         {
621*b1efbcd6SAlok Aggarwal           UPDATE_0_CHECK;
622*b1efbcd6SAlok Aggarwal           probLen = prob + LenLow + (posState << kLenNumLowBits);
623*b1efbcd6SAlok Aggarwal           offset = 0;
624*b1efbcd6SAlok Aggarwal           limit = 1 << kLenNumLowBits;
625*b1efbcd6SAlok Aggarwal         }
626*b1efbcd6SAlok Aggarwal         else
627*b1efbcd6SAlok Aggarwal         {
628*b1efbcd6SAlok Aggarwal           UPDATE_1_CHECK;
629*b1efbcd6SAlok Aggarwal           probLen = prob + LenChoice2;
630*b1efbcd6SAlok Aggarwal           IF_BIT_0_CHECK(probLen)
631*b1efbcd6SAlok Aggarwal           {
632*b1efbcd6SAlok Aggarwal             UPDATE_0_CHECK;
633*b1efbcd6SAlok Aggarwal             probLen = prob + LenMid + (posState << kLenNumMidBits);
634*b1efbcd6SAlok Aggarwal             offset = kLenNumLowSymbols;
635*b1efbcd6SAlok Aggarwal             limit = 1 << kLenNumMidBits;
636*b1efbcd6SAlok Aggarwal           }
637*b1efbcd6SAlok Aggarwal           else
638*b1efbcd6SAlok Aggarwal           {
639*b1efbcd6SAlok Aggarwal             UPDATE_1_CHECK;
640*b1efbcd6SAlok Aggarwal             probLen = prob + LenHigh;
641*b1efbcd6SAlok Aggarwal             offset = kLenNumLowSymbols + kLenNumMidSymbols;
642*b1efbcd6SAlok Aggarwal             limit = 1 << kLenNumHighBits;
643*b1efbcd6SAlok Aggarwal           }
644*b1efbcd6SAlok Aggarwal         }
645*b1efbcd6SAlok Aggarwal         TREE_DECODE_CHECK(probLen, limit, len);
646*b1efbcd6SAlok Aggarwal         len += offset;
647*b1efbcd6SAlok Aggarwal       }
648*b1efbcd6SAlok Aggarwal 
649*b1efbcd6SAlok Aggarwal       if (state < 4)
650*b1efbcd6SAlok Aggarwal       {
651*b1efbcd6SAlok Aggarwal         unsigned posSlot;
652*b1efbcd6SAlok Aggarwal         prob = probs + PosSlot +
653*b1efbcd6SAlok Aggarwal             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
654*b1efbcd6SAlok Aggarwal             kNumPosSlotBits);
655*b1efbcd6SAlok Aggarwal         TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
656*b1efbcd6SAlok Aggarwal         if (posSlot >= kStartPosModelIndex)
657*b1efbcd6SAlok Aggarwal         {
658*b1efbcd6SAlok Aggarwal           int numDirectBits = ((posSlot >> 1) - 1);
659*b1efbcd6SAlok Aggarwal 
660*b1efbcd6SAlok Aggarwal           /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
661*b1efbcd6SAlok Aggarwal 
662*b1efbcd6SAlok Aggarwal           if (posSlot < kEndPosModelIndex)
663*b1efbcd6SAlok Aggarwal           {
664*b1efbcd6SAlok Aggarwal             prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
665*b1efbcd6SAlok Aggarwal           }
666*b1efbcd6SAlok Aggarwal           else
667*b1efbcd6SAlok Aggarwal           {
668*b1efbcd6SAlok Aggarwal             numDirectBits -= kNumAlignBits;
669*b1efbcd6SAlok Aggarwal             do
670*b1efbcd6SAlok Aggarwal             {
671*b1efbcd6SAlok Aggarwal               NORMALIZE_CHECK
672*b1efbcd6SAlok Aggarwal               range >>= 1;
673*b1efbcd6SAlok Aggarwal               code -= range & (((code - range) >> 31) - 1);
674*b1efbcd6SAlok Aggarwal               /* if (code >= range) code -= range; */
675*b1efbcd6SAlok Aggarwal             }
676*b1efbcd6SAlok Aggarwal             while (--numDirectBits != 0);
677*b1efbcd6SAlok Aggarwal             prob = probs + Align;
678*b1efbcd6SAlok Aggarwal             numDirectBits = kNumAlignBits;
679*b1efbcd6SAlok Aggarwal           }
680*b1efbcd6SAlok Aggarwal           {
681*b1efbcd6SAlok Aggarwal             unsigned i = 1;
682*b1efbcd6SAlok Aggarwal             do
683*b1efbcd6SAlok Aggarwal             {
684*b1efbcd6SAlok Aggarwal               GET_BIT_CHECK(prob + i, i);
685*b1efbcd6SAlok Aggarwal             }
686*b1efbcd6SAlok Aggarwal             while (--numDirectBits != 0);
687*b1efbcd6SAlok Aggarwal           }
688*b1efbcd6SAlok Aggarwal         }
689*b1efbcd6SAlok Aggarwal       }
690*b1efbcd6SAlok Aggarwal     }
691*b1efbcd6SAlok Aggarwal   }
692*b1efbcd6SAlok Aggarwal   NORMALIZE_CHECK;
693*b1efbcd6SAlok Aggarwal   return res;
694*b1efbcd6SAlok Aggarwal }
695*b1efbcd6SAlok Aggarwal 
696*b1efbcd6SAlok Aggarwal 
697*b1efbcd6SAlok Aggarwal static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
698*b1efbcd6SAlok Aggarwal {
699*b1efbcd6SAlok Aggarwal   p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
700*b1efbcd6SAlok Aggarwal   p->range = 0xFFFFFFFF;
701*b1efbcd6SAlok Aggarwal   p->needFlush = 0;
702*b1efbcd6SAlok Aggarwal }
703*b1efbcd6SAlok Aggarwal 
704*b1efbcd6SAlok Aggarwal void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
705*b1efbcd6SAlok Aggarwal {
706*b1efbcd6SAlok Aggarwal   p->needFlush = 1;
707*b1efbcd6SAlok Aggarwal   p->remainLen = 0;
708*b1efbcd6SAlok Aggarwal   p->tempBufSize = 0;
709*b1efbcd6SAlok Aggarwal 
710*b1efbcd6SAlok Aggarwal   if (initDic)
711*b1efbcd6SAlok Aggarwal   {
712*b1efbcd6SAlok Aggarwal     p->processedPos = 0;
713*b1efbcd6SAlok Aggarwal     p->checkDicSize = 0;
714*b1efbcd6SAlok Aggarwal     p->needInitState = 1;
715*b1efbcd6SAlok Aggarwal   }
716*b1efbcd6SAlok Aggarwal   if (initState)
717*b1efbcd6SAlok Aggarwal     p->needInitState = 1;
718*b1efbcd6SAlok Aggarwal }
719*b1efbcd6SAlok Aggarwal 
720*b1efbcd6SAlok Aggarwal void LzmaDec_Init(CLzmaDec *p)
721*b1efbcd6SAlok Aggarwal {
722*b1efbcd6SAlok Aggarwal   p->dicPos = 0;
723*b1efbcd6SAlok Aggarwal   LzmaDec_InitDicAndState(p, True, True);
724*b1efbcd6SAlok Aggarwal }
725*b1efbcd6SAlok Aggarwal 
726*b1efbcd6SAlok Aggarwal static void LzmaDec_InitStateReal(CLzmaDec *p)
727*b1efbcd6SAlok Aggarwal {
728*b1efbcd6SAlok Aggarwal   UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
729*b1efbcd6SAlok Aggarwal   UInt32 i;
730*b1efbcd6SAlok Aggarwal   CLzmaProb *probs = p->probs;
731*b1efbcd6SAlok Aggarwal   for (i = 0; i < numProbs; i++)
732*b1efbcd6SAlok Aggarwal     probs[i] = kBitModelTotal >> 1;
733*b1efbcd6SAlok Aggarwal   p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
734*b1efbcd6SAlok Aggarwal   p->state = 0;
735*b1efbcd6SAlok Aggarwal   p->needInitState = 0;
736*b1efbcd6SAlok Aggarwal }
737*b1efbcd6SAlok Aggarwal 
738*b1efbcd6SAlok Aggarwal SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
739*b1efbcd6SAlok Aggarwal     ELzmaFinishMode finishMode, ELzmaStatus *status)
740*b1efbcd6SAlok Aggarwal {
741*b1efbcd6SAlok Aggarwal   SizeT inSize = *srcLen;
742*b1efbcd6SAlok Aggarwal   (*srcLen) = 0;
743*b1efbcd6SAlok Aggarwal   LzmaDec_WriteRem(p, dicLimit);
744*b1efbcd6SAlok Aggarwal 
745*b1efbcd6SAlok Aggarwal   *status = LZMA_STATUS_NOT_SPECIFIED;
746*b1efbcd6SAlok Aggarwal 
747*b1efbcd6SAlok Aggarwal   while (p->remainLen != kMatchSpecLenStart)
748*b1efbcd6SAlok Aggarwal   {
749*b1efbcd6SAlok Aggarwal       int checkEndMarkNow;
750*b1efbcd6SAlok Aggarwal 
751*b1efbcd6SAlok Aggarwal       if (p->needFlush != 0)
752*b1efbcd6SAlok Aggarwal       {
753*b1efbcd6SAlok Aggarwal         for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
754*b1efbcd6SAlok Aggarwal           p->tempBuf[p->tempBufSize++] = *src++;
755*b1efbcd6SAlok Aggarwal         if (p->tempBufSize < RC_INIT_SIZE)
756*b1efbcd6SAlok Aggarwal         {
757*b1efbcd6SAlok Aggarwal           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
758*b1efbcd6SAlok Aggarwal           return SZ_OK;
759*b1efbcd6SAlok Aggarwal         }
760*b1efbcd6SAlok Aggarwal         if (p->tempBuf[0] != 0)
761*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
762*b1efbcd6SAlok Aggarwal 
763*b1efbcd6SAlok Aggarwal         LzmaDec_InitRc(p, p->tempBuf);
764*b1efbcd6SAlok Aggarwal         p->tempBufSize = 0;
765*b1efbcd6SAlok Aggarwal       }
766*b1efbcd6SAlok Aggarwal 
767*b1efbcd6SAlok Aggarwal       checkEndMarkNow = 0;
768*b1efbcd6SAlok Aggarwal       if (p->dicPos >= dicLimit)
769*b1efbcd6SAlok Aggarwal       {
770*b1efbcd6SAlok Aggarwal         if (p->remainLen == 0 && p->code == 0)
771*b1efbcd6SAlok Aggarwal         {
772*b1efbcd6SAlok Aggarwal           *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
773*b1efbcd6SAlok Aggarwal           return SZ_OK;
774*b1efbcd6SAlok Aggarwal         }
775*b1efbcd6SAlok Aggarwal         if (finishMode == LZMA_FINISH_ANY)
776*b1efbcd6SAlok Aggarwal         {
777*b1efbcd6SAlok Aggarwal           *status = LZMA_STATUS_NOT_FINISHED;
778*b1efbcd6SAlok Aggarwal           return SZ_OK;
779*b1efbcd6SAlok Aggarwal         }
780*b1efbcd6SAlok Aggarwal         if (p->remainLen != 0)
781*b1efbcd6SAlok Aggarwal         {
782*b1efbcd6SAlok Aggarwal           *status = LZMA_STATUS_NOT_FINISHED;
783*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
784*b1efbcd6SAlok Aggarwal         }
785*b1efbcd6SAlok Aggarwal         checkEndMarkNow = 1;
786*b1efbcd6SAlok Aggarwal       }
787*b1efbcd6SAlok Aggarwal 
788*b1efbcd6SAlok Aggarwal       if (p->needInitState)
789*b1efbcd6SAlok Aggarwal         LzmaDec_InitStateReal(p);
790*b1efbcd6SAlok Aggarwal 
791*b1efbcd6SAlok Aggarwal       if (p->tempBufSize == 0)
792*b1efbcd6SAlok Aggarwal       {
793*b1efbcd6SAlok Aggarwal         SizeT processed;
794*b1efbcd6SAlok Aggarwal         const Byte *bufLimit;
795*b1efbcd6SAlok Aggarwal         if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
796*b1efbcd6SAlok Aggarwal         {
797*b1efbcd6SAlok Aggarwal           int dummyRes = LzmaDec_TryDummy(p, src, inSize);
798*b1efbcd6SAlok Aggarwal           if (dummyRes == DUMMY_ERROR)
799*b1efbcd6SAlok Aggarwal           {
800*b1efbcd6SAlok Aggarwal             (void) memcpy(p->tempBuf, src, inSize);
801*b1efbcd6SAlok Aggarwal             p->tempBufSize = (unsigned)inSize;
802*b1efbcd6SAlok Aggarwal             (*srcLen) += inSize;
803*b1efbcd6SAlok Aggarwal             *status = LZMA_STATUS_NEEDS_MORE_INPUT;
804*b1efbcd6SAlok Aggarwal             return SZ_OK;
805*b1efbcd6SAlok Aggarwal           }
806*b1efbcd6SAlok Aggarwal           if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
807*b1efbcd6SAlok Aggarwal           {
808*b1efbcd6SAlok Aggarwal             *status = LZMA_STATUS_NOT_FINISHED;
809*b1efbcd6SAlok Aggarwal             return SZ_ERROR_DATA;
810*b1efbcd6SAlok Aggarwal           }
811*b1efbcd6SAlok Aggarwal           bufLimit = src;
812*b1efbcd6SAlok Aggarwal         }
813*b1efbcd6SAlok Aggarwal         else
814*b1efbcd6SAlok Aggarwal           bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
815*b1efbcd6SAlok Aggarwal         p->buf = src;
816*b1efbcd6SAlok Aggarwal         if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
817*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
818*b1efbcd6SAlok Aggarwal 	/*LINTED*/
819*b1efbcd6SAlok Aggarwal         processed = (SizeT)(p->buf - src);
820*b1efbcd6SAlok Aggarwal         (*srcLen) += processed;
821*b1efbcd6SAlok Aggarwal         src += processed;
822*b1efbcd6SAlok Aggarwal         inSize -= processed;
823*b1efbcd6SAlok Aggarwal       }
824*b1efbcd6SAlok Aggarwal       else
825*b1efbcd6SAlok Aggarwal       {
826*b1efbcd6SAlok Aggarwal         unsigned rem = p->tempBufSize, lookAhead = 0;
827*b1efbcd6SAlok Aggarwal         while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
828*b1efbcd6SAlok Aggarwal           p->tempBuf[rem++] = src[lookAhead++];
829*b1efbcd6SAlok Aggarwal         p->tempBufSize = rem;
830*b1efbcd6SAlok Aggarwal         if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
831*b1efbcd6SAlok Aggarwal         {
832*b1efbcd6SAlok Aggarwal           int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
833*b1efbcd6SAlok Aggarwal           if (dummyRes == DUMMY_ERROR)
834*b1efbcd6SAlok Aggarwal           {
835*b1efbcd6SAlok Aggarwal             (*srcLen) += lookAhead;
836*b1efbcd6SAlok Aggarwal             *status = LZMA_STATUS_NEEDS_MORE_INPUT;
837*b1efbcd6SAlok Aggarwal             return SZ_OK;
838*b1efbcd6SAlok Aggarwal           }
839*b1efbcd6SAlok Aggarwal           if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
840*b1efbcd6SAlok Aggarwal           {
841*b1efbcd6SAlok Aggarwal             *status = LZMA_STATUS_NOT_FINISHED;
842*b1efbcd6SAlok Aggarwal             return SZ_ERROR_DATA;
843*b1efbcd6SAlok Aggarwal           }
844*b1efbcd6SAlok Aggarwal         }
845*b1efbcd6SAlok Aggarwal         p->buf = p->tempBuf;
846*b1efbcd6SAlok Aggarwal         if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
847*b1efbcd6SAlok Aggarwal           return SZ_ERROR_DATA;
848*b1efbcd6SAlok Aggarwal 	/*LINTED*/
849*b1efbcd6SAlok Aggarwal         lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
850*b1efbcd6SAlok Aggarwal         (*srcLen) += lookAhead;
851*b1efbcd6SAlok Aggarwal         src += lookAhead;
852*b1efbcd6SAlok Aggarwal         inSize -= lookAhead;
853*b1efbcd6SAlok Aggarwal         p->tempBufSize = 0;
854*b1efbcd6SAlok Aggarwal       }
855*b1efbcd6SAlok Aggarwal   }
856*b1efbcd6SAlok Aggarwal   if (p->code == 0)
857*b1efbcd6SAlok Aggarwal     *status = LZMA_STATUS_FINISHED_WITH_MARK;
858*b1efbcd6SAlok Aggarwal   return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
859*b1efbcd6SAlok Aggarwal }
860*b1efbcd6SAlok Aggarwal 
861*b1efbcd6SAlok Aggarwal SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
862*b1efbcd6SAlok Aggarwal {
863*b1efbcd6SAlok Aggarwal   SizeT outSize = *destLen;
864*b1efbcd6SAlok Aggarwal   SizeT inSize = *srcLen;
865*b1efbcd6SAlok Aggarwal   *srcLen = *destLen = 0;
866*b1efbcd6SAlok Aggarwal   for (;;)
867*b1efbcd6SAlok Aggarwal   {
868*b1efbcd6SAlok Aggarwal     SizeT inSizeCur = inSize, outSizeCur, dicPos;
869*b1efbcd6SAlok Aggarwal     ELzmaFinishMode curFinishMode;
870*b1efbcd6SAlok Aggarwal     SRes res;
871*b1efbcd6SAlok Aggarwal     if (p->dicPos == p->dicBufSize)
872*b1efbcd6SAlok Aggarwal       p->dicPos = 0;
873*b1efbcd6SAlok Aggarwal     dicPos = p->dicPos;
874*b1efbcd6SAlok Aggarwal     if (outSize > p->dicBufSize - dicPos)
875*b1efbcd6SAlok Aggarwal     {
876*b1efbcd6SAlok Aggarwal       outSizeCur = p->dicBufSize;
877*b1efbcd6SAlok Aggarwal       curFinishMode = LZMA_FINISH_ANY;
878*b1efbcd6SAlok Aggarwal     }
879*b1efbcd6SAlok Aggarwal     else
880*b1efbcd6SAlok Aggarwal     {
881*b1efbcd6SAlok Aggarwal       outSizeCur = dicPos + outSize;
882*b1efbcd6SAlok Aggarwal       curFinishMode = finishMode;
883*b1efbcd6SAlok Aggarwal     }
884*b1efbcd6SAlok Aggarwal 
885*b1efbcd6SAlok Aggarwal     res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
886*b1efbcd6SAlok Aggarwal     src += inSizeCur;
887*b1efbcd6SAlok Aggarwal     inSize -= inSizeCur;
888*b1efbcd6SAlok Aggarwal     *srcLen += inSizeCur;
889*b1efbcd6SAlok Aggarwal     outSizeCur = p->dicPos - dicPos;
890*b1efbcd6SAlok Aggarwal     (void) memcpy(dest, p->dic + dicPos, outSizeCur);
891*b1efbcd6SAlok Aggarwal     dest += outSizeCur;
892*b1efbcd6SAlok Aggarwal     outSize -= outSizeCur;
893*b1efbcd6SAlok Aggarwal     *destLen += outSizeCur;
894*b1efbcd6SAlok Aggarwal     if (res != 0)
895*b1efbcd6SAlok Aggarwal       return res;
896*b1efbcd6SAlok Aggarwal     if (outSizeCur == 0 || outSize == 0)
897*b1efbcd6SAlok Aggarwal       return SZ_OK;
898*b1efbcd6SAlok Aggarwal   }
899*b1efbcd6SAlok Aggarwal }
900*b1efbcd6SAlok Aggarwal 
901*b1efbcd6SAlok Aggarwal void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
902*b1efbcd6SAlok Aggarwal {
903*b1efbcd6SAlok Aggarwal   if (p->probs != 0)
904*b1efbcd6SAlok Aggarwal   	alloc->Free(alloc, p->probs, (p->numProbs * sizeof (*p->probs)));
905*b1efbcd6SAlok Aggarwal   p->probs = 0;
906*b1efbcd6SAlok Aggarwal }
907*b1efbcd6SAlok Aggarwal 
908*b1efbcd6SAlok Aggarwal static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
909*b1efbcd6SAlok Aggarwal {
910*b1efbcd6SAlok Aggarwal   if (p->dic != 0)
911*b1efbcd6SAlok Aggarwal   	alloc->Free(alloc, p->dic, ((p->prop).dicSize * sizeof (*p->dic)));
912*b1efbcd6SAlok Aggarwal   p->dic = 0;
913*b1efbcd6SAlok Aggarwal }
914*b1efbcd6SAlok Aggarwal 
915*b1efbcd6SAlok Aggarwal void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
916*b1efbcd6SAlok Aggarwal {
917*b1efbcd6SAlok Aggarwal   LzmaDec_FreeProbs(p, alloc);
918*b1efbcd6SAlok Aggarwal   LzmaDec_FreeDict(p, alloc);
919*b1efbcd6SAlok Aggarwal }
920*b1efbcd6SAlok Aggarwal 
921*b1efbcd6SAlok Aggarwal SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
922*b1efbcd6SAlok Aggarwal {
923*b1efbcd6SAlok Aggarwal   UInt32 dicSize;
924*b1efbcd6SAlok Aggarwal   Byte d;
925*b1efbcd6SAlok Aggarwal 
926*b1efbcd6SAlok Aggarwal   if (size < LZMA_PROPS_SIZE)
927*b1efbcd6SAlok Aggarwal     return SZ_ERROR_UNSUPPORTED;
928*b1efbcd6SAlok Aggarwal   else
929*b1efbcd6SAlok Aggarwal     dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
930*b1efbcd6SAlok Aggarwal 
931*b1efbcd6SAlok Aggarwal   if (dicSize < LZMA_DIC_MIN)
932*b1efbcd6SAlok Aggarwal     dicSize = LZMA_DIC_MIN;
933*b1efbcd6SAlok Aggarwal   p->dicSize = dicSize;
934*b1efbcd6SAlok Aggarwal 
935*b1efbcd6SAlok Aggarwal   d = data[0];
936*b1efbcd6SAlok Aggarwal   if (d >= (9 * 5 * 5))
937*b1efbcd6SAlok Aggarwal     return SZ_ERROR_UNSUPPORTED;
938*b1efbcd6SAlok Aggarwal 
939*b1efbcd6SAlok Aggarwal   p->lc = d % 9;
940*b1efbcd6SAlok Aggarwal   d /= 9;
941*b1efbcd6SAlok Aggarwal   p->pb = d / 5;
942*b1efbcd6SAlok Aggarwal   p->lp = d % 5;
943*b1efbcd6SAlok Aggarwal 
944*b1efbcd6SAlok Aggarwal   return SZ_OK;
945*b1efbcd6SAlok Aggarwal }
946*b1efbcd6SAlok Aggarwal 
947*b1efbcd6SAlok Aggarwal static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
948*b1efbcd6SAlok Aggarwal {
949*b1efbcd6SAlok Aggarwal   UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
950*b1efbcd6SAlok Aggarwal   if (p->probs == 0 || numProbs != p->numProbs)
951*b1efbcd6SAlok Aggarwal   {
952*b1efbcd6SAlok Aggarwal     LzmaDec_FreeProbs(p, alloc);
953*b1efbcd6SAlok Aggarwal     p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
954*b1efbcd6SAlok Aggarwal     p->numProbs = numProbs;
955*b1efbcd6SAlok Aggarwal     if (p->probs == 0)
956*b1efbcd6SAlok Aggarwal       return SZ_ERROR_MEM;
957*b1efbcd6SAlok Aggarwal   }
958*b1efbcd6SAlok Aggarwal   return SZ_OK;
959*b1efbcd6SAlok Aggarwal }
960*b1efbcd6SAlok Aggarwal 
961*b1efbcd6SAlok Aggarwal SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
962*b1efbcd6SAlok Aggarwal {
963*b1efbcd6SAlok Aggarwal   CLzmaProps propNew;
964*b1efbcd6SAlok Aggarwal   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
965*b1efbcd6SAlok Aggarwal   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
966*b1efbcd6SAlok Aggarwal   p->prop = propNew;
967*b1efbcd6SAlok Aggarwal   return SZ_OK;
968*b1efbcd6SAlok Aggarwal }
969*b1efbcd6SAlok Aggarwal 
970*b1efbcd6SAlok Aggarwal SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
971*b1efbcd6SAlok Aggarwal {
972*b1efbcd6SAlok Aggarwal   CLzmaProps propNew;
973*b1efbcd6SAlok Aggarwal   SizeT dicBufSize;
974*b1efbcd6SAlok Aggarwal   RINOK(LzmaProps_Decode(&propNew, props, propsSize));
975*b1efbcd6SAlok Aggarwal   RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
976*b1efbcd6SAlok Aggarwal   dicBufSize = propNew.dicSize;
977*b1efbcd6SAlok Aggarwal   if (p->dic == 0 || dicBufSize != p->dicBufSize)
978*b1efbcd6SAlok Aggarwal   {
979*b1efbcd6SAlok Aggarwal     LzmaDec_FreeDict(p, alloc);
980*b1efbcd6SAlok Aggarwal     p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
981*b1efbcd6SAlok Aggarwal     if (p->dic == 0)
982*b1efbcd6SAlok Aggarwal     {
983*b1efbcd6SAlok Aggarwal       LzmaDec_FreeProbs(p, alloc);
984*b1efbcd6SAlok Aggarwal       return SZ_ERROR_MEM;
985*b1efbcd6SAlok Aggarwal     }
986*b1efbcd6SAlok Aggarwal   }
987*b1efbcd6SAlok Aggarwal   p->dicBufSize = dicBufSize;
988*b1efbcd6SAlok Aggarwal   p->prop = propNew;
989*b1efbcd6SAlok Aggarwal   return SZ_OK;
990*b1efbcd6SAlok Aggarwal }
991*b1efbcd6SAlok Aggarwal 
992*b1efbcd6SAlok Aggarwal SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
993*b1efbcd6SAlok Aggarwal     const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
994*b1efbcd6SAlok Aggarwal     ELzmaStatus *status, ISzAlloc *alloc)
995*b1efbcd6SAlok Aggarwal {
996*b1efbcd6SAlok Aggarwal   CLzmaDec p;
997*b1efbcd6SAlok Aggarwal   SRes res;
998*b1efbcd6SAlok Aggarwal   SizeT inSize = *srcLen;
999*b1efbcd6SAlok Aggarwal   SizeT outSize = *destLen;
1000*b1efbcd6SAlok Aggarwal   *srcLen = *destLen = 0;
1001*b1efbcd6SAlok Aggarwal   if (inSize < RC_INIT_SIZE)
1002*b1efbcd6SAlok Aggarwal     return SZ_ERROR_INPUT_EOF;
1003*b1efbcd6SAlok Aggarwal 
1004*b1efbcd6SAlok Aggarwal   LzmaDec_Construct(&p);
1005*b1efbcd6SAlok Aggarwal   res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
1006*b1efbcd6SAlok Aggarwal   if (res != 0)
1007*b1efbcd6SAlok Aggarwal     return res;
1008*b1efbcd6SAlok Aggarwal   p.dic = dest;
1009*b1efbcd6SAlok Aggarwal   p.dicBufSize = outSize;
1010*b1efbcd6SAlok Aggarwal 
1011*b1efbcd6SAlok Aggarwal   LzmaDec_Init(&p);
1012*b1efbcd6SAlok Aggarwal 
1013*b1efbcd6SAlok Aggarwal   *srcLen = inSize;
1014*b1efbcd6SAlok Aggarwal   res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
1015*b1efbcd6SAlok Aggarwal 
1016*b1efbcd6SAlok Aggarwal   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
1017*b1efbcd6SAlok Aggarwal     res = SZ_ERROR_INPUT_EOF;
1018*b1efbcd6SAlok Aggarwal 
1019*b1efbcd6SAlok Aggarwal   (*destLen) = p.dicPos;
1020*b1efbcd6SAlok Aggarwal   LzmaDec_FreeProbs(&p, alloc);
1021*b1efbcd6SAlok Aggarwal   return res;
1022*b1efbcd6SAlok Aggarwal }
1023