Subversion Repositories spk

Rev

Details | Last modification | View Log | RSS feed

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