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