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