Home | History | Annotate | Download | only in Compress
      1 // Compress/CopyCoder.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../C/Alloc.h"
      6 
      7 #include "CopyCoder.h"
      8 
      9 namespace NCompress {
     10 
     11 static const UInt32 kBufSize = 1 << 17;
     12 
     13 CCopyCoder::~CCopyCoder()
     14 {
     15   ::MidFree(_buf);
     16 }
     17 
     18 STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
     19     ISequentialOutStream *outStream,
     20     const UInt64 * /* inSize */, const UInt64 *outSize,
     21     ICompressProgressInfo *progress)
     22 {
     23   if (!_buf)
     24   {
     25     _buf = (Byte *)::MidAlloc(kBufSize);
     26     if (!_buf)
     27       return E_OUTOFMEMORY;
     28   }
     29 
     30   TotalSize = 0;
     31 
     32   for (;;)
     33   {
     34     UInt32 size = kBufSize;
     35     if (outSize && size > *outSize - TotalSize)
     36       size = (UInt32)(*outSize - TotalSize);
     37     if (size == 0)
     38       return S_OK;
     39 
     40     HRESULT readRes = inStream->Read(_buf, size, &size);
     41 
     42     if (size == 0)
     43       return readRes;
     44 
     45     if (outStream)
     46     {
     47       UInt32 pos = 0;
     48       do
     49       {
     50         UInt32 curSize = size - pos;
     51         HRESULT res = outStream->Write(_buf + pos, curSize, &curSize);
     52         pos += curSize;
     53         TotalSize += curSize;
     54         RINOK(res);
     55         if (curSize == 0)
     56           return E_FAIL;
     57       }
     58       while (pos < size);
     59     }
     60     else
     61       TotalSize += size;
     62 
     63     RINOK(readRes);
     64 
     65     if (progress)
     66     {
     67       RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
     68     }
     69   }
     70 }
     71 
     72 STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream)
     73 {
     74   _inStream = inStream;
     75   TotalSize = 0;
     76   return S_OK;
     77 }
     78 
     79 STDMETHODIMP CCopyCoder::ReleaseInStream()
     80 {
     81   _inStream.Release();
     82   return S_OK;
     83 }
     84 
     85 STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
     86 {
     87   UInt32 realProcessedSize = 0;
     88   HRESULT res = _inStream->Read(data, size, &realProcessedSize);
     89   TotalSize += realProcessedSize;
     90   if (processedSize)
     91     *processedSize = realProcessedSize;
     92   return res;
     93 }
     94 
     95 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
     96 {
     97   *value = TotalSize;
     98   return S_OK;
     99 }
    100 
    101 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
    102 {
    103   CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
    104   return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
    105 }
    106 
    107 HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
    108 {
    109   NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
    110   CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
    111   RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));
    112   return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
    113 }
    114 
    115 }
    116