3 LZMA Decoder (optimized for Speed version)
5 LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18)
8 LZMA SDK is licensed under two licenses:
9 1) GNU Lesser General Public License (GNU LGPL)
10 2) Common Public License (CPL)
11 It means that you can select one of these two licenses and
12 follow rules of that license.
15 Igor Pavlov, as the author of this Code, expressly permits you to
16 statically or dynamically link your Code (or bind by name) to the
17 interfaces of this file without subjecting your linked Code to the
18 terms of the CPL or GNU LGPL. Any modifications or additions
19 to this file, however, are subject to the LGPL or CPL terms.
22 #include "LzmaDecode.h"
25 #define Byte unsigned char
28 #define kNumTopBits 24
29 #define kTopValue ((UInt32)1 << kNumTopBits)
31 #define kNumBitModelTotalBits 11
32 #define kBitModelTotal (1 << kNumBitModelTotalBits)
33 #define kNumMoveBits 5
35 #define RC_READ_BYTE (*Buffer++)
37 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
38 { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
42 #define RC_TEST { if (Buffer == BufferLim) \
43 { UInt32 size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
44 BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
46 #define RC_INIT Buffer = BufferLim = 0; RC_INIT2
50 #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
52 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
56 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
58 #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
59 #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
60 #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
62 #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
63 { UpdateBit0(p); mi <<= 1; A0; } else \
64 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
66 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
68 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
69 { int i = numLevels; res = 1; \
70 do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
71 res -= (1 << numLevels); }
74 #define kNumPosBitsMax 4
75 #define kNumPosStatesMax (1 << kNumPosBitsMax)
77 #define kLenNumLowBits 3
78 #define kLenNumLowSymbols (1 << kLenNumLowBits)
79 #define kLenNumMidBits 3
80 #define kLenNumMidSymbols (1 << kLenNumMidBits)
81 #define kLenNumHighBits 8
82 #define kLenNumHighSymbols (1 << kLenNumHighBits)
85 #define LenChoice2 (LenChoice + 1)
86 #define LenLow (LenChoice2 + 1)
87 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
88 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
89 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
93 #define kNumLitStates 7
95 #define kStartPosModelIndex 4
96 #define kEndPosModelIndex 14
97 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
99 #define kNumPosSlotBits 6
100 #define kNumLenToPosStates 4
102 #define kNumAlignBits 4
103 #define kAlignTableSize (1 << kNumAlignBits)
105 #define kMatchMinLen 2
108 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
109 #define IsRepG0 (IsRep + kNumStates)
110 #define IsRepG1 (IsRepG0 + kNumStates)
111 #define IsRepG2 (IsRepG1 + kNumStates)
112 #define IsRep0Long (IsRepG2 + kNumStates)
113 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
114 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
115 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
116 #define LenCoder (Align + kAlignTableSize)
117 #define RepLenCoder (LenCoder + kNumLenProbs)
118 #define Literal (RepLenCoder + kNumLenProbs)
120 #if Literal != LZMA_BASE_SIZE
124 #ifdef _LZMA_OUT_READ
126 typedef struct _LzmaVarState
133 ILzmaInCallback
*InCallback
;
136 UInt32 DictionarySize
;
137 UInt32 DictionaryPos
;
145 Byte TempDictionary
[4];
149 unsigned char *buffer
, UInt32 bufferSize
,
150 int lc
, int lp
, int pb
,
151 unsigned char *dictionary
, UInt32 dictionarySize
,
153 ILzmaInCallback
*InCallback
155 unsigned char *inStream
, UInt32 inSize
163 LzmaVarState
*vs
= (LzmaVarState
*)buffer
;
164 CProb
*p
= (CProb
*)(buffer
+ sizeof(LzmaVarState
));
165 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ lp
));
167 if (bufferSize
< numProbs
* sizeof(CProb
) + sizeof(LzmaVarState
))
168 return LZMA_RESULT_NOT_ENOUGH_MEM
;
169 vs
->Dictionary
= dictionary
;
170 vs
->DictionarySize
= dictionarySize
;
171 vs
->DictionaryPos
= 0;
173 vs
->Reps
[0] = vs
->Reps
[1] = vs
->Reps
[2] = vs
->Reps
[3] = 1;
179 dictionary
[dictionarySize
- 1] = 0;
180 for (i
= 0; i
< numProbs
; i
++)
181 p
[i
] = kBitModelTotal
>> 1;
186 RC_INIT(inStream
, inSize
);
189 vs
->BufferLim
= BufferLim
;
193 vs
->InCallback
= InCallback
;
196 return LZMA_RESULT_OK
;
199 int LzmaDecode(unsigned char *buffer
,
200 unsigned char *outStream
, UInt32 outSize
,
201 UInt32
*outSizeProcessed
)
203 LzmaVarState
*vs
= (LzmaVarState
*)buffer
;
204 Byte
*Buffer
= vs
->Buffer
;
205 Byte
*BufferLim
= vs
->BufferLim
;
206 UInt32 Range
= vs
->Range
;
207 UInt32 Code
= vs
->Code
;
209 ILzmaInCallback
*InCallback
= vs
->InCallback
;
211 CProb
*p
= (CProb
*)(buffer
+ sizeof(LzmaVarState
));
212 int state
= vs
->State
;
214 UInt32 rep0
= vs
->Reps
[0], rep1
= vs
->Reps
[1], rep2
= vs
->Reps
[2], rep3
= vs
->Reps
[3];
216 UInt32 posStateMask
= (1 << (vs
->pb
)) - 1;
217 UInt32 literalPosMask
= (1 << (vs
->lp
)) - 1;
219 int len
= vs
->RemainLen
;
220 UInt32 globalPos
= vs
->GlobalPos
;
222 Byte
*dictionary
= vs
->Dictionary
;
223 UInt32 dictionarySize
= vs
->DictionarySize
;
224 UInt32 dictionaryPos
= vs
->DictionaryPos
;
226 Byte tempDictionary
[4];
227 if (dictionarySize
== 0)
229 dictionary
= tempDictionary
;
231 tempDictionary
[0] = vs
->TempDictionary
[0];
236 *outSizeProcessed
= 0;
237 return LZMA_RESULT_OK
;
240 while(len
!= 0 && nowPos
< outSize
)
242 UInt32 pos
= dictionaryPos
- rep0
;
243 if (pos
>= dictionarySize
)
244 pos
+= dictionarySize
;
245 outStream
[nowPos
++] = dictionary
[dictionaryPos
] = dictionary
[pos
];
246 if (++dictionaryPos
== dictionarySize
)
250 if (dictionaryPos
== 0)
251 previousByte
= dictionary
[dictionarySize
- 1];
253 previousByte
= dictionary
[dictionaryPos
- 1];
257 Byte
*buffer
, UInt32 bufferSize
,
258 int lc
, int lp
, int pb
,
260 ILzmaInCallback
*InCallback
,
262 unsigned char *inStream
, UInt32 inSize
,
264 unsigned char *outStream
, UInt32 outSize
,
265 UInt32
*outSizeProcessed
)
267 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ lp
));
268 CProb
*p
= (CProb
*)buffer
;
272 Byte previousByte
= 0;
273 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
275 UInt32 posStateMask
= (1 << pb
) - 1;
276 UInt32 literalPosMask
= (1 << lp
) - 1;
284 if (bufferSize
< numProbs
* sizeof(CProb
))
285 return LZMA_RESULT_NOT_ENOUGH_MEM
;
286 for (i
= 0; i
< numProbs
; i
++)
287 p
[i
] = kBitModelTotal
>> 1;
293 RC_INIT(inStream
, inSize
);
297 *outSizeProcessed
= 0;
298 while(nowPos
< outSize
)
302 int posState
= (int)(
304 #ifdef _LZMA_OUT_READ
310 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
315 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
318 #ifdef _LZMA_OUT_READ
322 & literalPosMask
) << lc
) + (previousByte
>> (8 - lc
))));
324 if (state
>= kNumLitStates
)
327 #ifdef _LZMA_OUT_READ
328 UInt32 pos
= dictionaryPos
- rep0
;
329 if (pos
>= dictionarySize
)
330 pos
+= dictionarySize
;
331 matchByte
= dictionary
[pos
];
333 matchByte
= outStream
[nowPos
- rep0
];
341 bit
= (matchByte
& 0x100);
342 probLit
= prob
+ 0x100 + bit
+ symbol
;
343 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
345 while (symbol
< 0x100);
348 while (symbol
< 0x100)
350 CProb
*probLit
= prob
+ symbol
;
351 RC_GET_BIT(probLit
, symbol
)
353 previousByte
= (Byte
)symbol
;
355 outStream
[nowPos
++] = previousByte
;
356 #ifdef _LZMA_OUT_READ
357 dictionary
[dictionaryPos
] = previousByte
;
358 if (++dictionaryPos
== dictionarySize
)
361 if (state
< 4) state
= 0;
362 else if (state
< 10) state
-= 3;
369 prob
= p
+ IsRep
+ state
;
376 state
= state
< kNumLitStates
? 0 : 3;
382 prob
= p
+ IsRepG0
+ state
;
386 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
389 #ifdef _LZMA_OUT_READ
394 #ifdef _LZMA_OUT_READ
398 return LZMA_RESULT_DATA_ERROR
;
399 state
= state
< kNumLitStates
? 9 : 11;
400 #ifdef _LZMA_OUT_READ
401 pos
= dictionaryPos
- rep0
;
402 if (pos
>= dictionarySize
)
403 pos
+= dictionarySize
;
404 previousByte
= dictionary
[pos
];
405 dictionary
[dictionaryPos
] = previousByte
;
406 if (++dictionaryPos
== dictionarySize
)
409 previousByte
= outStream
[nowPos
- rep0
];
411 outStream
[nowPos
++] = previousByte
;
423 prob
= p
+ IsRepG1
+ state
;
432 prob
= p
+ IsRepG2
+ state
;
449 state
= state
< kNumLitStates
? 8 : 11;
450 prob
= p
+ RepLenCoder
;
454 CProb
*probLen
= prob
+ LenChoice
;
458 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
460 numBits
= kLenNumLowBits
;
465 probLen
= prob
+ LenChoice2
;
469 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
470 offset
= kLenNumLowSymbols
;
471 numBits
= kLenNumMidBits
;
476 probLen
= prob
+ LenHigh
;
477 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
478 numBits
= kLenNumHighBits
;
481 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
488 state
+= kNumLitStates
;
490 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
492 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
493 if (posSlot
>= kStartPosModelIndex
)
495 int numDirectBits
= ((posSlot
>> 1) - 1);
496 rep0
= (2 | ((UInt32
)posSlot
& 1));
497 if (posSlot
< kEndPosModelIndex
)
499 rep0
<<= numDirectBits
;
500 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
504 numDirectBits
-= kNumAlignBits
;
516 while (--numDirectBits
!= 0);
518 rep0
<<= kNumAlignBits
;
519 numDirectBits
= kNumAlignBits
;
526 CProb
*prob3
= prob
+ mi
;
527 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
530 while(--numDirectBits
!= 0);
535 if (++rep0
== (UInt32
)(0))
537 /* it's for stream version */
545 #ifdef _LZMA_OUT_READ
546 + globalPos
|| rep0
> dictionarySize
549 return LZMA_RESULT_DATA_ERROR
;
552 #ifdef _LZMA_OUT_READ
553 UInt32 pos
= dictionaryPos
- rep0
;
554 if (pos
>= dictionarySize
)
555 pos
+= dictionarySize
;
556 previousByte
= dictionary
[pos
];
557 dictionary
[dictionaryPos
] = previousByte
;
558 if (++dictionaryPos
== dictionarySize
)
561 previousByte
= outStream
[nowPos
- rep0
];
564 outStream
[nowPos
++] = previousByte
;
566 while(len
!= 0 && nowPos
< outSize
);
571 #ifdef _LZMA_OUT_READ
573 vs
->BufferLim
= BufferLim
;
576 vs
->DictionaryPos
= dictionaryPos
;
577 vs
->GlobalPos
= globalPos
+ nowPos
;
584 vs
->TempDictionary
[0] = tempDictionary
[0];
587 *outSizeProcessed
= nowPos
;
588 return LZMA_RESULT_OK
;