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