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