3 LZMA Decoder (optimized for Speed version)
5 LZMA SDK 4.17 Copyright (c) 1999-2005 Igor Pavlov (2005-04-05)
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
];
340 bit
= (matchByte
& 0x100);
341 probLit
= prob
+ 0x100 + bit
+ symbol
;
342 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
344 while (symbol
< 0x100);
346 while (symbol
< 0x100)
348 CProb
*probLit
= prob
+ symbol
;
349 RC_GET_BIT(probLit
, symbol
)
351 previousByte
= (Byte
)symbol
;
353 outStream
[nowPos
++] = previousByte
;
354 #ifdef _LZMA_OUT_READ
355 dictionary
[dictionaryPos
] = previousByte
;
356 if (++dictionaryPos
== dictionarySize
)
359 if (state
< 4) state
= 0;
360 else if (state
< 10) state
-= 3;
366 prob
= p
+ IsRep
+ state
;
373 state
= state
< kNumLitStates
? 0 : 3;
379 prob
= p
+ IsRepG0
+ state
;
383 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
386 #ifdef _LZMA_OUT_READ
391 #ifdef _LZMA_OUT_READ
395 return LZMA_RESULT_DATA_ERROR
;
396 state
= state
< kNumLitStates
? 9 : 11;
397 #ifdef _LZMA_OUT_READ
398 pos
= dictionaryPos
- rep0
;
399 if (pos
>= dictionarySize
)
400 pos
+= dictionarySize
;
401 previousByte
= dictionary
[pos
];
402 dictionary
[dictionaryPos
] = previousByte
;
403 if (++dictionaryPos
== dictionarySize
)
406 previousByte
= outStream
[nowPos
- rep0
];
408 outStream
[nowPos
++] = previousByte
;
420 prob
= p
+ IsRepG1
+ state
;
429 prob
= p
+ IsRepG2
+ state
;
446 state
= state
< kNumLitStates
? 8 : 11;
447 prob
= p
+ RepLenCoder
;
451 CProb
*probLen
= prob
+ LenChoice
;
455 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
457 numBits
= kLenNumLowBits
;
462 probLen
= prob
+ LenChoice2
;
466 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
467 offset
= kLenNumLowSymbols
;
468 numBits
= kLenNumMidBits
;
473 probLen
= prob
+ LenHigh
;
474 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
475 numBits
= kLenNumHighBits
;
478 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
485 state
+= kNumLitStates
;
487 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
489 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
490 if (posSlot
>= kStartPosModelIndex
)
492 int numDirectBits
= ((posSlot
>> 1) - 1);
493 rep0
= (2 | ((UInt32
)posSlot
& 1));
494 if (posSlot
< kEndPosModelIndex
)
496 rep0
<<= numDirectBits
;
497 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
501 numDirectBits
-= kNumAlignBits
;
513 while (--numDirectBits
!= 0);
515 rep0
<<= kNumAlignBits
;
516 numDirectBits
= kNumAlignBits
;
523 CProb
*prob3
= prob
+ mi
;
524 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
527 while(--numDirectBits
!= 0);
532 if (++rep0
== (UInt32
)(0))
534 /* it's for stream version */
542 #ifdef _LZMA_OUT_READ
543 + globalPos
|| rep0
> dictionarySize
546 return LZMA_RESULT_DATA_ERROR
;
549 #ifdef _LZMA_OUT_READ
550 UInt32 pos
= dictionaryPos
- rep0
;
551 if (pos
>= dictionarySize
)
552 pos
+= dictionarySize
;
553 previousByte
= dictionary
[pos
];
554 dictionary
[dictionaryPos
] = previousByte
;
555 if (++dictionaryPos
== dictionarySize
)
558 previousByte
= outStream
[nowPos
- rep0
];
561 outStream
[nowPos
++] = previousByte
;
563 while(len
!= 0 && nowPos
< outSize
);
568 #ifdef _LZMA_OUT_READ
570 vs
->BufferLim
= BufferLim
;
573 vs
->DictionaryPos
= dictionaryPos
;
574 vs
->GlobalPos
= globalPos
+ nowPos
;
581 vs
->TempDictionary
[0] = tempDictionary
[0];
584 *outSizeProcessed
= nowPos
;
585 return LZMA_RESULT_OK
;