misc/libphysfs/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp
changeset 12213 bb5522e88ab2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/misc/libphysfs/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp	Mon Apr 10 12:06:43 2017 -0400
@@ -0,0 +1,226 @@
+// LzmaRam.cpp
+
+#include "StdAfx.h"
+#include "../../../Common/Types.h"
+#include "../LZMA/LZMADecoder.h"
+#include "../LZMA/LZMAEncoder.h"
+#include "LzmaRam.h"
+
+extern "C"
+{
+  #include "../../../../C/Compress/Branch/BranchX86.h"
+}
+
+class CInStreamRam: 
+  public ISequentialInStream,
+  public CMyUnknownImp
+{
+  const Byte *Data;
+  size_t Size;
+  size_t Pos;
+public:
+  MY_UNKNOWN_IMP
+  void Init(const Byte *data, size_t size)
+  {
+    Data = data;
+    Size = size;
+    Pos = 0;
+  }
+  STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+  if (size > (Size - Pos))
+    size = (UInt32)(Size - Pos);
+  for (UInt32 i = 0; i < size; i++)
+    ((Byte *)data)[i] = Data[Pos + i];
+  Pos += size;
+  if(processedSize != NULL)
+    *processedSize = size;
+  return S_OK;
+}
+  
+class COutStreamRam: 
+  public ISequentialOutStream,
+  public CMyUnknownImp
+{
+  size_t Size;
+public:
+  Byte *Data;
+  size_t Pos;
+  bool Overflow;
+  void Init(Byte *data, size_t size)
+  {
+    Data = data;
+    Size = size;
+    Pos = 0;
+    Overflow = false;
+  }
+  void SetPos(size_t pos)
+  {
+    Overflow = false;
+    Pos = pos;
+  }
+  MY_UNKNOWN_IMP
+  HRESULT WriteByte(Byte b)
+  {
+    if (Pos >= Size)
+    {
+      Overflow = true;
+      return E_FAIL;
+    }
+    Data[Pos++] = b;
+    return S_OK;
+  }
+  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+  UInt32 i;
+  for (i = 0; i < size && Pos < Size; i++)
+    Data[Pos++] = ((const Byte *)data)[i];
+  if(processedSize != NULL)
+    *processedSize = i;
+  if (i != size)
+  {
+    Overflow = true;
+    return E_FAIL;
+  }
+  return S_OK;
+}
+  
+#define SZ_RAM_E_FAIL (1)
+#define SZ_RAM_E_OUTOFMEMORY (2)
+#define SZE_OUT_OVERFLOW (3)
+
+int LzmaRamEncode(
+    const Byte *inBuffer, size_t inSize, 
+    Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, 
+    UInt32 dictionarySize, ESzFilterMode filterMode)
+{
+  #ifndef _NO_EXCEPTIONS
+  try { 
+  #endif
+
+  *outSizeProcessed = 0;
+  const size_t kIdSize = 1;
+  const size_t kLzmaPropsSize = 5;
+  const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8;
+  if (outSize < kMinDestSize)
+    return SZE_OUT_OVERFLOW;
+  NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
+  CMyComPtr<ICompressCoder> encoder = encoderSpec;
+
+  PROPID propIDs[] = 
+  { 
+    NCoderPropID::kAlgorithm,
+    NCoderPropID::kDictionarySize,  
+    NCoderPropID::kNumFastBytes,
+  };
+  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
+  PROPVARIANT properties[kNumProps];
+  properties[0].vt = VT_UI4;
+  properties[1].vt = VT_UI4;
+  properties[2].vt = VT_UI4;
+  properties[0].ulVal = (UInt32)2;
+  properties[1].ulVal = (UInt32)dictionarySize;
+  properties[2].ulVal = (UInt32)64;
+
+  if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
+    return 1;
+  
+  COutStreamRam *outStreamSpec = new COutStreamRam;
+  if (outStreamSpec == 0)
+    return SZ_RAM_E_OUTOFMEMORY;
+  CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+  CInStreamRam *inStreamSpec = new CInStreamRam;
+  if (inStreamSpec == 0)
+    return SZ_RAM_E_OUTOFMEMORY;
+  CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
+
+  outStreamSpec->Init(outBuffer, outSize);
+  if (outStreamSpec->WriteByte(0) != S_OK)
+    return SZE_OUT_OVERFLOW;
+
+  if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
+    return SZE_OUT_OVERFLOW;
+  if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize)
+    return 1;
+  
+  int i;
+  for (i = 0; i < 8; i++)
+  {
+    UInt64 t = (UInt64)(inSize);
+    if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK)
+      return SZE_OUT_OVERFLOW;
+  }
+
+  Byte *filteredStream = 0;
+
+  bool useFilter = (filterMode != SZ_FILTER_NO);
+  if (useFilter)
+  {
+    if (inSize != 0)
+    {
+      filteredStream = (Byte *)MyAlloc(inSize);
+      if (filteredStream == 0)
+        return SZ_RAM_E_OUTOFMEMORY;
+      memmove(filteredStream, inBuffer, inSize);
+    }
+    UInt32 x86State;
+    x86_Convert_Init(x86State);
+    x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1);
+  }
+  
+  size_t minSize = 0;
+  int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
+  bool bestIsFiltered = false;
+  int mainResult = 0;
+  size_t startPos = outStreamSpec->Pos;
+  for (i = 0; i < numPasses; i++)
+  {
+    if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered)
+      break;
+    outStreamSpec->SetPos(startPos);
+    bool curModeIsFiltered = false;
+    if (useFilter && i == 0)
+      curModeIsFiltered = true;
+    if (numPasses > 1 && i == numPasses - 1)
+      curModeIsFiltered = true;
+
+    inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize);
+    
+    HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
+    
+    mainResult = 0;
+    if (lzmaResult == E_OUTOFMEMORY)
+    {
+      mainResult = SZ_RAM_E_OUTOFMEMORY;
+      break;
+    } 
+    if (i == 0 || outStreamSpec->Pos <= minSize)
+    {
+      minSize = outStreamSpec->Pos;
+      bestIsFiltered = curModeIsFiltered;
+    }
+    if (outStreamSpec->Overflow)
+      mainResult = SZE_OUT_OVERFLOW;
+    else if (lzmaResult != S_OK)
+    {
+      mainResult = SZ_RAM_E_FAIL;
+      break;
+    } 
+  }
+  *outSizeProcessed = outStreamSpec->Pos;
+  if (bestIsFiltered)
+    outBuffer[0] = 1;
+  if (useFilter)
+    MyFree(filteredStream);
+  return mainResult;
+  
+  #ifndef _NO_EXCEPTIONS
+  } catch(...) { return SZ_RAM_E_OUTOFMEMORY; }
+  #endif
+}