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