// Compress/CopyCoder.cpp #include "StdAfx.h" #include "../../../C/Alloc.h" #include "../Common/StreamUtils.h" #include "CopyCoder.h" namespace NCompress { static const UInt32 kBufferSize = 1 << 17; CCopyCoder::~CCopyCoder() { ::MidFree(_buffer); } STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (!_buffer) { _buffer = (Byte *)::MidAlloc(kBufferSize); if (!_buffer) return E_OUTOFMEMORY; } TotalSize = 0; for (;;) { UInt32 size = kBufferSize; if (outSize && size > *outSize - TotalSize) size = (UInt32)(*outSize - TotalSize); RINOK(inStream->Read(_buffer, size, &size)); if (size == 0) break; if (outStream) { RINOK(WriteStream(outStream, _buffer, size)); } TotalSize += size; if (progress) { RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); } } return S_OK; } STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) { *value = TotalSize; return S_OK; } HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { CMyComPtr copyCoder = new CCopyCoder; return copyCoder->Code(inStream, outStream, NULL, NULL, progress); } HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) { NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; CMyComPtr copyCoder = copyCoderSpec; RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)); return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; } }