SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT outSize = *destLen, inSize = *srcLen; *srcLen = *destLen = 0; for (;;) { SizeT srcSizeCur = inSize, outSizeCur, dicPos; ELzmaFinishMode curFinishMode; SRes res; if (p->decoder.dicPos == p->decoder.dicBufSize) p->decoder.dicPos = 0; dicPos = p->decoder.dicPos; if (outSize > p->decoder.dicBufSize - dicPos) { outSizeCur = p->decoder.dicBufSize; curFinishMode = LZMA_FINISH_ANY; } else { outSizeCur = dicPos + outSize; curFinishMode = finishMode; } res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status); src += srcSizeCur; inSize -= srcSizeCur; *srcLen += srcSizeCur; outSizeCur = p->decoder.dicPos - dicPos; memcpy(dest, p->decoder.dic + dicPos, outSizeCur); dest += outSizeCur; outSize -= outSizeCur; *destLen += outSizeCur; if (res != 0) return res; if (outSizeCur == 0 || outSize == 0) return SZ_OK; } }
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) { CLzma2Dec decoder; SRes res; SizeT outSize = *destLen, inSize = *srcLen; Byte props[LZMA_PROPS_SIZE]; Lzma2Dec_Construct(&decoder); *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; decoder.decoder.dic = dest; decoder.decoder.dicBufSize = outSize; RINOK(Lzma2Dec_GetOldProps(prop, props)); RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc)); *srcLen = inSize; res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status); *destLen = decoder.decoder.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; LzmaDec_FreeProbs(&decoder.decoder, alloc); return res; }
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) { CLzma2Dec state; SRes res = SZ_OK; Lzma2Dec_Construct(&state); if (coder->Props.size != 1) return SZ_ERROR_DATA; RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); state.decoder.dic = outBuffer; state.decoder.dicBufSize = outSize; Lzma2Dec_Init(&state); for (;;) { Byte *inBuf = NULL; size_t lookahead = (1 << 18); if (lookahead > inSize) lookahead = (size_t)inSize; res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); if (res != SZ_OK) break; { SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; ELzmaStatus status; res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); lookahead -= inProcessed; inSize -= inProcessed; if (res != SZ_OK) break; if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) { if (state.decoder.dicBufSize != outSize || lookahead != 0 || (status != LZMA_STATUS_FINISHED_WITH_MARK)) res = SZ_ERROR_DATA; break; } res = inStream->Skip((void *)inStream, inProcessed); if (res != SZ_OK) break; } } Lzma2Dec_FreeProbs(&state, allocMain); return res; }
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) { CLzma2Dec p; SRes res; SizeT outSize = *destLen, inSize = *srcLen; *destLen = *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; Lzma2Dec_Construct(&p); RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)); p.decoder.dic = dest; p.decoder.dicBufSize = outSize; Lzma2Dec_Init(&p); *srcLen = inSize; res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); *destLen = p.decoder.dicPos; if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) res = SZ_ERROR_INPUT_EOF; Lzma2Dec_FreeProbs(&p, alloc); return res; }
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress) { if (_inBuf == 0) return S_FALSE; SetOutStreamSize(outSize); for (;;) { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(inStream->Read(_inBuf, kInBufSize, &_inSize)); } SizeT dicPos = _state.decoder.dicPos; SizeT curSize = _state.decoder.dicBufSize - dicPos; const UInt32 kStepSize = ((UInt32)1 << 22); if (curSize > kStepSize) curSize = (SizeT)kStepSize; ELzmaFinishMode finishMode = LZMA_FINISH_ANY; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < curSize) { curSize = (SizeT)rem; /* // finishMode = LZMA_FINISH_END; we can't use LZMA_FINISH_END here to allow partial decoding */ } } SizeT inSizeProcessed = _inSize - _inPos; ELzmaStatus status; SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status); _inPos += (UInt32)inSizeProcessed; _inSizeProcessed += inSizeProcessed; SizeT outSizeProcessed = _state.decoder.dicPos - dicPos; _outSizeProcessed += outSizeProcessed; bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0); bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize); if (res != 0 || _state.decoder.dicPos == _state.decoder.dicBufSize || finished || stopDecoding) { HRESULT res2 = WriteStream(outStream, _state.decoder.dic, _state.decoder.dicPos); if (res != 0) return S_FALSE; RINOK(res2); if (stopDecoding) return S_OK; if (finished) return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE); } if (_state.decoder.dicPos == _state.decoder.dicBufSize) _state.decoder.dicPos = 0; if (progress != NULL) { RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed)); } } }