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 #if CONFIG(DECOMPRESS_OFAST)
23 #define __lzma_attribute_Ofast__ __attribute__((optimize("Ofast")))
25 #define __lzma_attribute_Ofast__
28 #include "lzmadecode.h"
31 #define kNumTopBits 24
32 #define kTopValue ((UInt32)1 << kNumTopBits)
34 #define kNumBitModelTotalBits 11
35 #define kBitModelTotal (1 << kNumBitModelTotalBits)
36 #define kNumMoveBits 5
38 /* Use sizeof(SizeT) sized reads whenever possible to avoid bad flash performance. Fall back
39 * to byte reads for last sizeof(SizeT) bytes since RC_TEST returns an error when BufferLim
40 * is *reached* (not surpassed!), meaning we can't allow that to happen while
41 * there are still bytes to decode from the algorithm's point of view. */
42 #define RC_READ_BYTE \
43 (look_ahead_ptr < sizeof(SizeT) ? look_ahead.raw[look_ahead_ptr++] \
44 : ((((uintptr_t) Buffer & (sizeof(SizeT) - 1)) \
45 || ((SizeT) (BufferLim - Buffer) <= sizeof(SizeT))) ? (*Buffer++) \
46 : ((look_ahead.dw = *(SizeT *)Buffer), (Buffer += sizeof(SizeT)), \
47 (look_ahead_ptr = 1), look_ahead.raw[0])))
49 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
53 for (i = 0; i < 5; i++) { \
55 Code = (Code << 8) | RC_READ_BYTE; \
60 #define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
62 #define RC_INIT(buffer, bufferSize) Buffer = buffer; \
63 BufferLim = buffer + bufferSize; RC_INIT2
66 #define RC_NORMALIZE \
67 if (Range < kTopValue) { \
70 Code = (Code << 8) | RC_READ_BYTE; \
75 bound = (Range >> kNumBitModelTotalBits) * *(p); \
78 #define UpdateBit0(p) \
80 *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits
82 #define UpdateBit1(p) \
85 *(p) -= (*(p)) >> kNumMoveBits
87 #define RC_GET_BIT2(p, mi, A0, A1) \
98 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ;, ;)
100 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
106 CProb *cp = probs + res; \
107 RC_GET_BIT(cp, res) \
108 } while (--i != 0); \
109 res -= (1 << numLevels); \
113 #define kNumPosBitsMax 4
114 #define kNumPosStatesMax (1 << kNumPosBitsMax)
116 #define kLenNumLowBits 3
117 #define kLenNumLowSymbols (1 << kLenNumLowBits)
118 #define kLenNumMidBits 3
119 #define kLenNumMidSymbols (1 << kLenNumMidBits)
120 #define kLenNumHighBits 8
121 #define kLenNumHighSymbols (1 << kLenNumHighBits)
124 #define LenChoice2 (LenChoice + 1)
125 #define LenLow (LenChoice2 + 1)
126 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
127 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
128 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
131 #define kNumStates 12
132 #define kNumLitStates 7
134 #define kStartPosModelIndex 4
135 #define kEndPosModelIndex 14
136 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
138 #define kNumPosSlotBits 6
139 #define kNumLenToPosStates 4
141 #define kNumAlignBits 4
142 #define kAlignTableSize (1 << kNumAlignBits)
144 #define kMatchMinLen 2
147 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
148 #define IsRepG0 (IsRep + kNumStates)
149 #define IsRepG1 (IsRepG0 + kNumStates)
150 #define IsRepG2 (IsRepG1 + kNumStates)
151 #define IsRep0Long (IsRepG2 + kNumStates)
152 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
153 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
154 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
155 #define LenCoder (Align + kAlignTableSize)
156 #define RepLenCoder (LenCoder + kNumLenProbs)
157 #define Literal (RepLenCoder + kNumLenProbs)
159 #if Literal != LZMA_BASE_SIZE
163 int LzmaDecodeProperties(CLzmaProperties
*propsRes
,
164 const unsigned char *propsData
, int size
)
167 if (size
< LZMA_PROPERTIES_SIZE
)
168 return LZMA_RESULT_DATA_ERROR
;
169 prop0
= propsData
[0];
170 if (prop0
>= (9 * 5 * 5))
171 return LZMA_RESULT_DATA_ERROR
;
173 for (propsRes
->pb
= 0; prop0
>= (9 * 5);
174 propsRes
->pb
++, prop0
-= (9 * 5))
176 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9)
178 propsRes
->lc
= prop0
;
180 * unsigned char remainder = (unsigned char)(prop0 / 9);
181 * propsRes->lc = prop0 % 9;
182 * propsRes->pb = remainder / 5;
183 * propsRes->lp = remainder % 5;
187 return LZMA_RESULT_OK
;
190 #define kLzmaStreamWasFinishedId (-1)
192 __lzma_attribute_Ofast__
193 int LzmaDecode(CLzmaDecoderState
*vs
,
194 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
195 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
197 CProb
*p
= vs
->Probs
;
199 Byte previousByte
= 0;
200 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
201 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
202 int lc
= vs
->Properties
.lc
;
206 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
209 const Byte
*BufferLim
;
210 int look_ahead_ptr
= sizeof(SizeT
);
212 Byte raw
[sizeof(SizeT
)];
218 *inSizeProcessed
= 0;
219 *outSizeProcessed
= 0;
223 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
224 + vs
->Properties
.lp
));
225 for (i
= 0; i
< numProbs
; i
++)
226 p
[i
] = kBitModelTotal
>> 1;
229 RC_INIT(inStream
, inSize
);
232 while (nowPos
< outSize
) {
235 int posState
= (int)((nowPos
)&posStateMask
);
237 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
241 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
242 ((((nowPos
) & literalPosMask
) << lc
)
243 + (previousByte
>> (8 - lc
))));
245 if (state
>= kNumLitStates
) {
247 matchByte
= outStream
[nowPos
- rep0
];
252 bit
= (matchByte
& 0x100);
253 probLit
= prob
+ 0x100 + bit
+ symbol
;
254 RC_GET_BIT2(probLit
, symbol
,
259 } while (symbol
< 0x100);
261 while (symbol
< 0x100) {
262 CProb
*probLit
= prob
+ symbol
;
263 RC_GET_BIT(probLit
, symbol
)
265 previousByte
= (Byte
)symbol
;
267 outStream
[nowPos
++] = previousByte
;
276 prob
= p
+ IsRep
+ state
;
282 state
= state
< kNumLitStates
? 0 : 3;
286 prob
= p
+ IsRepG0
+ state
;
289 prob
= p
+ IsRep0Long
290 + (state
<< kNumPosBitsMax
)
296 return LZMA_RESULT_DATA_ERROR
;
298 state
= state
< kNumLitStates
300 previousByte
= outStream
[nowPos
302 outStream
[nowPos
++] =
312 prob
= p
+ IsRepG1
+ state
;
318 prob
= p
+ IsRepG2
+ state
;
332 state
= state
< kNumLitStates
? 8 : 11;
333 prob
= p
+ RepLenCoder
;
337 CProb
*probLen
= prob
+ LenChoice
;
340 probLen
= prob
+ LenLow
341 + (posState
<< kLenNumLowBits
);
343 numBits
= kLenNumLowBits
;
346 probLen
= prob
+ LenChoice2
;
349 probLen
= prob
+ LenMid
352 offset
= kLenNumLowSymbols
;
353 numBits
= kLenNumMidBits
;
356 probLen
= prob
+ LenHigh
;
357 offset
= kLenNumLowSymbols
359 numBits
= kLenNumHighBits
;
362 RangeDecoderBitTreeDecode(probLen
, numBits
,
369 state
+= kNumLitStates
;
371 ((len
< kNumLenToPosStates
? len
:
372 kNumLenToPosStates
- 1) <<
374 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
,
376 if (posSlot
>= kStartPosModelIndex
) {
377 int numDirectBits
= ((posSlot
>> 1)
379 rep0
= (2 | ((UInt32
)posSlot
& 1));
380 if (posSlot
< kEndPosModelIndex
) {
381 rep0
<<= numDirectBits
;
382 prob
= p
+ SpecPos
+ rep0
385 numDirectBits
-= kNumAlignBits
;
394 } while (--numDirectBits
!= 0);
396 rep0
<<= kNumAlignBits
;
397 numDirectBits
= kNumAlignBits
;
405 RC_GET_BIT2(prob3
, mi
,
408 } while (--numDirectBits
!= 0);
412 if (++rep0
== (UInt32
)(0)) {
413 /* it's for stream version */
414 len
= kLzmaStreamWasFinishedId
;
421 return LZMA_RESULT_DATA_ERROR
;
425 previousByte
= outStream
[nowPos
- rep0
];
427 outStream
[nowPos
++] = previousByte
;
428 } while (len
!= 0 && nowPos
< outSize
);
433 * Tell static analysis we know len can have a dead assignment.
438 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
439 *outSizeProcessed
= nowPos
;
440 return LZMA_RESULT_OK
;