misc/libphysfs/lzma/CPP/7zip/Compress/LZMA_Alone/LzmaRam.cpp
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     1 // LzmaRam.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 #include "../../../Common/Types.h"
       
     5 #include "../LZMA/LZMADecoder.h"
       
     6 #include "../LZMA/LZMAEncoder.h"
       
     7 #include "LzmaRam.h"
       
     8 
       
     9 extern "C"
       
    10 {
       
    11   #include "../../../../C/Compress/Branch/BranchX86.h"
       
    12 }
       
    13 
       
    14 class CInStreamRam: 
       
    15   public ISequentialInStream,
       
    16   public CMyUnknownImp
       
    17 {
       
    18   const Byte *Data;
       
    19   size_t Size;
       
    20   size_t Pos;
       
    21 public:
       
    22   MY_UNKNOWN_IMP
       
    23   void Init(const Byte *data, size_t size)
       
    24   {
       
    25     Data = data;
       
    26     Size = size;
       
    27     Pos = 0;
       
    28   }
       
    29   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
       
    30 };
       
    31 
       
    32 STDMETHODIMP CInStreamRam::Read(void *data, UInt32 size, UInt32 *processedSize)
       
    33 {
       
    34   if (size > (Size - Pos))
       
    35     size = (UInt32)(Size - Pos);
       
    36   for (UInt32 i = 0; i < size; i++)
       
    37     ((Byte *)data)[i] = Data[Pos + i];
       
    38   Pos += size;
       
    39   if(processedSize != NULL)
       
    40     *processedSize = size;
       
    41   return S_OK;
       
    42 }
       
    43   
       
    44 class COutStreamRam: 
       
    45   public ISequentialOutStream,
       
    46   public CMyUnknownImp
       
    47 {
       
    48   size_t Size;
       
    49 public:
       
    50   Byte *Data;
       
    51   size_t Pos;
       
    52   bool Overflow;
       
    53   void Init(Byte *data, size_t size)
       
    54   {
       
    55     Data = data;
       
    56     Size = size;
       
    57     Pos = 0;
       
    58     Overflow = false;
       
    59   }
       
    60   void SetPos(size_t pos)
       
    61   {
       
    62     Overflow = false;
       
    63     Pos = pos;
       
    64   }
       
    65   MY_UNKNOWN_IMP
       
    66   HRESULT WriteByte(Byte b)
       
    67   {
       
    68     if (Pos >= Size)
       
    69     {
       
    70       Overflow = true;
       
    71       return E_FAIL;
       
    72     }
       
    73     Data[Pos++] = b;
       
    74     return S_OK;
       
    75   }
       
    76   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
       
    77 };
       
    78 
       
    79 STDMETHODIMP COutStreamRam::Write(const void *data, UInt32 size, UInt32 *processedSize)
       
    80 {
       
    81   UInt32 i;
       
    82   for (i = 0; i < size && Pos < Size; i++)
       
    83     Data[Pos++] = ((const Byte *)data)[i];
       
    84   if(processedSize != NULL)
       
    85     *processedSize = i;
       
    86   if (i != size)
       
    87   {
       
    88     Overflow = true;
       
    89     return E_FAIL;
       
    90   }
       
    91   return S_OK;
       
    92 }
       
    93   
       
    94 #define SZ_RAM_E_FAIL (1)
       
    95 #define SZ_RAM_E_OUTOFMEMORY (2)
       
    96 #define SZE_OUT_OVERFLOW (3)
       
    97 
       
    98 int LzmaRamEncode(
       
    99     const Byte *inBuffer, size_t inSize, 
       
   100     Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, 
       
   101     UInt32 dictionarySize, ESzFilterMode filterMode)
       
   102 {
       
   103   #ifndef _NO_EXCEPTIONS
       
   104   try { 
       
   105   #endif
       
   106 
       
   107   *outSizeProcessed = 0;
       
   108   const size_t kIdSize = 1;
       
   109   const size_t kLzmaPropsSize = 5;
       
   110   const size_t kMinDestSize = kIdSize + kLzmaPropsSize + 8;
       
   111   if (outSize < kMinDestSize)
       
   112     return SZE_OUT_OVERFLOW;
       
   113   NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
       
   114   CMyComPtr<ICompressCoder> encoder = encoderSpec;
       
   115 
       
   116   PROPID propIDs[] = 
       
   117   { 
       
   118     NCoderPropID::kAlgorithm,
       
   119     NCoderPropID::kDictionarySize,  
       
   120     NCoderPropID::kNumFastBytes,
       
   121   };
       
   122   const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
       
   123   PROPVARIANT properties[kNumProps];
       
   124   properties[0].vt = VT_UI4;
       
   125   properties[1].vt = VT_UI4;
       
   126   properties[2].vt = VT_UI4;
       
   127   properties[0].ulVal = (UInt32)2;
       
   128   properties[1].ulVal = (UInt32)dictionarySize;
       
   129   properties[2].ulVal = (UInt32)64;
       
   130 
       
   131   if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
       
   132     return 1;
       
   133   
       
   134   COutStreamRam *outStreamSpec = new COutStreamRam;
       
   135   if (outStreamSpec == 0)
       
   136     return SZ_RAM_E_OUTOFMEMORY;
       
   137   CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
       
   138   CInStreamRam *inStreamSpec = new CInStreamRam;
       
   139   if (inStreamSpec == 0)
       
   140     return SZ_RAM_E_OUTOFMEMORY;
       
   141   CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
       
   142 
       
   143   outStreamSpec->Init(outBuffer, outSize);
       
   144   if (outStreamSpec->WriteByte(0) != S_OK)
       
   145     return SZE_OUT_OVERFLOW;
       
   146 
       
   147   if (encoderSpec->WriteCoderProperties(outStream) != S_OK)
       
   148     return SZE_OUT_OVERFLOW;
       
   149   if (outStreamSpec->Pos != kIdSize + kLzmaPropsSize)
       
   150     return 1;
       
   151   
       
   152   int i;
       
   153   for (i = 0; i < 8; i++)
       
   154   {
       
   155     UInt64 t = (UInt64)(inSize);
       
   156     if (outStreamSpec->WriteByte((Byte)((t) >> (8 * i))) != S_OK)
       
   157       return SZE_OUT_OVERFLOW;
       
   158   }
       
   159 
       
   160   Byte *filteredStream = 0;
       
   161 
       
   162   bool useFilter = (filterMode != SZ_FILTER_NO);
       
   163   if (useFilter)
       
   164   {
       
   165     if (inSize != 0)
       
   166     {
       
   167       filteredStream = (Byte *)MyAlloc(inSize);
       
   168       if (filteredStream == 0)
       
   169         return SZ_RAM_E_OUTOFMEMORY;
       
   170       memmove(filteredStream, inBuffer, inSize);
       
   171     }
       
   172     UInt32 x86State;
       
   173     x86_Convert_Init(x86State);
       
   174     x86_Convert(filteredStream, (SizeT)inSize, 0, &x86State, 1);
       
   175   }
       
   176   
       
   177   size_t minSize = 0;
       
   178   int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
       
   179   bool bestIsFiltered = false;
       
   180   int mainResult = 0;
       
   181   size_t startPos = outStreamSpec->Pos;
       
   182   for (i = 0; i < numPasses; i++)
       
   183   {
       
   184     if (numPasses > 1 && i == numPasses - 1 && !bestIsFiltered)
       
   185       break;
       
   186     outStreamSpec->SetPos(startPos);
       
   187     bool curModeIsFiltered = false;
       
   188     if (useFilter && i == 0)
       
   189       curModeIsFiltered = true;
       
   190     if (numPasses > 1 && i == numPasses - 1)
       
   191       curModeIsFiltered = true;
       
   192 
       
   193     inStreamSpec->Init(curModeIsFiltered ? filteredStream : inBuffer, inSize);
       
   194     
       
   195     HRESULT lzmaResult = encoder->Code(inStream, outStream, 0, 0, 0);
       
   196     
       
   197     mainResult = 0;
       
   198     if (lzmaResult == E_OUTOFMEMORY)
       
   199     {
       
   200       mainResult = SZ_RAM_E_OUTOFMEMORY;
       
   201       break;
       
   202     } 
       
   203     if (i == 0 || outStreamSpec->Pos <= minSize)
       
   204     {
       
   205       minSize = outStreamSpec->Pos;
       
   206       bestIsFiltered = curModeIsFiltered;
       
   207     }
       
   208     if (outStreamSpec->Overflow)
       
   209       mainResult = SZE_OUT_OVERFLOW;
       
   210     else if (lzmaResult != S_OK)
       
   211     {
       
   212       mainResult = SZ_RAM_E_FAIL;
       
   213       break;
       
   214     } 
       
   215   }
       
   216   *outSizeProcessed = outStreamSpec->Pos;
       
   217   if (bestIsFiltered)
       
   218     outBuffer[0] = 1;
       
   219   if (useFilter)
       
   220     MyFree(filteredStream);
       
   221   return mainResult;
       
   222   
       
   223   #ifndef _NO_EXCEPTIONS
       
   224   } catch(...) { return SZ_RAM_E_OUTOFMEMORY; }
       
   225   #endif
       
   226 }