CopyCoder.cpp (2765B)
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::SetFinishMode(UInt32 /* finishMode */) 19 { 20 return S_OK; 21 } 22 23 STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream, 24 ISequentialOutStream *outStream, 25 const UInt64 * /* inSize */, const UInt64 *outSize, 26 ICompressProgressInfo *progress) 27 { 28 if (!_buf) 29 { 30 _buf = (Byte *)::MidAlloc(kBufSize); 31 if (!_buf) 32 return E_OUTOFMEMORY; 33 } 34 35 TotalSize = 0; 36 37 for (;;) 38 { 39 UInt32 size = kBufSize; 40 if (outSize && size > *outSize - TotalSize) 41 size = (UInt32)(*outSize - TotalSize); 42 if (size == 0) 43 return S_OK; 44 45 HRESULT readRes = inStream->Read(_buf, size, &size); 46 47 if (size == 0) 48 return readRes; 49 50 if (outStream) 51 { 52 UInt32 pos = 0; 53 do 54 { 55 UInt32 curSize = size - pos; 56 HRESULT res = outStream->Write(_buf + pos, curSize, &curSize); 57 pos += curSize; 58 TotalSize += curSize; 59 RINOK(res); 60 if (curSize == 0) 61 return E_FAIL; 62 } 63 while (pos < size); 64 } 65 else 66 TotalSize += size; 67 68 RINOK(readRes); 69 70 if (progress) 71 { 72 RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize)); 73 } 74 } 75 } 76 77 STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream) 78 { 79 _inStream = inStream; 80 TotalSize = 0; 81 return S_OK; 82 } 83 84 STDMETHODIMP CCopyCoder::ReleaseInStream() 85 { 86 _inStream.Release(); 87 return S_OK; 88 } 89 90 STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize) 91 { 92 UInt32 realProcessedSize = 0; 93 HRESULT res = _inStream->Read(data, size, &realProcessedSize); 94 TotalSize += realProcessedSize; 95 if (processedSize) 96 *processedSize = realProcessedSize; 97 return res; 98 } 99 100 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value) 101 { 102 *value = TotalSize; 103 return S_OK; 104 } 105 106 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) 107 { 108 CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder; 109 return copyCoder->Code(inStream, outStream, NULL, NULL, progress); 110 } 111 112 HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress) 113 { 114 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; 115 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 116 RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress)); 117 return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL; 118 } 119 120 }