strex: added `detectUrl()`
[iv.d.git] / dlzma / dec.d
blob9e9e431a19774ff9981e2ea5ef7207418c899842
1 /* converted by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
9 */
10 module iv.dlzma.dec;
12 private import iv.dlzma;
13 nothrow:
15 /* use smaller (by ~3KB), but slightly slower (prolly) decompression code? */
16 //version = LZMA_SIZE_OPT;
19 // ////////////////////////////////////////////////////////////////////////// //
20 // ////////////////////////////////////////////////////////////////////////// //
21 // ////////////////////////////////////////////////////////////////////////// //
22 // ////////////////////////////////////////////////////////////////////////// //
23 private:
24 enum kNumTopBits = 24;
25 enum kTopValue = (cast(uint)1 << kNumTopBits);
27 enum kNumBitModelTotalBits = 11;
28 enum kBitModelTotal = (1 << kNumBitModelTotalBits);
30 enum RC_INIT_SIZE = 5;
33 enum kNumMoveBits = 5;
34 enum NORMALIZE = `if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }`;
36 enum IF_BIT_0(string p) = `ttt = *(`~p~`); `~NORMALIZE~` bound = (range >> kNumBitModelTotalBits) * cast(uint)ttt;`; // if (code < bound)
38 enum UPDATE_0(string p) = `range = bound; *(`~p~`) = cast(CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));`;
39 enum UPDATE_1(string p) = `range -= bound; code -= bound; *(`~p~`) = cast(CLzmaProb)(ttt - (ttt >> kNumMoveBits));`;
41 enum GET_BIT2(string p, string i, string A0, string A1) =
42 IF_BIT_0!(p)~` if (code < bound)
43 { `~UPDATE_0!(p)~` `~i~` = (`~i~` + `~i~`); `~A0~` } else
44 { `~UPDATE_1!(p)~` `~i~` = (`~i~` + `~i~`) + 1; `~A1~` }
47 enum TREE_GET_BIT(string probs, string i) = `{ `~GET_BIT2!(probs~` + `~i, i, `{}`, `{}`)~` }`;
49 enum REV_BIT(string p, string i, string A0, string A1) =
50 IF_BIT_0!(p~` + `~i)~` if (code < bound)
51 { `~UPDATE_0!(p~` + `~i)~` `~A0~` } else
52 { `~UPDATE_1!(p~` + `~i)~` `~A1~` }
55 enum REV_BIT_VAR(string p, string i, string m) = REV_BIT!(p, i, i~` += `~m~`; `~m~` += `~m~`;`, m~` += `~m~`; `~i~` += `~m~`;`);
56 enum REV_BIT_CONST(string p, string i, string m) = REV_BIT!(p, i, i~` += `~m~`;`, i~` += `~m~` * 2;`);
57 enum REV_BIT_LAST(string p, string i, string m) = REV_BIT!(p, i, i~` -= `~m~`;`, `{}`);
59 enum TREE_DECODE(string probs, string limit, string i) = `
60 { `~i~` = 1; do { `~TREE_GET_BIT!(probs, i)~` } while (`~i~` < `~limit~`); `~i~` -= `~limit~`; }`;
62 /* #define LZMA_SIZE_OPT */
64 version(LZMA_SIZE_OPT) {
65 enum TREE_6_DECODE(string probs, string i) = TREE_DECODE!(probs, "(1 << 6)", i);
66 } else {
67 enum TREE_6_DECODE(string probs, string i) = `
68 { `~i~` = 1;`~
69 TREE_GET_BIT!(probs, i)~
70 TREE_GET_BIT!(probs, i)~
71 TREE_GET_BIT!(probs, i)~
72 TREE_GET_BIT!(probs, i)~
73 TREE_GET_BIT!(probs, i)~
74 TREE_GET_BIT!(probs, i)~`
75 `~i~` -= 0x40; }
79 enum NORMAL_LITER_DEC = TREE_GET_BIT!("prob", "symbol");
81 enum MATCHED_LITER_DEC = `
82 matchByte += matchByte;
83 bit = offs;
84 offs &= matchByte;
85 probLit = prob + (offs + bit + symbol);
86 `~GET_BIT2!("probLit", "symbol", "offs ^= bit;", "{}");
89 enum NORMALIZE_CHECK = `if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_INPUT_EOF; range <<= 8; code = (code << 8) | (*buf++); }`;
91 enum IF_BIT_0_CHECK(string p) = `ttt = *(`~p~`); `~NORMALIZE_CHECK~` bound = (range >> kNumBitModelTotalBits) * cast(uint)ttt;`; //if (code < bound)
93 enum UPDATE_0_CHECK = `range = bound;`;
94 enum UPDATE_1_CHECK = `range -= bound; code -= bound;`;
96 enum GET_BIT2_CHECK(string p, string i, string A0, string A1) =
97 IF_BIT_0_CHECK!(p)~` if (code < bound)
98 { `~UPDATE_0_CHECK~` `~i~` = (`~i~` + `~i~`); `~A0~` } else
99 { `~UPDATE_1_CHECK~` `~i~` = (`~i~` + `~i~`) + 1; `~A1~` }
102 enum GET_BIT_CHECK(string p, string i) = GET_BIT2_CHECK!(p, i, `{}` , `{}`);
104 enum TREE_DECODE_CHECK(string probs, string limit, string i) =
105 `{ `~i~` = 1; do { `~GET_BIT_CHECK!(probs~` + `~i, i)~` } while (`~i~` < `~limit~`); `~i~` -= `~limit~`; }`;
108 enum REV_BIT_CHECK(string p, string i, string m) =
109 IF_BIT_0_CHECK!(p~` + `~i)~` if (code < bound)
110 { `~UPDATE_0_CHECK~` `~i~` += `~m~`; `~m~` += `~m~`; } else
111 { `~UPDATE_1_CHECK~` `~m~` += `~m~`; `~i~` += `~m~`; }`;
114 enum kNumPosBitsMax = 4;
115 enum kNumPosStatesMax = (1 << kNumPosBitsMax);
117 enum kLenNumLowBits = 3;
118 enum kLenNumLowSymbols = (1 << kLenNumLowBits);
119 enum kLenNumHighBits = 8;
120 enum kLenNumHighSymbols = (1 << kLenNumHighBits);
122 enum LenLow = 0;
123 enum LenHigh = (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits));
124 enum kNumLenProbs = (LenHigh + kLenNumHighSymbols);
126 enum LenChoice = LenLow;
127 enum LenChoice2 = (LenLow + (1 << kLenNumLowBits));
129 enum kNumStates = 12;
130 enum kNumStates2 = 16;
131 enum kNumLitStates = 7;
133 enum kStartPosModelIndex = 4;
134 enum kEndPosModelIndex = 14;
135 enum kNumFullDistances = (1 << (kEndPosModelIndex >> 1));
137 enum kNumPosSlotBits = 6;
138 enum kNumLenToPosStates = 4;
140 enum kNumAlignBits = 4;
141 enum kAlignTableSize = (1 << kNumAlignBits);
143 enum kMatchMinLen = 2;
144 enum kMatchSpecLenStart = (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols);
146 enum kMatchSpecLen_Error_Data = (1 << 9);
147 enum kMatchSpecLen_Error_Fail = (kMatchSpecLen_Error_Data - 1);
149 /* External ASM code needs same CLzmaProb array layout. So don't change it. */
151 /* (probs_1664) is faster and better for code size at some platforms */
153 #ifdef MY_CPU_X86_OR_AMD64
155 enum kStartOffset = 1664;
156 //#define GET_PROBS p.probs_1664
158 #define GET_PROBS p.probs + kStartOffset
159 #else
160 #define kStartOffset 0
161 #define GET_PROBS p.probs
162 #endif
165 enum SpecPos = (-kStartOffset);
166 enum IsRep0Long = (SpecPos + kNumFullDistances);
167 enum RepLenCoder = (IsRep0Long + (kNumStates2 << kNumPosBitsMax));
168 enum LenCoder = (RepLenCoder + kNumLenProbs);
169 enum IsMatch = (LenCoder + kNumLenProbs);
170 enum Align = (IsMatch + (kNumStates2 << kNumPosBitsMax));
171 enum IsRep = (Align + kAlignTableSize);
172 enum IsRepG0 = (IsRep + kNumStates);
173 enum IsRepG1 = (IsRepG0 + kNumStates);
174 enum IsRepG2 = (IsRepG1 + kNumStates);
175 enum PosSlot = (IsRepG2 + kNumStates);
176 enum Literal = (PosSlot + (kNumLenToPosStates << kNumPosSlotBits));
177 enum NUM_BASE_PROBS = (Literal + kStartOffset);
179 static assert(Align == 0 || kStartOffset == 0, "Stop_Compiling_Bad_LZMA_kAlign");
181 static assert(NUM_BASE_PROBS == 1984, "Stop_Compiling_Bad_LZMA_PROBS");
184 enum LZMA_LIT_SIZE = 0x300;
186 enum LzmaProps_GetNumProbs(string p) = `(NUM_BASE_PROBS + (cast(uint)LZMA_LIT_SIZE << ((`~p~`).lc + (`~p~`).lp)))`;
189 enum CALC_POS_STATE(string processedPos, string pbMask) = `(((`~processedPos~`) & (`~pbMask~`)) << 4)`;
190 enum COMBINED_PS_STATE = `(posState + state)`;
191 enum GET_LEN_STATE = `(posState)`;
193 enum LZMA_DIC_MIN = (1 << 12);
196 p.remainLen : shows status of LZMA decoder:
197 < kMatchSpecLenStart : the number of bytes to be copied with (p.rep0) offset
198 = kMatchSpecLenStart : the LZMA stream was finished with end mark
199 = kMatchSpecLenStart + 1 : need init range coder
200 = kMatchSpecLenStart + 2 : need init range coder and state
201 = kMatchSpecLen_Error_Fail : Internal Code Failure
202 = kMatchSpecLen_Error_Data + [0 ... 273] : LZMA Data Error
205 /* ---------- LZMA_DECODE_REAL ---------- */
207 LzmaDec_DecodeReal_3() can be implemented in external ASM file.
208 3 - is the code compatibility version of that function for check at link time.
212 LZMA_DECODE_REAL()
214 RangeCoder is normalized
215 if (p.dicPos == limit)
217 LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases.
218 So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol
219 is not END_OF_PAYALOAD_MARKER, then the function doesn't write any byte to dictionary,
220 the function returns SZ_OK, and the caller can use (p.remainLen) and (p.reps[0]) later.
223 Processing:
224 The first LZMA symbol will be decoded in any case.
225 All main checks for limits are at the end of main loop,
226 It decodes additional LZMA-symbols while (p.buf < bufLimit && dicPos < limit),
227 RangeCoder is still without last normalization when (p.buf < bufLimit) is being checked.
228 But if (p.buf < bufLimit), the caller provided at least (LZMA_REQUIRED_INPUT_MAX + 1) bytes for
229 next iteration before limit (bufLimit + LZMA_REQUIRED_INPUT_MAX),
230 that is enough for worst case LZMA symbol with one additional RangeCoder normalization for one bit.
231 So that function never reads bufLimit [LZMA_REQUIRED_INPUT_MAX] byte.
233 Out:
234 RangeCoder is normalized
235 Result:
236 SZ_OK - OK
237 p.remainLen:
238 < kMatchSpecLenStart : the number of bytes to be copied with (p.reps[0]) offset
239 = kMatchSpecLenStart : the LZMA stream was finished with end mark
241 SZ_ERROR_DATA - error, when the MATCH-Symbol refers out of dictionary
242 p.remainLen : undefined
243 p.reps[*] : undefined
247 private int LZMA_DECODE_REAL (CLzmaDec *p, usize limit, const(ubyte)* bufLimit) @nogc {
248 CLzmaProb *probs = /*GET_PROBS*/p.probs_1664;
249 uint state = cast(uint)p.state;
250 uint rep0 = p.reps[0], rep1 = p.reps[1], rep2 = p.reps[2], rep3 = p.reps[3];
251 uint pbMask = (cast(uint)1 << (p.prop.pb)) - 1;
252 uint lc = p.prop.lc;
253 uint lpMask = (cast(uint)0x100 << p.prop.lp) - (cast(uint)0x100 >> lc);
255 ubyte *dic = p.dic;
256 usize dicBufSize = p.dicBufSize;
257 usize dicPos = p.dicPos;
259 uint processedPos = p.processedPos;
260 uint checkDicSize = p.checkDicSize;
261 uint len = 0;
263 const(ubyte)* buf = p.buf;
264 uint range = p.range;
265 uint code = p.code;
269 CLzmaProb *prob;
270 uint bound;
271 uint ttt;
272 uint posState = mixin(CALC_POS_STATE!("processedPos", "pbMask"));
274 prob = probs + IsMatch + mixin(COMBINED_PS_STATE);
275 mixin(IF_BIT_0!"prob");
276 if (code < bound)
278 uint symbol;
279 mixin(UPDATE_0!"prob");
280 prob = probs + Literal;
281 if (processedPos != 0 || checkDicSize != 0)
282 prob += cast(uint)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc);
283 processedPos++;
285 if (state < kNumLitStates)
287 state -= (state < 4) ? state : 3;
288 symbol = 1;
289 version(LZMA_SIZE_OPT) {
290 do { mixin(NORMAL_LITER_DEC); } while (symbol < 0x100);
291 } else {
292 mixin(NORMAL_LITER_DEC);
293 mixin(NORMAL_LITER_DEC);
294 mixin(NORMAL_LITER_DEC);
295 mixin(NORMAL_LITER_DEC);
296 mixin(NORMAL_LITER_DEC);
297 mixin(NORMAL_LITER_DEC);
298 mixin(NORMAL_LITER_DEC);
299 mixin(NORMAL_LITER_DEC);
302 else
304 uint matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
305 uint offs = 0x100;
306 state -= (state < 10) ? 3 : 6;
307 symbol = 1;
308 version(LZMA_SIZE_OPT) {
311 uint bit;
312 CLzmaProb *probLit;
313 mixin(MATCHED_LITER_DEC);
315 while (symbol < 0x100);
316 } else {
318 uint bit;
319 CLzmaProb *probLit;
320 mixin(MATCHED_LITER_DEC);
321 mixin(MATCHED_LITER_DEC);
322 mixin(MATCHED_LITER_DEC);
323 mixin(MATCHED_LITER_DEC);
324 mixin(MATCHED_LITER_DEC);
325 mixin(MATCHED_LITER_DEC);
326 mixin(MATCHED_LITER_DEC);
327 mixin(MATCHED_LITER_DEC);
332 dic[dicPos++] = cast(ubyte)symbol;
333 continue;
337 mixin(UPDATE_1!"prob");
338 prob = probs + IsRep + state;
339 mixin(IF_BIT_0!"prob");
340 if (code < bound)
342 mixin(UPDATE_0!"prob");
343 state += kNumStates;
344 prob = probs + LenCoder;
346 else
348 mixin(UPDATE_1!"prob");
349 prob = probs + IsRepG0 + state;
350 mixin(IF_BIT_0!"prob");
351 if (code < bound)
353 mixin(UPDATE_0!"prob");
354 prob = probs + IsRep0Long + mixin(COMBINED_PS_STATE);
355 mixin(IF_BIT_0!"prob");
356 if (code < bound)
358 mixin(UPDATE_0!"prob");
360 // that case was checked before with kBadRepCode
361 // if (checkDicSize == 0 && processedPos == 0) { len = kMatchSpecLen_Error_Data + 1; break; }
362 // The caller doesn't allow (dicPos == limit) case here
363 // so we don't need the following check:
364 // if (dicPos == limit) { state = state < kNumLitStates ? 9 : 11; len = 1; break; }
366 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
367 dicPos++;
368 processedPos++;
369 state = state < kNumLitStates ? 9 : 11;
370 continue;
372 mixin(UPDATE_1!"prob");
374 else
376 uint distance;
377 mixin(UPDATE_1!"prob");
378 prob = probs + IsRepG1 + state;
379 mixin(IF_BIT_0!"prob");
380 if (code < bound)
382 mixin(UPDATE_0!"prob");
383 distance = rep1;
385 else
387 mixin(UPDATE_1!"prob");
388 prob = probs + IsRepG2 + state;
389 mixin(IF_BIT_0!"prob");
390 if (code < bound)
392 mixin(UPDATE_0!"prob");
393 distance = rep2;
395 else
397 mixin(UPDATE_1!"prob");
398 distance = rep3;
399 rep3 = rep2;
401 rep2 = rep1;
403 rep1 = rep0;
404 rep0 = distance;
406 state = state < kNumLitStates ? 8 : 11;
407 prob = probs + RepLenCoder;
410 version(LZMA_SIZE_OPT) {
412 uint lim, offset;
413 CLzmaProb *probLen = prob + LenChoice;
414 mixin(IF_BIT_0!"probLen");
415 if (code < bound)
417 mixin(UPDATE_0!"probLen");
418 probLen = prob + LenLow + mixin(GET_LEN_STATE);
419 offset = 0;
420 lim = (1 << kLenNumLowBits);
422 else
424 mixin(UPDATE_1!"probLen");
425 probLen = prob + LenChoice2;
426 mixin(IF_BIT_0!"probLen");
427 if (code < bound)
429 mixin(UPDATE_0!"probLen");
430 probLen = prob + LenLow + mixin(GET_LEN_STATE) + (1 << kLenNumLowBits);
431 offset = kLenNumLowSymbols;
432 lim = (1 << kLenNumLowBits);
434 else
436 mixin(UPDATE_1!"probLen");
437 probLen = prob + LenHigh;
438 offset = kLenNumLowSymbols * 2;
439 lim = (1 << kLenNumHighBits);
442 mixin(TREE_DECODE!("probLen", "lim", "len"));
443 len += offset;
445 } else {
447 CLzmaProb *probLen = prob + LenChoice;
448 mixin(IF_BIT_0!"probLen");
449 if (code < bound)
451 mixin(UPDATE_0!"probLen");
452 probLen = prob + LenLow + mixin(GET_LEN_STATE);
453 len = 1;
454 mixin(TREE_GET_BIT!("probLen", "len"));
455 mixin(TREE_GET_BIT!("probLen", "len"));
456 mixin(TREE_GET_BIT!("probLen", "len"));
457 len -= 8;
459 else
461 mixin(UPDATE_1!"probLen");
462 probLen = prob + LenChoice2;
463 mixin(IF_BIT_0!"probLen");
464 if (code < bound)
466 mixin(UPDATE_0!"probLen");
467 probLen = prob + LenLow + mixin(GET_LEN_STATE) + (1 << kLenNumLowBits);
468 len = 1;
469 mixin(TREE_GET_BIT!("probLen", "len"));
470 mixin(TREE_GET_BIT!("probLen", "len"));
471 mixin(TREE_GET_BIT!("probLen", "len"));
473 else
475 mixin(UPDATE_1!"probLen");
476 probLen = prob + LenHigh;
477 mixin(TREE_DECODE!("probLen", "(1 << kLenNumHighBits)", "len"));
478 len += kLenNumLowSymbols * 2;
484 if (state >= kNumStates)
486 uint distance;
487 prob = probs + PosSlot +
488 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
489 mixin(TREE_6_DECODE!("prob", "distance"));
490 if (distance >= kStartPosModelIndex)
492 uint posSlot = cast(uint)distance;
493 uint numDirectBits = cast(uint)(((distance >> 1) - 1));
494 distance = (2 | (distance & 1));
495 if (posSlot < kEndPosModelIndex)
497 distance <<= numDirectBits;
498 prob = probs + SpecPos;
500 uint m = 1;
501 distance++;
504 mixin(REV_BIT_VAR!("prob", "distance", "m"));
506 while (--numDirectBits);
507 distance -= m;
510 else
512 numDirectBits -= kNumAlignBits;
515 mixin(NORMALIZE);
516 range >>= 1;
519 uint t;
520 code -= range;
521 t = (0 - (cast(uint)code >> 31)); /* (uint)((int32_t)code >> 31) */
522 distance = (distance << 1) + (t + 1);
523 code += range & t;
526 distance <<= 1;
527 if (code >= range)
529 code -= range;
530 distance |= 1;
534 while (--numDirectBits);
535 prob = probs + Align;
536 distance <<= kNumAlignBits;
538 uint i = 1;
539 mixin(REV_BIT_CONST!("prob", "i", "1"));
540 mixin(REV_BIT_CONST!("prob", "i", "2"));
541 mixin(REV_BIT_CONST!("prob", "i", "4"));
542 mixin(REV_BIT_LAST!("prob", "i", "8"));
543 distance |= i;
545 if (distance == cast(uint)0xFFFFFFFFU)
547 len = kMatchSpecLenStart;
548 state -= kNumStates;
549 break;
554 rep3 = rep2;
555 rep2 = rep1;
556 rep1 = rep0;
557 rep0 = distance + 1;
558 state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
559 if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize))
561 len += kMatchSpecLen_Error_Data + kMatchMinLen;
562 // len = kMatchSpecLen_Error_Data;
563 // len += kMatchMinLen;
564 break;
568 len += kMatchMinLen;
571 usize rem;
572 uint curLen;
573 usize pos;
575 if ((rem = limit - dicPos) == 0)
578 We stop decoding and return SZ_OK, and we can resume decoding later.
579 Any error conditions can be tested later in caller code.
580 For more strict mode we can stop decoding with error
581 // len += kMatchSpecLen_Error_Data;
583 break;
586 curLen = ((rem < len) ? cast(uint)rem : len);
587 pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
589 processedPos += cast(uint)curLen;
591 len -= curLen;
592 if (curLen <= dicBufSize - pos)
594 ubyte *dest = dic + dicPos;
595 ptrdiff_t src = cast(ptrdiff_t)pos - cast(ptrdiff_t)dicPos;
596 const(ubyte)* lim = dest + curLen;
597 dicPos += cast(usize)curLen;
599 *(dest) = cast(ubyte)*(dest + src);
600 while (++dest != lim);
602 else
606 dic[dicPos++] = dic[pos];
607 if (++pos == dicBufSize)
608 pos = 0;
610 while (--curLen != 0);
615 while (dicPos < limit && buf < bufLimit);
617 mixin(NORMALIZE);
619 p.buf = buf;
620 p.range = range;
621 p.code = code;
622 p.remainLen = cast(uint)len; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too.
623 p.dicPos = dicPos;
624 p.processedPos = processedPos;
625 p.reps[0] = rep0;
626 p.reps[1] = rep1;
627 p.reps[2] = rep2;
628 p.reps[3] = rep3;
629 p.state = cast(uint)state;
630 if (len >= kMatchSpecLen_Error_Data)
631 return SZ_ERROR_DATA;
632 return SZ_OK;
636 private void LzmaDec_WriteRem (CLzmaDec* p, usize limit) @nogc {
637 uint len = cast(uint)p.remainLen;
638 if (len == 0 /* || len >= kMatchSpecLenStart */)
639 return;
641 usize dicPos = p.dicPos;
642 ubyte *dic;
643 usize dicBufSize;
644 usize rep0; /* we use usize to avoid the BUG of VC14 for AMD64 */
646 usize rem = limit - dicPos;
647 if (rem < len)
649 len = cast(uint)(rem);
650 if (len == 0)
651 return;
655 if (p.checkDicSize == 0 && p.prop.dicSize - p.processedPos <= len)
656 p.checkDicSize = p.prop.dicSize;
658 p.processedPos += cast(uint)len;
659 p.remainLen -= cast(uint)len;
660 dic = p.dic;
661 rep0 = p.reps[0];
662 dicBufSize = p.dicBufSize;
665 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
666 dicPos++;
668 while (--len);
669 p.dicPos = dicPos;
675 At staring of new stream we have one of the following symbols:
676 - Literal - is allowed
677 - Non-Rep-Match - is allowed only if it's end marker symbol
678 - Rep-Match - is not allowed
679 We use early check of (RangeCoder:Code) over kBadRepCode to simplify main decoding code
682 enum kRange0 = 0xFFFFFFFF;
683 enum kBound0 = ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1));
684 enum kBadRepCode = (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)));
685 static assert(kBadRepCode == (0xC0000000 - 0x400), "Stop_Compiling_Bad_LZMA_Check");
689 LzmaDec_DecodeReal2():
690 It calls LZMA_DECODE_REAL() and it adjusts limit according (p.checkDicSize).
692 We correct (p.checkDicSize) after LZMA_DECODE_REAL() and in LzmaDec_WriteRem(),
693 and we support the following state of (p.checkDicSize):
694 if (total_processed < p.prop.dicSize) then
696 (total_processed == p.processedPos)
697 (p.checkDicSize == 0)
699 else
700 (p.checkDicSize == p.prop.dicSize)
703 private int LzmaDec_DecodeReal2 (CLzmaDec *p, usize limit, const(ubyte)* bufLimit) @nogc {
704 if (p.checkDicSize == 0)
706 uint rem = p.prop.dicSize - p.processedPos;
707 if (limit - p.dicPos > rem)
708 limit = p.dicPos + rem;
711 int res = LZMA_DECODE_REAL(p, limit, bufLimit);
712 if (p.checkDicSize == 0 && p.processedPos >= p.prop.dicSize)
713 p.checkDicSize = p.prop.dicSize;
714 return res;
720 alias ELzmaDummy = int;
721 enum
723 DUMMY_INPUT_EOF, /* need more input data */
724 DUMMY_LIT,
725 DUMMY_MATCH,
726 DUMMY_REP
730 enum IS_DUMMY_END_MARKER_POSSIBLE(string dummyRes) = `((`~dummyRes~`) == DUMMY_MATCH)`;
732 private ELzmaDummy LzmaDec_TryDummy (const(CLzmaDec)* p, const(ubyte)* buf, const(ubyte)** bufOut) @nogc {
733 uint range = p.range;
734 uint code = p.code;
735 const(ubyte)* bufLimit = *bufOut;
736 const(CLzmaProb)* probs = /*GET_PROBS*/p.probs_1664;
737 uint state = cast(uint)p.state;
738 ELzmaDummy res;
740 for (;;)
742 const(CLzmaProb)* prob;
743 uint bound;
744 uint ttt;
745 uint posState = mixin(CALC_POS_STATE!("p.processedPos", "(cast(uint)1 << p.prop.pb) - 1"));
747 prob = probs + IsMatch + mixin(COMBINED_PS_STATE);
748 mixin(IF_BIT_0_CHECK!"prob");
749 if (code < bound)
751 mixin(UPDATE_0_CHECK);
753 prob = probs + Literal;
754 if (p.checkDicSize != 0 || p.processedPos != 0)
755 prob += (cast(uint)LZMA_LIT_SIZE *
756 ((((p.processedPos) & ((cast(uint)1 << (p.prop.lp)) - 1)) << p.prop.lc) +
757 (cast(uint)p.dic[(p.dicPos == 0 ? p.dicBufSize : p.dicPos) - 1] >> (8 - p.prop.lc))));
759 if (state < kNumLitStates)
761 uint symbol = 1;
762 do { mixin(GET_BIT_CHECK!("prob + symbol", "symbol")); } while (symbol < 0x100);
764 else
766 uint matchByte = p.dic[p.dicPos - p.reps[0] +
767 (p.dicPos < p.reps[0] ? p.dicBufSize : 0)];
768 uint offs = 0x100;
769 uint symbol = 1;
772 uint bit;
773 const(CLzmaProb)* probLit;
774 matchByte += matchByte;
775 bit = offs;
776 offs &= matchByte;
777 probLit = prob + (offs + bit + symbol);
778 mixin(GET_BIT2_CHECK!("probLit", "symbol", "offs ^= bit;" , "{}"));
780 while (symbol < 0x100);
782 res = DUMMY_LIT;
784 else
786 uint len;
787 mixin(UPDATE_1_CHECK);
789 prob = probs + IsRep + state;
790 mixin(IF_BIT_0_CHECK!"prob");
791 if (code < bound)
793 mixin(UPDATE_0_CHECK);
794 state = 0;
795 prob = probs + LenCoder;
796 res = DUMMY_MATCH;
798 else
800 mixin(UPDATE_1_CHECK);
801 res = DUMMY_REP;
802 prob = probs + IsRepG0 + state;
803 mixin(IF_BIT_0_CHECK!"prob");
804 if (code < bound)
806 mixin(UPDATE_0_CHECK);
807 prob = probs + IsRep0Long + mixin(COMBINED_PS_STATE);
808 mixin(IF_BIT_0_CHECK!"prob");
809 if (code < bound)
811 mixin(UPDATE_0_CHECK);
812 break;
814 else
816 mixin(UPDATE_1_CHECK);
819 else
821 mixin(UPDATE_1_CHECK);
822 prob = probs + IsRepG1 + state;
823 mixin(IF_BIT_0_CHECK!"prob");
824 if (code < bound)
826 mixin(UPDATE_0_CHECK);
828 else
830 mixin(UPDATE_1_CHECK);
831 prob = probs + IsRepG2 + state;
832 mixin(IF_BIT_0_CHECK!"prob");
833 if (code < bound)
835 mixin(UPDATE_0_CHECK);
837 else
839 mixin(UPDATE_1_CHECK);
843 state = kNumStates;
844 prob = probs + RepLenCoder;
847 uint limit, offset;
848 const(CLzmaProb)* probLen = prob + LenChoice;
849 mixin(IF_BIT_0_CHECK!"probLen");
850 if (code < bound)
852 mixin(UPDATE_0_CHECK);
853 probLen = prob + LenLow + mixin(GET_LEN_STATE);
854 offset = 0;
855 limit = 1 << kLenNumLowBits;
857 else
859 mixin(UPDATE_1_CHECK);
860 probLen = prob + LenChoice2;
861 mixin(IF_BIT_0_CHECK!"probLen");
862 if (code < bound)
864 mixin(UPDATE_0_CHECK);
865 probLen = prob + LenLow + mixin(GET_LEN_STATE) + (1 << kLenNumLowBits);
866 offset = kLenNumLowSymbols;
867 limit = 1 << kLenNumLowBits;
869 else
871 mixin(UPDATE_1_CHECK);
872 probLen = prob + LenHigh;
873 offset = kLenNumLowSymbols * 2;
874 limit = 1 << kLenNumHighBits;
877 mixin(TREE_DECODE_CHECK!("probLen", "limit", "len"));
878 len += offset;
881 if (state < 4)
883 uint posSlot;
884 prob = probs + PosSlot +
885 ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) <<
886 kNumPosSlotBits);
887 mixin(TREE_DECODE_CHECK!("prob", "1 << kNumPosSlotBits", "posSlot"));
888 if (posSlot >= kStartPosModelIndex)
890 uint numDirectBits = ((posSlot >> 1) - 1);
892 if (posSlot < kEndPosModelIndex)
894 prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits);
896 else
898 numDirectBits -= kNumAlignBits;
901 mixin(NORMALIZE_CHECK);
902 range >>= 1;
903 code -= range & (((code - range) >> 31) - 1);
904 /* if (code >= range) code -= range; */
906 while (--numDirectBits);
907 prob = probs + Align;
908 numDirectBits = kNumAlignBits;
911 uint i = 1;
912 uint m = 1;
915 mixin(REV_BIT_CHECK!("prob", "i", "m"));
917 while (--numDirectBits);
922 break;
924 mixin(NORMALIZE_CHECK);
926 *bufOut = buf;
927 return res;
931 private void LzmaDec_InitDicAndState (CLzmaDec *p, /*BoolInt*/int initDic, /*BoolInt*/int initState) @nogc {
932 p.remainLen = kMatchSpecLenStart + 1;
933 p.tempBufSize = 0;
935 if (initDic)
937 p.processedPos = 0;
938 p.checkDicSize = 0;
939 p.remainLen = kMatchSpecLenStart + 2;
941 if (initState)
942 p.remainLen = kMatchSpecLenStart + 2;
946 //==========================================================================
948 // LzmaDec_Init
950 //==========================================================================
951 public void LzmaDec_Init (CLzmaDec* p) @nogc {
952 p.dicPos = 0;
953 LzmaDec_InitDicAndState(p, 1/*True*/, 1/*True*/);
958 LZMA supports optional end_marker.
959 So the decoder can lookahead for one additional LZMA-Symbol to check end_marker.
960 That additional LZMA-Symbol can require up to LZMA_REQUIRED_INPUT_MAX bytes in input stream.
961 When the decoder reaches dicLimit, it looks (finishMode) parameter:
962 if (finishMode == LZMA_FINISH_ANY), the decoder doesn't lookahead
963 if (finishMode != LZMA_FINISH_ANY), the decoder lookahead, if end_marker is possible for current position
965 When the decoder lookahead, and the lookahead symbol is not end_marker, we have two ways:
966 1) Strict mode (default) : the decoder returns SZ_ERROR_DATA.
967 2) The relaxed mode (alternative mode) : we could return SZ_OK, and the caller
968 must check (status) value. The caller can show the error,
969 if the end of stream is expected, and the (status) is noit
970 LZMA_STATUS_FINISHED_WITH_MARK or LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK.
974 enum RETURN__NOT_FINISHED__FOR_FINISH = q{
975 *status = LZMA_STATUS_NOT_FINISHED;
976 return SZ_ERROR_DATA; /* for strict mode */
977 /* return SZ_OK;*/ /* for relaxed mode */
981 //==========================================================================
983 // LzmaDec_DecodeToDic
985 //==========================================================================
986 public SRes LzmaDec_DecodeToDic (CLzmaDec* p, usize dicLimit, const(ubyte)* src, usize *srcLen,
987 ELzmaFinishMode finishMode, ELzmaStatus *status) @nogc
989 usize inSize = *srcLen;
990 (*srcLen) = 0;
991 *status = LZMA_STATUS_NOT_SPECIFIED;
993 if (p.remainLen > kMatchSpecLenStart)
995 if (p.remainLen > kMatchSpecLenStart + 2)
996 return p.remainLen == kMatchSpecLen_Error_Fail ? SZ_ERROR_FAIL : SZ_ERROR_DATA;
998 for (; inSize > 0 && p.tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
999 p.tempBuf[p.tempBufSize++] = *src++;
1000 if (p.tempBufSize != 0 && p.tempBuf[0] != 0)
1001 return SZ_ERROR_DATA;
1002 if (p.tempBufSize < RC_INIT_SIZE)
1004 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1005 return SZ_OK;
1007 p.code =
1008 (cast(uint)p.tempBuf[1] << 24)
1009 | (cast(uint)p.tempBuf[2] << 16)
1010 | (cast(uint)p.tempBuf[3] << 8)
1011 | (cast(uint)p.tempBuf[4]);
1013 if (p.checkDicSize == 0
1014 && p.processedPos == 0
1015 && p.code >= kBadRepCode)
1016 return SZ_ERROR_DATA;
1018 p.range = 0xFFFFFFFF;
1019 p.tempBufSize = 0;
1021 if (p.remainLen > kMatchSpecLenStart + 1)
1023 usize numProbs = mixin(LzmaProps_GetNumProbs!"&p.prop");
1024 usize i;
1025 CLzmaProb *probs = p.probs;
1026 for (i = 0; i < numProbs; i++)
1027 probs[i] = kBitModelTotal >> 1;
1028 p.reps[0] = p.reps[1] = p.reps[2] = p.reps[3] = 1;
1029 p.state = 0;
1032 p.remainLen = 0;
1035 for (;;)
1037 if (p.remainLen == kMatchSpecLenStart)
1039 if (p.code != 0)
1040 return SZ_ERROR_DATA;
1041 *status = LZMA_STATUS_FINISHED_WITH_MARK;
1042 return SZ_OK;
1045 LzmaDec_WriteRem(p, dicLimit);
1048 // (p.remainLen == 0 || p.dicPos == dicLimit)
1050 int checkEndMarkNow = 0;
1052 if (p.dicPos >= dicLimit)
1054 if (p.remainLen == 0 && p.code == 0)
1056 *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
1057 return SZ_OK;
1059 if (finishMode == LZMA_FINISH_ANY)
1061 *status = LZMA_STATUS_NOT_FINISHED;
1062 return SZ_OK;
1064 if (p.remainLen != 0)
1066 mixin(RETURN__NOT_FINISHED__FOR_FINISH);
1068 checkEndMarkNow = 1;
1071 // (p.remainLen == 0)
1073 if (p.tempBufSize == 0)
1075 const(ubyte)* bufLimit;
1076 int dummyProcessed = -1;
1078 if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
1080 const(ubyte)* bufOut = src + inSize;
1082 ELzmaDummy dummyRes = LzmaDec_TryDummy(p, src, &bufOut);
1084 if (dummyRes == DUMMY_INPUT_EOF)
1086 usize i;
1087 if (inSize >= LZMA_REQUIRED_INPUT_MAX)
1088 break;
1089 (*srcLen) += inSize;
1090 p.tempBufSize = cast(uint)inSize;
1091 for (i = 0; i < inSize; i++)
1092 p.tempBuf[i] = src[i];
1093 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1094 return SZ_OK;
1097 dummyProcessed = cast(int)(bufOut - src);
1098 if (cast(uint)dummyProcessed > LZMA_REQUIRED_INPUT_MAX)
1099 break;
1101 if (checkEndMarkNow && !mixin(IS_DUMMY_END_MARKER_POSSIBLE!"dummyRes"))
1103 uint i;
1104 (*srcLen) += cast(uint)dummyProcessed;
1105 p.tempBufSize = cast(uint)dummyProcessed;
1106 for (i = 0; i < cast(uint)dummyProcessed; i++)
1107 p.tempBuf[i] = src[i];
1108 // p.remainLen = kMatchSpecLen_Error_Data;
1109 mixin(RETURN__NOT_FINISHED__FOR_FINISH);
1112 bufLimit = src;
1113 // we will decode only one iteration
1115 else
1116 bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
1118 p.buf = src;
1121 int res = LzmaDec_DecodeReal2(p, dicLimit, bufLimit);
1123 usize processed = cast(usize)(p.buf - src);
1125 if (dummyProcessed < 0)
1127 if (processed > inSize)
1128 break;
1130 else if (cast(uint)dummyProcessed != processed)
1131 break;
1133 src += processed;
1134 inSize -= processed;
1135 (*srcLen) += processed;
1137 if (res != SZ_OK)
1139 p.remainLen = kMatchSpecLen_Error_Data;
1140 return SZ_ERROR_DATA;
1143 continue;
1147 // we have some data in (p.tempBuf)
1148 // in strict mode: tempBufSize is not enough for one Symbol decoding.
1149 // in relaxed mode: tempBufSize not larger than required for one Symbol decoding.
1151 uint rem = p.tempBufSize;
1152 uint ahead = 0;
1153 int dummyProcessed = -1;
1155 while (rem < LZMA_REQUIRED_INPUT_MAX && ahead < inSize)
1156 p.tempBuf[rem++] = src[ahead++];
1158 // ahead - the size of new data copied from (src) to (p.tempBuf)
1159 // rem - the size of temp buffer including new data from (src)
1161 if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
1163 const(ubyte)* bufOut = p.tempBuf.ptr + rem;
1165 ELzmaDummy dummyRes = LzmaDec_TryDummy(p, p.tempBuf.ptr, &bufOut);
1167 if (dummyRes == DUMMY_INPUT_EOF)
1169 if (rem >= LZMA_REQUIRED_INPUT_MAX)
1170 break;
1171 p.tempBufSize = rem;
1172 (*srcLen) += cast(usize)ahead;
1173 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1174 return SZ_OK;
1177 dummyProcessed = cast(int)(bufOut - p.tempBuf.ptr);
1179 if (cast(uint)dummyProcessed < p.tempBufSize)
1180 break;
1182 if (checkEndMarkNow && !mixin(IS_DUMMY_END_MARKER_POSSIBLE!"dummyRes"))
1184 (*srcLen) += cast(uint)dummyProcessed - p.tempBufSize;
1185 p.tempBufSize = cast(uint)dummyProcessed;
1186 // p.remainLen = kMatchSpecLen_Error_Data;
1187 mixin(RETURN__NOT_FINISHED__FOR_FINISH);
1191 p.buf = p.tempBuf.ptr;
1194 // we decode one symbol from (p.tempBuf) here, so the (bufLimit) is equal to (p.buf)
1195 int res = LzmaDec_DecodeReal2(p, dicLimit, p.buf);
1197 usize processed = cast(usize)(p.buf - p.tempBuf.ptr);
1198 rem = p.tempBufSize;
1200 if (dummyProcessed < 0)
1202 if (processed > LZMA_REQUIRED_INPUT_MAX)
1203 break;
1204 if (processed < rem)
1205 break;
1207 else if (cast(uint)dummyProcessed != processed)
1208 break;
1210 processed -= rem;
1212 src += processed;
1213 inSize -= processed;
1214 (*srcLen) += processed;
1215 p.tempBufSize = 0;
1217 if (res != SZ_OK)
1219 p.remainLen = kMatchSpecLen_Error_Data;
1220 return SZ_ERROR_DATA;
1227 /* Some unexpected error: internal error of code, memory corruption or hardware failure */
1228 p.remainLen = kMatchSpecLen_Error_Fail;
1229 return SZ_ERROR_FAIL;
1234 //==========================================================================
1236 // LzmaDec_DecodeToBuf
1238 //==========================================================================
1239 public SRes LzmaDec_DecodeToBuf (CLzmaDec* p, ubyte* dest, usize* destLen, const(ubyte)* src, usize *srcLen,
1240 ELzmaFinishMode finishMode, ELzmaStatus *status) @nogc
1242 usize outSize = *destLen;
1243 usize inSize = *srcLen;
1244 *srcLen = *destLen = 0;
1245 for (;;)
1247 usize inSizeCur = inSize, outSizeCur, dicPos;
1248 ELzmaFinishMode curFinishMode;
1249 SRes res;
1250 if (p.dicPos == p.dicBufSize)
1251 p.dicPos = 0;
1252 dicPos = p.dicPos;
1253 if (outSize > p.dicBufSize - dicPos)
1255 outSizeCur = p.dicBufSize;
1256 curFinishMode = LZMA_FINISH_ANY;
1258 else
1260 outSizeCur = dicPos + outSize;
1261 curFinishMode = finishMode;
1264 res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
1265 src += inSizeCur;
1266 inSize -= inSizeCur;
1267 *srcLen += inSizeCur;
1268 outSizeCur = p.dicPos - dicPos;
1269 import core.stdc.string : memcpy;
1270 memcpy(dest, p.dic + dicPos, outSizeCur);
1271 dest += outSizeCur;
1272 outSize -= outSizeCur;
1273 *destLen += outSizeCur;
1274 if (res != 0)
1275 return res;
1276 if (outSizeCur == 0 || outSize == 0)
1277 return SZ_OK;
1282 private void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc) {
1283 ISzAlloc_Free(alloc, p.dic);
1284 p.dic = null;
1288 //==========================================================================
1290 // LzmaDec_FreeProbs
1292 //==========================================================================
1293 public void LzmaDec_FreeProbs (CLzmaDec *p, ISzAllocPtr alloc) {
1294 ISzAlloc_Free(alloc, p.probs);
1295 p.probs = null;
1298 //==========================================================================
1300 // LzmaDec_Free
1302 //==========================================================================
1303 public void LzmaDec_Free (CLzmaDec* p, ISzAllocPtr alloc) {
1304 LzmaDec_FreeProbs(p, alloc);
1305 LzmaDec_FreeDict(p, alloc);
1309 //==========================================================================
1311 // LzmaProps_Decode
1313 //==========================================================================
1314 public SRes LzmaProps_Decode (CLzmaProps* p, const(ubyte)* data, uint size) @nogc {
1315 uint dicSize;
1316 ubyte d;
1318 if (size < LZMA_PROPS_SIZE)
1319 return SZ_ERROR_UNSUPPORTED;
1320 else
1321 dicSize = data[1] | (cast(uint)data[2] << 8) | (cast(uint)data[3] << 16) | (cast(uint)data[4] << 24);
1323 if (dicSize < LZMA_DIC_MIN)
1324 dicSize = LZMA_DIC_MIN;
1325 p.dicSize = dicSize;
1327 d = data[0];
1328 if (d >= (9 * 5 * 5))
1329 return SZ_ERROR_UNSUPPORTED;
1331 p.lc = cast(ubyte)(d % 9);
1332 d /= 9;
1333 p.pb = cast(ubyte)(d / 5);
1334 p.lp = cast(ubyte)(d % 5);
1336 return SZ_OK;
1339 private SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const(CLzmaProps)* propNew, ISzAllocPtr alloc)
1341 uint numProbs = mixin(LzmaProps_GetNumProbs!"propNew");
1342 if (!p.probs || numProbs != p.numProbs)
1344 LzmaDec_FreeProbs(p, alloc);
1345 p.probs = cast(CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * CLzmaProb.sizeof);
1346 if (!p.probs)
1347 return SZ_ERROR_MEM;
1348 p.probs_1664 = p.probs + 1664;
1349 p.numProbs = numProbs;
1351 return SZ_OK;
1355 //==========================================================================
1357 // LzmaDec_AllocateProbs
1359 //==========================================================================
1360 public SRes LzmaDec_AllocateProbs (CLzmaDec* p, const(ubyte)* props, uint propsSize, ISzAllocPtr alloc) {
1361 CLzmaProps propNew;
1362 int rinres = LzmaProps_Decode(&propNew, props, propsSize);
1363 if (rinres != 0) return rinres;
1364 rinres = LzmaDec_AllocateProbs2(p, &propNew, alloc);
1365 if (rinres != 0) return rinres;
1366 p.prop = propNew;
1367 return SZ_OK;
1371 //==========================================================================
1373 // LzmaDec_Allocate
1375 //==========================================================================
1376 public SRes LzmaDec_Allocate (CLzmaDec* p, const(ubyte)* props, uint propsSize, ISzAllocPtr alloc) {
1377 CLzmaProps propNew;
1378 usize dicBufSize;
1379 int rinres = LzmaProps_Decode(&propNew, props, propsSize);
1380 if (rinres != 0) return rinres;
1381 rinres = LzmaDec_AllocateProbs2(p, &propNew, alloc);
1382 if (rinres != 0) return rinres;
1385 uint dictSize = propNew.dicSize;
1386 usize mask = (cast(uint)1 << 12) - 1;
1387 if (dictSize >= (cast(uint)1 << 30)) mask = (cast(uint)1 << 22) - 1;
1388 else if (dictSize >= (cast(uint)1 << 22)) mask = (cast(uint)1 << 20) - 1;
1389 dicBufSize = (cast(usize)dictSize + mask) & ~mask;
1390 if (dicBufSize < dictSize)
1391 dicBufSize = dictSize;
1394 if (!p.dic || dicBufSize != p.dicBufSize)
1396 LzmaDec_FreeDict(p, alloc);
1397 p.dic = cast(ubyte *)ISzAlloc_Alloc(alloc, dicBufSize);
1398 if (!p.dic)
1400 LzmaDec_FreeProbs(p, alloc);
1401 return SZ_ERROR_MEM;
1404 p.dicBufSize = dicBufSize;
1405 p.prop = propNew;
1406 return SZ_OK;
1410 //==========================================================================
1412 // LzmaDecode
1414 //==========================================================================
1415 public SRes LzmaDecode (ubyte* dest, usize* destLen, const(ubyte)* src, usize *srcLen,
1416 const(ubyte)* propData, uint propSize, ELzmaFinishMode finishMode,
1417 ELzmaStatus *status, ISzAllocPtr alloc)
1419 CLzmaDec p;
1420 SRes res;
1421 usize outSize = *destLen, inSize = *srcLen;
1422 *destLen = *srcLen = 0;
1423 *status = LZMA_STATUS_NOT_SPECIFIED;
1424 if (inSize < RC_INIT_SIZE)
1425 return SZ_ERROR_INPUT_EOF;
1426 //LzmaDec_Construct(&p);
1427 { p.dic = null; p.probs = null; }
1428 int rinres = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
1429 if (rinres != 0) return rinres;
1430 p.dic = dest;
1431 p.dicBufSize = outSize;
1432 LzmaDec_Init(&p);
1433 *srcLen = inSize;
1434 res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
1435 *destLen = p.dicPos;
1436 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
1437 res = SZ_ERROR_INPUT_EOF;
1438 LzmaDec_FreeProbs(&p, alloc);
1439 return res;