SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; while (p->state != LZMA2_STATE_ERROR) { SizeT dicPos; if (p->state == LZMA2_STATE_FINISHED) { *status = LZMA_STATUS_FINISHED_WITH_MARK; return SZ_OK; } dicPos = p->decoder.dicPos; if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } (*srcLen)++; p->state = Lzma2Dec_UpdateState(p, *src++); if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) break; continue; } { SizeT inCur = inSize - *srcLen; SizeT outCur = dicLimit - dicPos; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; if (outCur >= p->unpackSize) { outCur = (SizeT)p->unpackSize; curFinishMode = LZMA_FINISH_END; } if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (inCur == 0) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->state == LZMA2_STATE_DATA) { BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); LzmaDec_InitDicAndState(&p->decoder, initDic, False); } if (inCur > outCur) inCur = outCur; if (inCur == 0) break; LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); src += inCur; *srcLen += inCur; p->unpackSize -= (UInt32)inCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; } else { SRes res; if (p->state == LZMA2_STATE_DATA) { BoolInt initDic = (p->control >= 0xE0); BoolInt initState = (p->control >= 0xA0); LzmaDec_InitDicAndState(&p->decoder, initDic, initState); p->state = LZMA2_STATE_DATA_CONT; } if (inCur > p->packSize) inCur = (SizeT)p->packSize; res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); src += inCur; *srcLen += inCur; p->packSize -= (UInt32)inCur; outCur = p->decoder.dicPos - dicPos; p->unpackSize -= (UInt32)outCur; if (res != 0) break; if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) { if (p->packSize == 0) break; return SZ_OK; } if (inCur == 0 && outCur == 0) { if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || p->unpackSize != 0 || p->packSize != 0) break; p->state = LZMA2_STATE_CONTROL; } *status = LZMA_STATUS_NOT_SPECIFIED; } } } *status = LZMA_STATUS_NOT_SPECIFIED; p->state = LZMA2_STATE_ERROR; return SZ_ERROR_DATA; }
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) { SizeT inSize = *srcLen; *srcLen = 0; *status = LZMA_STATUS_NOT_SPECIFIED; while (p->state != LZMA2_STATE_FINISHED) { SizeT dicPos = p->decoder.dicPos; if (p->state == LZMA2_STATE_ERROR) return SZ_ERROR_DATA; if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) { *status = LZMA_STATUS_NOT_FINISHED; return SZ_OK; } if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } (*srcLen)++; p->state = Lzma2Dec_UpdateState(p, *src++); continue; } { SizeT destSizeCur = dicLimit - dicPos; SizeT srcSizeCur = inSize - *srcLen; ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; if (p->unpackSize <= destSizeCur) { destSizeCur = (SizeT)p->unpackSize; curFinishMode = LZMA_FINISH_END; } if (LZMA2_IS_UNCOMPRESSED_STATE(p)) { if (*srcLen == inSize) { *status = LZMA_STATUS_NEEDS_MORE_INPUT; return SZ_OK; } if (p->state == LZMA2_STATE_DATA) { Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); if (initDic) p->needInitProp = p->needInitState = True; else if (p->needInitDic) return SZ_ERROR_DATA; p->needInitDic = False; LzmaDec_InitDicAndState(&p->decoder, initDic, False); } if (srcSizeCur > destSizeCur) srcSizeCur = destSizeCur; if (srcSizeCur == 0) return SZ_ERROR_DATA; LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur); src += srcSizeCur; *srcLen += srcSizeCur; p->unpackSize -= (UInt32)srcSizeCur; p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; } else { SizeT outSizeProcessed; SRes res; if (p->state == LZMA2_STATE_DATA) { int mode = LZMA2_GET_LZMA_MODE(p); Bool initDic = (mode == 3); Bool initState = (mode > 0); if ((!initDic && p->needInitDic) || (!initState && p->needInitState)) return SZ_ERROR_DATA; LzmaDec_InitDicAndState(&p->decoder, initDic, initState); p->needInitDic = False; p->needInitState = False; p->state = LZMA2_STATE_DATA_CONT; } if (srcSizeCur > p->packSize) srcSizeCur = (SizeT)p->packSize; res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status); src += srcSizeCur; *srcLen += srcSizeCur; p->packSize -= (UInt32)srcSizeCur; outSizeProcessed = p->decoder.dicPos - dicPos; p->unpackSize -= (UInt32)outSizeProcessed; RINOK(res); if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) return res; if (srcSizeCur == 0 && outSizeProcessed == 0) { if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK || p->unpackSize != 0 || p->packSize != 0) return SZ_ERROR_DATA; p->state = LZMA2_STATE_CONTROL; } if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK) *status = LZMA_STATUS_NOT_FINISHED; } } } *status = LZMA_STATUS_FINISHED_WITH_MARK; return SZ_OK; }