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.
27 #include "LzmaDecode.h"
29 #define kNumTopBits 24
30 #define kTopValue ((UInt32)1 << kNumTopBits)
32 #define kNumBitModelTotalBits 11
33 #define kBitModelTotal (1 << kNumBitModelTotalBits)
34 #define kNumMoveBits 5
36 #define RC_READ_BYTE (*Buffer++)
38 #define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
39 { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
43 #ifndef CFG_BOOTSTRAP_CODE
44 #define RC_TEST { if (Buffer == BufferLim) \
45 { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return result; } \
46 BufferLim = Buffer + size; if (size == 0) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }}
47 #else //CFG_BOOTSTRAP_CODE
48 #define RC_TEST { if (Buffer == BufferLim) \
49 { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { return result; } \
50 BufferLim = Buffer + size; if (size == 0) { return LZMA_RESULT_DATA_ERROR; } }}
51 #endif //CFG_BOOTSTRAP_CODE
53 #define RC_INIT Buffer = BufferLim = 0; RC_INIT2
57 #ifndef CFG_BOOTSTRAP_CODE
58 #define RC_TEST { if (Buffer == BufferLim) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }
59 #else //CFG_BOOTSTRAP_CODE
60 #define RC_TEST { if (Buffer == BufferLim) { return LZMA_RESULT_DATA_ERROR; } }
61 #endif //CFG_BOOTSTRAP_CODE
63 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
67 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
68 #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
69 #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
70 #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
72 #define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
73 { UpdateBit0(p); mi <<= 1; A0; } else \
74 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
76 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
78 #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
79 { int i = numLevels; res = 1; \
80 do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
81 res -= (1 << numLevels); }
84 #define kNumPosBitsMax 4
85 #define kNumPosStatesMax (1 << kNumPosBitsMax)
87 #define kLenNumLowBits 3
88 #define kLenNumLowSymbols (1 << kLenNumLowBits)
89 #define kLenNumMidBits 3
90 #define kLenNumMidSymbols (1 << kLenNumMidBits)
91 #define kLenNumHighBits 8
92 #define kLenNumHighSymbols (1 << kLenNumHighBits)
95 #define LenChoice2 (LenChoice + 1)
96 #define LenLow (LenChoice2 + 1)
97 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
98 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
99 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
102 #define kNumStates 12
103 #define kNumLitStates 7
105 #define kStartPosModelIndex 4
106 #define kEndPosModelIndex 14
107 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
109 #define kNumPosSlotBits 6
110 #define kNumLenToPosStates 4
112 #define kNumAlignBits 4
113 #define kAlignTableSize (1 << kNumAlignBits)
115 #define kMatchMinLen 2
118 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
119 #define IsRepG0 (IsRep + kNumStates)
120 #define IsRepG1 (IsRepG0 + kNumStates)
121 #define IsRepG2 (IsRepG1 + kNumStates)
122 #define IsRep0Long (IsRepG2 + kNumStates)
123 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
124 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
125 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
126 #define LenCoder (Align + kAlignTableSize)
127 #define RepLenCoder (LenCoder + kNumLenProbs)
128 #define Literal (RepLenCoder + kNumLenProbs)
130 #if Literal != LZMA_BASE_SIZE
134 int LzmaDecodeProperties(CLzmaProperties
*propsRes
, const unsigned char *propsData
, int size
)
137 if (size
< LZMA_PROPERTIES_SIZE
)
139 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
140 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
142 return LZMA_RESULT_DATA_ERROR
;
144 prop0
= propsData
[0];
145 if (prop0
>= (9 * 5 * 5))
147 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
148 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
150 return LZMA_RESULT_DATA_ERROR
;
153 for (propsRes
->pb
= 0; prop0
>= (9 * 5); propsRes
->pb
++, prop0
-= (9 * 5));
154 for (propsRes
->lp
= 0; prop0
>= 9; propsRes
->lp
++, prop0
-= 9);
155 propsRes
->lc
= prop0
;
157 unsigned char remainder = (unsigned char)(prop0 / 9);
158 propsRes->lc = prop0 % 9;
159 propsRes->pb = remainder / 5;
160 propsRes->lp = remainder % 5;
164 #ifdef _LZMA_OUT_READ
167 propsRes
->DictionarySize
= 0;
168 for (i
= 0; i
< 4; i
++)
169 propsRes
->DictionarySize
+= (UInt32
)(propsData
[1 + i
]) << (i
* 8);
170 if (propsRes
->DictionarySize
== 0)
171 propsRes
->DictionarySize
= 1;
174 return LZMA_RESULT_OK
;
177 #define kLzmaStreamWasFinishedId (-1)
179 int LzmaDecode(CLzmaDecoderState
*vs
,
181 ILzmaInCallback
*InCallback
,
183 const unsigned char *inStream
, SizeT inSize
, SizeT
*inSizeProcessed
,
185 unsigned char *outStream
, SizeT outSize
, SizeT
*outSizeProcessed
)
187 CProb
*p
= vs
->Probs
;
189 Byte previousByte
= 0;
190 UInt32 posStateMask
= (1 << (vs
->Properties
.pb
)) - 1;
191 UInt32 literalPosMask
= (1 << (vs
->Properties
.lp
)) - 1;
192 int lc
= vs
->Properties
.lc
;
194 #ifdef _LZMA_OUT_READ
196 UInt32 Range
= vs
->Range
;
197 UInt32 Code
= vs
->Code
;
199 const Byte
*Buffer
= vs
->Buffer
;
200 const Byte
*BufferLim
= vs
->BufferLim
;
202 const Byte
*Buffer
= inStream
;
203 const Byte
*BufferLim
= inStream
+ inSize
;
205 int state
= vs
->State
;
206 UInt32 rep0
= vs
->Reps
[0], rep1
= vs
->Reps
[1], rep2
= vs
->Reps
[2], rep3
= vs
->Reps
[3];
207 int len
= vs
->RemainLen
;
208 UInt32 globalPos
= vs
->GlobalPos
;
209 UInt32 distanceLimit
= vs
->DistanceLimit
;
211 Byte
*dictionary
= vs
->Dictionary
;
212 UInt32 dictionarySize
= vs
->Properties
.DictionarySize
;
213 UInt32 dictionaryPos
= vs
->DictionaryPos
;
215 Byte tempDictionary
[4];
218 *inSizeProcessed
= 0;
220 *outSizeProcessed
= 0;
221 if (len
== kLzmaStreamWasFinishedId
)
222 return LZMA_RESULT_OK
;
224 if (dictionarySize
== 0)
226 dictionary
= tempDictionary
;
228 tempDictionary
[0] = vs
->TempDictionary
[0];
231 if (len
== kLzmaNeedInitId
)
234 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
236 for (i
= 0; i
< numProbs
; i
++)
237 p
[i
] = kBitModelTotal
>> 1;
238 rep0
= rep1
= rep2
= rep3
= 1;
243 dictionary
[dictionarySize
- 1] = 0;
247 RC_INIT(inStream
, inSize
);
252 while(len
!= 0 && nowPos
< outSize
)
254 UInt32 pos
= dictionaryPos
- rep0
;
255 if (pos
>= dictionarySize
)
256 pos
+= dictionarySize
;
257 outStream
[nowPos
++] = dictionary
[dictionaryPos
] = dictionary
[pos
];
258 if (++dictionaryPos
== dictionarySize
)
262 if (dictionaryPos
== 0)
263 previousByte
= dictionary
[dictionarySize
- 1];
265 previousByte
= dictionary
[dictionaryPos
- 1];
267 #else /* if !_LZMA_OUT_READ */
270 UInt32 rep0
= 1, rep1
= 1, rep2
= 1, rep3
= 1;
273 const Byte
*BufferLim
;
278 *inSizeProcessed
= 0;
280 *outSizeProcessed
= 0;
284 UInt32 numProbs
= Literal
+ ((UInt32
)LZMA_LIT_SIZE
<< (lc
+ vs
->Properties
.lp
));
285 for (i
= 0; i
< numProbs
; i
++)
286 p
[i
] = kBitModelTotal
>> 1;
292 RC_INIT(inStream
, inSize
);
295 #endif /* _LZMA_OUT_READ */
297 while(nowPos
< outSize
)
301 int posState
= (int)(
303 #ifdef _LZMA_OUT_READ
309 prob
= p
+ IsMatch
+ (state
<< kNumPosBitsMax
) + posState
;
314 prob
= p
+ Literal
+ (LZMA_LIT_SIZE
*
317 #ifdef _LZMA_OUT_READ
321 & literalPosMask
) << lc
) + (previousByte
>> (8 - lc
))));
323 if (state
>= kNumLitStates
)
326 #ifdef _LZMA_OUT_READ
327 UInt32 pos
= dictionaryPos
- rep0
;
328 if (pos
>= dictionarySize
)
329 pos
+= dictionarySize
;
330 matchByte
= dictionary
[pos
];
332 matchByte
= outStream
[nowPos
- rep0
];
339 bit
= (matchByte
& 0x100);
340 probLit
= prob
+ 0x100 + bit
+ symbol
;
341 RC_GET_BIT2(probLit
, symbol
, if (bit
!= 0) break, if (bit
== 0) break)
343 while (symbol
< 0x100);
345 while (symbol
< 0x100)
347 CProb
*probLit
= prob
+ symbol
;
348 RC_GET_BIT(probLit
, symbol
)
350 previousByte
= (Byte
)symbol
;
352 outStream
[nowPos
++] = previousByte
;
353 #ifdef _LZMA_OUT_READ
354 if (distanceLimit
< dictionarySize
)
357 dictionary
[dictionaryPos
] = previousByte
;
358 if (++dictionaryPos
== dictionarySize
)
361 if (state
< 4) state
= 0;
362 else if (state
< 10) state
-= 3;
368 prob
= p
+ IsRep
+ state
;
375 state
= state
< kNumLitStates
? 0 : 3;
381 prob
= p
+ IsRepG0
+ state
;
385 prob
= p
+ IsRep0Long
+ (state
<< kNumPosBitsMax
) + posState
;
388 #ifdef _LZMA_OUT_READ
393 #ifdef _LZMA_OUT_READ
394 if (distanceLimit
== 0)
399 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
400 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
402 return LZMA_RESULT_DATA_ERROR
;
405 state
= state
< kNumLitStates
? 9 : 11;
406 #ifdef _LZMA_OUT_READ
407 pos
= dictionaryPos
- rep0
;
408 if (pos
>= dictionarySize
)
409 pos
+= dictionarySize
;
410 previousByte
= dictionary
[pos
];
411 dictionary
[dictionaryPos
] = previousByte
;
412 if (++dictionaryPos
== dictionarySize
)
415 previousByte
= outStream
[nowPos
- rep0
];
417 outStream
[nowPos
++] = previousByte
;
418 #ifdef _LZMA_OUT_READ
419 if (distanceLimit
< dictionarySize
)
434 prob
= p
+ IsRepG1
+ state
;
443 prob
= p
+ IsRepG2
+ state
;
460 state
= state
< kNumLitStates
? 8 : 11;
461 prob
= p
+ RepLenCoder
;
465 CProb
*probLen
= prob
+ LenChoice
;
469 probLen
= prob
+ LenLow
+ (posState
<< kLenNumLowBits
);
471 numBits
= kLenNumLowBits
;
476 probLen
= prob
+ LenChoice2
;
480 probLen
= prob
+ LenMid
+ (posState
<< kLenNumMidBits
);
481 offset
= kLenNumLowSymbols
;
482 numBits
= kLenNumMidBits
;
487 probLen
= prob
+ LenHigh
;
488 offset
= kLenNumLowSymbols
+ kLenNumMidSymbols
;
489 numBits
= kLenNumHighBits
;
492 RangeDecoderBitTreeDecode(probLen
, numBits
, len
);
499 state
+= kNumLitStates
;
501 ((len
< kNumLenToPosStates
? len
: kNumLenToPosStates
- 1) <<
503 RangeDecoderBitTreeDecode(prob
, kNumPosSlotBits
, posSlot
);
504 if (posSlot
>= kStartPosModelIndex
)
506 int numDirectBits
= ((posSlot
>> 1) - 1);
507 rep0
= (2 | ((UInt32
)posSlot
& 1));
508 if (posSlot
< kEndPosModelIndex
)
510 rep0
<<= numDirectBits
;
511 prob
= p
+ SpecPos
+ rep0
- posSlot
- 1;
515 numDirectBits
-= kNumAlignBits
;
527 while (--numDirectBits
!= 0);
529 rep0
<<= kNumAlignBits
;
530 numDirectBits
= kNumAlignBits
;
537 CProb
*prob3
= prob
+ mi
;
538 RC_GET_BIT2(prob3
, mi
, ; , rep0
|= i
);
541 while(--numDirectBits
!= 0);
546 if (++rep0
== (UInt32
)(0))
548 /* it's for stream version */
549 len
= kLzmaStreamWasFinishedId
;
555 #ifdef _LZMA_OUT_READ
556 if (rep0
> distanceLimit
)
561 #if defined(DEBUG_ENABLE_BOOTSTRAP_PRINTF) || !defined(CFG_BOOTSTRAP_CODE)
562 printf("ERROR: %s, %d\n", __FILE__
, __LINE__
);
564 return LZMA_RESULT_DATA_ERROR
;
567 #ifdef _LZMA_OUT_READ
568 if (dictionarySize
- distanceLimit
> (UInt32
)len
)
569 distanceLimit
+= len
;
571 distanceLimit
= dictionarySize
;
576 #ifdef _LZMA_OUT_READ
577 UInt32 pos
= dictionaryPos
- rep0
;
578 if (pos
>= dictionarySize
)
579 pos
+= dictionarySize
;
580 previousByte
= dictionary
[pos
];
581 dictionary
[dictionaryPos
] = previousByte
;
582 if (++dictionaryPos
== dictionarySize
)
585 previousByte
= outStream
[nowPos
- rep0
];
588 outStream
[nowPos
++] = previousByte
;
590 while(len
!= 0 && nowPos
< outSize
);
595 #ifdef _LZMA_OUT_READ
598 vs
->DictionaryPos
= dictionaryPos
;
599 vs
->GlobalPos
= globalPos
+ (UInt32
)nowPos
;
600 vs
->DistanceLimit
= distanceLimit
;
607 vs
->TempDictionary
[0] = tempDictionary
[0];
612 vs
->BufferLim
= BufferLim
;
614 *inSizeProcessed
= (SizeT
)(Buffer
- inStream
);
616 *outSizeProcessed
= nowPos
;
617 return LZMA_RESULT_OK
;
620 #endif /* CONFIG_LZMA */
This page took 0.08755 seconds and 5 git commands to generate.