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.
24 #include "LzmaDecode.h"
26 #define kNumTopBits 24
27 #define kTopValue ((UInt32)1 << kNumTopBits)
29 #define kNumBitModelTotalBits 11
30 #define kBitModelTotal (1 << kNumBitModelTotalBits)
31 #define kNumMoveBits 5
33 #define RC_READ_BYTE (*Buffer++)
35 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
36 { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
40 #define RC_TEST { if (Buffer == BufferLim) \
41 { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return result; } \
42 BufferLim = Buffer + size; if (size == 0) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }}
44 #define RC_INIT Buffer = BufferLim = 0; RC_INIT2
48 #define RC_TEST { if (Buffer == BufferLim) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }
50 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
54 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
56 #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
57 #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
58 #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
60 #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
61 { UpdateBit0(p); mi <<= 1; A0; } else \
62 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
64 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
66 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
67 { int i = numLevels; res = 1; \
68 do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
69 res -= (1 << numLevels); }
72 #define kNumPosBitsMax 4
73 #define kNumPosStatesMax (1 << kNumPosBitsMax)
75 #define kLenNumLowBits 3
76 #define kLenNumLowSymbols (1 << kLenNumLowBits)
77 #define kLenNumMidBits 3
78 #define kLenNumMidSymbols (1 << kLenNumMidBits)
79 #define kLenNumHighBits 8
80 #define kLenNumHighSymbols (1 << kLenNumHighBits)
83 #define LenChoice2 (LenChoice + 1)
84 #define LenLow (LenChoice2 + 1)
85 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
86 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
87 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
91 #define kNumLitStates 7
93 #define kStartPosModelIndex 4
94 #define kEndPosModelIndex 14
95 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
97 #define kNumPosSlotBits 6
98 #define kNumLenToPosStates 4
100 #define kNumAlignBits 4
101 #define kAlignTableSize (1 << kNumAlignBits)
103 #define kMatchMinLen 2
106 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
107 #define IsRepG0 (IsRep + kNumStates)
108 #define IsRepG1 (IsRepG0 + kNumStates)
109 #define IsRepG2 (IsRepG1 + kNumStates)
110 #define IsRep0Long (IsRepG2 + kNumStates)
111 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
112 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
113 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
114 #define LenCoder (Align + kAlignTableSize)
115 #define RepLenCoder (LenCoder + kNumLenProbs)
116 #define Literal (RepLenCoder + kNumLenProbs)
118 #if Literal != LZMA_BASE_SIZE
122 int LzmaDecodeProperties(CLzmaProperties
*propsRes
, const unsigned char *propsData
, int size
)
125 if (size
< LZMA_PROPERTIES_SIZE
)
127 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
128 return LZMA_RESULT_DATA_ERROR
;
130 prop0
= propsData
[0];
131 if (prop0
>= (9 * 5 * 5))
133 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
134 return LZMA_RESULT_DATA_ERROR
;
137 for (propsRes
->pb
= 0; prop0
>= (9 * 5); propsRes
->pb
++, prop0
-= (9 * 5));
138 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9);
139 propsRes
->lc
= prop0
;
141 unsigned char remainder = (unsigned char)(prop0 / 9);
142 propsRes->lc = prop0 % 9;
143 propsRes->pb = remainder / 5;
144 propsRes->lp = remainder % 5;
148 #ifdef _LZMA_OUT_READ
151 propsRes
->DictionarySize
= 0;
152 for (i
= 0; i
< 4; i
++)
153 propsRes
->DictionarySize
+= (UInt32
)(propsData
[1 + i
]) << (i
* 8);
154 if (propsRes
->DictionarySize
== 0)
155 propsRes
->DictionarySize
= 1;
158 return LZMA_RESULT_OK
;
161 #define kLzmaStreamWasFinishedId (-1)
163 int LzmaDecode(CLzmaDecoderState
*vs
,
165 ILzmaInCallback
*InCallback
,
167 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
169 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
171 CProb
*p
= vs
->Probs
;
173 Byte previousByte
= 0;
174 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
175 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
176 int lc
= vs
->Properties
.lc
;
178 #ifdef _LZMA_OUT_READ
180 UInt32 Range
= vs
->Range
;
181 UInt32 Code
= vs
->Code
;
183 const Byte
*Buffer
= vs
->Buffer
;
184 const Byte
*BufferLim
= vs
->BufferLim
;
186 const Byte
*Buffer
= inStream
;
187 const Byte
*BufferLim
= inStream
+ inSize
;
189 int state
= vs
->State
;
190 UInt32 rep0
= vs
->Reps
[0], rep1
= vs
->Reps
[1], rep2
= vs
->Reps
[2], rep3
= vs
->Reps
[3];
191 int len
= vs
->RemainLen
;
192 UInt32 globalPos
= vs
->GlobalPos
;
193 UInt32 distanceLimit
= vs
->DistanceLimit
;
195 Byte
*dictionary
= vs
->Dictionary
;
196 UInt32 dictionarySize
= vs
->Properties
.DictionarySize
;
197 UInt32 dictionaryPos
= vs
->DictionaryPos
;
199 Byte tempDictionary
[4];
202 *inSizeProcessed
= 0;
204 *outSizeProcessed
= 0;
205 if (len
== kLzmaStreamWasFinishedId
)
206 return LZMA_RESULT_OK
;
208 if (dictionarySize
== 0)
210 dictionary
= tempDictionary
;
212 tempDictionary
[0] = vs
->TempDictionary
[0];
215 if (len
== kLzmaNeedInitId
)
218 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
220 for (i
= 0; i
< numProbs
; i
++)
221 p
[i
] = kBitModelTotal
>> 1;
222 rep0
= rep1
= rep2
= rep3
= 1;
227 dictionary
[dictionarySize
- 1] = 0;
231 RC_INIT(inStream
, inSize
);
236 while(len
!= 0 && nowPos
< outSize
)
238 UInt32 pos
= dictionaryPos
- rep0
;
239 if (pos
>= dictionarySize
)
240 pos
+= dictionarySize
;
241 outStream
[nowPos
++] = dictionary
[dictionaryPos
] = dictionary
[pos
];
242 if (++dictionaryPos
== dictionarySize
)
246 if (dictionaryPos
== 0)
247 previousByte
= dictionary
[dictionarySize
- 1];
249 previousByte
= dictionary
[dictionaryPos
- 1];
251 #else /* if !_LZMA_OUT_READ */
254 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
257 const Byte
*BufferLim
;
262 *inSizeProcessed
= 0;
264 *outSizeProcessed
= 0;
268 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
269 for (i
= 0; i
< numProbs
; i
++)
270 p
[i
] = kBitModelTotal
>> 1;
276 RC_INIT(inStream
, inSize
);
279 #endif /* _LZMA_OUT_READ */
281 while(nowPos
< outSize
)
285 int posState
= (int)(
287 #ifdef _LZMA_OUT_READ
293 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
298 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
301 #ifdef _LZMA_OUT_READ
305 & literalPosMask
) << lc
) + (previousByte
>> (8 - lc
))));
307 if (state
>= kNumLitStates
)
310 #ifdef _LZMA_OUT_READ
311 UInt32 pos
= dictionaryPos
- rep0
;
312 if (pos
>= dictionarySize
)
313 pos
+= dictionarySize
;
314 matchByte
= dictionary
[pos
];
316 matchByte
= outStream
[nowPos
- rep0
];
323 bit
= (matchByte
& 0x100);
324 probLit
= prob
+ 0x100 + bit
+ symbol
;
325 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
327 while (symbol
< 0x100);
329 while (symbol
< 0x100)
331 CProb
*probLit
= prob
+ symbol
;
332 RC_GET_BIT(probLit
, symbol
)
334 previousByte
= (Byte
)symbol
;
336 outStream
[nowPos
++] = previousByte
;
337 #ifdef _LZMA_OUT_READ
338 if (distanceLimit
< dictionarySize
)
341 dictionary
[dictionaryPos
] = previousByte
;
342 if (++dictionaryPos
== dictionarySize
)
345 if (state
< 4) state
= 0;
346 else if (state
< 10) state
-= 3;
352 prob
= p
+ IsRep
+ state
;
359 state
= state
< kNumLitStates
? 0 : 3;
365 prob
= p
+ IsRepG0
+ state
;
369 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
372 #ifdef _LZMA_OUT_READ
377 #ifdef _LZMA_OUT_READ
378 if (distanceLimit
== 0)
383 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
384 return LZMA_RESULT_DATA_ERROR
;
387 state
= state
< kNumLitStates
? 9 : 11;
388 #ifdef _LZMA_OUT_READ
389 pos
= dictionaryPos
- rep0
;
390 if (pos
>= dictionarySize
)
391 pos
+= dictionarySize
;
392 previousByte
= dictionary
[pos
];
393 dictionary
[dictionaryPos
] = previousByte
;
394 if (++dictionaryPos
== dictionarySize
)
397 previousByte
= outStream
[nowPos
- rep0
];
399 outStream
[nowPos
++] = previousByte
;
400 #ifdef _LZMA_OUT_READ
401 if (distanceLimit
< dictionarySize
)
416 prob
= p
+ IsRepG1
+ state
;
425 prob
= p
+ IsRepG2
+ state
;
442 state
= state
< kNumLitStates
? 8 : 11;
443 prob
= p
+ RepLenCoder
;
447 CProb
*probLen
= prob
+ LenChoice
;
451 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
453 numBits
= kLenNumLowBits
;
458 probLen
= prob
+ LenChoice2
;
462 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
463 offset
= kLenNumLowSymbols
;
464 numBits
= kLenNumMidBits
;
469 probLen
= prob
+ LenHigh
;
470 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
471 numBits
= kLenNumHighBits
;
474 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
481 state
+= kNumLitStates
;
483 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
485 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
486 if (posSlot
>= kStartPosModelIndex
)
488 int numDirectBits
= ((posSlot
>> 1) - 1);
489 rep0
= (2 | ((UInt32
)posSlot
& 1));
490 if (posSlot
< kEndPosModelIndex
)
492 rep0
<<= numDirectBits
;
493 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
497 numDirectBits
-= kNumAlignBits
;
509 while (--numDirectBits
!= 0);
511 rep0
<<= kNumAlignBits
;
512 numDirectBits
= kNumAlignBits
;
519 CProb
*prob3
= prob
+ mi
;
520 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
523 while(--numDirectBits
!= 0);
528 if (++rep0
== (UInt32
)(0))
530 /* it's for stream version */
531 len
= kLzmaStreamWasFinishedId
;
537 #ifdef _LZMA_OUT_READ
538 if (rep0
> distanceLimit
)
543 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
544 return LZMA_RESULT_DATA_ERROR
;
547 #ifdef _LZMA_OUT_READ
548 if (dictionarySize
- distanceLimit
> (UInt32
)len
)
549 distanceLimit
+= len
;
551 distanceLimit
= dictionarySize
;
556 #ifdef _LZMA_OUT_READ
557 UInt32 pos
= dictionaryPos
- rep0
;
558 if (pos
>= dictionarySize
)
559 pos
+= dictionarySize
;
560 previousByte
= dictionary
[pos
];
561 dictionary
[dictionaryPos
] = previousByte
;
562 if (++dictionaryPos
== dictionarySize
)
565 previousByte
= outStream
[nowPos
- rep0
];
568 outStream
[nowPos
++] = previousByte
;
570 while(len
!= 0 && nowPos
< outSize
);
575 #ifdef _LZMA_OUT_READ
578 vs
->DictionaryPos
= dictionaryPos
;
579 vs
->GlobalPos
= globalPos
+ (UInt32
)nowPos
;
580 vs
->DistanceLimit
= distanceLimit
;
587 vs
->TempDictionary
[0] = tempDictionary
[0];
592 vs
->BufferLim
= BufferLim
;
594 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
596 *outSizeProcessed
= nowPos
;
597 return LZMA_RESULT_OK
;
600 #endif /* CONFIG_LZMA */
This page took 0.084124 seconds and 5 git commands to generate.