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
11namespace NCompress {
12
13static const UInt32 kBufferSize = 1 << 17;
14
15CCopyCoder::~CCopyCoder()
16{
17  ::MidFree(_buffer);
18}
19
20STDMETHODIMP 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
54STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
55{
56  *value = TotalSize;
57  return S_OK;
58}
59
60HRESULT 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
66HRESULT 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