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. */
33 #define RC_READ_BYTE (look_ahead_ptr < 4 ? look_ahead.raw[look_ahead_ptr++] \
34 : ((((uintptr_t) Buffer & 3) || ((SizeT) (BufferLim - Buffer) < 4)) ? (*Buffer++) \
35 : ((look_ahead.dw = *(UInt32 *)Buffer), (Buffer += 4), (look_ahead_ptr = 1), look_ahead.raw[0])))
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; }}
41 #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
43 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
46 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
48 #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
49 #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
50 #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
52 #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
53 { UpdateBit0(p); mi <<= 1; A0; } else \
54 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
56 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
58 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
59 { int i = numLevels; res = 1; \
60 do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
61 res -= (1 << numLevels); }
64 #define kNumPosBitsMax 4
65 #define kNumPosStatesMax (1 << kNumPosBitsMax)
67 #define kLenNumLowBits 3
68 #define kLenNumLowSymbols (1 << kLenNumLowBits)
69 #define kLenNumMidBits 3
70 #define kLenNumMidSymbols (1 << kLenNumMidBits)
71 #define kLenNumHighBits 8
72 #define kLenNumHighSymbols (1 << kLenNumHighBits)
75 #define LenChoice2 (LenChoice + 1)
76 #define LenLow (LenChoice2 + 1)
77 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
78 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
79 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
83 #define kNumLitStates 7
85 #define kStartPosModelIndex 4
86 #define kEndPosModelIndex 14
87 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
89 #define kNumPosSlotBits 6
90 #define kNumLenToPosStates 4
92 #define kNumAlignBits 4
93 #define kAlignTableSize (1 << kNumAlignBits)
95 #define kMatchMinLen 2
98 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
99 #define IsRepG0 (IsRep + kNumStates)
100 #define IsRepG1 (IsRepG0 + kNumStates)
101 #define IsRepG2 (IsRepG1 + kNumStates)
102 #define IsRep0Long (IsRepG2 + kNumStates)
103 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
104 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
105 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
106 #define LenCoder (Align + kAlignTableSize)
107 #define RepLenCoder (LenCoder + kNumLenProbs)
108 #define Literal (RepLenCoder + kNumLenProbs)
110 #if Literal != LZMA_BASE_SIZE
114 int LzmaDecodeProperties(CLzmaProperties
*propsRes
, const unsigned char *propsData
, int size
)
117 if (size
< LZMA_PROPERTIES_SIZE
)
118 return LZMA_RESULT_DATA_ERROR
;
119 prop0
= propsData
[0];
120 if (prop0
>= (9 * 5 * 5))
121 return LZMA_RESULT_DATA_ERROR
;
123 for (propsRes
->pb
= 0; prop0
>= (9 * 5); propsRes
->pb
++, prop0
-= (9 * 5));
124 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9);
125 propsRes
->lc
= prop0
;
127 unsigned char remainder = (unsigned char)(prop0 / 9);
128 propsRes->lc = prop0 % 9;
129 propsRes->pb = remainder / 5;
130 propsRes->lp = remainder % 5;
134 return LZMA_RESULT_OK
;
137 #define kLzmaStreamWasFinishedId (-1)
139 int LzmaDecode(CLzmaDecoderState
*vs
,
140 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
141 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
143 CProb
*p
= vs
->Probs
;
145 Byte previousByte
= 0;
146 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
147 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
148 int lc
= vs
->Properties
.lc
;
152 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
155 const Byte
*BufferLim
;
156 int look_ahead_ptr
= 4;
165 *inSizeProcessed
= 0;
166 *outSizeProcessed
= 0;
170 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
171 for (i
= 0; i
< numProbs
; i
++)
172 p
[i
] = kBitModelTotal
>> 1;
175 RC_INIT(inStream
, inSize
);
178 while(nowPos
< outSize
)
182 int posState
= (int)(
187 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
192 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
196 & literalPosMask
) << lc
) + (previousByte
>> (8 - lc
))));
198 if (state
>= kNumLitStates
)
201 matchByte
= outStream
[nowPos
- rep0
];
207 bit
= (matchByte
& 0x100);
208 probLit
= prob
+ 0x100 + bit
+ symbol
;
209 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
211 while (symbol
< 0x100);
213 while (symbol
< 0x100)
215 CProb
*probLit
= prob
+ symbol
;
216 RC_GET_BIT(probLit
, symbol
)
218 previousByte
= (Byte
)symbol
;
220 outStream
[nowPos
++] = previousByte
;
221 if (state
< 4) state
= 0;
222 else if (state
< 10) state
-= 3;
228 prob
= p
+ IsRep
+ state
;
235 state
= state
< kNumLitStates
? 0 : 3;
241 prob
= p
+ IsRepG0
+ state
;
245 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
251 return LZMA_RESULT_DATA_ERROR
;
253 state
= state
< kNumLitStates
? 9 : 11;
254 previousByte
= outStream
[nowPos
- rep0
];
255 outStream
[nowPos
++] = previousByte
;
268 prob
= p
+ IsRepG1
+ state
;
277 prob
= p
+ IsRepG2
+ state
;
294 state
= state
< kNumLitStates
? 8 : 11;
295 prob
= p
+ RepLenCoder
;
299 CProb
*probLen
= prob
+ LenChoice
;
303 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
305 numBits
= kLenNumLowBits
;
310 probLen
= prob
+ LenChoice2
;
314 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
315 offset
= kLenNumLowSymbols
;
316 numBits
= kLenNumMidBits
;
321 probLen
= prob
+ LenHigh
;
322 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
323 numBits
= kLenNumHighBits
;
326 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
333 state
+= kNumLitStates
;
335 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
337 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
338 if (posSlot
>= kStartPosModelIndex
)
340 int numDirectBits
= ((posSlot
>> 1) - 1);
341 rep0
= (2 | ((UInt32
)posSlot
& 1));
342 if (posSlot
< kEndPosModelIndex
)
344 rep0
<<= numDirectBits
;
345 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
349 numDirectBits
-= kNumAlignBits
;
361 while (--numDirectBits
!= 0);
363 rep0
<<= kNumAlignBits
;
364 numDirectBits
= kNumAlignBits
;
371 CProb
*prob3
= prob
+ mi
;
372 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
375 while(--numDirectBits
!= 0);
380 if (++rep0
== (UInt32
)(0))
382 /* it's for stream version */
383 len
= kLzmaStreamWasFinishedId
;
390 return LZMA_RESULT_DATA_ERROR
;
395 previousByte
= outStream
[nowPos
- rep0
];
397 outStream
[nowPos
++] = previousByte
;
399 while(len
!= 0 && nowPos
< outSize
);
405 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
406 *outSizeProcessed
= nowPos
;
407 return LZMA_RESULT_OK
;