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"
24 #define kNumTopBits 24
25 #define kTopValue ((UInt32)1 << kNumTopBits)
27 #define kNumBitModelTotalBits 11
28 #define kBitModelTotal (1 << kNumBitModelTotalBits)
29 #define kNumMoveBits 5
31 #define RC_READ_BYTE (*Buffer++)
33 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
34 { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
36 #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
38 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
40 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
42 #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
43 #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
44 #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
46 #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
47 { UpdateBit0(p); mi <<= 1; A0; } else \
48 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
50 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
52 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
53 { int i = numLevels; res = 1; \
54 do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
55 res -= (1 << numLevels); }
57 #define kNumPosBitsMax 4
58 #define kNumPosStatesMax (1 << kNumPosBitsMax)
60 #define kLenNumLowBits 3
61 #define kLenNumLowSymbols (1 << kLenNumLowBits)
62 #define kLenNumMidBits 3
63 #define kLenNumMidSymbols (1 << kLenNumMidBits)
64 #define kLenNumHighBits 8
65 #define kLenNumHighSymbols (1 << kLenNumHighBits)
68 #define LenChoice2 (LenChoice + 1)
69 #define LenLow (LenChoice2 + 1)
70 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
71 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
72 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
75 #define kNumLitStates 7
77 #define kStartPosModelIndex 4
78 #define kEndPosModelIndex 14
79 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
81 #define kNumPosSlotBits 6
82 #define kNumLenToPosStates 4
84 #define kNumAlignBits 4
85 #define kAlignTableSize (1 << kNumAlignBits)
87 #define kMatchMinLen 2
90 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
91 #define IsRepG0 (IsRep + kNumStates)
92 #define IsRepG1 (IsRepG0 + kNumStates)
93 #define IsRepG2 (IsRepG1 + kNumStates)
94 #define IsRep0Long (IsRepG2 + kNumStates)
95 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
96 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
97 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
98 #define LenCoder (Align + kAlignTableSize)
99 #define RepLenCoder (LenCoder + kNumLenProbs)
100 #define Literal (RepLenCoder + kNumLenProbs)
102 #if Literal != LZMA_BASE_SIZE
106 int LzmaDecodeProperties(CLzmaProperties
*propsRes
, const unsigned char *propsData
, int size
)
109 if (size
< LZMA_PROPERTIES_SIZE
)
110 return LZMA_RESULT_DATA_ERROR
;
111 prop0
= propsData
[0];
112 if (prop0
>= (9 * 5 * 5))
113 return LZMA_RESULT_DATA_ERROR
;
115 for (propsRes
->pb
= 0; prop0
>= (9 * 5); propsRes
->pb
++, prop0
-= (9 * 5));
116 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9);
117 propsRes
->lc
= prop0
;
119 unsigned char remainder = (unsigned char)(prop0 / 9);
120 propsRes->lc = prop0 % 9;
121 propsRes->pb = remainder / 5;
122 propsRes->lp = remainder % 5;
126 return LZMA_RESULT_OK
;
129 #define kLzmaStreamWasFinishedId (-1)
131 int LzmaDecode(CLzmaDecoderState
*vs
,
132 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
133 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
135 CProb
*p
= vs
->Probs
;
137 Byte previousByte
= 0;
138 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
139 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
140 int lc
= vs
->Properties
.lc
;
143 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
146 const Byte
*BufferLim
;
150 *inSizeProcessed
= 0;
151 *outSizeProcessed
= 0;
155 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
156 for (i
= 0; i
< numProbs
; i
++)
157 p
[i
] = kBitModelTotal
>> 1;
160 RC_INIT(inStream
, inSize
);
162 while(nowPos
< outSize
)
166 int posState
= (int)(
171 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
176 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
180 & literalPosMask
) << lc
) + (previousByte
>> (8 - lc
))));
182 if (state
>= kNumLitStates
)
185 matchByte
= outStream
[nowPos
- rep0
];
191 bit
= (matchByte
& 0x100);
192 probLit
= prob
+ 0x100 + bit
+ symbol
;
193 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
195 while (symbol
< 0x100);
197 while (symbol
< 0x100)
199 CProb
*probLit
= prob
+ symbol
;
200 RC_GET_BIT(probLit
, symbol
)
202 previousByte
= (Byte
)symbol
;
204 outStream
[nowPos
++] = previousByte
;
205 if (state
< 4) state
= 0;
206 else if (state
< 10) state
-= 3;
212 prob
= p
+ IsRep
+ state
;
219 state
= state
< kNumLitStates
? 0 : 3;
225 prob
= p
+ IsRepG0
+ state
;
229 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
235 return LZMA_RESULT_DATA_ERROR
;
237 state
= state
< kNumLitStates
? 9 : 11;
238 previousByte
= outStream
[nowPos
- rep0
];
239 outStream
[nowPos
++] = previousByte
;
252 prob
= p
+ IsRepG1
+ state
;
261 prob
= p
+ IsRepG2
+ state
;
278 state
= state
< kNumLitStates
? 8 : 11;
279 prob
= p
+ RepLenCoder
;
283 CProb
*probLen
= prob
+ LenChoice
;
287 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
289 numBits
= kLenNumLowBits
;
294 probLen
= prob
+ LenChoice2
;
298 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
299 offset
= kLenNumLowSymbols
;
300 numBits
= kLenNumMidBits
;
305 probLen
= prob
+ LenHigh
;
306 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
307 numBits
= kLenNumHighBits
;
310 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
317 state
+= kNumLitStates
;
319 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
321 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
322 if (posSlot
>= kStartPosModelIndex
)
324 int numDirectBits
= ((posSlot
>> 1) - 1);
325 rep0
= (2 | ((UInt32
)posSlot
& 1));
326 if (posSlot
< kEndPosModelIndex
)
328 rep0
<<= numDirectBits
;
329 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
333 numDirectBits
-= kNumAlignBits
;
345 while (--numDirectBits
!= 0);
347 rep0
<<= kNumAlignBits
;
348 numDirectBits
= kNumAlignBits
;
355 CProb
*prob3
= prob
+ mi
;
356 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
359 while(--numDirectBits
!= 0);
364 if (++rep0
== (UInt32
)(0))
366 /* it's for stream version */
367 len
= kLzmaStreamWasFinishedId
;
374 return LZMA_RESULT_DATA_ERROR
;
378 previousByte
= outStream
[nowPos
- rep0
];
380 outStream
[nowPos
++] = previousByte
;
382 while(len
!= 0 && nowPos
< outSize
);
387 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
388 *outSizeProcessed
= nowPos
;
389 return LZMA_RESULT_OK
;