diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2018-03-12 14:19:17 +0300 |
---|---|---|
committer | Kornel <kornel@geekhood.net> | 2018-03-12 14:19:46 +0300 |
commit | f19b649c73cd8b74c4e0b8a3a728a82c6bda47b4 (patch) | |
tree | 3725026df472886583a019239ed169e356ce1f63 /CPP/7zip/Compress/XzDecoder.cpp | |
parent | 866a06f5a0c0ede11979504a318e150030aa7a11 (diff) |
18.0318.03
Diffstat (limited to 'CPP/7zip/Compress/XzDecoder.cpp')
-rw-r--r-- | CPP/7zip/Compress/XzDecoder.cpp | 289 |
1 files changed, 88 insertions, 201 deletions
diff --git a/CPP/7zip/Compress/XzDecoder.cpp b/CPP/7zip/Compress/XzDecoder.cpp index c28ac900..7a974311 100644 --- a/CPP/7zip/Compress/XzDecoder.cpp +++ b/CPP/7zip/Compress/XzDecoder.cpp @@ -4,248 +4,119 @@ #include "../../../C/Alloc.h" -#include "../Common/StreamUtils.h" - -#include "../Archive/IArchive.h" +#include "../Common/CWrappers.h" #include "XzDecoder.h" -using namespace NArchive; - namespace NCompress { namespace NXz { +#define RET_IF_WRAP_ERROR_CONFIRMED(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK && sRes == sResErrorCode) return wrapRes; -CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(NULL), OutBuf(NULL) -{ - XzUnpacker_Construct(&p, &g_Alloc); -} - -CXzUnpackerCPP::~CXzUnpackerCPP() -{ - XzUnpacker_Free(&p); - MidFree(InBuf); - MidFree(OutBuf); -} - +#define RET_IF_WRAP_ERROR(wrapRes, sRes, sResErrorCode) \ + if (wrapRes != S_OK /* && (sRes == SZ_OK || sRes == sResErrorCode) */) return wrapRes; -void CStatInfo::Clear() +static HRESULT SResToHRESULT_Code(SRes res) throw() { - InSize = 0; - OutSize = 0; - PhySize = 0; - - NumStreams = 0; - NumBlocks = 0; - - UnpackSize_Defined = false; - - NumStreams_Defined = false; - NumBlocks_Defined = false; - - IsArc = false; - UnexpectedEnd = false; - DataAfterEnd = false; - Unsupported = false; - HeadersError = false; - DataError = false; - CrcError = false; + if (res < 0) + return res; + switch (res) + { + case SZ_OK: return S_OK; + case SZ_ERROR_MEM: return E_OUTOFMEMORY; + case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL; + } + return S_FALSE; } HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream, const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress) { - const size_t kInBufSize = (size_t)1 << 20; - const size_t kOutBufSize = (size_t)1 << 21; - - Clear(); - DecodeRes = SZ_OK; - - XzUnpacker_Init(&xzu.p); + MainDecodeSRes = S_OK; + MainDecodeSRes_wasUsed = false; + XzStatInfo_Clear(&Stat); - if (!xzu.InBuf) + if (!xz) { - xzu.InBuf = (Byte *)MidAlloc(kInBufSize); - if (!xzu.InBuf) + xz = XzDecMt_Create(&g_Alloc, &g_MidAlloc); + if (!xz) return E_OUTOFMEMORY; } - if (!xzu.OutBuf) - { - xzu.OutBuf = (Byte *)MidAlloc(kOutBufSize); - if (!xzu.OutBuf) - return E_OUTOFMEMORY; - } - - UInt32 inSize = 0; - UInt32 inPos = 0; - SizeT outPos = 0; - HRESULT readRes = S_OK; + CXzDecMtProps props; + XzDecMtProps_Init(&props); - for (;;) + int isMT = False; + + #ifndef _7ZIP_ST { - if (inPos == inSize && readRes == S_OK) + props.numThreads = 1; + UInt32 numThreads = _numThreads; + + if (_tryMt && numThreads > 1) { - inPos = inSize = 0; - readRes = seqInStream->Read(xzu.InBuf, kInBufSize, &inSize); + size_t memUsage = (size_t)_memUsage; + if (memUsage != _memUsage) + memUsage = (size_t)0 - 1; + props.memUseMax = memUsage; + isMT = (numThreads > 1); } - SizeT inLen = inSize - inPos; - SizeT outLen = kOutBufSize - outPos; - ECoderFinishMode finishMode = CODER_FINISH_ANY; + props.numThreads = numThreads; + } + #endif - /* - // 17.01 : the code was disabled: - if (inSize == 0) - finishMode = CODER_FINISH_END; - */ + CSeqInStreamWrap inWrap; + CSeqOutStreamWrap outWrap; + CCompressProgressWrap progressWrap; - if (outSizeLimit) - { - const UInt64 rem = *outSizeLimit - OutSize; - if (outLen >= rem) - { - outLen = (SizeT)rem; - if (finishStream) - finishMode = CODER_FINISH_END; - } - } - - ECoderStatus status; + inWrap.Init(seqInStream); + outWrap.Init(outStream); + progressWrap.Init(progress); - const SizeT outLenRequested = outLen; + SRes res = XzDecMt_Decode(xz, + &props, + outSizeLimit, finishStream, + &outWrap.vt, + &inWrap.vt, + &Stat, + &isMT, + progress ? &progressWrap.vt : NULL); - SRes res = XzUnpacker_Code(&xzu.p, - xzu.OutBuf + outPos, &outLen, - xzu.InBuf + inPos, &inLen, - finishMode, &status); + MainDecodeSRes = res; - DecodeRes = res; + #ifndef _7ZIP_ST + // _tryMt = isMT; + #endif - inPos += (UInt32)inLen; - outPos += outLen; + RET_IF_WRAP_ERROR(outWrap.Res, res, SZ_ERROR_WRITE) + RET_IF_WRAP_ERROR(progressWrap.Res, res, SZ_ERROR_PROGRESS) + RET_IF_WRAP_ERROR_CONFIRMED(inWrap.Res, res, SZ_ERROR_READ) - InSize += inLen; - OutSize += outLen; + // return E_OUTOFMEMORY; - bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK); + MainDecodeSRes_wasUsed = true; - if (outLen >= outLenRequested || finished) - { - if (outStream && outPos != 0) - { - RINOK(WriteStream(outStream, xzu.OutBuf, outPos)); - } - outPos = 0; - } - - if (progress) - { - RINOK(progress->SetRatioInfo(&InSize, &OutSize)); - } - - if (!finished) - continue; - - { - PhySize = InSize; - NumStreams = xzu.p.numStartedStreams; - if (NumStreams > 0) - IsArc = true; - NumBlocks = xzu.p.numTotalBlocks; - - UnpackSize_Defined = true; - NumStreams_Defined = true; - NumBlocks_Defined = true; - - UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p); - - if (res == SZ_OK) - { - if (status == CODER_STATUS_NEEDS_MORE_INPUT) - { - extraSize = 0; - if (!XzUnpacker_IsStreamWasFinished(&xzu.p)) - { - // finished at padding bytes, but padding is not aligned for 4 - UnexpectedEnd = true; - res = SZ_ERROR_DATA; - } - } - else // status == CODER_STATUS_NOT_FINISHED - res = SZ_ERROR_DATA; - } - else if (res == SZ_ERROR_NO_ARCHIVE) - { - if (InSize == extraSize) - IsArc = false; - else - { - if (extraSize != 0 || inPos != inSize) - { - DataAfterEnd = true; - res = SZ_OK; - } - } - } - - DecodeRes = res; - PhySize -= extraSize; - - switch (res) - { - case SZ_OK: break; - case SZ_ERROR_NO_ARCHIVE: IsArc = false; break; - case SZ_ERROR_ARCHIVE: HeadersError = true; break; - case SZ_ERROR_UNSUPPORTED: Unsupported = true; break; - case SZ_ERROR_CRC: CrcError = true; break; - case SZ_ERROR_DATA: DataError = true; break; - default: DataError = true; break; - } - - return readRes; - } + if (res == SZ_OK && finishStream) + { + /* + if (inSize && *inSize != Stat.PhySize) + res = SZ_ERROR_DATA; + */ + if (outSizeLimit && *outSizeLimit != outWrap.Processed) + res = SZ_ERROR_DATA; } -} - -Int32 CDecoder::Get_Extract_OperationResult() const -{ - Int32 opRes; - if (!IsArc) - opRes = NExtract::NOperationResult::kIsNotArc; - else if (UnexpectedEnd) - opRes = NExtract::NOperationResult::kUnexpectedEnd; - else if (DataAfterEnd) - opRes = NExtract::NOperationResult::kDataAfterEnd; - else if (CrcError) - opRes = NExtract::NOperationResult::kCRCError; - else if (Unsupported) - opRes = NExtract::NOperationResult::kUnsupportedMethod; - else if (HeadersError) - opRes = NExtract::NOperationResult::kDataError; - else if (DataError) - opRes = NExtract::NOperationResult::kDataError; - else if (DecodeRes != SZ_OK) - opRes = NExtract::NOperationResult::kDataError; - else - opRes = NExtract::NOperationResult::kOK; - return opRes; + return SResToHRESULT_Code(res); } - HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { - RINOK(_decoder.Decode(inStream, outStream, outSize, _finishStream, progress)); - Int32 opRes = _decoder.Get_Extract_OperationResult(); - if (opRes == NArchive::NExtract::NOperationResult::kUnsupportedMethod) - return E_NOTIMPL; - if (opRes != NArchive::NExtract::NOperationResult::kOK) - return S_FALSE; - return S_OK; + return Decode(inStream, outStream, outSize, _finishStream, progress); } STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode) @@ -256,8 +127,24 @@ STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode) STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value) { - *value = _decoder.InSize; + *value = Stat.InSize; + return S_OK; +} + +#ifndef _7ZIP_ST + +STDMETHODIMP CComDecoder::SetNumberOfThreads(UInt32 numThreads) +{ + _numThreads = numThreads; return S_OK; } +STDMETHODIMP CComDecoder::SetMemLimit(UInt64 memUsage) +{ + _memUsage = memUsage; + return S_OK; +} + +#endif + }} |