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 15 CCopyCoder::~CCopyCoder() 16 { 17 ::MidFree(_buffer); 18 } 19 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 54 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) 55 { 56 *value = TotalSize; 57 return S_OK; 58 } 59 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 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