diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp | 327 |
1 files changed, 204 insertions, 123 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp b/3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp index 9002678ae08..4f05b4833b6 100644 --- a/3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp +++ b/3rdparty/lzma/CPP/7zip/Compress/LzmaDecoder.cpp @@ -24,243 +24,324 @@ static HRESULT SResToHRESULT(SRes res) namespace NCompress { namespace NLzma { -CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false), - _inBufSize(1 << 20), - _outBufSize(1 << 22), +CDecoder::CDecoder(): FinishStream(false), - NeedMoreInput(false) + _propsWereSet(false), + _outSizeDefined(false), + _outStep(1 << 20), + _inBufSize(0), + _inBufSizeNew(1 << 20), + _lzmaStatus(LZMA_STATUS_NOT_SPECIFIED), + _inBuf(NULL) { - _inSizeProcessed = 0; - _inPos = _inSize = 0; - LzmaDec_Construct(&_state); + _inProcessed = 0; + _inPos = _inLim = 0; + + /* + AlignOffsetAlloc_CreateVTable(&_alloc); + _alloc.numAlignBits = 7; + _alloc.offset = 0; + */ + LzmaDec_CONSTRUCT(&_state) } CDecoder::~CDecoder() { - LzmaDec_Free(&_state, &g_Alloc); + LzmaDec_Free(&_state, &g_AlignedAlloc); // &_alloc.vt MyFree(_inBuf); } -STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; } -STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; } +Z7_COM7F_IMF(CDecoder::SetInBufSize(UInt32 , UInt32 size)) + { _inBufSizeNew = size; return S_OK; } +Z7_COM7F_IMF(CDecoder::SetOutBufSize(UInt32 , UInt32 size)) + { _outStep = size; return S_OK; } HRESULT CDecoder::CreateInputBuffer() { - if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated) + if (!_inBuf || _inBufSizeNew != _inBufSize) { MyFree(_inBuf); - _inBuf = (Byte *)MyAlloc(_inBufSize); - if (_inBuf == 0) + _inBufSize = 0; + _inBuf = (Byte *)MyAlloc(_inBufSizeNew); + if (!_inBuf) return E_OUTOFMEMORY; - _inBufSizeAllocated = _inBufSize; + _inBufSize = _inBufSizeNew; } return S_OK; } -STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size) + +Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)) { - RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc))); + RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_AlignedAlloc))) // &_alloc.vt _propsWereSet = true; return CreateInputBuffer(); } + void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize) { _outSizeDefined = (outSize != NULL); + _outSize = 0; if (_outSizeDefined) _outSize = *outSize; - _outSizeProcessed = 0; - _wrPos = 0; + _outProcessed = 0; + _lzmaStatus = LZMA_STATUS_NOT_SPECIFIED; + LzmaDec_Init(&_state); } -STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) + +Z7_COM7F_IMF(CDecoder::SetOutStreamSize(const UInt64 *outSize)) { - _inSizeProcessed = 0; - _inPos = _inSize = 0; - NeedMoreInput = false; + _inProcessed = 0; + _inPos = _inLim = 0; SetOutStreamSizeResume(outSize); return S_OK; } -STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode) + +Z7_COM7F_IMF(CDecoder::SetFinishMode(UInt32 finishMode)) { FinishStream = (finishMode != 0); return S_OK; } + +Z7_COM7F_IMF(CDecoder::GetInStreamProcessedSize(UInt64 *value)) +{ + *value = _inProcessed; + return S_OK; +} + + HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - if (_inBuf == 0 || !_propsWereSet) + if (!_inBuf || !_propsWereSet) return S_FALSE; + + const UInt64 startInProgress = _inProcessed; + SizeT wrPos = _state.dicPos; + HRESULT readRes = S_OK; - UInt64 startInProgress = _inSizeProcessed; - - SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); for (;;) { - if (_inPos == _inSize) + if (_inPos == _inLim && readRes == S_OK) { - _inPos = _inSize = 0; - RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + _inPos = _inLim = 0; + readRes = inStream->Read(_inBuf, _inBufSize, &_inLim); + } + + const SizeT dicPos = _state.dicPos; + SizeT size; + { + SizeT next = _state.dicBufSize; + if (next - wrPos > _outStep) + next = wrPos + _outStep; + size = next - dicPos; } - SizeT dicPos = _state.dicPos; - SizeT curSize = next - dicPos; - ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { - const UInt64 rem = _outSize - _outSizeProcessed; - if (rem <= curSize) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - curSize = (SizeT)rem; + size = (SizeT)rem; if (FinishStream) finishMode = LZMA_FINISH_END; } } - SizeT inSizeProcessed = _inSize - _inPos; + SizeT inProcessed = _inLim - _inPos; ELzmaStatus status; - SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); - _inPos += (UInt32)inSizeProcessed; - _inSizeProcessed += inSizeProcessed; - SizeT outSizeProcessed = _state.dicPos - dicPos; - _outSizeProcessed += outSizeProcessed; + const SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + const SizeT outProcessed = _state.dicPos - dicPos; + _outProcessed += outProcessed; - bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); - bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); + // we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0) + const bool outFinished = (_outSizeDefined && _outProcessed >= _outSize); - if (res != 0 || _state.dicPos == next || finished || stopDecoding) + const bool needStop = (res != 0 + || (inProcessed == 0 && outProcessed == 0) + || status == LZMA_STATUS_FINISHED_WITH_MARK + || (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)); + + if (needStop || outProcessed >= size) { - HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos); + const HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos); - _wrPos = _state.dicPos; if (_state.dicPos == _state.dicBufSize) - { _state.dicPos = 0; - _wrPos = 0; - } - next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize); + wrPos = _state.dicPos; + + RINOK(res2) - if (res != 0) - return S_FALSE; - RINOK(res2); - if (stopDecoding) + if (needStop) { - if (status == LZMA_STATUS_NEEDS_MORE_INPUT) - NeedMoreInput = true; - if (FinishStream && - status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + if (res != 0) + { + // return SResToHRESULT(res); return S_FALSE; - return S_OK; - } - if (finished) - { - if (status == LZMA_STATUS_NEEDS_MORE_INPUT) - NeedMoreInput = true; - return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); + } + + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + { + if (FinishStream) + if (_outSizeDefined && _outSize != _outProcessed) + return S_FALSE; + return readRes; + } + + if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT) + if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return readRes; + + return S_FALSE; } } + if (progress) { - UInt64 inSize = _inSizeProcessed - startInProgress; - RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed)); + const UInt64 inSize = _inProcessed - startInProgress; + RINOK(progress->SetRatioInfo(&inSize, &_outProcessed)) } } } -STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, - const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) + +Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)) { - if (_inBuf == 0) + if (!_inBuf) return E_INVALIDARG; SetOutStreamSize(outSize); - return CodeSpec(inStream, outStream, progress); + HRESULT res = CodeSpec(inStream, outStream, progress); + if (res == S_OK) + if (FinishStream && inSize && *inSize != _inProcessed) + res = S_FALSE; + return res; } -#ifndef NO_READ_FROM_CODER -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; } +#ifndef Z7_NO_READ_FROM_CODER -STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) +Z7_COM7F_IMF(CDecoder::SetInStream(ISequentialInStream *inStream)) + { _inStream = inStream; return S_OK; } +Z7_COM7F_IMF(CDecoder::ReleaseInStream()) + { _inStream.Release(); return S_OK; } + +Z7_COM7F_IMF(CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)) { if (processedSize) *processedSize = 0; - do + + ELzmaFinishMode finishMode = LZMA_FINISH_ANY; + if (_outSizeDefined) { - if (_inPos == _inSize) + const UInt64 rem = _outSize - _outProcessed; + if (size >= rem) { - _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); + size = (UInt32)rem; + if (FinishStream) + finishMode = LZMA_FINISH_END; } + } + + HRESULT readRes = S_OK; + + for (;;) + { + if (_inPos == _inLim && readRes == S_OK) { - SizeT inProcessed = _inSize - _inPos; + _inPos = _inLim = 0; + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + } - if (_outSizeDefined) - { - const UInt64 rem = _outSize - _outSizeProcessed; - if (rem < size) - size = (UInt32)rem; - } + SizeT inProcessed = _inLim - _inPos; + SizeT outProcessed = size; + ELzmaStatus status; + + const SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, + _inBuf + _inPos, &inProcessed, finishMode, &status); + + _lzmaStatus = status; + _inPos += (UInt32)inProcessed; + _inProcessed += inProcessed; + _outProcessed += outProcessed; + size -= (UInt32)outProcessed; + data = (Byte *)data + outProcessed; + if (processedSize) + *processedSize += (UInt32)outProcessed; + + if (res != 0) + return S_FALSE; + + /* + if (status == LZMA_STATUS_FINISHED_WITH_MARK) + return readRes; - SizeT outProcessed = size; - ELzmaStatus status; - SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, - _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); - _inPos += (UInt32)inProcessed; - _inSizeProcessed += inProcessed; - _outSizeProcessed += outProcessed; - size -= (UInt32)outProcessed; - data = (Byte *)data + outProcessed; - if (processedSize) - *processedSize += (UInt32)outProcessed; - RINOK(SResToHRESULT(res)); - if (inProcessed == 0 && outProcessed == 0) - return S_OK; + if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT) + { + if (FinishStream + && _outSizeDefined && _outProcessed >= _outSize + && status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) + return S_FALSE; + return readRes; } + */ + + if (inProcessed == 0 && outProcessed == 0) + return readRes; } - while (size != 0); - return S_OK; } + HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress) { SetOutStreamSizeResume(outSize); return CodeSpec(_inStream, outStream, progress); } + HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize) { - RINOK(CreateInputBuffer()); + RINOK(CreateInputBuffer()) + if (processedSize) *processedSize = 0; - while (size > 0) + + HRESULT readRes = S_OK; + + while (size != 0) { - if (_inPos == _inSize) + if (_inPos == _inLim) { - _inPos = _inSize = 0; - RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize)); - if (_inSize == 0) + _inPos = _inLim = 0; + if (readRes == S_OK) + readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim); + if (_inLim == 0) break; } - { - UInt32 curSize = _inSize - _inPos; - if (curSize > size) - curSize = size; - memcpy(data, _inBuf + _inPos, curSize); - _inPos += curSize; - _inSizeProcessed += curSize; - size -= curSize; - data = (Byte *)data + curSize; - if (processedSize) - *processedSize += curSize; - } + + UInt32 cur = _inLim - _inPos; + if (cur > size) + cur = size; + memcpy(data, _inBuf + _inPos, cur); + _inPos += cur; + _inProcessed += cur; + size -= cur; + data = (Byte *)data + cur; + if (processedSize) + *processedSize += cur; } - return S_OK; + + return readRes; } #endif |