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.
12 private import iv
.dlzma
;
15 /* use smaller (by ~3KB), but slightly slower (prolly) decompression code? */
16 //version = LZMA_SIZE_OPT;
19 // ////////////////////////////////////////////////////////////////////////// //
20 // ////////////////////////////////////////////////////////////////////////// //
21 // ////////////////////////////////////////////////////////////////////////// //
22 // ////////////////////////////////////////////////////////////////////////// //
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
);
67 enum TREE_6_DECODE(string probs
, string i
) = `
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
)~`
79 enum NORMAL_LITER_DEC
= TREE_GET_BIT
!("prob", "symbol");
81 enum MATCHED_LITER_DEC
= `
82 matchByte += 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
);
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
160 #define kStartOffset 0
161 #define GET_PROBS p.probs
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.
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.
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.
234 RangeCoder is normalized
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;
253 uint lpMask
= (cast(uint)0x100 << p
.prop
.lp
) - (cast(uint)0x100 >> lc
);
256 usize dicBufSize
= p
.dicBufSize
;
257 usize dicPos
= p
.dicPos
;
259 uint processedPos
= p
.processedPos
;
260 uint checkDicSize
= p
.checkDicSize
;
263 const(ubyte)* buf
= p
.buf
;
264 uint range
= p
.range
;
272 uint posState
= mixin(CALC_POS_STATE
!("processedPos", "pbMask"));
274 prob
= probs
+ IsMatch
+ mixin(COMBINED_PS_STATE
);
275 mixin(IF_BIT_0
!"prob");
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
);
285 if (state
< kNumLitStates
)
287 state
-= (state
< 4) ? state
: 3;
289 version(LZMA_SIZE_OPT
) {
290 do { mixin(NORMAL_LITER_DEC
); } while (symbol
< 0x100);
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
);
304 uint matchByte
= dic
[dicPos
- rep0
+ (dicPos
< rep0 ? dicBufSize
: 0)];
306 state
-= (state
< 10) ?
3 : 6;
308 version(LZMA_SIZE_OPT
) {
313 mixin(MATCHED_LITER_DEC
);
315 while (symbol
< 0x100);
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
;
337 mixin(UPDATE_1
!"prob");
338 prob
= probs
+ IsRep
+ state
;
339 mixin(IF_BIT_0
!"prob");
342 mixin(UPDATE_0
!"prob");
344 prob
= probs
+ LenCoder
;
348 mixin(UPDATE_1
!"prob");
349 prob
= probs
+ IsRepG0
+ state
;
350 mixin(IF_BIT_0
!"prob");
353 mixin(UPDATE_0
!"prob");
354 prob
= probs
+ IsRep0Long
+ mixin(COMBINED_PS_STATE
);
355 mixin(IF_BIT_0
!"prob");
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)];
369 state
= state
< kNumLitStates ?
9 : 11;
372 mixin(UPDATE_1
!"prob");
377 mixin(UPDATE_1
!"prob");
378 prob
= probs
+ IsRepG1
+ state
;
379 mixin(IF_BIT_0
!"prob");
382 mixin(UPDATE_0
!"prob");
387 mixin(UPDATE_1
!"prob");
388 prob
= probs
+ IsRepG2
+ state
;
389 mixin(IF_BIT_0
!"prob");
392 mixin(UPDATE_0
!"prob");
397 mixin(UPDATE_1
!"prob");
406 state
= state
< kNumLitStates ?
8 : 11;
407 prob
= probs
+ RepLenCoder
;
410 version(LZMA_SIZE_OPT
) {
413 CLzmaProb
*probLen
= prob
+ LenChoice
;
414 mixin(IF_BIT_0
!"probLen");
417 mixin(UPDATE_0
!"probLen");
418 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
);
420 lim
= (1 << kLenNumLowBits
);
424 mixin(UPDATE_1
!"probLen");
425 probLen
= prob
+ LenChoice2
;
426 mixin(IF_BIT_0
!"probLen");
429 mixin(UPDATE_0
!"probLen");
430 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
) + (1 << kLenNumLowBits
);
431 offset
= kLenNumLowSymbols
;
432 lim
= (1 << kLenNumLowBits
);
436 mixin(UPDATE_1
!"probLen");
437 probLen
= prob
+ LenHigh
;
438 offset
= kLenNumLowSymbols
* 2;
439 lim
= (1 << kLenNumHighBits
);
442 mixin(TREE_DECODE
!("probLen", "lim", "len"));
447 CLzmaProb
*probLen
= prob
+ LenChoice
;
448 mixin(IF_BIT_0
!"probLen");
451 mixin(UPDATE_0
!"probLen");
452 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
);
454 mixin(TREE_GET_BIT
!("probLen", "len"));
455 mixin(TREE_GET_BIT
!("probLen", "len"));
456 mixin(TREE_GET_BIT
!("probLen", "len"));
461 mixin(UPDATE_1
!"probLen");
462 probLen
= prob
+ LenChoice2
;
463 mixin(IF_BIT_0
!"probLen");
466 mixin(UPDATE_0
!"probLen");
467 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
) + (1 << kLenNumLowBits
);
469 mixin(TREE_GET_BIT
!("probLen", "len"));
470 mixin(TREE_GET_BIT
!("probLen", "len"));
471 mixin(TREE_GET_BIT
!("probLen", "len"));
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
)
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
;
504 mixin(REV_BIT_VAR
!("prob", "distance", "m"));
506 while (--numDirectBits
);
512 numDirectBits
-= kNumAlignBits
;
521 t
= (0 - (cast(uint)code
>> 31)); /* (uint)((int32_t)code >> 31) */
522 distance
= (distance
<< 1) + (t
+ 1);
534 while (--numDirectBits
);
535 prob
= probs
+ Align
;
536 distance
<<= kNumAlignBits
;
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"));
545 if (distance
== cast(uint)0xFFFFFFFFU
)
547 len
= kMatchSpecLenStart
;
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;
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;
586 curLen
= ((rem
< len
) ?
cast(uint)rem
: len
);
587 pos
= dicPos
- rep0
+ (dicPos
< rep0 ? dicBufSize
: 0);
589 processedPos
+= cast(uint)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
);
606 dic
[dicPos
++] = dic
[pos
];
607 if (++pos
== dicBufSize
)
610 while (--curLen
!= 0);
615 while (dicPos
< limit
&& buf
< bufLimit
);
622 p
.remainLen
= cast(uint)len
; // & (kMatchSpecLen_Error_Data - 1); // we can write real length for error matches too.
624 p
.processedPos
= processedPos
;
629 p
.state
= cast(uint)state
;
630 if (len
>= kMatchSpecLen_Error_Data
)
631 return SZ_ERROR_DATA
;
636 private void LzmaDec_WriteRem (CLzmaDec
* p
, usize limit
) @nogc {
637 uint len
= cast(uint)p
.remainLen
;
638 if (len
== 0 /* || len >= kMatchSpecLenStart */)
641 usize dicPos
= p
.dicPos
;
644 usize rep0
; /* we use usize to avoid the BUG of VC14 for AMD64 */
646 usize rem
= limit
- dicPos
;
649 len
= cast(uint)(rem
);
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
;
662 dicBufSize
= p
.dicBufSize
;
665 dic
[dicPos
] = dic
[dicPos
- rep0
+ (dicPos
< rep0 ? dicBufSize
: 0)];
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)
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
;
720 alias ELzmaDummy
= int;
723 DUMMY_INPUT_EOF
, /* need more input data */
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
;
735 const(ubyte)* bufLimit
= *bufOut
;
736 const(CLzmaProb
)* probs
= /*GET_PROBS*/p
.probs_1664
;
737 uint state
= cast(uint)p
.state
;
742 const(CLzmaProb
)* prob
;
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");
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
)
762 do { mixin(GET_BIT_CHECK
!("prob + symbol", "symbol")); } while (symbol
< 0x100);
766 uint matchByte
= p
.dic
[p
.dicPos
- p
.reps
[0] +
767 (p
.dicPos
< p
.reps
[0] ? p
.dicBufSize
: 0)];
773 const(CLzmaProb
)* probLit
;
774 matchByte
+= matchByte
;
777 probLit
= prob
+ (offs
+ bit
+ symbol
);
778 mixin(GET_BIT2_CHECK
!("probLit", "symbol", "offs ^= bit;" , "{}"));
780 while (symbol
< 0x100);
787 mixin(UPDATE_1_CHECK
);
789 prob
= probs
+ IsRep
+ state
;
790 mixin(IF_BIT_0_CHECK
!"prob");
793 mixin(UPDATE_0_CHECK
);
795 prob
= probs
+ LenCoder
;
800 mixin(UPDATE_1_CHECK
);
802 prob
= probs
+ IsRepG0
+ state
;
803 mixin(IF_BIT_0_CHECK
!"prob");
806 mixin(UPDATE_0_CHECK
);
807 prob
= probs
+ IsRep0Long
+ mixin(COMBINED_PS_STATE
);
808 mixin(IF_BIT_0_CHECK
!"prob");
811 mixin(UPDATE_0_CHECK
);
816 mixin(UPDATE_1_CHECK
);
821 mixin(UPDATE_1_CHECK
);
822 prob
= probs
+ IsRepG1
+ state
;
823 mixin(IF_BIT_0_CHECK
!"prob");
826 mixin(UPDATE_0_CHECK
);
830 mixin(UPDATE_1_CHECK
);
831 prob
= probs
+ IsRepG2
+ state
;
832 mixin(IF_BIT_0_CHECK
!"prob");
835 mixin(UPDATE_0_CHECK
);
839 mixin(UPDATE_1_CHECK
);
844 prob
= probs
+ RepLenCoder
;
848 const(CLzmaProb
)* probLen
= prob
+ LenChoice
;
849 mixin(IF_BIT_0_CHECK
!"probLen");
852 mixin(UPDATE_0_CHECK
);
853 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
);
855 limit
= 1 << kLenNumLowBits
;
859 mixin(UPDATE_1_CHECK
);
860 probLen
= prob
+ LenChoice2
;
861 mixin(IF_BIT_0_CHECK
!"probLen");
864 mixin(UPDATE_0_CHECK
);
865 probLen
= prob
+ LenLow
+ mixin(GET_LEN_STATE
) + (1 << kLenNumLowBits
);
866 offset
= kLenNumLowSymbols
;
867 limit
= 1 << kLenNumLowBits
;
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"));
884 prob
= probs
+ PosSlot
+
885 ((len
< kNumLenToPosStates
- 1 ? len
: kNumLenToPosStates
- 1) <<
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
);
898 numDirectBits
-= kNumAlignBits
;
901 mixin(NORMALIZE_CHECK
);
903 code
-= range
& (((code
- range
) >> 31) - 1);
904 /* if (code >= range) code -= range; */
906 while (--numDirectBits
);
907 prob
= probs
+ Align
;
908 numDirectBits
= kNumAlignBits
;
915 mixin(REV_BIT_CHECK
!("prob", "i", "m"));
917 while (--numDirectBits
);
924 mixin(NORMALIZE_CHECK
);
931 private void LzmaDec_InitDicAndState (CLzmaDec
*p
, /*BoolInt*/int initDic
, /*BoolInt*/int initState
) @nogc {
932 p
.remainLen
= kMatchSpecLenStart
+ 1;
939 p
.remainLen
= kMatchSpecLenStart
+ 2;
942 p
.remainLen
= kMatchSpecLenStart
+ 2;
946 //==========================================================================
950 //==========================================================================
951 public void LzmaDec_Init (CLzmaDec
* p
) @nogc {
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
;
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
;
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;
1021 if (p
.remainLen
> kMatchSpecLenStart
+ 1)
1023 usize numProbs
= mixin(LzmaProps_GetNumProbs
!"&p.prop");
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;
1037 if (p
.remainLen
== kMatchSpecLenStart
)
1040 return SZ_ERROR_DATA
;
1041 *status
= LZMA_STATUS_FINISHED_WITH_MARK
;
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
;
1059 if (finishMode
== LZMA_FINISH_ANY
)
1061 *status
= LZMA_STATUS_NOT_FINISHED
;
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
)
1087 if (inSize
>= LZMA_REQUIRED_INPUT_MAX
)
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
;
1097 dummyProcessed
= cast(int)(bufOut
- src
);
1098 if (cast(uint)dummyProcessed
> LZMA_REQUIRED_INPUT_MAX
)
1101 if (checkEndMarkNow
&& !mixin(IS_DUMMY_END_MARKER_POSSIBLE
!"dummyRes"))
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
);
1113 // we will decode only one iteration
1116 bufLimit
= src
+ inSize
- LZMA_REQUIRED_INPUT_MAX
;
1121 int res
= LzmaDec_DecodeReal2(p
, dicLimit
, bufLimit
);
1123 usize processed
= cast(usize
)(p
.buf
- src
);
1125 if (dummyProcessed
< 0)
1127 if (processed
> inSize
)
1130 else if (cast(uint)dummyProcessed
!= processed
)
1134 inSize
-= processed
;
1135 (*srcLen
) += processed
;
1139 p
.remainLen
= kMatchSpecLen_Error_Data
;
1140 return SZ_ERROR_DATA
;
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
;
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
)
1171 p
.tempBufSize
= rem
;
1172 (*srcLen
) += cast(usize
)ahead
;
1173 *status
= LZMA_STATUS_NEEDS_MORE_INPUT
;
1177 dummyProcessed
= cast(int)(bufOut
- p
.tempBuf
.ptr
);
1179 if (cast(uint)dummyProcessed
< p
.tempBufSize
)
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
)
1204 if (processed
< rem
)
1207 else if (cast(uint)dummyProcessed
!= processed
)
1213 inSize
-= processed
;
1214 (*srcLen
) += processed
;
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;
1247 usize inSizeCur
= inSize
, outSizeCur
, dicPos
;
1248 ELzmaFinishMode curFinishMode
;
1250 if (p
.dicPos
== p
.dicBufSize
)
1253 if (outSize
> p
.dicBufSize
- dicPos
)
1255 outSizeCur
= p
.dicBufSize
;
1256 curFinishMode
= LZMA_FINISH_ANY
;
1260 outSizeCur
= dicPos
+ outSize
;
1261 curFinishMode
= finishMode
;
1264 res
= LzmaDec_DecodeToDic(p
, outSizeCur
, src
, &inSizeCur
, curFinishMode
, status
);
1266 inSize
-= inSizeCur
;
1267 *srcLen
+= inSizeCur
;
1268 outSizeCur
= p
.dicPos
- dicPos
;
1269 import core
.stdc
.string
: memcpy
;
1270 memcpy(dest
, p
.dic
+ dicPos
, outSizeCur
);
1272 outSize
-= outSizeCur
;
1273 *destLen
+= outSizeCur
;
1276 if (outSizeCur
== 0 || outSize
== 0)
1282 private void LzmaDec_FreeDict(CLzmaDec
*p
, ISzAllocPtr alloc
) {
1283 ISzAlloc_Free(alloc
, p
.dic
);
1288 //==========================================================================
1290 // LzmaDec_FreeProbs
1292 //==========================================================================
1293 public void LzmaDec_FreeProbs (CLzmaDec
*p
, ISzAllocPtr alloc
) {
1294 ISzAlloc_Free(alloc
, p
.probs
);
1298 //==========================================================================
1302 //==========================================================================
1303 public void LzmaDec_Free (CLzmaDec
* p
, ISzAllocPtr alloc
) {
1304 LzmaDec_FreeProbs(p
, alloc
);
1305 LzmaDec_FreeDict(p
, alloc
);
1309 //==========================================================================
1313 //==========================================================================
1314 public SRes
LzmaProps_Decode (CLzmaProps
* p
, const(ubyte)* data
, uint size
) @nogc {
1318 if (size
< LZMA_PROPS_SIZE
)
1319 return SZ_ERROR_UNSUPPORTED
;
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
;
1328 if (d
>= (9 * 5 * 5))
1329 return SZ_ERROR_UNSUPPORTED
;
1331 p
.lc
= cast(ubyte)(d
% 9);
1333 p
.pb
= cast(ubyte)(d
/ 5);
1334 p
.lp
= cast(ubyte)(d
% 5);
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
);
1347 return SZ_ERROR_MEM
;
1348 p
.probs_1664
= p
.probs
+ 1664;
1349 p
.numProbs
= numProbs
;
1355 //==========================================================================
1357 // LzmaDec_AllocateProbs
1359 //==========================================================================
1360 public SRes
LzmaDec_AllocateProbs (CLzmaDec
* p
, const(ubyte)* props
, uint propsSize
, ISzAllocPtr alloc
) {
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
;
1371 //==========================================================================
1375 //==========================================================================
1376 public SRes
LzmaDec_Allocate (CLzmaDec
* p
, const(ubyte)* props
, uint propsSize
, ISzAllocPtr alloc
) {
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
);
1400 LzmaDec_FreeProbs(p
, alloc
);
1401 return SZ_ERROR_MEM
;
1404 p
.dicBufSize
= dicBufSize
;
1410 //==========================================================================
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
)
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
;
1431 p
.dicBufSize
= outSize
;
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
);