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
Z7_COM7F_IMF(CCopyCoder::SetFinishMode (UInt32))18 Z7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */))
19 {
20 return S_OK;
21 }
22
Z7_COM7F_IMF(CCopyCoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress))23 Z7_COM7F_IMF(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)
41 {
42 const UInt64 rem = *outSize - TotalSize;
43 if (size > rem)
44 {
45 size = (UInt32)rem;
46 if (size == 0)
47 {
48 /* if we enable the following check,
49 we will make one call of Read(_buf, 0) for empty stream */
50 // if (TotalSize != 0)
51 return S_OK;
52 }
53 }
54 }
55
56 HRESULT readRes;
57 {
58 UInt32 pos = 0;
59 do
60 {
61 const UInt32 curSize = size - pos;
62 UInt32 processed = 0;
63 readRes = inStream->Read(_buf + pos, curSize, &processed);
64 if (processed > curSize)
65 return E_FAIL; // internal code failure
66 pos += processed;
67 if (readRes != S_OK || processed == 0)
68 break;
69 }
70 while (pos < kBufSize);
71 size = pos;
72 }
73
74 if (size == 0)
75 return readRes;
76
77 if (outStream)
78 {
79 UInt32 pos = 0;
80 do
81 {
82 const UInt32 curSize = size - pos;
83 UInt32 processed = 0;
84 const HRESULT res = outStream->Write(_buf + pos, curSize, &processed);
85 if (processed > curSize)
86 return E_FAIL; // internal code failure
87 pos += processed;
88 TotalSize += processed;
89 RINOK(res)
90 if (processed == 0)
91 return E_FAIL;
92 }
93 while (pos < size);
94 }
95 else
96 TotalSize += size;
97
98 RINOK(readRes)
99
100 if (size != kBufSize)
101 return S_OK;
102
103 if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0)
104 {
105 RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize))
106 }
107 }
108 }
109
Z7_COM7F_IMF(CCopyCoder::SetInStream (ISequentialInStream * inStream))110 Z7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream))
111 {
112 _inStream = inStream;
113 TotalSize = 0;
114 return S_OK;
115 }
116
Z7_COM7F_IMF(CCopyCoder::ReleaseInStream ())117 Z7_COM7F_IMF(CCopyCoder::ReleaseInStream())
118 {
119 _inStream.Release();
120 return S_OK;
121 }
122
Z7_COM7F_IMF(CCopyCoder::Read (void * data,UInt32 size,UInt32 * processedSize))123 Z7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
124 {
125 UInt32 realProcessedSize = 0;
126 HRESULT res = _inStream->Read(data, size, &realProcessedSize);
127 TotalSize += realProcessedSize;
128 if (processedSize)
129 *processedSize = realProcessedSize;
130 return res;
131 }
132
Z7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize (UInt64 * value))133 Z7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value))
134 {
135 *value = TotalSize;
136 return S_OK;
137 }
138
CopyStream(ISequentialInStream * inStream,ISequentialOutStream * outStream,ICompressProgressInfo * progress)139 HRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
140 {
141 CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
142 return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
143 }
144
CopyStream_ExactSize(ISequentialInStream * inStream,ISequentialOutStream * outStream,UInt64 size,ICompressProgressInfo * progress)145 HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
146 {
147 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
148 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
149 RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress))
150 return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
151 }
152
153 }
154