summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp80
1 files changed, 59 insertions, 21 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp b/3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp
index ac6ab2e718a..b779e08b5b3 100644
--- a/3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp
+++ b/3rdparty/lzma/CPP/7zip/Compress/CopyCoder.cpp
@@ -15,10 +15,15 @@ CCopyCoder::~CCopyCoder()
::MidFree(_buf);
}
-STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
+Z7_COM7F_IMF(CCopyCoder::SetFinishMode(UInt32 /* finishMode */))
+{
+ return S_OK;
+}
+
+Z7_COM7F_IMF(CCopyCoder::Code(ISequentialInStream *inStream,
ISequentialOutStream *outStream,
const UInt64 * /* inSize */, const UInt64 *outSize,
- ICompressProgressInfo *progress)
+ ICompressProgressInfo *progress))
{
if (!_buf)
{
@@ -32,12 +37,39 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
for (;;)
{
UInt32 size = kBufSize;
- if (outSize && size > *outSize - TotalSize)
- size = (UInt32)(*outSize - TotalSize);
- if (size == 0)
- return S_OK;
+ if (outSize)
+ {
+ const UInt64 rem = *outSize - TotalSize;
+ if (size > rem)
+ {
+ size = (UInt32)rem;
+ if (size == 0)
+ {
+ /* if we enable the following check,
+ we will make one call of Read(_buf, 0) for empty stream */
+ // if (TotalSize != 0)
+ return S_OK;
+ }
+ }
+ }
- HRESULT readRes = inStream->Read(_buf, size, &size);
+ HRESULT readRes;
+ {
+ UInt32 pos = 0;
+ do
+ {
+ const UInt32 curSize = size - pos;
+ UInt32 processed = 0;
+ readRes = inStream->Read(_buf + pos, curSize, &processed);
+ if (processed > curSize)
+ return E_FAIL; // internal code failure
+ pos += processed;
+ if (readRes != S_OK || processed == 0)
+ break;
+ }
+ while (pos < kBufSize);
+ size = pos;
+ }
if (size == 0)
return readRes;
@@ -47,12 +79,15 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
UInt32 pos = 0;
do
{
- UInt32 curSize = size - pos;
- HRESULT res = outStream->Write(_buf + pos, curSize, &curSize);
- pos += curSize;
- TotalSize += curSize;
- RINOK(res);
- if (curSize == 0)
+ const UInt32 curSize = size - pos;
+ UInt32 processed = 0;
+ const HRESULT res = outStream->Write(_buf + pos, curSize, &processed);
+ if (processed > curSize)
+ return E_FAIL; // internal code failure
+ pos += processed;
+ TotalSize += processed;
+ RINOK(res)
+ if (processed == 0)
return E_FAIL;
}
while (pos < size);
@@ -60,29 +95,32 @@ STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
else
TotalSize += size;
- RINOK(readRes);
+ RINOK(readRes)
+
+ if (size != kBufSize)
+ return S_OK;
- if (progress)
+ if (progress && (TotalSize & (((UInt32)1 << 22) - 1)) == 0)
{
- RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize));
+ RINOK(progress->SetRatioInfo(&TotalSize, &TotalSize))
}
}
}
-STDMETHODIMP CCopyCoder::SetInStream(ISequentialInStream *inStream)
+Z7_COM7F_IMF(CCopyCoder::SetInStream(ISequentialInStream *inStream))
{
_inStream = inStream;
TotalSize = 0;
return S_OK;
}
-STDMETHODIMP CCopyCoder::ReleaseInStream()
+Z7_COM7F_IMF(CCopyCoder::ReleaseInStream())
{
_inStream.Release();
return S_OK;
}
-STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+Z7_COM7F_IMF(CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize))
{
UInt32 realProcessedSize = 0;
HRESULT res = _inStream->Read(data, size, &realProcessedSize);
@@ -92,7 +130,7 @@ STDMETHODIMP CCopyCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
return res;
}
-STDMETHODIMP CCopyCoder::GetInStreamProcessedSize(UInt64 *value)
+Z7_COM7F_IMF(CCopyCoder::GetInStreamProcessedSize(UInt64 *value))
{
*value = TotalSize;
return S_OK;
@@ -108,7 +146,7 @@ HRESULT CopyStream_ExactSize(ISequentialInStream *inStream, ISequentialOutStream
{
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
- RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress));
+ RINOK(copyCoder->Code(inStream, outStream, NULL, &size, progress))
return copyCoderSpec->TotalSize == size ? S_OK : E_FAIL;
}