egra: added slightly faster sorter to agg mini
[iv.d.git] / vfs / lzmadec.d
blob3380efff0000ccc3e5e4dd2e62a32b07f95410b8
1 /* LzmaDec.h -- LZMA Decoder
2 2017-04-03 : Igor Pavlov : Public domain */
3 module iv.vfs.lzmadec;
4 private nothrow @trusted @nogc:
6 //version = _LZMA_PROB32;
7 /* _LZMA_PROB32 can increase the speed on some CPUs,
8 but memory usage for CLzmaDec::probs will be doubled in that case */
10 //version = _LZMA_SIZE_OPT;
12 alias Byte = ubyte;
13 alias UInt16 = ushort;
14 alias UInt32 = uint;
15 alias SizeT = size_t;
17 version(_LZMA_PROB32) {
18 alias CLzmaProb = UInt32;
19 } else {
20 alias CLzmaProb = UInt16;
23 public enum SRes {
24 OK,
25 ERROR_UNSUPPORTED,
26 ERROR_MEM,
27 ERROR_DATA,
28 ERROR_INPUT_EOF,
29 ERROR_FAIL,
32 /* ---------- LZMA Properties ---------- */
34 public enum LZMA_PROPS_SIZE = 5;
36 public struct CLzmaProps {
37 uint lc, lp, pb;
38 UInt32 dicSize;
41 /* LzmaProps_Decode - decodes properties
42 Returns:
43 SRes.OK
44 SRes.ERROR_UNSUPPORTED - Unsupported properties
47 //!SRes LzmaProps_Decode(CLzmaProps *p, const(Byte)* data, uint size);
50 /* ---------- LZMA Decoder state ---------- */
52 /* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
53 Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
55 enum LZMA_REQUIRED_INPUT_MAX = 20;
57 public struct CLzmaDec {
58 private:
59 CLzmaProps prop;
60 CLzmaProb* probs;
61 public Byte* dic;
62 const(Byte)* buf;
63 UInt32 range, code;
64 public SizeT dicPos;
65 public SizeT dicBufSize;
66 UInt32 processedPos;
67 UInt32 checkDicSize;
68 uint state;
69 UInt32[4] reps;
70 uint remainLen;
71 int needFlush;
72 int needInitState;
73 UInt32 numProbs;
74 uint tempBufSize;
75 Byte[LZMA_REQUIRED_INPUT_MAX] tempBuf;
78 //#define LzmaDec_Construct(p) { (p).dic = 0; (p).probs = 0; }
80 //void LzmaDec_Init(CLzmaDec *p);
82 /* There are two types of LZMA streams:
83 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
84 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
86 public alias ELzmaFinishMode = int;
87 public enum /*ELzmaFinishMode*/ {
88 LZMA_FINISH_ANY, /* finish at any point */
89 LZMA_FINISH_END /* block must be finished at the end */
92 /* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
94 You must use LZMA_FINISH_END, when you know that current output buffer
95 covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
97 If LZMA decoder sees end marker before reaching output limit, it returns SRes.OK,
98 and output value of destLen will be less than output buffer size limit.
99 You can check status result also.
101 You can use multiple checks to test data integrity after full decompression:
102 1) Check Result and "status" variable.
103 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
104 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
105 You must use correct finish mode in that case. */
107 public alias ELzmaStatus = int;
108 public enum /*ELzmaStatus*/ {
109 LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
110 LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
111 LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
112 LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
113 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
116 /* ELzmaStatus is used only as output value for function call */
119 /* ---------- Interfaces ---------- */
121 /* There are 3 levels of interfaces:
122 1) Dictionary Interface
123 2) Buffer Interface
124 3) One Call Interface
125 You can select any of these interfaces, but don't mix functions from different
126 groups for same object. */
129 /* There are two variants to allocate state for Dictionary Interface:
130 1) LzmaDec_Allocate / LzmaDec_Free
131 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
132 You can use variant 2, if you set dictionary buffer manually.
133 For Buffer Interface you must always use variant 1.
135 LzmaDec_Allocate* can return:
136 SRes.OK
137 SRes.ERROR_MEM - Memory allocation error
138 SRes.ERROR_UNSUPPORTED - Unsupported properties
142 SRes LzmaDec_AllocateProbs(CLzmaDec *p, const(Byte)* props, uint propsSize);
143 void LzmaDec_FreeProbs(CLzmaDec *p);
145 SRes LzmaDec_Allocate(CLzmaDec *state, const(Byte)* prop, uint propsSize);
146 void LzmaDec_Free(CLzmaDec *state);
149 /* ---------- Dictionary Interface ---------- */
151 /* You can use it, if you want to eliminate the overhead for data copying from
152 dictionary to some other external buffer.
153 You must work with CLzmaDec variables directly in this interface.
155 STEPS:
156 LzmaDec_Constr()
157 LzmaDec_Allocate()
158 for (each new stream)
160 LzmaDec_Init()
161 while (it needs more decompression)
163 LzmaDec_DecodeToDic()
164 use data from CLzmaDec::dic and update CLzmaDec::dicPos
167 LzmaDec_Free()
170 /* LzmaDec_DecodeToDic
172 The decoding to internal dictionary buffer (CLzmaDec::dic).
173 You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
175 finishMode:
176 It has meaning only if the decoding reaches output limit (dicLimit).
177 LZMA_FINISH_ANY - Decode just dicLimit bytes.
178 LZMA_FINISH_END - Stream must be finished after dicLimit.
180 Returns:
181 SRes.OK
182 status:
183 LZMA_STATUS_FINISHED_WITH_MARK
184 LZMA_STATUS_NOT_FINISHED
185 LZMA_STATUS_NEEDS_MORE_INPUT
186 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
187 SRes.ERROR_DATA - Data error
190 //SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const(Byte)* src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
193 /* ---------- Buffer Interface ---------- */
195 /* It's zlib-like interface.
196 See LzmaDec_DecodeToDic description for information about STEPS and return results,
197 but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
198 to work with CLzmaDec variables manually.
200 finishMode:
201 It has meaning only if the decoding reaches output limit (*destLen).
202 LZMA_FINISH_ANY - Decode just destLen bytes.
203 LZMA_FINISH_END - Stream must be finished after (*destLen).
206 //SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const(Byte)* src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
209 /* ---------- One Call Interface ---------- */
211 /* LzmaDecode
213 finishMode:
214 It has meaning only if the decoding reaches output limit (*destLen).
215 LZMA_FINISH_ANY - Decode just destLen bytes.
216 LZMA_FINISH_END - Stream must be finished after (*destLen).
218 Returns:
219 SRes.OK
220 status:
221 LZMA_STATUS_FINISHED_WITH_MARK
222 LZMA_STATUS_NOT_FINISHED
223 LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
224 SRes.ERROR_DATA - Data error
225 SRes.ERROR_MEM - Memory allocation error
226 SRes.ERROR_UNSUPPORTED - Unsupported properties
227 SRes.ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
231 SRes LzmaDecode(Byte *dest, SizeT *destLen, const(Byte)* src, SizeT *srcLen,
232 const(Byte)* propData, uint propSize, ELzmaFinishMode finishMode,
233 ELzmaStatus *status, ISzAllocPtr alloc);
236 // ////////////////////////////////////////////////////////////////////////// //
237 private:
239 enum kNumTopBits = 24;
240 enum kTopValue = 1U<<kNumTopBits;
242 enum kNumBitModelTotalBits = 11;
243 enum kBitModelTotal = 1<<kNumBitModelTotalBits;
244 enum kNumMoveBits = 5;
246 enum RC_INIT_SIZE = 5;
248 //enum NORMALIZE = "if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }";
250 //#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
251 //#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
252 //#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
253 enum GET_BIT2(string p, string i, string A0, string A1) =
254 "ttt = *("~p~"); if (range < kTopValue) { range <<= 8; code = (code<<8)|(*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)\n"~
255 "{ range = bound; *("~p~") = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits)); "~i~" = ("~i~"+"~i~"); "~A0~" } else\n"~
256 "{ range -= bound; code -= bound; *("~p~") = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits)); "~i~" = ("~i~"+"~i~")+1; "~A1~" }";
257 //#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
258 enum GET_BIT(string p, string i) = GET_BIT2!(p, i, "", "");
260 enum TREE_GET_BIT(string probs, string i) = "{"~GET_BIT!("("~probs~"+"~i~")", i)~"}";
262 enum TREE_DECODE(string probs, string limit, string i) =
263 "{ "~i~" = 1; do { "~TREE_GET_BIT!(probs, i)~" } while ("~i~" < "~limit~"); "~i~" -= "~limit~"; }";
266 version(_LZMA_SIZE_OPT) {
267 enum TREE_6_DECODE(string probs, string i) = TREE_DECODE!(probs, "(1<<6)", i);
268 } else {
269 enum TREE_6_DECODE(string probs, string i) =
270 "{ "~i~" = 1;\n"~
271 TREE_GET_BIT!(probs, i)~
272 TREE_GET_BIT!(probs, i)~
273 TREE_GET_BIT!(probs, i)~
274 TREE_GET_BIT!(probs, i)~
275 TREE_GET_BIT!(probs, i)~
276 TREE_GET_BIT!(probs, i)~
277 i~" -= 0x40; }";
280 enum NORMAL_LITER_DEC = GET_BIT!("prob + symbol", "symbol");
281 enum MATCHED_LITER_DEC =
282 "matchByte <<= 1;\n"~
283 "bit = (matchByte & offs);\n"~
284 "probLit = prob + offs + bit + symbol;\n"~
285 GET_BIT2!("probLit", "symbol", "offs &= ~bit;", "offs &= bit;");
287 enum NORMALIZE_CHECK = "if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }";
289 //#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
290 //#define UPDATE_0_CHECK range = bound;
291 //#define UPDATE_1_CHECK range -= bound; code -= bound;
292 enum GET_BIT2_CHECK(string p, string i, string A0, string A1) =
293 "ttt = *("~p~"); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)\n"~
294 "{ range = bound; "~i~" = ("~i~" + "~i~"); "~A0~" } else\n"~
295 "{ range -= bound; code -= bound; "~i~" = ("~i~" + "~i~") + 1; "~A1~" }";
296 enum GET_BIT_CHECK(string p, string i) = GET_BIT2_CHECK!(p, i, "{}", "{}");
297 enum TREE_DECODE_CHECK(string probs, string limit, string i) =
298 "{ "~i~" = 1; do { "~GET_BIT_CHECK!(probs~"+"~i, i)~" } while ("~i~" < "~limit~"); "~i~" -= "~limit~"; }";
301 enum kNumPosBitsMax = 4;
302 enum kNumPosStatesMax = (1 << kNumPosBitsMax);
304 enum kLenNumLowBits = 3;
305 enum kLenNumLowSymbols = (1 << kLenNumLowBits);
306 enum kLenNumMidBits = 3;
307 enum kLenNumMidSymbols = (1 << kLenNumMidBits);
308 enum kLenNumHighBits = 8;
309 enum kLenNumHighSymbols = (1 << kLenNumHighBits);
311 enum LenChoice = 0;
312 enum LenChoice2 = (LenChoice + 1);
313 enum LenLow = (LenChoice2 + 1);
314 enum LenMid = (LenLow + (kNumPosStatesMax << kLenNumLowBits));
315 enum LenHigh = (LenMid + (kNumPosStatesMax << kLenNumMidBits));
316 enum kNumLenProbs = (LenHigh + kLenNumHighSymbols);
319 enum kNumStates = 12;
320 enum kNumLitStates = 7;
322 enum kStartPosModelIndex = 4;
323 enum kEndPosModelIndex = 14;
324 enum kNumFullDistances = (1 << (kEndPosModelIndex >> 1));
326 enum kNumPosSlotBits = 6;
327 enum kNumLenToPosStates = 4;
329 enum kNumAlignBits = 4;
330 enum kAlignTableSize = (1 << kNumAlignBits);
332 enum kMatchMinLen = 2;
333 enum kMatchSpecLenStart = (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols);
335 enum IsMatch = 0;
336 enum IsRep = (IsMatch + (kNumStates << kNumPosBitsMax));
337 enum IsRepG0 = (IsRep + kNumStates);
338 enum IsRepG1 = (IsRepG0 + kNumStates);
339 enum IsRepG2 = (IsRepG1 + kNumStates);
340 enum IsRep0Long = (IsRepG2 + kNumStates);
341 enum PosSlot = (IsRep0Long + (kNumStates << kNumPosBitsMax));
342 enum SpecPos = (PosSlot + (kNumLenToPosStates << kNumPosSlotBits));
343 enum Align = (SpecPos + kNumFullDistances - kEndPosModelIndex);
344 enum LenCoder = (Align + kAlignTableSize);
345 enum RepLenCoder = (LenCoder + kNumLenProbs);
346 enum Literal = (RepLenCoder + kNumLenProbs);
348 enum LZMA_BASE_SIZE = 1846;
349 enum LZMA_LIT_SIZE = 0x300;
351 static assert(Literal == LZMA_BASE_SIZE);
353 //#define LzmaProps_GetNumProbs(p) (Literal + ((UInt32)LZMA_LIT_SIZE << ((p).lc + (p).lp)))
355 enum LZMA_DIC_MIN = (1 << 12);
357 /* First LZMA-symbol is always decoded.
358 And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
359 Out:
360 Result:
361 SRes.OK - OK
362 SRes.ERROR_DATA - Error
363 p->remainLen:
364 < kMatchSpecLenStart : normal remain
365 = kMatchSpecLenStart : finished
366 = kMatchSpecLenStart + 1 : Flush marker (unused now)
367 = kMatchSpecLenStart + 2 : State Init Marker (unused now)
370 private SRes LzmaDec_DecodeReal (CLzmaDec* p, SizeT limit, const(Byte)* bufLimit) {
371 CLzmaProb* probs = p.probs;
373 uint state = p.state;
374 UInt32 rep0 = p.reps.ptr[0], rep1 = p.reps.ptr[1], rep2 = p.reps.ptr[2], rep3 = p.reps.ptr[3];
375 uint pbMask = (1U<<(p.prop.pb))-1;
376 uint lpMask = (1U<<(p.prop.lp))-1;
377 uint lc = p.prop.lc;
379 Byte* dic = p.dic;
380 SizeT dicBufSize = p.dicBufSize;
381 SizeT dicPos = p.dicPos;
383 UInt32 processedPos = p.processedPos;
384 UInt32 checkDicSize = p.checkDicSize;
385 uint len = 0;
387 const(Byte)* buf = p.buf;
388 UInt32 range = p.range;
389 UInt32 code = p.code;
391 do {
392 CLzmaProb *prob;
393 UInt32 bound;
394 uint ttt;
395 uint posState = processedPos & pbMask;
397 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
398 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
400 uint symbol;
401 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
402 prob = probs + Literal;
403 if (processedPos != 0 || checkDicSize != 0)
404 prob += (cast(UInt32)LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
405 (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
406 processedPos++;
408 if (state < kNumLitStates)
410 state -= (state < 4) ? state : 3;
411 symbol = 1;
412 version(_LZMA_SIZE_OPT) {
413 do { mixin(NORMAL_LITER_DEC); } while (symbol < 0x100);
414 } else {
415 mixin(NORMAL_LITER_DEC);
416 mixin(NORMAL_LITER_DEC);
417 mixin(NORMAL_LITER_DEC);
418 mixin(NORMAL_LITER_DEC);
419 mixin(NORMAL_LITER_DEC);
420 mixin(NORMAL_LITER_DEC);
421 mixin(NORMAL_LITER_DEC);
422 mixin(NORMAL_LITER_DEC);
425 else
427 uint matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
428 uint offs = 0x100;
429 state -= (state < 10) ? 3 : 6;
430 symbol = 1;
431 version(_LZMA_SIZE_OPT) {
434 uint bit;
435 CLzmaProb *probLit;
436 mixin(MATCHED_LITER_DEC);
438 while (symbol < 0x100);
439 } else {
441 uint bit;
442 CLzmaProb *probLit;
443 mixin(MATCHED_LITER_DEC);
444 mixin(MATCHED_LITER_DEC);
445 mixin(MATCHED_LITER_DEC);
446 mixin(MATCHED_LITER_DEC);
447 mixin(MATCHED_LITER_DEC);
448 mixin(MATCHED_LITER_DEC);
449 mixin(MATCHED_LITER_DEC);
450 mixin(MATCHED_LITER_DEC);
455 dic[dicPos++] = cast(Byte)symbol;
456 continue;
460 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
461 prob = probs + IsRep + state;
462 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
464 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
465 state += kNumStates;
466 prob = probs + LenCoder;
468 else
470 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
471 if (checkDicSize == 0 && processedPos == 0)
472 return SRes.ERROR_DATA;
473 prob = probs + IsRepG0 + state;
474 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
476 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
477 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
478 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
480 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
481 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
482 dicPos++;
483 processedPos++;
484 state = state < kNumLitStates ? 9 : 11;
485 continue;
487 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
489 else
491 UInt32 distance;
492 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
493 prob = probs + IsRepG1 + state;
494 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
496 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
497 distance = rep1;
499 else
501 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
502 prob = probs + IsRepG2 + state;
503 ttt = *(prob); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
505 range = bound; *(prob) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
506 distance = rep2;
508 else
510 range -= bound; code -= bound; *(prob) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
511 distance = rep3;
512 rep3 = rep2;
514 rep2 = rep1;
516 rep1 = rep0;
517 rep0 = distance;
519 state = state < kNumLitStates ? 8 : 11;
520 prob = probs + RepLenCoder;
523 version(_LZMA_SIZE_OPT) {
525 uint lim, offset;
526 CLzmaProb *probLen = prob + LenChoice;
527 ttt = *(probLen); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
529 range = bound; *(probLen) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
530 probLen = prob + LenLow + (posState << kLenNumLowBits);
531 offset = 0;
532 lim = (1 << kLenNumLowBits);
534 else
536 range -= bound; code -= bound; *(probLen) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
537 probLen = prob + LenChoice2;
538 ttt = *(probLen); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
540 range = bound; *(probLen) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
541 probLen = prob + LenMid + (posState << kLenNumMidBits);
542 offset = kLenNumLowSymbols;
543 lim = (1 << kLenNumMidBits);
545 else
547 range -= bound; code -= bound; *(probLen) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
548 probLen = prob + LenHigh;
549 offset = kLenNumLowSymbols + kLenNumMidSymbols;
550 lim = (1 << kLenNumHighBits);
553 mixin(TREE_DECODE!("probLen", "lim", "len"));
554 len += offset;
556 } else {
558 CLzmaProb *probLen = prob + LenChoice;
559 ttt = *(probLen); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
561 range = bound; *(probLen) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
562 probLen = prob + LenLow + (posState << kLenNumLowBits);
563 len = 1;
564 mixin(TREE_GET_BIT!("probLen", "len"));
565 mixin(TREE_GET_BIT!("probLen", "len"));
566 mixin(TREE_GET_BIT!("probLen", "len"));
567 len -= 8;
569 else
571 range -= bound; code -= bound; *(probLen) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
572 probLen = prob + LenChoice2;
573 ttt = *(probLen); if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } bound = (range>>kNumBitModelTotalBits)*ttt; if (code < bound)
575 range = bound; *(probLen) = cast(CLzmaProb)(ttt+((kBitModelTotal-ttt)>>kNumMoveBits));
576 probLen = prob + LenMid + (posState << kLenNumMidBits);
577 len = 1;
578 mixin(TREE_GET_BIT!("probLen", "len"));
579 mixin(TREE_GET_BIT!("probLen", "len"));
580 mixin(TREE_GET_BIT!("probLen", "len"));
582 else
584 range -= bound; code -= bound; *(probLen) = cast(CLzmaProb)(ttt-(ttt>>kNumMoveBits));
585 probLen = prob + LenHigh;
586 mixin(TREE_DECODE!("probLen", "(1 << kLenNumHighBits)", "len"));
587 len += kLenNumLowSymbols + kLenNumMidSymbols;
593 if (state >= kNumStates)
595 UInt32 distance;
596 prob = probs + PosSlot +
597 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
598 mixin(TREE_6_DECODE!("prob", "distance"));
599 if (distance >= kStartPosModelIndex)
601 uint posSlot = cast(uint)distance;
602 uint numDirectBits = cast(uint)(((distance >> 1) - 1));
603 distance = (2 | (distance & 1));
604 if (posSlot < kEndPosModelIndex)
606 distance <<= numDirectBits;
607 prob = probs + SpecPos + distance - posSlot - 1;
609 UInt32 mask = 1;
610 uint i = 1;
613 mixin(GET_BIT2!("prob + i", "i", "{}" , "distance |= mask;"));
614 mask <<= 1;
616 while (--numDirectBits != 0);
619 else
621 numDirectBits -= kNumAlignBits;
624 if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
625 range >>= 1;
628 UInt32 t;
629 code -= range;
630 t = (0 - (cast(UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
631 distance = (distance << 1) + (t + 1);
632 code += range & t;
635 distance <<= 1;
636 if (code >= range)
638 code -= range;
639 distance |= 1;
643 while (--numDirectBits != 0);
644 prob = probs + Align;
645 distance <<= kNumAlignBits;
647 uint i = 1;
648 mixin(GET_BIT2!("prob + i", "i", "", "distance |= 1;"));
649 mixin(GET_BIT2!("prob + i", "i", "", "distance |= 2;"));
650 mixin(GET_BIT2!("prob + i", "i", "", "distance |= 4;"));
651 mixin(GET_BIT2!("prob + i", "i", "", "distance |= 8;"));
653 if (distance == cast(UInt32)0xFFFFFFFF)
655 len += kMatchSpecLenStart;
656 state -= kNumStates;
657 break;
662 rep3 = rep2;
663 rep2 = rep1;
664 rep1 = rep0;
665 rep0 = distance + 1;
666 if (checkDicSize == 0)
668 if (distance >= processedPos)
670 p.dicPos = dicPos;
671 return SRes.ERROR_DATA;
674 else if (distance >= checkDicSize)
676 p.dicPos = dicPos;
677 return SRes.ERROR_DATA;
679 state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
682 len += kMatchMinLen;
685 SizeT rem;
686 uint curLen;
687 SizeT pos;
689 if ((rem = limit - dicPos) == 0)
691 p.dicPos = dicPos;
692 return SRes.ERROR_DATA;
695 curLen = ((rem < len) ? cast(uint)rem : len);
696 pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
698 processedPos += curLen;
700 len -= curLen;
701 if (curLen <= dicBufSize - pos)
703 Byte *dest = dic + dicPos;
704 ptrdiff_t src = cast(ptrdiff_t)pos - cast(ptrdiff_t)dicPos;
705 const(Byte)* lim = dest + curLen;
706 dicPos += curLen;
708 *(dest) = cast(Byte)*(dest + src);
709 while (++dest != lim);
711 else
715 dic[dicPos++] = dic[pos];
716 if (++pos == dicBufSize)
717 pos = 0;
719 while (--curLen != 0);
724 while (dicPos < limit && buf < bufLimit);
726 if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
728 p.buf = buf;
729 p.range = range;
730 p.code = code;
731 p.remainLen = len;
732 p.dicPos = dicPos;
733 p.processedPos = processedPos;
734 p.reps.ptr[0] = rep0;
735 p.reps.ptr[1] = rep1;
736 p.reps.ptr[2] = rep2;
737 p.reps.ptr[3] = rep3;
738 p.state = state;
740 return SRes.OK;
743 private void LzmaDec_WriteRem (CLzmaDec* p, SizeT limit) {
744 if (p.remainLen != 0 && p.remainLen < kMatchSpecLenStart)
746 Byte *dic = p.dic;
747 SizeT dicPos = p.dicPos;
748 SizeT dicBufSize = p.dicBufSize;
749 uint len = p.remainLen;
750 SizeT rep0 = p.reps.ptr[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */
751 SizeT rem = limit - dicPos;
752 if (rem < len)
753 len = cast(uint)(rem);
755 if (p.checkDicSize == 0 && p.prop.dicSize - p.processedPos <= len)
756 p.checkDicSize = p.prop.dicSize;
758 p.processedPos += len;
759 p.remainLen -= len;
760 while (len != 0)
762 len--;
763 dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)];
764 dicPos++;
766 p.dicPos = dicPos;
770 private SRes LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const(Byte)* bufLimit)
774 SizeT limit2 = limit;
775 if (p.checkDicSize == 0)
777 UInt32 rem = p.prop.dicSize - p.processedPos;
778 if (limit - p.dicPos > rem)
779 limit2 = p.dicPos + rem;
782 if (auto sres = LzmaDec_DecodeReal(p, limit2, bufLimit)) return sres;
784 if (p.checkDicSize == 0 && p.processedPos >= p.prop.dicSize)
785 p.checkDicSize = p.prop.dicSize;
787 LzmaDec_WriteRem(p, limit);
789 while (p.dicPos < limit && p.buf < bufLimit && p.remainLen < kMatchSpecLenStart);
791 if (p.remainLen > kMatchSpecLenStart)
792 p.remainLen = kMatchSpecLenStart;
794 return SRes.OK;
797 alias ELzmaDummy = int;
798 enum /*ELzmaDummy*/ {
799 DUMMY_ERROR, /* unexpected end of input stream */
800 DUMMY_LIT,
801 DUMMY_MATCH,
802 DUMMY_REP
805 private ELzmaDummy LzmaDec_TryDummy(const(CLzmaDec)* p, const(Byte)* buf, SizeT inSize)
807 UInt32 range = p.range;
808 UInt32 code = p.code;
809 const(Byte)* bufLimit = buf + inSize;
810 const(CLzmaProb)* probs = p.probs;
811 uint state = p.state;
812 ELzmaDummy res;
815 const(CLzmaProb)* prob;
816 UInt32 bound;
817 uint ttt;
818 uint posState = (p.processedPos) & ((1 << p.prop.pb) - 1);
820 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
821 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
823 range = bound;
825 /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
827 prob = probs + Literal;
828 if (p.checkDicSize != 0 || p.processedPos != 0)
829 prob += (cast(UInt32)LZMA_LIT_SIZE *
830 ((((p.processedPos) & ((1 << (p.prop.lp)) - 1)) << p.prop.lc) +
831 (p.dic[(p.dicPos == 0 ? p.dicBufSize : p.dicPos) - 1] >> (8 - p.prop.lc))));
833 if (state < kNumLitStates)
835 uint symbol = 1;
836 do { mixin(GET_BIT_CHECK!("prob + symbol", "symbol")); } while (symbol < 0x100);
838 else
840 uint matchByte = p.dic[p.dicPos - p.reps.ptr[0] +
841 (p.dicPos < p.reps.ptr[0] ? p.dicBufSize : 0)];
842 uint offs = 0x100;
843 uint symbol = 1;
846 uint bit;
847 const(CLzmaProb)* probLit;
848 matchByte <<= 1;
849 bit = (matchByte & offs);
850 probLit = prob + offs + bit + symbol;
851 mixin(GET_BIT2_CHECK!("probLit", "symbol", "offs &= ~bit;", "offs &= bit;"));
853 while (symbol < 0x100);
855 res = DUMMY_LIT;
857 else
859 uint len;
860 range -= bound; code -= bound;
862 prob = probs + IsRep + state;
863 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
865 range = bound;
866 state = 0;
867 prob = probs + LenCoder;
868 res = DUMMY_MATCH;
870 else
872 range -= bound; code -= bound;
873 res = DUMMY_REP;
874 prob = probs + IsRepG0 + state;
875 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
877 range = bound;
878 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
879 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
881 range = bound;
882 if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
883 return DUMMY_REP;
885 else
887 range -= bound; code -= bound;
890 else
892 range -= bound; code -= bound;
893 prob = probs + IsRepG1 + state;
894 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
896 range = bound;
898 else
900 range -= bound; code -= bound;
901 prob = probs + IsRepG2 + state;
902 ttt = *(prob); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
904 range = bound;
906 else
908 range -= bound; code -= bound;
912 state = kNumStates;
913 prob = probs + RepLenCoder;
916 uint limit, offset;
917 const(CLzmaProb)* probLen = prob + LenChoice;
918 ttt = *(probLen); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
920 range = bound;
921 probLen = prob + LenLow + (posState << kLenNumLowBits);
922 offset = 0;
923 limit = 1 << kLenNumLowBits;
925 else
927 range -= bound; code -= bound;
928 probLen = prob + LenChoice2;
929 ttt = *(probLen); if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
931 range = bound;
932 probLen = prob + LenMid + (posState << kLenNumMidBits);
933 offset = kLenNumLowSymbols;
934 limit = 1 << kLenNumMidBits;
936 else
938 range -= bound; code -= bound;
939 probLen = prob + LenHigh;
940 offset = kLenNumLowSymbols + kLenNumMidSymbols;
941 limit = 1 << kLenNumHighBits;
944 mixin(TREE_DECODE_CHECK!("probLen", "limit", "len"));
945 len += offset;
948 if (state < 4)
950 uint posSlot;
951 prob = probs + PosSlot +
952 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
953 kNumPosSlotBits);
954 mixin(TREE_DECODE_CHECK!("prob", "1 << kNumPosSlotBits", "posSlot"));
955 if (posSlot >= kStartPosModelIndex)
957 uint numDirectBits = ((posSlot >> 1) - 1);
959 /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
961 if (posSlot < kEndPosModelIndex)
963 prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
965 else
967 numDirectBits -= kNumAlignBits;
970 if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
971 range >>= 1;
972 code -= range & (((code - range) >> 31) - 1);
973 /* if (code >= range) code -= range; */
975 while (--numDirectBits != 0);
976 prob = probs + Align;
977 numDirectBits = kNumAlignBits;
980 uint i = 1;
983 mixin(GET_BIT_CHECK!("prob + i", "i"));
985 while (--numDirectBits != 0);
991 if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
992 return res;
996 void LzmaDec_InitDicAndState(CLzmaDec *p, bool initDic, bool initState)
998 p.needFlush = 1;
999 p.remainLen = 0;
1000 p.tempBufSize = 0;
1002 if (initDic)
1004 p.processedPos = 0;
1005 p.checkDicSize = 0;
1006 p.needInitState = 1;
1008 if (initState)
1009 p.needInitState = 1;
1012 public void LzmaDec_Init(CLzmaDec *p)
1014 p.dicPos = 0;
1015 LzmaDec_InitDicAndState(p, true, true);
1018 private void LzmaDec_InitStateReal(CLzmaDec *p)
1020 SizeT numProbs = (Literal+(cast(UInt32)LZMA_LIT_SIZE<<((&p.prop).lc+(&p.prop).lp)));
1021 SizeT i;
1022 CLzmaProb *probs = p.probs;
1023 for (i = 0; i < numProbs; i++)
1024 probs[i] = kBitModelTotal >> 1;
1025 p.reps.ptr[0] = p.reps.ptr[1] = p.reps.ptr[2] = p.reps.ptr[3] = 1;
1026 p.state = 0;
1027 p.needInitState = 0;
1030 public SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const(Byte)* src, SizeT *srcLen,
1031 ELzmaFinishMode finishMode, ELzmaStatus *status)
1033 SizeT inSize = *srcLen;
1034 (*srcLen) = 0;
1035 LzmaDec_WriteRem(p, dicLimit);
1037 *status = LZMA_STATUS_NOT_SPECIFIED;
1039 while (p.remainLen != kMatchSpecLenStart)
1041 int checkEndMarkNow;
1043 if (p.needFlush)
1045 for (; inSize > 0 && p.tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
1046 p.tempBuf.ptr[p.tempBufSize++] = *src++;
1047 if (p.tempBufSize < RC_INIT_SIZE)
1049 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1050 return SRes.OK;
1052 if (p.tempBuf.ptr[0] != 0)
1053 return SRes.ERROR_DATA;
1054 p.code =
1055 (cast(UInt32)p.tempBuf.ptr[1] << 24)
1056 | (cast(UInt32)p.tempBuf.ptr[2] << 16)
1057 | (cast(UInt32)p.tempBuf.ptr[3] << 8)
1058 | (cast(UInt32)p.tempBuf.ptr[4]);
1059 p.range = 0xFFFFFFFF;
1060 p.needFlush = 0;
1061 p.tempBufSize = 0;
1064 checkEndMarkNow = 0;
1065 if (p.dicPos >= dicLimit)
1067 if (p.remainLen == 0 && p.code == 0)
1069 *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
1070 return SRes.OK;
1072 if (finishMode == LZMA_FINISH_ANY)
1074 *status = LZMA_STATUS_NOT_FINISHED;
1075 return SRes.OK;
1077 if (p.remainLen != 0)
1079 *status = LZMA_STATUS_NOT_FINISHED;
1080 return SRes.ERROR_DATA;
1082 checkEndMarkNow = 1;
1085 if (p.needInitState)
1086 LzmaDec_InitStateReal(p);
1088 if (p.tempBufSize == 0)
1090 SizeT processed;
1091 const(Byte)* bufLimit;
1092 if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
1094 int dummyRes = LzmaDec_TryDummy(p, src, inSize);
1095 if (dummyRes == DUMMY_ERROR)
1097 import core.stdc.string : memcpy;
1098 memcpy(p.tempBuf.ptr, src, inSize);
1099 p.tempBufSize = cast(uint)inSize;
1100 (*srcLen) += inSize;
1101 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1102 return SRes.OK;
1104 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
1106 *status = LZMA_STATUS_NOT_FINISHED;
1107 return SRes.ERROR_DATA;
1109 bufLimit = src;
1111 else
1112 bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
1113 p.buf = src;
1114 if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
1115 return SRes.ERROR_DATA;
1116 processed = cast(SizeT)(p.buf - src);
1117 (*srcLen) += processed;
1118 src += processed;
1119 inSize -= processed;
1121 else
1123 uint rem = p.tempBufSize, lookAhead = 0;
1124 while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
1125 p.tempBuf.ptr[rem++] = src[lookAhead++];
1126 p.tempBufSize = rem;
1127 if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
1129 int dummyRes = LzmaDec_TryDummy(p, p.tempBuf.ptr, rem);
1130 if (dummyRes == DUMMY_ERROR)
1132 (*srcLen) += lookAhead;
1133 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
1134 return SRes.OK;
1136 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
1138 *status = LZMA_STATUS_NOT_FINISHED;
1139 return SRes.ERROR_DATA;
1142 p.buf = p.tempBuf.ptr;
1143 if (LzmaDec_DecodeReal2(p, dicLimit, p.buf) != 0)
1144 return SRes.ERROR_DATA;
1147 uint kkk = cast(uint)(p.buf - p.tempBuf.ptr);
1148 if (rem < kkk)
1149 return SRes.ERROR_FAIL; /* some internal error */
1150 rem -= kkk;
1151 if (lookAhead < rem)
1152 return SRes.ERROR_FAIL; /* some internal error */
1153 lookAhead -= rem;
1155 (*srcLen) += lookAhead;
1156 src += lookAhead;
1157 inSize -= lookAhead;
1158 p.tempBufSize = 0;
1161 if (p.code == 0)
1162 *status = LZMA_STATUS_FINISHED_WITH_MARK;
1163 return (p.code == 0) ? SRes.OK : SRes.ERROR_DATA;
1166 public SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const(Byte)* src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
1168 import core.stdc.string : memcpy;
1169 SizeT outSize = *destLen;
1170 SizeT inSize = *srcLen;
1171 *srcLen = *destLen = 0;
1172 for (;;)
1174 SizeT inSizeCur = inSize, outSizeCur, dicPos;
1175 ELzmaFinishMode curFinishMode;
1176 SRes res;
1177 if (p.dicPos == p.dicBufSize)
1178 p.dicPos = 0;
1179 dicPos = p.dicPos;
1180 if (outSize > p.dicBufSize - dicPos)
1182 outSizeCur = p.dicBufSize;
1183 curFinishMode = LZMA_FINISH_ANY;
1185 else
1187 outSizeCur = dicPos + outSize;
1188 curFinishMode = finishMode;
1191 res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
1192 src += inSizeCur;
1193 inSize -= inSizeCur;
1194 *srcLen += inSizeCur;
1195 outSizeCur = p.dicPos - dicPos;
1196 memcpy(dest, p.dic + dicPos, outSizeCur);
1197 dest += outSizeCur;
1198 outSize -= outSizeCur;
1199 *destLen += outSizeCur;
1200 if (res != 0)
1201 return res;
1202 if (outSizeCur == 0 || outSize == 0)
1203 return SRes.OK;
1207 public void LzmaDec_FreeProbs(CLzmaDec *p) {
1208 import core.stdc.stdlib : free;
1209 if (p.probs !is null) free(p.probs);
1210 p.probs = null;
1213 private void LzmaDec_FreeDict(CLzmaDec *p) {
1214 import core.stdc.stdlib : free;
1215 if (p.dic !is null) free(p.dic);
1216 p.dic = null;
1219 public void LzmaDec_Free(CLzmaDec *p) {
1220 LzmaDec_FreeProbs(p);
1221 LzmaDec_FreeDict(p);
1224 public SRes LzmaProps_Decode(CLzmaProps *p, const(Byte)*data, uint size)
1226 UInt32 dicSize;
1227 Byte d;
1229 if (size < LZMA_PROPS_SIZE)
1230 return SRes.ERROR_UNSUPPORTED;
1231 else
1232 dicSize = data[1] | (data[2] << 8) | (data[3] << 16) | (data[4] << 24);
1234 if (dicSize < LZMA_DIC_MIN)
1235 dicSize = LZMA_DIC_MIN;
1236 p.dicSize = dicSize;
1238 d = data[0];
1239 if (d >= (9 * 5 * 5))
1240 return SRes.ERROR_UNSUPPORTED;
1242 p.lc = d % 9;
1243 d /= 9;
1244 p.pb = d / 5;
1245 p.lp = d % 5;
1247 return SRes.OK;
1250 private SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const(CLzmaProps)* propNew) {
1251 import core.stdc.stdlib : malloc;
1252 UInt32 numProbs = (Literal+(cast(UInt32)LZMA_LIT_SIZE<<((propNew).lc+(propNew).lp)));
1253 if (!p.probs || numProbs != p.numProbs)
1255 LzmaDec_FreeProbs(p);
1256 p.probs = cast(CLzmaProb *)malloc(numProbs * CLzmaProb.sizeof);
1257 p.numProbs = numProbs;
1258 if (!p.probs)
1259 return SRes.ERROR_MEM;
1261 return SRes.OK;
1264 public SRes LzmaDec_AllocateProbs(CLzmaDec *p, const(Byte)* props, uint propsSize)
1266 CLzmaProps propNew;
1267 if (auto sres = LzmaProps_Decode(&propNew, props, propsSize)) return sres;
1268 if (auto sres = LzmaDec_AllocateProbs2(p, &propNew)) return sres;
1269 p.prop = propNew;
1270 return SRes.OK;
1273 public SRes LzmaDec_Allocate(CLzmaDec *p, const(Byte)*props, uint propsSize)
1275 import core.stdc.stdlib : malloc;
1276 CLzmaProps propNew;
1277 SizeT dicBufSize;
1278 if (auto sres = LzmaProps_Decode(&propNew, props, propsSize)) return sres;
1279 if (auto sres = LzmaDec_AllocateProbs2(p, &propNew)) return sres;
1282 UInt32 dictSize = propNew.dicSize;
1283 SizeT mask = (1U << 12) - 1;
1284 if (dictSize >= (1U << 30)) mask = (1U << 22) - 1;
1285 else if (dictSize >= (1U << 22)) mask = (1U << 20) - 1;
1286 dicBufSize = (cast(SizeT)dictSize + mask) & ~mask;
1287 if (dicBufSize < dictSize)
1288 dicBufSize = dictSize;
1291 if (!p.dic || dicBufSize != p.dicBufSize)
1293 LzmaDec_FreeDict(p);
1294 p.dic = cast(Byte *)malloc(dicBufSize);
1295 if (!p.dic)
1297 LzmaDec_FreeProbs(p);
1298 return SRes.ERROR_MEM;
1301 p.dicBufSize = dicBufSize;
1302 p.prop = propNew;
1303 return SRes.OK;
1306 public SRes LzmaDecode(Byte *dest, SizeT *destLen, const(Byte)* src, SizeT *srcLen,
1307 const(Byte)* propData, uint propSize, ELzmaFinishMode finishMode,
1308 ELzmaStatus *status)
1310 CLzmaDec p;
1311 SRes res;
1312 SizeT outSize = *destLen, inSize = *srcLen;
1313 *destLen = *srcLen = 0;
1314 *status = LZMA_STATUS_NOT_SPECIFIED;
1315 if (inSize < RC_INIT_SIZE)
1316 return SRes.ERROR_INPUT_EOF;
1317 //LzmaDec_Construct(&p);
1318 p.dic = null; p.probs = null;
1319 if (auto sres = LzmaDec_AllocateProbs(&p, propData, propSize)) return sres;
1320 p.dic = dest;
1321 p.dicBufSize = outSize;
1322 LzmaDec_Init(&p);
1323 *srcLen = inSize;
1324 res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
1325 *destLen = p.dicPos;
1326 if (res == SRes.OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
1327 res = SRes.ERROR_INPUT_EOF;
1328 LzmaDec_FreeProbs(&p);
1329 return res;