blob: fb57f4fd4dd7cf160bde30578d033f053388b787 [file] [log] [blame]
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +00001/*
2 LzmaDecode.c
3 LZMA Decoder (optimized for Speed version)
Stefan Reinauer14e22772010-04-27 06:56:47 +00004
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +00005 LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
6 http://www.7-zip.org/
7
8 LZMA SDK is licensed under two licenses:
9 1) GNU Lesser General Public License (GNU LGPL)
10 2) Common Public License (CPL)
Stefan Reinauer14e22772010-04-27 06:56:47 +000011 It means that you can select one of these two licenses and
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000012 follow rules of that license.
13
14 SPECIAL EXCEPTION:
Stefan Reinauer14e22772010-04-27 06:56:47 +000015 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
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000019 to this file, however, are subject to the LGPL or CPL terms.
20*/
21
22#include "lzmadecode.h"
23
24#define kNumTopBits 24
25#define kTopValue ((UInt32)1 << kNumTopBits)
26
27#define kNumBitModelTotalBits 11
28#define kBitModelTotal (1 << kNumBitModelTotalBits)
29#define kNumMoveBits 5
30
Vladimir Serbinenko3d6ffe72014-02-05 17:00:40 +010031/* Use 32-bit reads whenever possible to avoid bad flash performance. */
32#define RC_READ_BYTE (look_ahead_ptr < 4 ? look_ahead.raw[look_ahead_ptr++] \
33 : ((((UInt32) Buffer & 3) || ((SizeT) (BufferLim - Buffer) < 4)) ? (*Buffer++) \
34 : ((look_ahead.dw = *(UInt32 *)Buffer), (Buffer += 4), (look_ahead_ptr = 1), look_ahead.raw[0])))
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000035
36#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
37 { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
38
39
40#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
41
42#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
Stefan Reinauer14e22772010-04-27 06:56:47 +000043
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000044
45#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
46
47#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
48#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
49#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
50
51#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
52 { UpdateBit0(p); mi <<= 1; A0; } else \
Stefan Reinauer14e22772010-04-27 06:56:47 +000053 { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
54
55#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000056
57#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
58 { int i = numLevels; res = 1; \
Stefan Reinauer6e244da2009-04-04 13:28:40 +000059 do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000060 res -= (1 << numLevels); }
61
62
63#define kNumPosBitsMax 4
64#define kNumPosStatesMax (1 << kNumPosBitsMax)
65
66#define kLenNumLowBits 3
67#define kLenNumLowSymbols (1 << kLenNumLowBits)
68#define kLenNumMidBits 3
69#define kLenNumMidSymbols (1 << kLenNumMidBits)
70#define kLenNumHighBits 8
71#define kLenNumHighSymbols (1 << kLenNumHighBits)
72
73#define LenChoice 0
74#define LenChoice2 (LenChoice + 1)
75#define LenLow (LenChoice2 + 1)
76#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
77#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
Stefan Reinauer14e22772010-04-27 06:56:47 +000078#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +000079
80
81#define kNumStates 12
82#define kNumLitStates 7
83
84#define kStartPosModelIndex 4
85#define kEndPosModelIndex 14
86#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
87
88#define kNumPosSlotBits 6
89#define kNumLenToPosStates 4
90
91#define kNumAlignBits 4
92#define kAlignTableSize (1 << kNumAlignBits)
93
94#define kMatchMinLen 2
95
96#define IsMatch 0
97#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
98#define IsRepG0 (IsRep + kNumStates)
99#define IsRepG1 (IsRepG0 + kNumStates)
100#define IsRepG2 (IsRepG1 + kNumStates)
101#define IsRep0Long (IsRepG2 + kNumStates)
102#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
103#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
104#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
105#define LenCoder (Align + kAlignTableSize)
106#define RepLenCoder (LenCoder + kNumLenProbs)
107#define Literal (RepLenCoder + kNumLenProbs)
108
109#if Literal != LZMA_BASE_SIZE
110StopCompilingDueBUG
111#endif
112
113int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
114{
115 unsigned char prop0;
116 if (size < LZMA_PROPERTIES_SIZE)
117 return LZMA_RESULT_DATA_ERROR;
118 prop0 = propsData[0];
119 if (prop0 >= (9 * 5 * 5))
120 return LZMA_RESULT_DATA_ERROR;
121 {
122 for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
123 for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
124 propsRes->lc = prop0;
125 /*
126 unsigned char remainder = (unsigned char)(prop0 / 9);
127 propsRes->lc = prop0 % 9;
128 propsRes->pb = remainder / 5;
129 propsRes->lp = remainder % 5;
130 */
131 }
132
133 return LZMA_RESULT_OK;
134}
135
136#define kLzmaStreamWasFinishedId (-1)
137
138int LzmaDecode(CLzmaDecoderState *vs,
139 const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
140 unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
141{
142 CProb *p = vs->Probs;
143 SizeT nowPos = 0;
144 Byte previousByte = 0;
145 UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
146 UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
147 int lc = vs->Properties.lc;
148
149
150 int state = 0;
151 UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
152 int len = 0;
153 const Byte *Buffer;
154 const Byte *BufferLim;
Vladimir Serbinenko3d6ffe72014-02-05 17:00:40 +0100155 int look_ahead_ptr = 4;
156 union
157 {
158 Byte raw[4];
159 UInt32 dw;
160 } look_ahead;
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000161 UInt32 Range;
162 UInt32 Code;
163
164 *inSizeProcessed = 0;
165 *outSizeProcessed = 0;
166
167 {
168 UInt32 i;
169 UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
170 for (i = 0; i < numProbs; i++)
171 p[i] = kBitModelTotal >> 1;
172 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000173
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000174 RC_INIT(inStream, inSize);
175
176
177 while(nowPos < outSize)
178 {
179 CProb *prob;
180 UInt32 bound;
181 int posState = (int)(
Stefan Reinauer14e22772010-04-27 06:56:47 +0000182 (nowPos
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000183 )
184 & posStateMask);
185
186 prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
187 IfBit0(prob)
188 {
189 int symbol = 1;
190 UpdateBit0(prob)
Stefan Reinauer14e22772010-04-27 06:56:47 +0000191 prob = p + Literal + (LZMA_LIT_SIZE *
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000192 (((
Stefan Reinauer14e22772010-04-27 06:56:47 +0000193 (nowPos
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000194 )
195 & literalPosMask) << lc) + (previousByte >> (8 - lc))));
196
197 if (state >= kNumLitStates)
198 {
199 int matchByte;
200 matchByte = outStream[nowPos - rep0];
201 do
202 {
203 int bit;
204 CProb *probLit;
205 matchByte <<= 1;
206 bit = (matchByte & 0x100);
207 probLit = prob + 0x100 + bit + symbol;
208 RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
209 }
210 while (symbol < 0x100);
211 }
212 while (symbol < 0x100)
213 {
214 CProb *probLit = prob + symbol;
215 RC_GET_BIT(probLit, symbol)
216 }
217 previousByte = (Byte)symbol;
218
219 outStream[nowPos++] = previousByte;
220 if (state < 4) state = 0;
221 else if (state < 10) state -= 3;
222 else state -= 6;
223 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000224 else
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000225 {
226 UpdateBit1(prob);
227 prob = p + IsRep + state;
228 IfBit0(prob)
229 {
230 UpdateBit0(prob);
231 rep3 = rep2;
232 rep2 = rep1;
233 rep1 = rep0;
234 state = state < kNumLitStates ? 0 : 3;
235 prob = p + LenCoder;
236 }
237 else
238 {
239 UpdateBit1(prob);
240 prob = p + IsRepG0 + state;
241 IfBit0(prob)
242 {
243 UpdateBit0(prob);
244 prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
245 IfBit0(prob)
246 {
247 UpdateBit0(prob);
Stefan Reinauer14e22772010-04-27 06:56:47 +0000248
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000249 if (nowPos == 0)
250 return LZMA_RESULT_DATA_ERROR;
Stefan Reinauer14e22772010-04-27 06:56:47 +0000251
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000252 state = state < kNumLitStates ? 9 : 11;
253 previousByte = outStream[nowPos - rep0];
254 outStream[nowPos++] = previousByte;
255
256 continue;
257 }
258 else
259 {
260 UpdateBit1(prob);
261 }
262 }
263 else
264 {
265 UInt32 distance;
266 UpdateBit1(prob);
267 prob = p + IsRepG1 + state;
268 IfBit0(prob)
269 {
270 UpdateBit0(prob);
271 distance = rep1;
272 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000273 else
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000274 {
275 UpdateBit1(prob);
276 prob = p + IsRepG2 + state;
277 IfBit0(prob)
278 {
279 UpdateBit0(prob);
280 distance = rep2;
281 }
282 else
283 {
284 UpdateBit1(prob);
285 distance = rep3;
286 rep3 = rep2;
287 }
288 rep2 = rep1;
289 }
290 rep1 = rep0;
291 rep0 = distance;
292 }
293 state = state < kNumLitStates ? 8 : 11;
294 prob = p + RepLenCoder;
295 }
296 {
297 int numBits, offset;
298 CProb *probLen = prob + LenChoice;
299 IfBit0(probLen)
300 {
301 UpdateBit0(probLen);
302 probLen = prob + LenLow + (posState << kLenNumLowBits);
303 offset = 0;
304 numBits = kLenNumLowBits;
305 }
306 else
307 {
308 UpdateBit1(probLen);
309 probLen = prob + LenChoice2;
310 IfBit0(probLen)
311 {
312 UpdateBit0(probLen);
313 probLen = prob + LenMid + (posState << kLenNumMidBits);
314 offset = kLenNumLowSymbols;
315 numBits = kLenNumMidBits;
316 }
317 else
318 {
319 UpdateBit1(probLen);
320 probLen = prob + LenHigh;
321 offset = kLenNumLowSymbols + kLenNumMidSymbols;
322 numBits = kLenNumHighBits;
323 }
324 }
325 RangeDecoderBitTreeDecode(probLen, numBits, len);
326 len += offset;
327 }
328
329 if (state < 4)
330 {
331 int posSlot;
332 state += kNumLitStates;
333 prob = p + PosSlot +
Stefan Reinauer14e22772010-04-27 06:56:47 +0000334 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
Carl-Daniel Hailfingercba07dd2006-09-14 15:12:36 +0000335 kNumPosSlotBits);
336 RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
337 if (posSlot >= kStartPosModelIndex)
338 {
339 int numDirectBits = ((posSlot >> 1) - 1);
340 rep0 = (2 | ((UInt32)posSlot & 1));
341 if (posSlot < kEndPosModelIndex)
342 {
343 rep0 <<= numDirectBits;
344 prob = p + SpecPos + rep0 - posSlot - 1;
345 }
346 else
347 {
348 numDirectBits -= kNumAlignBits;
349 do
350 {
351 RC_NORMALIZE
352 Range >>= 1;
353 rep0 <<= 1;
354 if (Code >= Range)
355 {
356 Code -= Range;
357 rep0 |= 1;
358 }
359 }
360 while (--numDirectBits != 0);
361 prob = p + Align;
362 rep0 <<= kNumAlignBits;
363 numDirectBits = kNumAlignBits;
364 }
365 {
366 int i = 1;
367 int mi = 1;
368 do
369 {
370 CProb *prob3 = prob + mi;
371 RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
372 i <<= 1;
373 }
374 while(--numDirectBits != 0);
375 }
376 }
377 else
378 rep0 = posSlot;
379 if (++rep0 == (UInt32)(0))
380 {
381 /* it's for stream version */
382 len = kLzmaStreamWasFinishedId;
383 break;
384 }
385 }
386
387 len += kMatchMinLen;
388 if (rep0 > nowPos)
389 return LZMA_RESULT_DATA_ERROR;
390
391
392 do
393 {
394 previousByte = outStream[nowPos - rep0];
395 len--;
396 outStream[nowPos++] = previousByte;
397 }
398 while(len != 0 && nowPos < outSize);
399 }
400 }
401 RC_NORMALIZE;
402
403
404 *inSizeProcessed = (SizeT)(Buffer - inStream);
405 *outSizeProcessed = nowPos;
406 return LZMA_RESULT_OK;
407}