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
SetFinishMode(UInt32)18 STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */)
19 {
20 return S_OK;
21 }
22
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress)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
SetInStream(ISequentialInStream * inStream)77 STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream)
78 {
79 _inStream = inStream;
80 TotalSize = 0;
81 return S_OK;
82 }
83
ReleaseInStream()84 STDMETHODIMP CCopyCoder::ReleaseInStream()
85 {
86 _inStream.Release();
87 return S_OK;
88 }
89
Read(void * data,UInt32 size,UInt32 * processedSize)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
GetInStreamProcessedSize(UInt64 * value)100 STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
101 {
102 *value = TotalSize;
103 return S_OK;
104 }
105
CopyStream(ISequentialInStream * inStream,ISequentialOutStream * outStream,ICompressProgressInfo * progress)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
CopyStream_ExactSize(ISequentialInStream * inStream,ISequentialOutStream * outStream,UInt64 size,ICompressProgressInfo * progress)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 }
121