misc/libphysfs/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp
changeset 13881 99b265e0d1d0
parent 13880 5f819b90d479
child 13882 b172a5d40eee
equal deleted inserted replaced
13880:5f819b90d479 13881:99b265e0d1d0
     1 // LZMADecoder.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "LZMADecoder.h"
       
     6 #include "../../../Common/Defs.h"
       
     7 
       
     8 namespace NCompress {
       
     9 namespace NLZMA {
       
    10 
       
    11 const int kLenIdFinished = -1;
       
    12 const int kLenIdNeedInit = -2;
       
    13 
       
    14 void CDecoder::Init()
       
    15 {
       
    16   { 
       
    17     for(int i = 0; i < kNumStates; i++)
       
    18     {
       
    19       for (UInt32 j = 0; j <= _posStateMask; j++)
       
    20       {
       
    21         _isMatch[i][j].Init();
       
    22         _isRep0Long[i][j].Init();
       
    23       }
       
    24       _isRep[i].Init();
       
    25       _isRepG0[i].Init();
       
    26       _isRepG1[i].Init();
       
    27       _isRepG2[i].Init();
       
    28     }
       
    29   }
       
    30   { 
       
    31     for (UInt32 i = 0; i < kNumLenToPosStates; i++)
       
    32     _posSlotDecoder[i].Init();
       
    33   }
       
    34   { 
       
    35     for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
       
    36       _posDecoders[i].Init();
       
    37   }
       
    38   _posAlignDecoder.Init();
       
    39   _lenDecoder.Init(_posStateMask + 1);
       
    40   _repMatchLenDecoder.Init(_posStateMask + 1);
       
    41   _literalDecoder.Init();
       
    42 
       
    43   _state.Init();
       
    44   _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0;
       
    45 }
       
    46 
       
    47 HRESULT CDecoder::CodeSpec(UInt32 curSize)
       
    48 {
       
    49   if (_outSizeDefined)
       
    50   {
       
    51     const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize();
       
    52     if (curSize > rem)
       
    53       curSize = (UInt32)rem;
       
    54   }
       
    55 
       
    56   if (_remainLen == kLenIdFinished)
       
    57     return S_OK;
       
    58   if (_remainLen == kLenIdNeedInit)
       
    59   {
       
    60     _rangeDecoder.Init();
       
    61     Init();
       
    62     _remainLen = 0;
       
    63   }
       
    64   if (curSize == 0)
       
    65     return S_OK;
       
    66 
       
    67   UInt32 rep0 = _reps[0];
       
    68   UInt32 rep1 = _reps[1];
       
    69   UInt32 rep2 = _reps[2];
       
    70   UInt32 rep3 = _reps[3];
       
    71   CState state = _state;
       
    72   Byte previousByte;
       
    73 
       
    74   while(_remainLen > 0 && curSize > 0)
       
    75   {
       
    76     previousByte = _outWindowStream.GetByte(rep0);
       
    77     _outWindowStream.PutByte(previousByte);
       
    78     _remainLen--;
       
    79     curSize--;
       
    80   }
       
    81   UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
       
    82   if (nowPos64 == 0)
       
    83     previousByte = 0;
       
    84   else
       
    85     previousByte = _outWindowStream.GetByte(0);
       
    86 
       
    87   while(curSize > 0)
       
    88   {
       
    89     {
       
    90       #ifdef _NO_EXCEPTIONS
       
    91       if (_rangeDecoder.Stream.ErrorCode != S_OK)
       
    92         return _rangeDecoder.Stream.ErrorCode;
       
    93       #endif
       
    94       if (_rangeDecoder.Stream.WasFinished())
       
    95         return S_FALSE;
       
    96       UInt32 posState = UInt32(nowPos64) & _posStateMask;
       
    97       if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0)
       
    98       {
       
    99         if(!state.IsCharState())
       
   100           previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, 
       
   101               (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0));
       
   102         else
       
   103           previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, 
       
   104               (UInt32)nowPos64, previousByte);
       
   105         _outWindowStream.PutByte(previousByte);
       
   106         state.UpdateChar();
       
   107         curSize--;
       
   108         nowPos64++;
       
   109       }
       
   110       else             
       
   111       {
       
   112         UInt32 len;
       
   113         if(_isRep[state.Index].Decode(&_rangeDecoder) == 1)
       
   114         {
       
   115           len = 0;
       
   116           if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0)
       
   117           {
       
   118             if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0)
       
   119             {
       
   120               state.UpdateShortRep();
       
   121               len = 1;
       
   122             }
       
   123           }
       
   124           else
       
   125           {
       
   126             UInt32 distance;
       
   127             if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0)
       
   128               distance = rep1;
       
   129             else 
       
   130             {
       
   131               if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0)
       
   132                 distance = rep2;
       
   133               else
       
   134               {
       
   135                 distance = rep3;
       
   136                 rep3 = rep2;
       
   137               }
       
   138               rep2 = rep1;
       
   139             }
       
   140             rep1 = rep0;
       
   141             rep0 = distance;
       
   142           }
       
   143           if (len == 0)
       
   144           {
       
   145             len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
       
   146             state.UpdateRep();
       
   147           }
       
   148         }
       
   149         else
       
   150         {
       
   151           rep3 = rep2;
       
   152           rep2 = rep1;
       
   153           rep1 = rep0;
       
   154           len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
       
   155           state.UpdateMatch();
       
   156           UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
       
   157           if (posSlot >= kStartPosModelIndex)
       
   158           {
       
   159             UInt32 numDirectBits = (posSlot >> 1) - 1;
       
   160             rep0 = ((2 | (posSlot & 1)) << numDirectBits);
       
   161 
       
   162             if (posSlot < kEndPosModelIndex)
       
   163               rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + 
       
   164                   rep0 - posSlot - 1, &_rangeDecoder, numDirectBits);
       
   165             else
       
   166             {
       
   167               rep0 += (_rangeDecoder.DecodeDirectBits(
       
   168                   numDirectBits - kNumAlignBits) << kNumAlignBits);
       
   169               rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder);
       
   170               if (rep0 == 0xFFFFFFFF)
       
   171               {
       
   172                 _remainLen = kLenIdFinished;
       
   173                 return S_OK;
       
   174               }
       
   175             }
       
   176           }
       
   177           else
       
   178             rep0 = posSlot;
       
   179         }
       
   180         UInt32 locLen = len;
       
   181         if (len > curSize)
       
   182           locLen = (UInt32)curSize;
       
   183         if (!_outWindowStream.CopyBlock(rep0, locLen))
       
   184           return S_FALSE;
       
   185         previousByte = _outWindowStream.GetByte(0);
       
   186         curSize -= locLen;
       
   187         nowPos64 += locLen;
       
   188         len -= locLen;
       
   189         if (len != 0)
       
   190         {
       
   191           _remainLen = (Int32)len;
       
   192           break;
       
   193         }
       
   194 
       
   195         #ifdef _NO_EXCEPTIONS
       
   196         if (_outWindowStream.ErrorCode != S_OK)
       
   197           return _outWindowStream.ErrorCode;
       
   198         #endif
       
   199       }
       
   200     }
       
   201   }
       
   202   if (_rangeDecoder.Stream.WasFinished())
       
   203     return S_FALSE;
       
   204   _reps[0] = rep0;
       
   205   _reps[1] = rep1;
       
   206   _reps[2] = rep2;
       
   207   _reps[3] = rep3;
       
   208   _state = state;
       
   209 
       
   210   return S_OK;
       
   211 }
       
   212 
       
   213 STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
       
   214     ISequentialOutStream *outStream, 
       
   215     const UInt64 *, const UInt64 *outSize,
       
   216     ICompressProgressInfo *progress)
       
   217 {
       
   218   SetInStream(inStream);
       
   219   _outWindowStream.SetStream(outStream);
       
   220   SetOutStreamSize(outSize);
       
   221   CDecoderFlusher flusher(this);
       
   222 
       
   223   for (;;)
       
   224   {
       
   225     UInt32 curSize = 1 << 18;
       
   226     RINOK(CodeSpec(curSize));
       
   227     if (_remainLen == kLenIdFinished)
       
   228       break;
       
   229     if (progress != NULL)
       
   230     {
       
   231       UInt64 inSize = _rangeDecoder.GetProcessedSize();
       
   232       UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
       
   233       RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
       
   234     }
       
   235     if (_outSizeDefined)
       
   236       if (_outWindowStream.GetProcessedSize() >= _outSize)
       
   237         break;
       
   238   } 
       
   239   flusher.NeedFlush = false;
       
   240   return Flush();
       
   241 }
       
   242 
       
   243 
       
   244 #ifdef _NO_EXCEPTIONS
       
   245 
       
   246 #define LZMA_TRY_BEGIN
       
   247 #define LZMA_TRY_END
       
   248 
       
   249 #else
       
   250 
       
   251 #define LZMA_TRY_BEGIN try { 
       
   252 #define LZMA_TRY_END } \
       
   253   catch(const CInBufferException &e)  { return e.ErrorCode; } \
       
   254   catch(const CLZOutWindowException &e)  { return e.ErrorCode; } \
       
   255   catch(...) { return S_FALSE; }
       
   256 
       
   257 #endif
       
   258 
       
   259 
       
   260 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
       
   261       ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
       
   262       ICompressProgressInfo *progress)
       
   263 {
       
   264   LZMA_TRY_BEGIN
       
   265   return CodeReal(inStream, outStream, inSize, outSize, progress); 
       
   266   LZMA_TRY_END
       
   267 }
       
   268 
       
   269 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
       
   270 {
       
   271   if (size < 5)
       
   272     return E_INVALIDARG;
       
   273   int lc = properties[0] % 9;
       
   274   Byte remainder = (Byte)(properties[0] / 9);
       
   275   int lp = remainder % 5;
       
   276   int pb = remainder / 5;
       
   277   if (pb > NLength::kNumPosStatesBitsMax)
       
   278     return E_INVALIDARG;
       
   279   _posStateMask = (1 << pb) - 1;
       
   280   UInt32 dictionarySize = 0;
       
   281   for (int i = 0; i < 4; i++)
       
   282     dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
       
   283   if (!_outWindowStream.Create(dictionarySize))
       
   284     return E_OUTOFMEMORY;
       
   285   if (!_literalDecoder.Create(lp, lc))
       
   286     return E_OUTOFMEMORY;
       
   287   if (!_rangeDecoder.Create(1 << 20))
       
   288     return E_OUTOFMEMORY;
       
   289   return S_OK;
       
   290 }
       
   291 
       
   292 STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
       
   293 {
       
   294   *value = _rangeDecoder.GetProcessedSize();
       
   295   return S_OK;
       
   296 }
       
   297 
       
   298 STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
       
   299 {
       
   300   _rangeDecoder.SetStream(inStream);
       
   301   return S_OK;
       
   302 }
       
   303 
       
   304 STDMETHODIMP CDecoder::ReleaseInStream()
       
   305 {
       
   306   _rangeDecoder.ReleaseStream();
       
   307   return S_OK;
       
   308 }
       
   309 
       
   310 STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
       
   311 {
       
   312   _outSizeDefined = (outSize != NULL);
       
   313   if (_outSizeDefined)
       
   314     _outSize = *outSize;
       
   315   _remainLen = kLenIdNeedInit;
       
   316   _outWindowStream.Init();
       
   317   return S_OK;
       
   318 }
       
   319 
       
   320 #ifndef NO_READ_FROM_CODER
       
   321 
       
   322 STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
       
   323 {
       
   324   LZMA_TRY_BEGIN
       
   325   if (processedSize)
       
   326     *processedSize = 0;
       
   327   const UInt64 startPos = _outWindowStream.GetProcessedSize();
       
   328   _outWindowStream.SetMemStream((Byte *)data);
       
   329   RINOK(CodeSpec(size));
       
   330   if (processedSize)
       
   331     *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos);
       
   332   return Flush();
       
   333   LZMA_TRY_END
       
   334 }
       
   335 
       
   336 #endif
       
   337 
       
   338 }}