99d1117701a0c03354a3238d06459adadccc91e9
[openwrt.git] / target / linux / ifxmips / image / u-boot / files / lib_generic / LzmaDecode.c
1 /*
2   LzmaDecode.c
3   LZMA Decoder (optimized for Speed version)
4   
5   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)
11   It means that you can select one of these two licenses and 
12   follow rules of that license.
13
14   SPECIAL EXCEPTION:
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.
20 */
21
22 #ifdef CONFIG_LZMA
23
24 #include "LzmaDecode.h"
25
26 #define kNumTopBits 24
27 #define kTopValue ((UInt32)1 << kNumTopBits)
28
29 #define kNumBitModelTotalBits 11
30 #define kBitModelTotal (1 << kNumBitModelTotalBits)
31 #define kNumMoveBits 5
32
33 #define RC_READ_BYTE (*Buffer++)
34
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; }}
37
38 #ifdef _LZMA_IN_CB
39
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; } }}
43
44 #define RC_INIT Buffer = BufferLim = 0; RC_INIT2
45
46 #else
47
48 #define RC_TEST { if (Buffer == BufferLim) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }
49
50 #define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
51  
52 #endif
53
54 #define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
55
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;
59
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; } 
63   
64 #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               
65
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); }
70
71
72 #define kNumPosBitsMax 4
73 #define kNumPosStatesMax (1 << kNumPosBitsMax)
74
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)
81
82 #define LenChoice 0
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) 
88
89
90 #define kNumStates 12
91 #define kNumLitStates 7
92
93 #define kStartPosModelIndex 4
94 #define kEndPosModelIndex 14
95 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
96
97 #define kNumPosSlotBits 6
98 #define kNumLenToPosStates 4
99
100 #define kNumAlignBits 4
101 #define kAlignTableSize (1 << kNumAlignBits)
102
103 #define kMatchMinLen 2
104
105 #define IsMatch 0
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)
117
118 #if Literal != LZMA_BASE_SIZE
119 StopCompilingDueBUG
120 #endif
121
122 int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
123 {
124   unsigned char prop0;
125   if (size < LZMA_PROPERTIES_SIZE)
126   {
127     printf("ERROR: %s, %d\n", __FILE__, __LINE__);
128     return LZMA_RESULT_DATA_ERROR;
129   }
130   prop0 = propsData[0];
131   if (prop0 >= (9 * 5 * 5))
132   {
133     printf("ERROR: %s, %d\n", __FILE__, __LINE__);
134     return LZMA_RESULT_DATA_ERROR;
135   }
136   {
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;
140     /*
141     unsigned char remainder = (unsigned char)(prop0 / 9);
142     propsRes->lc = prop0 % 9;
143     propsRes->pb = remainder / 5;
144     propsRes->lp = remainder % 5;
145     */
146   }
147
148   #ifdef _LZMA_OUT_READ
149   {
150     int i;
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;
156   }
157   #endif
158   return LZMA_RESULT_OK;
159 }
160
161 #define kLzmaStreamWasFinishedId (-1)
162
163 int LzmaDecode(CLzmaDecoderState *vs,
164     #ifdef _LZMA_IN_CB
165     ILzmaInCallback *InCallback,
166     #else
167     const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
168     #endif
169     unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
170 {
171   CProb *p = vs->Probs;
172   SizeT nowPos = 0;
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;
177
178   #ifdef _LZMA_OUT_READ
179   
180   UInt32 Range = vs->Range;
181   UInt32 Code = vs->Code;
182   #ifdef _LZMA_IN_CB
183   const Byte *Buffer = vs->Buffer;
184   const Byte *BufferLim = vs->BufferLim;
185   #else
186   const Byte *Buffer = inStream;
187   const Byte *BufferLim = inStream + inSize;
188   #endif
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;
194
195   Byte *dictionary = vs->Dictionary;
196   UInt32 dictionarySize = vs->Properties.DictionarySize;
197   UInt32 dictionaryPos = vs->DictionaryPos;
198
199   Byte tempDictionary[4];
200
201   #ifndef _LZMA_IN_CB
202   *inSizeProcessed = 0;
203   #endif
204   *outSizeProcessed = 0;
205   if (len == kLzmaStreamWasFinishedId)
206     return LZMA_RESULT_OK;
207
208   if (dictionarySize == 0)
209   {
210     dictionary = tempDictionary;
211     dictionarySize = 1;
212     tempDictionary[0] = vs->TempDictionary[0];
213   }
214
215   if (len == kLzmaNeedInitId)
216   {
217     {
218       UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
219       UInt32 i;
220       for (i = 0; i < numProbs; i++)
221         p[i] = kBitModelTotal >> 1; 
222       rep0 = rep1 = rep2 = rep3 = 1;
223       state = 0;
224       globalPos = 0;
225       distanceLimit = 0;
226       dictionaryPos = 0;
227       dictionary[dictionarySize - 1] = 0;
228       #ifdef _LZMA_IN_CB
229       RC_INIT;
230       #else
231       RC_INIT(inStream, inSize);
232       #endif
233     }
234     len = 0;
235   }
236   while(len != 0 && nowPos < outSize)
237   {
238     UInt32 pos = dictionaryPos - rep0;
239     if (pos >= dictionarySize)
240       pos += dictionarySize;
241     outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
242     if (++dictionaryPos == dictionarySize)
243       dictionaryPos = 0;
244     len--;
245   }
246   if (dictionaryPos == 0)
247     previousByte = dictionary[dictionarySize - 1];
248   else
249     previousByte = dictionary[dictionaryPos - 1];
250
251   #else /* if !_LZMA_OUT_READ */
252
253   int state = 0;
254   UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
255   int len = 0;
256   const Byte *Buffer;
257   const Byte *BufferLim;
258   UInt32 Range;
259   UInt32 Code;
260
261   #ifndef _LZMA_IN_CB
262   *inSizeProcessed = 0;
263   #endif
264   *outSizeProcessed = 0;
265
266   {
267     UInt32 i;
268     UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
269     for (i = 0; i < numProbs; i++)
270       p[i] = kBitModelTotal >> 1;
271   }
272   
273   #ifdef _LZMA_IN_CB
274   RC_INIT;
275   #else
276   RC_INIT(inStream, inSize);
277   #endif
278
279   #endif /* _LZMA_OUT_READ */
280
281   while(nowPos < outSize)
282   {
283     CProb *prob;
284     UInt32 bound;
285     int posState = (int)(
286         (nowPos 
287         #ifdef _LZMA_OUT_READ
288         + globalPos
289         #endif
290         )
291         & posStateMask);
292
293     prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
294     IfBit0(prob)
295     {
296       int symbol = 1;
297       UpdateBit0(prob)
298       prob = p + Literal + (LZMA_LIT_SIZE * 
299         (((
300         (nowPos 
301         #ifdef _LZMA_OUT_READ
302         + globalPos
303         #endif
304         )
305         & literalPosMask) << lc) + (previousByte >> (8 - lc))));
306
307       if (state >= kNumLitStates)
308       {
309         int matchByte;
310         #ifdef _LZMA_OUT_READ
311         UInt32 pos = dictionaryPos - rep0;
312         if (pos >= dictionarySize)
313           pos += dictionarySize;
314         matchByte = dictionary[pos];
315         #else
316         matchByte = outStream[nowPos - rep0];
317         #endif
318         do
319         {
320           int bit;
321           CProb *probLit;
322           matchByte <<= 1;
323           bit = (matchByte & 0x100);
324           probLit = prob + 0x100 + bit + symbol;
325           RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
326         }
327         while (symbol < 0x100);
328       }
329       while (symbol < 0x100)
330       {
331         CProb *probLit = prob + symbol;
332         RC_GET_BIT(probLit, symbol)
333       }
334       previousByte = (Byte)symbol;
335
336       outStream[nowPos++] = previousByte;
337       #ifdef _LZMA_OUT_READ
338       if (distanceLimit < dictionarySize)
339         distanceLimit++;
340
341       dictionary[dictionaryPos] = previousByte;
342       if (++dictionaryPos == dictionarySize)
343         dictionaryPos = 0;
344       #endif
345       if (state < 4) state = 0;
346       else if (state < 10) state -= 3;
347       else state -= 6;
348     }
349     else             
350     {
351       UpdateBit1(prob);
352       prob = p + IsRep + state;
353       IfBit0(prob)
354       {
355         UpdateBit0(prob);
356         rep3 = rep2;
357         rep2 = rep1;
358         rep1 = rep0;
359         state = state < kNumLitStates ? 0 : 3;
360         prob = p + LenCoder;
361       }
362       else
363       {
364         UpdateBit1(prob);
365         prob = p + IsRepG0 + state;
366         IfBit0(prob)
367         {
368           UpdateBit0(prob);
369           prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
370           IfBit0(prob)
371           {
372             #ifdef _LZMA_OUT_READ
373             UInt32 pos;
374             #endif
375             UpdateBit0(prob);
376             
377             #ifdef _LZMA_OUT_READ
378             if (distanceLimit == 0)
379             #else
380             if (nowPos == 0)
381             #endif
382             {
383               printf("ERROR: %s, %d\n", __FILE__, __LINE__);
384               return LZMA_RESULT_DATA_ERROR;
385             }
386             
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)
395               dictionaryPos = 0;
396             #else
397             previousByte = outStream[nowPos - rep0];
398             #endif
399             outStream[nowPos++] = previousByte;
400             #ifdef _LZMA_OUT_READ
401             if (distanceLimit < dictionarySize)
402               distanceLimit++;
403             #endif
404
405             continue;
406           }
407           else
408           {
409             UpdateBit1(prob);
410           }
411         }
412         else
413         {
414           UInt32 distance;
415           UpdateBit1(prob);
416           prob = p + IsRepG1 + state;
417           IfBit0(prob)
418           {
419             UpdateBit0(prob);
420             distance = rep1;
421           }
422           else 
423           {
424             UpdateBit1(prob);
425             prob = p + IsRepG2 + state;
426             IfBit0(prob)
427             {
428               UpdateBit0(prob);
429               distance = rep2;
430             }
431             else
432             {
433               UpdateBit1(prob);
434               distance = rep3;
435               rep3 = rep2;
436             }
437             rep2 = rep1;
438           }
439           rep1 = rep0;
440           rep0 = distance;
441         }
442         state = state < kNumLitStates ? 8 : 11;
443         prob = p + RepLenCoder;
444       }
445       {
446         int numBits, offset;
447         CProb *probLen = prob + LenChoice;
448         IfBit0(probLen)
449         {
450           UpdateBit0(probLen);
451           probLen = prob + LenLow + (posState << kLenNumLowBits);
452           offset = 0;
453           numBits = kLenNumLowBits;
454         }
455         else
456         {
457           UpdateBit1(probLen);
458           probLen = prob + LenChoice2;
459           IfBit0(probLen)
460           {
461             UpdateBit0(probLen);
462             probLen = prob + LenMid + (posState << kLenNumMidBits);
463             offset = kLenNumLowSymbols;
464             numBits = kLenNumMidBits;
465           }
466           else
467           {
468             UpdateBit1(probLen);
469             probLen = prob + LenHigh;
470             offset = kLenNumLowSymbols + kLenNumMidSymbols;
471             numBits = kLenNumHighBits;
472           }
473         }
474         RangeDecoderBitTreeDecode(probLen, numBits, len);
475         len += offset;
476       }
477
478       if (state < 4)
479       {
480         int posSlot;
481         state += kNumLitStates;
482         prob = p + PosSlot +
483             ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
484             kNumPosSlotBits);
485         RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
486         if (posSlot >= kStartPosModelIndex)
487         {
488           int numDirectBits = ((posSlot >> 1) - 1);
489           rep0 = (2 | ((UInt32)posSlot & 1));
490           if (posSlot < kEndPosModelIndex)
491           {
492             rep0 <<= numDirectBits;
493             prob = p + SpecPos + rep0 - posSlot - 1;
494           }
495           else
496           {
497             numDirectBits -= kNumAlignBits;
498             do
499             {
500               RC_NORMALIZE
501               Range >>= 1;
502               rep0 <<= 1;
503               if (Code >= Range)
504               {
505                 Code -= Range;
506                 rep0 |= 1;
507               }
508             }
509             while (--numDirectBits != 0);
510             prob = p + Align;
511             rep0 <<= kNumAlignBits;
512             numDirectBits = kNumAlignBits;
513           }
514           {
515             int i = 1;
516             int mi = 1;
517             do
518             {
519               CProb *prob3 = prob + mi;
520               RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
521               i <<= 1;
522             }
523             while(--numDirectBits != 0);
524           }
525         }
526         else
527           rep0 = posSlot;
528         if (++rep0 == (UInt32)(0))
529         {
530           /* it's for stream version */
531           len = kLzmaStreamWasFinishedId;
532           break;
533         }
534       }
535
536       len += kMatchMinLen;
537       #ifdef _LZMA_OUT_READ
538       if (rep0 > distanceLimit) 
539       #else
540       if (rep0 > nowPos)
541       #endif
542       {
543         printf("ERROR: %s, %d\n", __FILE__, __LINE__);
544         return LZMA_RESULT_DATA_ERROR;
545       }
546
547       #ifdef _LZMA_OUT_READ
548       if (dictionarySize - distanceLimit > (UInt32)len)
549         distanceLimit += len;
550       else
551         distanceLimit = dictionarySize;
552       #endif
553
554       do
555       {
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)
563           dictionaryPos = 0;
564         #else
565         previousByte = outStream[nowPos - rep0];
566         #endif
567         len--;
568         outStream[nowPos++] = previousByte;
569       }
570       while(len != 0 && nowPos < outSize);
571     }
572   }
573   RC_NORMALIZE;
574
575   #ifdef _LZMA_OUT_READ
576   vs->Range = Range;
577   vs->Code = Code;
578   vs->DictionaryPos = dictionaryPos;
579   vs->GlobalPos = globalPos + (UInt32)nowPos;
580   vs->DistanceLimit = distanceLimit;
581   vs->Reps[0] = rep0;
582   vs->Reps[1] = rep1;
583   vs->Reps[2] = rep2;
584   vs->Reps[3] = rep3;
585   vs->State = state;
586   vs->RemainLen = len;
587   vs->TempDictionary[0] = tempDictionary[0];
588   #endif
589
590   #ifdef _LZMA_IN_CB
591   vs->Buffer = Buffer;
592   vs->BufferLim = BufferLim;
593   #else
594   *inSizeProcessed = (SizeT)(Buffer - inStream);
595   #endif
596   *outSizeProcessed = nowPos;
597   return LZMA_RESULT_OK;
598 }
599
600 #endif /* CONFIG_LZMA */