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