misc/libphysfs/lzma/CPP/7zip/Common/FilterCoder.cpp
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     1 // FilterCoder.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "FilterCoder.h"
       
     6 extern "C" 
       
     7 { 
       
     8 #include "../../../C/Alloc.h"
       
     9 }
       
    10 #include "../../Common/Defs.h"
       
    11 #include "StreamUtils.h"
       
    12 
       
    13 static const UInt32 kBufferSize = 1 << 17;
       
    14 
       
    15 CFilterCoder::CFilterCoder()
       
    16 { 
       
    17   _buffer = (Byte *)::MidAlloc(kBufferSize); 
       
    18 }
       
    19 
       
    20 CFilterCoder::~CFilterCoder() 
       
    21 { 
       
    22   ::MidFree(_buffer); 
       
    23 }
       
    24 
       
    25 HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
       
    26 {
       
    27   if (_outSizeIsDefined)
       
    28   {
       
    29     UInt64 remSize = _outSize - _nowPos64;
       
    30     if (size > remSize)
       
    31       size = (UInt32)remSize;
       
    32   }
       
    33   UInt32 processedSize = 0;
       
    34   RINOK(WriteStream(outStream, _buffer, size, &processedSize));
       
    35   if (size != processedSize)
       
    36     return E_FAIL;
       
    37   _nowPos64 += processedSize;
       
    38   return S_OK;
       
    39 }
       
    40 
       
    41 
       
    42 STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
       
    43       ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
       
    44       ICompressProgressInfo *progress)
       
    45 {
       
    46   RINOK(Init());
       
    47   UInt32 bufferPos = 0;
       
    48   _outSizeIsDefined = (outSize != 0);
       
    49   if (_outSizeIsDefined)
       
    50     _outSize = *outSize;
       
    51 
       
    52   while(NeedMore())
       
    53   {
       
    54     UInt32 processedSize;
       
    55     
       
    56     // Change it: It can be optimized using ReadPart
       
    57     RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
       
    58     
       
    59     UInt32 endPos = bufferPos + processedSize;
       
    60 
       
    61     bufferPos = Filter->Filter(_buffer, endPos);
       
    62     if (bufferPos > endPos)
       
    63     {
       
    64       for (; endPos< bufferPos; endPos++)
       
    65         _buffer[endPos] = 0;
       
    66       bufferPos = Filter->Filter(_buffer, endPos);
       
    67     }
       
    68 
       
    69     if (bufferPos == 0)
       
    70     {
       
    71       if (endPos > 0)
       
    72         return WriteWithLimit(outStream, endPos);
       
    73       return S_OK;
       
    74     }
       
    75     RINOK(WriteWithLimit(outStream, bufferPos));
       
    76     if (progress != NULL)
       
    77     {
       
    78       RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
       
    79     }
       
    80     UInt32 i = 0;
       
    81     while(bufferPos < endPos)
       
    82       _buffer[i++] = _buffer[bufferPos++];
       
    83     bufferPos = i;
       
    84   }
       
    85   return S_OK;
       
    86 }
       
    87 
       
    88 // #ifdef _ST_MODE
       
    89 STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
       
    90 {
       
    91   _bufferPos = 0;
       
    92   _outStream = outStream;
       
    93   return Init();
       
    94 }
       
    95 
       
    96 STDMETHODIMP CFilterCoder::ReleaseOutStream()
       
    97 {
       
    98   _outStream.Release();
       
    99   return S_OK;
       
   100 };
       
   101 
       
   102 
       
   103 STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
       
   104 {
       
   105   UInt32 processedSizeTotal = 0;
       
   106   while(size > 0)
       
   107   {
       
   108     UInt32 sizeMax = kBufferSize - _bufferPos;
       
   109     UInt32 sizeTemp = size;
       
   110     if (sizeTemp > sizeMax)
       
   111       sizeTemp = sizeMax;
       
   112     memmove(_buffer + _bufferPos, data, sizeTemp);
       
   113     size -= sizeTemp;
       
   114     processedSizeTotal += sizeTemp;
       
   115     data = (const Byte *)data + sizeTemp;
       
   116     UInt32 endPos = _bufferPos + sizeTemp;
       
   117     _bufferPos = Filter->Filter(_buffer, endPos);
       
   118     if (_bufferPos == 0)
       
   119     {
       
   120       _bufferPos = endPos;
       
   121       break;
       
   122     }
       
   123     if (_bufferPos > endPos)
       
   124     {
       
   125       if (size != 0)
       
   126         return E_FAIL;
       
   127       break;
       
   128     }
       
   129     RINOK(WriteWithLimit(_outStream, _bufferPos));
       
   130     UInt32 i = 0;
       
   131     while(_bufferPos < endPos)
       
   132       _buffer[i++] = _buffer[_bufferPos++];
       
   133     _bufferPos = i;
       
   134   }
       
   135   if (processedSize != NULL)
       
   136     *processedSize = processedSizeTotal;
       
   137   return S_OK;
       
   138 }
       
   139 
       
   140 STDMETHODIMP CFilterCoder::Flush()
       
   141 {
       
   142   if (_bufferPos != 0)
       
   143   {
       
   144     UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
       
   145     if (endPos > _bufferPos)
       
   146     {
       
   147       for (; _bufferPos < endPos; _bufferPos++)
       
   148         _buffer[_bufferPos] = 0;
       
   149       if (Filter->Filter(_buffer, endPos) != endPos)
       
   150         return E_FAIL;
       
   151     }
       
   152     UInt32 processedSize;
       
   153     RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
       
   154     if (_bufferPos != processedSize)
       
   155       return E_FAIL;
       
   156     _bufferPos = 0;
       
   157   }
       
   158   CMyComPtr<IOutStreamFlush> flush;
       
   159   _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
       
   160   if (flush)
       
   161     return  flush->Flush();
       
   162   return S_OK;
       
   163 }
       
   164 
       
   165 
       
   166 STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
       
   167 {
       
   168   _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
       
   169   _inStream = inStream;
       
   170   return Init();
       
   171 }
       
   172 
       
   173 STDMETHODIMP CFilterCoder::ReleaseInStream()
       
   174 {
       
   175   _inStream.Release();
       
   176   return S_OK;
       
   177 };
       
   178 
       
   179 STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
       
   180 {
       
   181   UInt32 processedSizeTotal = 0;
       
   182   while(size > 0)
       
   183   {
       
   184     if (_convertedPosBegin != _convertedPosEnd)
       
   185     {
       
   186       UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
       
   187       memmove(data, _buffer + _convertedPosBegin, sizeTemp);
       
   188       _convertedPosBegin += sizeTemp;
       
   189       data = (void *)((Byte *)data + sizeTemp);
       
   190       size -= sizeTemp;
       
   191       processedSizeTotal += sizeTemp;
       
   192       break;
       
   193     }
       
   194     int i;
       
   195     for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
       
   196       _buffer[i] = _buffer[i + _convertedPosEnd];
       
   197     _bufferPos = i;
       
   198     _convertedPosBegin = _convertedPosEnd = 0;
       
   199     UInt32 processedSizeTemp;
       
   200     UInt32 size0 = kBufferSize - _bufferPos;
       
   201     // Optimize it:
       
   202     RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
       
   203     _bufferPos = _bufferPos + processedSizeTemp;
       
   204     _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
       
   205     if (_convertedPosEnd == 0)
       
   206     {
       
   207       if (_bufferPos == 0)
       
   208         break;
       
   209       else
       
   210       {
       
   211         _convertedPosEnd = _bufferPos; // check it
       
   212         continue;
       
   213       }
       
   214     }
       
   215     if (_convertedPosEnd > _bufferPos)
       
   216     {
       
   217       for (; _bufferPos < _convertedPosEnd; _bufferPos++)
       
   218         _buffer[_bufferPos] = 0;
       
   219       _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
       
   220     }
       
   221   }
       
   222   if (processedSize != NULL)
       
   223     *processedSize = processedSizeTotal;
       
   224   return S_OK;
       
   225 }
       
   226 
       
   227 // #endif // _ST_MODE
       
   228 
       
   229 #ifndef _NO_CRYPTO
       
   230 STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
       
   231 {
       
   232   return _setPassword->CryptoSetPassword(data, size);
       
   233 }
       
   234 #endif
       
   235 
       
   236 #ifndef EXTRACT_ONLY
       
   237 STDMETHODIMP CFilterCoder::SetCoderProperties(const PROPID *propIDs, 
       
   238       const PROPVARIANT *properties, UInt32 numProperties)
       
   239 {
       
   240   return _SetCoderProperties->SetCoderProperties(propIDs, properties, numProperties);
       
   241 }
       
   242 
       
   243 STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
       
   244 {
       
   245   return _writeCoderProperties->WriteCoderProperties(outStream);
       
   246 }
       
   247 
       
   248 /*
       
   249 STDMETHODIMP CFilterCoder::ResetSalt()
       
   250 {
       
   251   return _CryptoResetSalt->ResetSalt();
       
   252 }
       
   253 */
       
   254 
       
   255 STDMETHODIMP CFilterCoder::ResetInitVector()
       
   256 {
       
   257   return _CryptoResetInitVector->ResetInitVector();
       
   258 }
       
   259 #endif
       
   260 
       
   261 STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
       
   262 {
       
   263   return _setDecoderProperties->SetDecoderProperties2(data, size);
       
   264 }