1 // Compress/CopyCoder.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "../../../C/Alloc.h"
6 
7 #include "../Common/StreamUtils.h"
8 
9 #include "CopyCoder.h"
10 
11 namespace NCompress {
12 
13 static const UInt32 kBufferSize = 1 << 17;
14 
~CCopyCoder()15 CCopyCoder::~CCopyCoder()
16 {
17   ::MidFree(_buffer);
18 }
19 
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress)20 STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
21     ISequentialOutStream *outStream,
22     const UInt64 * /* inSize */, const UInt64 *outSize,
23     ICompressProgressInfo *progress)
24 {
25   if (!_buffer)
26   {
27     _buffer = (Byte *)::MidAlloc(kBufferSize);
28     if (!_buffer)
29       return E_OUTOFMEMORY;
30   }
31 
32   TotalSize = 0;
33   for (;;)
34   {
35     UInt32 size = kBufferSize;
36     if (outSize && size > *outSize - TotalSize)
37       size = (UInt32)(*outSize - TotalSize);
38     RINOK(inStream->Read(_buffer, size, &size));
39     if (size == 0)
40       break;
41     if (outStream)
42     {
43       RINOK(WriteStream(outStream, _buffer, size));
44     }
45     TotalSize += size;
46     if (progress)
47     {
48       RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
49     }
50   }
51   return S_OK;
52 }
53 
GetInStreamProcessedSize(UInt64 * value)54 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
55 {
56   *value = TotalSize;
57   return S_OK;
58 }
59 
CopyStream(ISequentialInStream * inStream,ISequentialOutStream * outStream,ICompressProgressInfo * progress)60 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
61 {
62   CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
63   return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
64 }
65 
CopyStream_ExactSize(ISequentialInStream * inStream,ISequentialOutStream * outStream,UInt64 size,ICompressProgressInfo * progress)66 HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
67 {
68   NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
69   CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
70   RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));
71   return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
72 }
73 
74 }
75