misc/libphysfs/lzma/CPP/7zip/Compress/Branch/x86_2.cpp
changeset 12213 bb5522e88ab2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Compress/Branch/x86_2.cpp	Mon Apr 10 12:06:43 2017 -0400
@@ -0,0 +1,392 @@
+// x86_2.cpp
+
+#include "StdAfx.h"
+#include "x86_2.h"
+
+extern "C" 
+{ 
+#include "../../../../C/Alloc.h"
+}
+
+namespace NCompress {
+namespace NBcj2 {
+
+inline bool IsJcc(Byte b0, Byte b1) { return (b0 == 0x0F && (b1 & 0xF0) == 0x80); }
+inline bool IsJ(Byte b0, Byte b1) { return ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)); }
+inline unsigned GetIndex(Byte b0, Byte b1) { return ((b1 == 0xE8) ? b0 : ((b1 == 0xE9) ? 256 : 257)); }
+
+#ifndef EXTRACT_ONLY
+
+static const int kBufferSize = 1 << 17;
+
+static bool inline Test86MSByte(Byte b)
+{
+  return (b == 0 || b == 0xFF);
+}
+
+bool CEncoder::Create()
+{
+  if (!_mainStream.Create(1 << 16))
+    return false;
+  if (!_callStream.Create(1 << 20))
+    return false;
+  if (!_jumpStream.Create(1 << 20))
+    return false;
+  if (!_rangeEncoder.Create(1 << 20))
+    return false;
+  if (_buffer == 0)
+  {
+    _buffer = (Byte *)MidAlloc(kBufferSize);
+    if (_buffer == 0)
+      return false;
+  }
+  return true;
+}
+
+CEncoder::~CEncoder()
+{
+  ::MidFree(_buffer);
+}
+
+HRESULT CEncoder::Flush()
+{
+  RINOK(_mainStream.Flush());
+  RINOK(_callStream.Flush());
+  RINOK(_jumpStream.Flush());
+  _rangeEncoder.FlushData();
+  return _rangeEncoder.FlushStream();
+}
+
+const UInt32 kDefaultLimit = (1 << 24);
+
+HRESULT CEncoder::CodeReal(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != 1 || numOutStreams != 4)
+    return E_INVALIDARG;
+
+  if (!Create())
+    return E_OUTOFMEMORY;
+
+  bool sizeIsDefined = false;
+  UInt64 inSize = 0;
+  if (inSizes != NULL)
+    if (inSizes[0] != NULL)
+    {
+      inSize = *inSizes[0];
+      if (inSize <= kDefaultLimit)
+        sizeIsDefined = true;
+    }
+
+  ISequentialInStream *inStream = inStreams[0];
+
+  _mainStream.SetStream(outStreams[0]);
+  _mainStream.Init();
+  _callStream.SetStream(outStreams[1]);
+  _callStream.Init();
+  _jumpStream.SetStream(outStreams[2]);
+  _jumpStream.Init();
+  _rangeEncoder.SetStream(outStreams[3]);
+  _rangeEncoder.Init();
+  for (int i = 0; i < 256 + 2; i++)
+    _statusEncoder[i].Init();
+  CCoderReleaser releaser(this);
+
+  CMyComPtr<ICompressGetSubStreamSize> getSubStreamSize;
+  {
+    inStream->QueryInterface(IID_ICompressGetSubStreamSize, (void **)&getSubStreamSize);
+  }
+
+  UInt32 nowPos = 0;
+  UInt64 nowPos64 = 0;
+  UInt32 bufferPos = 0;
+
+  Byte prevByte = 0;
+
+  UInt64 subStreamIndex = 0;
+  UInt64 subStreamStartPos  = 0;
+  UInt64 subStreamEndPos = 0;
+
+  for (;;)
+  {
+    UInt32 processedSize = 0;
+    for (;;)
+    {
+      UInt32 size = kBufferSize - (bufferPos + processedSize);
+      UInt32 processedSizeLoc;
+      if (size == 0)
+        break;
+      RINOK(inStream->Read(_buffer + bufferPos + processedSize, size, &processedSizeLoc));
+      if (processedSizeLoc == 0)
+        break;
+      processedSize += processedSizeLoc;
+    }
+    UInt32 endPos = bufferPos + processedSize;
+    
+    if (endPos < 5)
+    {
+      // change it 
+      for (bufferPos = 0; bufferPos < endPos; bufferPos++)
+      {
+        Byte b = _buffer[bufferPos];
+        _mainStream.WriteByte(b);
+        UInt32 index;
+        if (b == 0xE8)
+          index = prevByte;
+        else if (b == 0xE9)
+          index = 256;
+        else if (IsJcc(prevByte, b))
+          index = 257;
+        else
+        {
+          prevByte = b;
+          continue;
+        }
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);
+        prevByte = b;
+      }
+      return Flush();
+    }
+
+    bufferPos = 0;
+
+    UInt32 limit = endPos - 5;
+    while(bufferPos <= limit)
+    {
+      Byte b = _buffer[bufferPos];
+      _mainStream.WriteByte(b);
+      if (!IsJ(prevByte, b))
+      {
+        bufferPos++;
+        prevByte = b;
+        continue;
+      }
+      Byte nextByte = _buffer[bufferPos + 4];
+      UInt32 src = 
+        (UInt32(nextByte) << 24) |
+        (UInt32(_buffer[bufferPos + 3]) << 16) |
+        (UInt32(_buffer[bufferPos + 2]) << 8) |
+        (_buffer[bufferPos + 1]);
+      UInt32 dest = (nowPos + bufferPos + 5) + src;
+      // if (Test86MSByte(nextByte))
+      bool convert;
+      if (getSubStreamSize != NULL)
+      {
+        UInt64 currentPos = (nowPos64 + bufferPos);
+        while (subStreamEndPos < currentPos)
+        {
+          UInt64 subStreamSize;
+          HRESULT result = getSubStreamSize->GetSubStreamSize(subStreamIndex, &subStreamSize);
+          if (result == S_OK)
+          {
+            subStreamStartPos = subStreamEndPos;
+            subStreamEndPos += subStreamSize;          
+            subStreamIndex++;
+          }
+          else if (result == S_FALSE || result == E_NOTIMPL)
+          {
+            getSubStreamSize.Release();
+            subStreamStartPos = 0;
+            subStreamEndPos = subStreamStartPos - 1;          
+          }
+          else
+            return result;
+        }
+        if (getSubStreamSize == NULL)
+        {
+          if (sizeIsDefined)
+            convert = (dest < inSize);
+          else
+            convert = Test86MSByte(nextByte);
+        }
+        else if (subStreamEndPos - subStreamStartPos > kDefaultLimit)
+          convert = Test86MSByte(nextByte);
+        else
+        {
+          UInt64 dest64 = (currentPos + 5) + Int64(Int32(src));
+          convert = (dest64 >= subStreamStartPos && dest64 < subStreamEndPos);
+        }
+      }
+      else if (sizeIsDefined)
+        convert = (dest < inSize);
+      else
+        convert = Test86MSByte(nextByte);
+      unsigned index = GetIndex(prevByte, b);
+      if (convert)
+      {
+        _statusEncoder[index].Encode(&_rangeEncoder, 1);
+        bufferPos += 5;
+        COutBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
+        for (int i = 24; i >= 0; i -= 8)
+          s.WriteByte((Byte)(dest >> i));
+        prevByte = nextByte;
+      }
+      else
+      {
+        _statusEncoder[index].Encode(&_rangeEncoder, 0);
+        bufferPos++;
+        prevByte = b;
+      }
+    }
+    nowPos += bufferPos;
+    nowPos64 += bufferPos;
+
+    if (progress != NULL)
+    {
+      /*
+      const UInt64 compressedSize = 
+        _mainStream.GetProcessedSize() + 
+        _callStream.GetProcessedSize() +
+        _jumpStream.GetProcessedSize() +
+        _rangeEncoder.GetProcessedSize();
+      */
+      RINOK(progress->SetRatioInfo(&nowPos64, NULL));
+    }
+ 
+    UInt32 i = 0;
+    while(bufferPos < endPos)
+      _buffer[i++] = _buffer[bufferPos++];
+    bufferPos = i;
+  }
+}
+
+STDMETHODIMP CEncoder::Code(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  try
+  {
+    return CodeReal(inStreams, inSizes, numInStreams,
+      outStreams, outSizes,numOutStreams, progress);
+  }
+  catch(const COutBufferException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+#endif
+
+HRESULT CDecoder::CodeReal(ISequentialInStream **inStreams,
+      const UInt64 ** /* inSizes */,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 ** /* outSizes */,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  if (numInStreams != 4 || numOutStreams != 1)
+    return E_INVALIDARG;
+
+  if (!_mainInStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+  if (!_callStream.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  if (!_jumpStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+  if (!_rangeDecoder.Create(1 << 20))
+    return E_OUTOFMEMORY;
+  if (!_outStream.Create(1 << 16))
+    return E_OUTOFMEMORY;
+
+  _mainInStream.SetStream(inStreams[0]);
+  _callStream.SetStream(inStreams[1]);
+  _jumpStream.SetStream(inStreams[2]);
+  _rangeDecoder.SetStream(inStreams[3]);
+  _outStream.SetStream(outStreams[0]);
+
+  _mainInStream.Init();
+  _callStream.Init();
+  _jumpStream.Init();
+  _rangeDecoder.Init();
+  _outStream.Init();
+
+  for (int i = 0; i < 256 + 2; i++)
+    _statusDecoder[i].Init();
+
+  CCoderReleaser releaser(this);
+
+  Byte prevByte = 0;
+  UInt32 processedBytes = 0;
+  for (;;)
+  {
+    if (processedBytes >= (1 << 20) && progress != NULL)
+    {
+      /*
+      const UInt64 compressedSize = 
+        _mainInStream.GetProcessedSize() + 
+        _callStream.GetProcessedSize() +
+        _jumpStream.GetProcessedSize() +
+        _rangeDecoder.GetProcessedSize();
+      */
+      const UInt64 nowPos64 = _outStream.GetProcessedSize();
+      RINOK(progress->SetRatioInfo(NULL, &nowPos64));
+      processedBytes = 0;
+    }
+    UInt32 i;
+    Byte b = 0;
+    const UInt32 kBurstSize = (1 << 18);
+    for (i = 0; i < kBurstSize; i++)
+    {
+      if (!_mainInStream.ReadByte(b))
+        return Flush();
+      _outStream.WriteByte(b);
+      if (IsJ(prevByte, b))
+        break;
+      prevByte = b;
+    }
+    processedBytes += i;
+    if (i == kBurstSize)
+      continue;
+    unsigned index = GetIndex(prevByte, b);
+    if (_statusDecoder[index].Decode(&_rangeDecoder) == 1)
+    {
+      UInt32 src = 0;
+      CInBuffer &s = (b == 0xE8) ? _callStream : _jumpStream;
+      for (int i = 0; i < 4; i++)
+      {
+        Byte b0;
+        if(!s.ReadByte(b0))
+          return S_FALSE;
+        src <<= 8;
+        src |= ((UInt32)b0);
+      }
+      UInt32 dest = src - (UInt32(_outStream.GetProcessedSize()) + 4) ;
+      _outStream.WriteByte((Byte)(dest));
+      _outStream.WriteByte((Byte)(dest >> 8));
+      _outStream.WriteByte((Byte)(dest >> 16));
+      _outStream.WriteByte((Byte)(dest >> 24));
+      prevByte = (Byte)(dest >> 24);
+      processedBytes += 4;
+    }
+    else
+      prevByte = b;
+  }
+}
+
+STDMETHODIMP CDecoder::Code(ISequentialInStream **inStreams,
+      const UInt64 **inSizes,
+      UInt32 numInStreams,
+      ISequentialOutStream **outStreams,
+      const UInt64 **outSizes,
+      UInt32 numOutStreams,
+      ICompressProgressInfo *progress)
+{
+  try
+  {
+    return CodeReal(inStreams, inSizes, numInStreams,
+        outStreams, outSizes,numOutStreams, progress);
+  }
+  catch(const CInBufferException &e) { return e.ErrorCode; }
+  catch(const COutBufferException &e) { return e.ErrorCode; }
+  catch(...) { return S_FALSE; }
+}
+
+}}