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