misc/libphysfs/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp
changeset 12213 bb5522e88ab2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Compress/LZMA/LZMADecoder.cpp	Mon Apr 10 12:06:43 2017 -0400
@@ -0,0 +1,338 @@
+// LZMADecoder.cpp
+
+#include "StdAfx.h"
+
+#include "LZMADecoder.h"
+#include "../../../Common/Defs.h"
+
+namespace NCompress {
+namespace NLZMA {
+
+const int kLenIdFinished = -1;
+const int kLenIdNeedInit = -2;
+
+void CDecoder::Init()
+{
+  { 
+    for(int i = 0; i < kNumStates; i++)
+    {
+      for (UInt32 j = 0; j <= _posStateMask; j++)
+      {
+        _isMatch[i][j].Init();
+        _isRep0Long[i][j].Init();
+      }
+      _isRep[i].Init();
+      _isRepG0[i].Init();
+      _isRepG1[i].Init();
+      _isRepG2[i].Init();
+    }
+  }
+  { 
+    for (UInt32 i = 0; i < kNumLenToPosStates; i++)
+    _posSlotDecoder[i].Init();
+  }
+  { 
+    for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
+      _posDecoders[i].Init();
+  }
+  _posAlignDecoder.Init();
+  _lenDecoder.Init(_posStateMask + 1);
+  _repMatchLenDecoder.Init(_posStateMask + 1);
+  _literalDecoder.Init();
+
+  _state.Init();
+  _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0;
+}
+
+HRESULT CDecoder::CodeSpec(UInt32 curSize)
+{
+  if (_outSizeDefined)
+  {
+    const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize();
+    if (curSize > rem)
+      curSize = (UInt32)rem;
+  }
+
+  if (_remainLen == kLenIdFinished)
+    return S_OK;
+  if (_remainLen == kLenIdNeedInit)
+  {
+    _rangeDecoder.Init();
+    Init();
+    _remainLen = 0;
+  }
+  if (curSize == 0)
+    return S_OK;
+
+  UInt32 rep0 = _reps[0];
+  UInt32 rep1 = _reps[1];
+  UInt32 rep2 = _reps[2];
+  UInt32 rep3 = _reps[3];
+  CState state = _state;
+  Byte previousByte;
+
+  while(_remainLen > 0 && curSize > 0)
+  {
+    previousByte = _outWindowStream.GetByte(rep0);
+    _outWindowStream.PutByte(previousByte);
+    _remainLen--;
+    curSize--;
+  }
+  UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+  if (nowPos64 == 0)
+    previousByte = 0;
+  else
+    previousByte = _outWindowStream.GetByte(0);
+
+  while(curSize > 0)
+  {
+    {
+      #ifdef _NO_EXCEPTIONS
+      if (_rangeDecoder.Stream.ErrorCode != S_OK)
+        return _rangeDecoder.Stream.ErrorCode;
+      #endif
+      if (_rangeDecoder.Stream.WasFinished())
+        return S_FALSE;
+      UInt32 posState = UInt32(nowPos64) & _posStateMask;
+      if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0)
+      {
+        if(!state.IsCharState())
+          previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, 
+              (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0));
+        else
+          previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, 
+              (UInt32)nowPos64, previousByte);
+        _outWindowStream.PutByte(previousByte);
+        state.UpdateChar();
+        curSize--;
+        nowPos64++;
+      }
+      else             
+      {
+        UInt32 len;
+        if(_isRep[state.Index].Decode(&_rangeDecoder) == 1)
+        {
+          len = 0;
+          if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0)
+          {
+            if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0)
+            {
+              state.UpdateShortRep();
+              len = 1;
+            }
+          }
+          else
+          {
+            UInt32 distance;
+            if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0)
+              distance = rep1;
+            else 
+            {
+              if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0)
+                distance = rep2;
+              else
+              {
+                distance = rep3;
+                rep3 = rep2;
+              }
+              rep2 = rep1;
+            }
+            rep1 = rep0;
+            rep0 = distance;
+          }
+          if (len == 0)
+          {
+            len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
+            state.UpdateRep();
+          }
+        }
+        else
+        {
+          rep3 = rep2;
+          rep2 = rep1;
+          rep1 = rep0;
+          len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
+          state.UpdateMatch();
+          UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
+          if (posSlot >= kStartPosModelIndex)
+          {
+            UInt32 numDirectBits = (posSlot >> 1) - 1;
+            rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+
+            if (posSlot < kEndPosModelIndex)
+              rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + 
+                  rep0 - posSlot - 1, &_rangeDecoder, numDirectBits);
+            else
+            {
+              rep0 += (_rangeDecoder.DecodeDirectBits(
+                  numDirectBits - kNumAlignBits) << kNumAlignBits);
+              rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder);
+              if (rep0 == 0xFFFFFFFF)
+              {
+                _remainLen = kLenIdFinished;
+                return S_OK;
+              }
+            }
+          }
+          else
+            rep0 = posSlot;
+        }
+        UInt32 locLen = len;
+        if (len > curSize)
+          locLen = (UInt32)curSize;
+        if (!_outWindowStream.CopyBlock(rep0, locLen))
+          return S_FALSE;
+        previousByte = _outWindowStream.GetByte(0);
+        curSize -= locLen;
+        nowPos64 += locLen;
+        len -= locLen;
+        if (len != 0)
+        {
+          _remainLen = (Int32)len;
+          break;
+        }
+
+        #ifdef _NO_EXCEPTIONS
+        if (_outWindowStream.ErrorCode != S_OK)
+          return _outWindowStream.ErrorCode;
+        #endif
+      }
+    }
+  }
+  if (_rangeDecoder.Stream.WasFinished())
+    return S_FALSE;
+  _reps[0] = rep0;
+  _reps[1] = rep1;
+  _reps[2] = rep2;
+  _reps[3] = rep3;
+  _state = state;
+
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
+    ISequentialOutStream *outStream, 
+    const UInt64 *, const UInt64 *outSize,
+    ICompressProgressInfo *progress)
+{
+  SetInStream(inStream);
+  _outWindowStream.SetStream(outStream);
+  SetOutStreamSize(outSize);
+  CDecoderFlusher flusher(this);
+
+  for (;;)
+  {
+    UInt32 curSize = 1 << 18;
+    RINOK(CodeSpec(curSize));
+    if (_remainLen == kLenIdFinished)
+      break;
+    if (progress != NULL)
+    {
+      UInt64 inSize = _rangeDecoder.GetProcessedSize();
+      UInt64 nowPos64 = _outWindowStream.GetProcessedSize();
+      RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
+    }
+    if (_outSizeDefined)
+      if (_outWindowStream.GetProcessedSize() >= _outSize)
+        break;
+  } 
+  flusher.NeedFlush = false;
+  return Flush();
+}
+
+
+#ifdef _NO_EXCEPTIONS
+
+#define LZMA_TRY_BEGIN
+#define LZMA_TRY_END
+
+#else
+
+#define LZMA_TRY_BEGIN try { 
+#define LZMA_TRY_END } \
+  catch(const CInBufferException &e)  { return e.ErrorCode; } \
+  catch(const CLZOutWindowException &e)  { return e.ErrorCode; } \
+  catch(...) { return S_FALSE; }
+
+#endif
+
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
+      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+      ICompressProgressInfo *progress)
+{
+  LZMA_TRY_BEGIN
+  return CodeReal(inStream, outStream, inSize, outSize, progress); 
+  LZMA_TRY_END
+}
+
+STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
+{
+  if (size < 5)
+    return E_INVALIDARG;
+  int lc = properties[0] % 9;
+  Byte remainder = (Byte)(properties[0] / 9);
+  int lp = remainder % 5;
+  int pb = remainder / 5;
+  if (pb > NLength::kNumPosStatesBitsMax)
+    return E_INVALIDARG;
+  _posStateMask = (1 << pb) - 1;
+  UInt32 dictionarySize = 0;
+  for (int i = 0; i < 4; i++)
+    dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
+  if (!_outWindowStream.Create(dictionarySize))
+    return E_OUTOFMEMORY;
+  if (!_literalDecoder.Create(lp, lc))
+    return E_OUTOFMEMORY;
+  if (!_rangeDecoder.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
+{
+  *value = _rangeDecoder.GetProcessedSize();
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
+{
+  _rangeDecoder.SetStream(inStream);
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::ReleaseInStream()
+{
+  _rangeDecoder.ReleaseStream();
+  return S_OK;
+}
+
+STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
+{
+  _outSizeDefined = (outSize != NULL);
+  if (_outSizeDefined)
+    _outSize = *outSize;
+  _remainLen = kLenIdNeedInit;
+  _outWindowStream.Init();
+  return S_OK;
+}
+
+#ifndef NO_READ_FROM_CODER
+
+STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  LZMA_TRY_BEGIN
+  if (processedSize)
+    *processedSize = 0;
+  const UInt64 startPos = _outWindowStream.GetProcessedSize();
+  _outWindowStream.SetMemStream((Byte *)data);
+  RINOK(CodeSpec(size));
+  if (processedSize)
+    *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos);
+  return Flush();
+  LZMA_TRY_END
+}
+
+#endif
+
+}}