xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/CopyCoder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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