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