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