3 LZMA Decoder (optimized for Speed version)
5 LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
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 kNumTopBits 24
26 #define kTopValue ((UInt32)1 << kNumTopBits)
28 #define kNumBitModelTotalBits 11
29 #define kBitModelTotal (1 << kNumBitModelTotalBits)
30 #define kNumMoveBits 5
32 /* Use 32-bit reads whenever possible to avoid bad flash performance. Fall back
33 * to byte reads for last 4 bytes since RC_TEST returns an error when BufferLim
34 * is *reached* (not surpassed!), meaning we can't allow that to happen while
35 * there are still bytes to decode from the algorithm's point of view. */
36 #define RC_READ_BYTE \
37 (look_ahead_ptr < 4 ? look_ahead.raw[look_ahead_ptr++] \
38 : ((((uintptr_t) Buffer & 3) \
39 || ((SizeT) (BufferLim - Buffer) <= 4)) ? (*Buffer++) \
40 : ((look_ahead.dw = *(UInt32 *)Buffer), (Buffer += 4), \
41 (look_ahead_ptr = 1), look_ahead.raw[0])))
43 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
47 for (i = 0; i < 5; i++) { \
49 Code = (Code << 8) | RC_READ_BYTE; \
54 #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
56 #define RC_INIT(buffer, bufferSize) Buffer = buffer; \
57 BufferLim = buffer + bufferSize; RC_INIT2
60 #define RC_NORMALIZE \
61 if (Range < kTopValue) { \
64 Code = (Code << 8) | RC_READ_BYTE; \
69 bound = (Range >> kNumBitModelTotalBits) * *(p); \
72 #define UpdateBit0(p) \
74 *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits
76 #define UpdateBit1(p) \
79 *(p) -= (*(p)) >> kNumMoveBits
81 #define RC_GET_BIT2(p, mi, A0, A1) \
92 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ;, ;)
94 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
100 CProb *cp = probs + res; \
101 RC_GET_BIT(cp, res) \
102 } while (--i != 0); \
103 res -= (1 << numLevels); \
107 #define kNumPosBitsMax 4
108 #define kNumPosStatesMax (1 << kNumPosBitsMax)
110 #define kLenNumLowBits 3
111 #define kLenNumLowSymbols (1 << kLenNumLowBits)
112 #define kLenNumMidBits 3
113 #define kLenNumMidSymbols (1 << kLenNumMidBits)
114 #define kLenNumHighBits 8
115 #define kLenNumHighSymbols (1 << kLenNumHighBits)
118 #define LenChoice2 (LenChoice + 1)
119 #define LenLow (LenChoice2 + 1)
120 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
121 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
122 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
125 #define kNumStates 12
126 #define kNumLitStates 7
128 #define kStartPosModelIndex 4
129 #define kEndPosModelIndex 14
130 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
132 #define kNumPosSlotBits 6
133 #define kNumLenToPosStates 4
135 #define kNumAlignBits 4
136 #define kAlignTableSize (1 << kNumAlignBits)
138 #define kMatchMinLen 2
141 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
142 #define IsRepG0 (IsRep + kNumStates)
143 #define IsRepG1 (IsRepG0 + kNumStates)
144 #define IsRepG2 (IsRepG1 + kNumStates)
145 #define IsRep0Long (IsRepG2 + kNumStates)
146 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
147 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
148 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
149 #define LenCoder (Align + kAlignTableSize)
150 #define RepLenCoder (LenCoder + kNumLenProbs)
151 #define Literal (RepLenCoder + kNumLenProbs)
153 #if Literal != LZMA_BASE_SIZE
157 int LzmaDecodeProperties(CLzmaProperties
*propsRes
,
158 const unsigned char *propsData
, int size
)
161 if (size
< LZMA_PROPERTIES_SIZE
)
162 return LZMA_RESULT_DATA_ERROR
;
163 prop0
= propsData
[0];
164 if (prop0
>= (9 * 5 * 5))
165 return LZMA_RESULT_DATA_ERROR
;
167 for (propsRes
->pb
= 0; prop0
>= (9 * 5);
168 propsRes
->pb
++, prop0
-= (9 * 5))
170 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9)
172 propsRes
->lc
= prop0
;
174 * unsigned char remainder = (unsigned char)(prop0 / 9);
175 * propsRes->lc = prop0 % 9;
176 * propsRes->pb = remainder / 5;
177 * propsRes->lp = remainder % 5;
181 return LZMA_RESULT_OK
;
184 #define kLzmaStreamWasFinishedId (-1)
186 int LzmaDecode(CLzmaDecoderState
*vs
,
187 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
188 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
190 CProb
*p
= vs
->Probs
;
192 Byte previousByte
= 0;
193 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
194 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
195 int lc
= vs
->Properties
.lc
;
199 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
202 const Byte
*BufferLim
;
203 int look_ahead_ptr
= 4;
211 *inSizeProcessed
= 0;
212 *outSizeProcessed
= 0;
216 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
217 + vs
->Properties
.lp
));
218 for (i
= 0; i
< numProbs
; i
++)
219 p
[i
] = kBitModelTotal
>> 1;
222 RC_INIT(inStream
, inSize
);
225 while (nowPos
< outSize
) {
228 int posState
= (int)((nowPos
)&posStateMask
);
230 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
234 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
235 ((((nowPos
) & literalPosMask
) << lc
)
236 + (previousByte
>> (8 - lc
))));
238 if (state
>= kNumLitStates
) {
240 matchByte
= outStream
[nowPos
- rep0
];
245 bit
= (matchByte
& 0x100);
246 probLit
= prob
+ 0x100 + bit
+ symbol
;
247 RC_GET_BIT2(probLit
, symbol
,
252 } while (symbol
< 0x100);
254 while (symbol
< 0x100) {
255 CProb
*probLit
= prob
+ symbol
;
256 RC_GET_BIT(probLit
, symbol
)
258 previousByte
= (Byte
)symbol
;
260 outStream
[nowPos
++] = previousByte
;
269 prob
= p
+ IsRep
+ state
;
275 state
= state
< kNumLitStates
? 0 : 3;
279 prob
= p
+ IsRepG0
+ state
;
282 prob
= p
+ IsRep0Long
283 + (state
<< kNumPosBitsMax
)
289 return LZMA_RESULT_DATA_ERROR
;
291 state
= state
< kNumLitStates
293 previousByte
= outStream
[nowPos
295 outStream
[nowPos
++] =
304 prob
= p
+ IsRepG1
+ state
;
310 prob
= p
+ IsRepG2
+ state
;
324 state
= state
< kNumLitStates
? 8 : 11;
325 prob
= p
+ RepLenCoder
;
329 CProb
*probLen
= prob
+ LenChoice
;
332 probLen
= prob
+ LenLow
333 + (posState
<< kLenNumLowBits
);
335 numBits
= kLenNumLowBits
;
338 probLen
= prob
+ LenChoice2
;
341 probLen
= prob
+ LenMid
344 offset
= kLenNumLowSymbols
;
345 numBits
= kLenNumMidBits
;
348 probLen
= prob
+ LenHigh
;
349 offset
= kLenNumLowSymbols
351 numBits
= kLenNumHighBits
;
354 RangeDecoderBitTreeDecode(probLen
, numBits
,
361 state
+= kNumLitStates
;
363 ((len
< kNumLenToPosStates
? len
:
364 kNumLenToPosStates
- 1) <<
366 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
,
368 if (posSlot
>= kStartPosModelIndex
) {
369 int numDirectBits
= ((posSlot
>> 1)
371 rep0
= (2 | ((UInt32
)posSlot
& 1));
372 if (posSlot
< kEndPosModelIndex
) {
373 rep0
<<= numDirectBits
;
374 prob
= p
+ SpecPos
+ rep0
377 numDirectBits
-= kNumAlignBits
;
386 } while (--numDirectBits
!= 0);
388 rep0
<<= kNumAlignBits
;
389 numDirectBits
= kNumAlignBits
;
397 RC_GET_BIT2(prob3
, mi
,
400 } while (--numDirectBits
!= 0);
404 if (++rep0
== (UInt32
)(0)) {
405 /* it's for stream version */
406 len
= kLzmaStreamWasFinishedId
;
413 return LZMA_RESULT_DATA_ERROR
;
417 previousByte
= outStream
[nowPos
- rep0
];
419 outStream
[nowPos
++] = previousByte
;
420 } while (len
!= 0 && nowPos
< outSize
);
426 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
427 *outSizeProcessed
= nowPos
;
428 return LZMA_RESULT_OK
;