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