1370b324cSopenharmony_ci// Compress/CopyCoder.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../../C/Alloc.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "CopyCoder.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_cinamespace NCompress {
10370b324cSopenharmony_ci
11370b324cSopenharmony_cistatic const UInt32 kBufSize = 1 << 17;
12370b324cSopenharmony_ci
13370b324cSopenharmony_ciCCopyCoder::~CCopyCoder()
14370b324cSopenharmony_ci{
15370b324cSopenharmony_ci  ::MidFree(_buf);
16370b324cSopenharmony_ci}
17370b324cSopenharmony_ci
18370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */))
19370b324cSopenharmony_ci{
20370b324cSopenharmony_ci  return S_OK;
21370b324cSopenharmony_ci}
22370b324cSopenharmony_ci
23370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream,
24370b324cSopenharmony_ci    ISequentialOutStream *outStream,
25370b324cSopenharmony_ci    const UInt64 * /* inSize */, const UInt64 *outSize,
26370b324cSopenharmony_ci    ICompressProgressInfo *progress))
27370b324cSopenharmony_ci{
28370b324cSopenharmony_ci  if (!_buf)
29370b324cSopenharmony_ci  {
30370b324cSopenharmony_ci    _buf = (Byte *)::MidAlloc(kBufSize);
31370b324cSopenharmony_ci    if (!_buf)
32370b324cSopenharmony_ci      return E_OUTOFMEMORY;
33370b324cSopenharmony_ci  }
34370b324cSopenharmony_ci
35370b324cSopenharmony_ci  TotalSize = 0;
36370b324cSopenharmony_ci
37370b324cSopenharmony_ci  for (;;)
38370b324cSopenharmony_ci  {
39370b324cSopenharmony_ci    UInt32 size = kBufSize;
40370b324cSopenharmony_ci    if (outSize)
41370b324cSopenharmony_ci    {
42370b324cSopenharmony_ci      const UInt64 rem = *outSize - TotalSize;
43370b324cSopenharmony_ci      if (size > rem)
44370b324cSopenharmony_ci      {
45370b324cSopenharmony_ci        size = (UInt32)rem;
46370b324cSopenharmony_ci        if (size == 0)
47370b324cSopenharmony_ci        {
48370b324cSopenharmony_ci          /* if we enable the following check,
49370b324cSopenharmony_ci             we will make one call of Read(_buf, 0) for empty stream */
50370b324cSopenharmony_ci          // if (TotalSize != 0)
51370b324cSopenharmony_ci          return S_OK;
52370b324cSopenharmony_ci        }
53370b324cSopenharmony_ci      }
54370b324cSopenharmony_ci    }
55370b324cSopenharmony_ci
56370b324cSopenharmony_ci    HRESULT readRes;
57370b324cSopenharmony_ci    {
58370b324cSopenharmony_ci      UInt32 pos = 0;
59370b324cSopenharmony_ci      do
60370b324cSopenharmony_ci      {
61370b324cSopenharmony_ci        const UInt32 curSize = size - pos;
62370b324cSopenharmony_ci        UInt32 processed = 0;
63370b324cSopenharmony_ci        readRes = inStream->Read(_buf + pos, curSize, &processed);
64370b324cSopenharmony_ci        if (processed > curSize)
65370b324cSopenharmony_ci          return E_FAIL; // internal code failure
66370b324cSopenharmony_ci        pos += processed;
67370b324cSopenharmony_ci        if (readRes != S_OK || processed == 0)
68370b324cSopenharmony_ci          break;
69370b324cSopenharmony_ci      }
70370b324cSopenharmony_ci      while (pos < kBufSize);
71370b324cSopenharmony_ci      size = pos;
72370b324cSopenharmony_ci    }
73370b324cSopenharmony_ci
74370b324cSopenharmony_ci    if (size == 0)
75370b324cSopenharmony_ci      return readRes;
76370b324cSopenharmony_ci
77370b324cSopenharmony_ci    if (outStream)
78370b324cSopenharmony_ci    {
79370b324cSopenharmony_ci      UInt32 pos = 0;
80370b324cSopenharmony_ci      do
81370b324cSopenharmony_ci      {
82370b324cSopenharmony_ci        const UInt32 curSize = size - pos;
83370b324cSopenharmony_ci        UInt32 processed = 0;
84370b324cSopenharmony_ci        const HRESULT res = outStream->Write(_buf + pos, curSize, &processed);
85370b324cSopenharmony_ci        if (processed > curSize)
86370b324cSopenharmony_ci          return E_FAIL; // internal code failure
87370b324cSopenharmony_ci        pos += processed;
88370b324cSopenharmony_ci        TotalSize += processed;
89370b324cSopenharmony_ci        RINOK(res)
90370b324cSopenharmony_ci        if (processed == 0)
91370b324cSopenharmony_ci          return E_FAIL;
92370b324cSopenharmony_ci      }
93370b324cSopenharmony_ci      while (pos < size);
94370b324cSopenharmony_ci    }
95370b324cSopenharmony_ci    else
96370b324cSopenharmony_ci      TotalSize += size;
97370b324cSopenharmony_ci
98370b324cSopenharmony_ci    RINOK(readRes)
99370b324cSopenharmony_ci
100370b324cSopenharmony_ci    if (size != kBufSize)
101370b324cSopenharmony_ci      return S_OK;
102370b324cSopenharmony_ci
103370b324cSopenharmony_ci    if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0)
104370b324cSopenharmony_ci    {
105370b324cSopenharmony_ci      RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize))
106370b324cSopenharmony_ci    }
107370b324cSopenharmony_ci  }
108370b324cSopenharmony_ci}
109370b324cSopenharmony_ci
110370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream))
111370b324cSopenharmony_ci{
112370b324cSopenharmony_ci  _inStream = inStream;
113370b324cSopenharmony_ci  TotalSize = 0;
114370b324cSopenharmony_ci  return S_OK;
115370b324cSopenharmony_ci}
116370b324cSopenharmony_ci
117370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::ReleaseInStream())
118370b324cSopenharmony_ci{
119370b324cSopenharmony_ci  _inStream.Release();
120370b324cSopenharmony_ci  return S_OK;
121370b324cSopenharmony_ci}
122370b324cSopenharmony_ci
123370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
124370b324cSopenharmony_ci{
125370b324cSopenharmony_ci  UInt32 realProcessedSize = 0;
126370b324cSopenharmony_ci  HRESULT res = _inStream->Read(data, size, &realProcessedSize);
127370b324cSopenharmony_ci  TotalSize += realProcessedSize;
128370b324cSopenharmony_ci  if (processedSize)
129370b324cSopenharmony_ci    *processedSize = realProcessedSize;
130370b324cSopenharmony_ci  return res;
131370b324cSopenharmony_ci}
132370b324cSopenharmony_ci
133370b324cSopenharmony_ciZ7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value))
134370b324cSopenharmony_ci{
135370b324cSopenharmony_ci  *value = TotalSize;
136370b324cSopenharmony_ci  return S_OK;
137370b324cSopenharmony_ci}
138370b324cSopenharmony_ci
139370b324cSopenharmony_ciHRESULT CopyStream(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
140370b324cSopenharmony_ci{
141370b324cSopenharmony_ci  CMyComPtr<ICompressCoder> copyCoder = new CCopyCoder;
142370b324cSopenharmony_ci  return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
143370b324cSopenharmony_ci}
144370b324cSopenharmony_ci
145370b324cSopenharmony_ciHRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream *outStream, UInt64 size, ICompressProgressInfo *progress)
146370b324cSopenharmony_ci{
147370b324cSopenharmony_ci  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
148370b324cSopenharmony_ci  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
149370b324cSopenharmony_ci  RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress))
150370b324cSopenharmony_ci  return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
151370b324cSopenharmony_ci}
152370b324cSopenharmony_ci
153370b324cSopenharmony_ci}
154