#include "Precomp.h"
#ifdef XZ_DUMP
#include <stdio.h>
#endif
#ifdef SHOW_DEBUG_INFO
#include <stdio.h>
#endif
#ifdef SHOW_DEBUG_INFO
#define PRF …
#else
#define PRF(x) …
#endif
#define PRF_STR(s) …
#define PRF_STR_INT(s, d) …
#include <stdlib.h>
#include <string.h>
#include "7zCrc.h"
#include "Alloc.h"
#include "Bra.h"
#include "CpuArch.h"
#include "Delta.h"
#include "Lzma2Dec.h"
#ifdef USE_SUBBLOCK
#include "Bcj3Dec.c"
#include "SbDec.h"
#endif
#include "Xz.h"
#define XZ_CHECK_SIZE_MAX …
#define CODER_BUF_SIZE …
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
{ … }
#define BRA_BUF_SIZE …
CBraState;
static void BraState_Free(void *pp, ISzAllocPtr alloc)
{ … }
static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{ … }
static void BraState_Init(void *pp)
{ … }
#define CASE_BRA_CONV(isa) …
static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
{ … }
static SRes BraState_Code2(void *pp,
Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode,
ECoderStatus *status)
{ … }
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc);
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
{ … }
#ifdef USE_SUBBLOCK
static void SbState_Free(void *pp, ISzAllocPtr alloc)
{
CSbDec *p = (CSbDec *)pp;
SbDec_Free(p);
ISzAlloc_Free(alloc, pp);
}
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{
UNUSED_VAR(pp);
UNUSED_VAR(props);
UNUSED_VAR(alloc);
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
}
static void SbState_Init(void *pp)
{
SbDec_Init((CSbDec *)pp);
}
static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode,
ECoderStatus *status)
{
CSbDec *p = (CSbDec *)pp;
SRes res;
UNUSED_VAR(srcWasFinished);
p->dest = dest;
p->destLen = *destLen;
p->src = src;
p->srcLen = *srcLen;
p->finish = finishMode;
res = SbDec_Decode((CSbDec *)pp);
*destLen -= p->destLen;
*srcLen -= p->srcLen;
*status = (*destLen == 0 && *srcLen == 0) ?
CODER_STATUS_FINISHED_WITH_MARK :
CODER_STATUS_NOT_FINISHED;
return res;
}
static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
{
CSbDec *decoder = (CSbDec *)p->p;
if (!decoder)
{
decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
if (!decoder)
return SZ_ERROR_MEM;
p->p = decoder;
p->Free = SbState_Free;
p->SetProps = SbState_SetProps;
p->Init = SbState_Init;
p->Code2 = SbState_Code2;
p->Filter = NULL;
}
SbDec_Construct(decoder);
SbDec_SetAlloc(decoder, alloc);
return SZ_OK;
}
#endif
CLzma2Dec_Spec;
static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
{ … }
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
{ … }
static void Lzma2State_Init(void *pp)
{ … }
static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
int srcWasFinished, ECoderFinishMode finishMode,
ECoderStatus *status)
{ … }
static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
{ … }
static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
{ … }
static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
{ … }
static void MixCoder_Free(CMixCoder *p)
{ … }
static void MixCoder_Init(CMixCoder *p)
{ … }
static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
{ … }
static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
{ … }
static SRes MixCoder_Code(CMixCoder *p,
Byte *dest, SizeT *destLen, int destFinish,
const Byte *src, SizeT *srcLen, int srcWasFinished,
ECoderFinishMode finishMode)
{ … }
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
{ … }
static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
{ … }
#define READ_VARINT_AND_CHECK(buf, pos, size, res) …
static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p)
{ … }
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
{ … }
static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
{ … }
void XzUnpacker_Init(CXzUnpacker *p)
{ … }
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
{ … }
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
{ … }
void XzUnpacker_Free(CXzUnpacker *p)
{ … }
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
{ … }
static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
{ … }
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, int srcFinished,
ECoderFinishMode finishMode, ECoderStatus *status)
{ … }
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen,
ECoderFinishMode finishMode, ECoderStatus *status)
{ … }
BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
{ … }
BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
{ … }
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
{ … }
#ifndef _7ZIP_ST
#include "MtDec.h"
#endif
void XzDecMtProps_Init(CXzDecMtProps *p)
{ … }
#ifndef _7ZIP_ST
typedef struct
{
Byte *outBuf;
size_t outBufSize;
size_t outPreSize;
size_t inPreSize;
size_t inPreHeaderSize;
size_t blockPackSize_for_Index;
size_t blockPackTotal;
size_t inCodeSize;
size_t outCodeSize;
ECoderStatus status;
SRes codeRes;
BoolInt skipMode;
EMtDecParseState parseState;
BoolInt parsing_Truncated;
BoolInt atBlockHeader;
CXzStreamFlags streamFlags;
UInt64 numStreams;
UInt64 numTotalBlocks;
UInt64 numBlocks;
BoolInt dec_created;
CXzUnpacker dec;
Byte mtPad[1 << 7];
} CXzDecMtThread;
#endif
CXzDecMt;
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
{ … }
#ifndef _7ZIP_ST
static void XzDecMt_FreeOutBufs(CXzDecMt *p)
{
unsigned i;
for (i = 0; i < MTDEC__THREADS_MAX; i++)
{
CXzDecMtThread *coder = &p->coders[i];
if (coder->outBuf)
{
ISzAlloc_Free(p->allocMid, coder->outBuf);
coder->outBuf = NULL;
coder->outBufSize = 0;
}
}
p->unpackBlockMaxSize = 0;
}
#endif
static void XzDecMt_FreeSt(CXzDecMt *p)
{ … }
void XzDecMt_Destroy(CXzDecMtHandle pp)
{ … }
#ifndef _7ZIP_ST
static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
{
CXzDecMt *me = (CXzDecMt *)obj;
CXzDecMtThread *coder = &me->coders[coderIndex];
size_t srcSize = cc->srcSize;
cc->srcSize = 0;
cc->outPos = 0;
cc->state = MTDEC_PARSE_CONTINUE;
cc->canCreateNewThread = True;
if (cc->startCall)
{
coder->outPreSize = 0;
coder->inPreSize = 0;
coder->inPreHeaderSize = 0;
coder->parseState = MTDEC_PARSE_CONTINUE;
coder->parsing_Truncated = False;
coder->skipMode = False;
coder->codeRes = SZ_OK;
coder->status = CODER_STATUS_NOT_SPECIFIED;
coder->inCodeSize = 0;
coder->outCodeSize = 0;
coder->numStreams = me->numStreams;
coder->numTotalBlocks = me->numTotalBlocks;
coder->numBlocks = me->numBlocks;
if (!coder->dec_created)
{
XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
coder->dec_created = True;
}
XzUnpacker_Init(&coder->dec);
if (me->isBlockHeaderState_Parse)
{
coder->dec.streamFlags = me->streamFlags;
coder->atBlockHeader = True;
XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
}
else
{
coder->atBlockHeader = False;
me->isBlockHeaderState_Parse = True;
}
coder->dec.numStartedStreams = me->numStreams;
coder->dec.numTotalBlocks = me->numTotalBlocks;
coder->dec.numBlocks = me->numBlocks;
}
while (!coder->skipMode)
{
ECoderStatus status;
SRes res;
size_t srcSize2 = srcSize;
size_t destSize = (size_t)0 - 1;
coder->dec.parseMode = True;
coder->dec.headerParsedOk = False;
PRF_STR_INT("Parse", srcSize2);
res = XzUnpacker_Code(&coder->dec,
NULL, &destSize,
cc->src, &srcSize2, cc->srcFinished,
CODER_FINISH_END, &status);
coder->codeRes = res;
coder->status = status;
cc->srcSize += srcSize2;
srcSize -= srcSize2;
coder->inPreHeaderSize += srcSize2;
coder->inPreSize = coder->inPreHeaderSize;
if (res != SZ_OK)
{
cc->state =
coder->parseState = MTDEC_PARSE_END;
return;
}
if (coder->dec.headerParsedOk)
{
const CXzBlock *block = &coder->dec.block;
if (XzBlock_HasUnpackSize(block)
&& XzBlock_HasPackSize(block))
{
{
if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
{
cc->state = MTDEC_PARSE_OVERFLOW;
return;
}
}
{
UInt64 packSize = block->packSize;
UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
{
coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
coder->blockPackTotal = (size_t)blockPackSum;
coder->outPreSize = (size_t)block->unpackSize;
coder->streamFlags = coder->dec.streamFlags;
me->streamFlags = coder->dec.streamFlags;
coder->skipMode = True;
break;
}
}
}
}
else
{
if (!cc->srcFinished)
return;
cc->state =
coder->parseState = MTDEC_PARSE_END;
return;
}
cc->state = MTDEC_PARSE_OVERFLOW;
return;
}
{
UInt64 rem = coder->blockPackTotal - coder->inPreSize;
size_t cur = srcSize;
if (cur > rem)
cur = (size_t)rem;
cc->srcSize += cur;
coder->inPreSize += cur;
srcSize -= cur;
if (coder->inPreSize == coder->blockPackTotal)
{
if (srcSize == 0)
{
if (!cc->srcFinished)
return;
cc->state = MTDEC_PARSE_END;
}
else if ((cc->src)[cc->srcSize] == 0)
cc->state = MTDEC_PARSE_END;
else
{
cc->state = MTDEC_PARSE_NEW;
{
size_t blockMax = me->unpackBlockMaxSize;
if (blockMax < coder->outPreSize)
blockMax = coder->outPreSize;
{
UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
if (me->props.memUseMax < required)
cc->canCreateNewThread = False;
}
}
if (me->outSize_Defined)
{
const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
if (rem2 < coder->outPreSize)
{
coder->parsing_Truncated = True;
cc->state = MTDEC_PARSE_END;
}
me->outProcessed_Parse += coder->outPreSize;
}
}
}
else if (cc->srcFinished)
cc->state = MTDEC_PARSE_END;
else
return;
coder->parseState = cc->state;
cc->outPos = coder->outPreSize;
me->numStreams = coder->dec.numStartedStreams;
me->numTotalBlocks = coder->dec.numTotalBlocks;
me->numBlocks = coder->dec.numBlocks + 1;
return;
}
}
static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
{
CXzDecMt *me = (CXzDecMt *)pp;
CXzDecMtThread *coder = &me->coders[coderIndex];
Byte *dest;
if (!coder->dec.headerParsedOk)
return SZ_OK;
dest = coder->outBuf;
if (!dest || coder->outBufSize < coder->outPreSize)
{
if (dest)
{
ISzAlloc_Free(me->allocMid, dest);
coder->outBuf = NULL;
coder->outBufSize = 0;
}
{
size_t outPreSize = coder->outPreSize;
if (outPreSize == 0)
outPreSize = 1;
dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
}
if (!dest)
return SZ_ERROR_MEM;
coder->outBuf = dest;
coder->outBufSize = coder->outPreSize;
if (coder->outBufSize > me->unpackBlockMaxSize)
me->unpackBlockMaxSize = coder->outBufSize;
}
XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
{
SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
coder->codeRes = res;
if (res != SZ_OK)
{
if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
return SZ_OK;
return res;
}
}
return SZ_OK;
}
static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
const Byte *src, size_t srcSize, int srcFinished,
UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
{
CXzDecMt *me = (CXzDecMt *)pp;
CXzDecMtThread *coder = &me->coders[coderIndex];
*inCodePos = coder->inCodeSize;
*outCodePos = coder->outCodeSize;
*stop = True;
if (srcSize > coder->inPreSize - coder->inCodeSize)
return SZ_ERROR_FAIL;
if (coder->inCodeSize < coder->inPreHeaderSize)
{
size_t step = coder->inPreHeaderSize - coder->inCodeSize;
if (step > srcSize)
step = srcSize;
src += step;
srcSize -= step;
coder->inCodeSize += step;
*inCodePos = coder->inCodeSize;
if (coder->inCodeSize < coder->inPreHeaderSize)
{
*stop = False;
return SZ_OK;
}
}
if (!coder->dec.headerParsedOk)
return SZ_OK;
if (!coder->outBuf)
return SZ_OK;
if (coder->codeRes == SZ_OK)
{
ECoderStatus status;
SRes res;
size_t srcProcessed = srcSize;
size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
res = XzUnpacker_Code(&coder->dec,
NULL, &outSizeCur,
src, &srcProcessed, srcFinished,
CODER_FINISH_END,
&status);
coder->codeRes = res;
coder->status = status;
coder->inCodeSize += srcProcessed;
coder->outCodeSize = coder->dec.outDataWritten;
*inCodePos = coder->inCodeSize;
*outCodePos = coder->outCodeSize;
if (res == SZ_OK)
{
if (srcProcessed == srcSize)
*stop = False;
return SZ_OK;
}
}
if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
{
*inCodePos = coder->inPreSize;
*outCodePos = coder->outPreSize;
return SZ_OK;
}
return coder->codeRes;
}
#define XZDECMT_STREAM_WRITE_STEP …
static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
BoolInt needWriteToStream,
const Byte *src, size_t srcSize, BoolInt isCross,
BoolInt *needContinue,
BoolInt *canRecode)
{
CXzDecMt *me = (CXzDecMt *)pp;
const CXzDecMtThread *coder = &me->coders[coderIndex];
*needContinue = False;
*canRecode = True;
if (!needWriteToStream)
return SZ_OK;
if (!coder->dec.headerParsedOk || !coder->outBuf)
{
if (me->finishedDecoderIndex < 0)
me->finishedDecoderIndex = (int)coderIndex;
return SZ_OK;
}
if (me->finishedDecoderIndex >= 0)
return SZ_OK;
me->mtc.inProcessed += coder->inCodeSize;
*canRecode = False;
{
SRes res;
size_t size = coder->outCodeSize;
Byte *data = coder->outBuf;
if (!me->isBlockHeaderState_Write)
{
XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
me->dec.decodeOnlyOneBlock = False;
me->dec.numStartedStreams = coder->dec.numStartedStreams;
me->dec.streamFlags = coder->streamFlags;
me->isBlockHeaderState_Write = True;
}
me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
if (coder->outPreSize != size)
{
if (me->props.ignoreErrors)
{
memset(data + size, 0, coder->outPreSize - size);
size = coder->outPreSize;
}
if (me->mainErrorCode == SZ_OK)
{
if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
me->mainErrorCode = SZ_ERROR_INPUT_EOF;
else
me->mainErrorCode = SZ_ERROR_DATA;
}
}
if (me->writeRes != SZ_OK)
return me->writeRes;
res = SZ_OK;
{
if (me->outSize_Defined)
{
const UInt64 rem = me->outSize - me->outProcessed;
if (size > rem)
size = (SizeT)rem;
}
for (;;)
{
size_t cur = size;
size_t written;
if (cur > XZDECMT_STREAM_WRITE_STEP)
cur = XZDECMT_STREAM_WRITE_STEP;
written = ISeqOutStream_Write(me->outStream, data, cur);
me->outProcessed += written;
if (written != cur)
{
me->writeRes = SZ_ERROR_WRITE;
res = me->writeRes;
break;
}
data += cur;
size -= cur;
if (size == 0)
break;
res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
if (res != SZ_OK)
break;
}
}
if (coder->codeRes != SZ_OK)
if (!me->props.ignoreErrors)
{
me->finishedDecoderIndex = (int)coderIndex;
return res;
}
RINOK(res);
if (coder->inPreSize != coder->inCodeSize
|| coder->blockPackTotal != coder->inCodeSize)
{
me->finishedDecoderIndex = (int)coderIndex;
return SZ_OK;
}
if (coder->parseState != MTDEC_PARSE_END)
{
*needContinue = True;
return SZ_OK;
}
}
PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
{
CXzUnpacker *dec = &me->dec;
PRF_STR_INT("PostSingle", srcSize);
{
size_t srcProcessed = srcSize;
ECoderStatus status;
size_t outSizeCur = 0;
SRes res;
dec->decodeToStreamSignature = True;
me->mainDecoderWasCalled = True;
if (coder->parsing_Truncated)
{
me->parsing_Truncated = True;
return SZ_OK;
}
res = XzUnpacker_Code(dec,
NULL, &outSizeCur,
src, &srcProcessed,
me->mtc.readWasFinished,
CODER_FINISH_END,
&status);
me->status = status;
me->codeRes = res;
if (isCross)
me->mtc.crossStart += srcProcessed;
me->mtc.inProcessed += srcProcessed;
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
srcSize -= srcProcessed;
src += srcProcessed;
if (res != SZ_OK)
{
return SZ_OK;
}
if (dec->state == XZ_STATE_STREAM_HEADER)
{
*needContinue = True;
me->isBlockHeaderState_Parse = False;
me->isBlockHeaderState_Write = False;
if (!isCross)
{
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
if (!crossBuf)
return SZ_ERROR_MEM;
if (srcSize != 0)
memcpy(crossBuf, src, srcSize);
me->mtc.crossStart = 0;
me->mtc.crossEnd = srcSize;
}
PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd);
return SZ_OK;
}
if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0)
{
return SZ_ERROR_FAIL;
}
if (me->mtc.readWasFinished)
{
return SZ_OK;
}
}
{
size_t inPos;
size_t inLim;
UInt64 inProgressPrev = me->mtc.inProcessed;
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
if (!crossBuf)
return SZ_ERROR_MEM;
inPos = 0;
inLim = 0;
for (;;)
{
SizeT inProcessed;
SizeT outProcessed;
ECoderStatus status;
SRes res;
if (inPos == inLim)
{
if (!me->mtc.readWasFinished)
{
inPos = 0;
inLim = me->mtc.inBufSize;
me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim);
me->mtc.readProcessed += inLim;
if (inLim == 0 || me->mtc.readRes != SZ_OK)
me->mtc.readWasFinished = True;
}
}
inProcessed = inLim - inPos;
outProcessed = 0;
res = XzUnpacker_Code(dec,
NULL, &outProcessed,
crossBuf + inPos, &inProcessed,
(inProcessed == 0),
CODER_FINISH_END, &status);
me->codeRes = res;
me->status = status;
inPos += inProcessed;
me->mtc.inProcessed += inProcessed;
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
if (res != SZ_OK)
{
return SZ_OK;
}
if (dec->state == XZ_STATE_STREAM_HEADER)
{
*needContinue = True;
me->mtc.crossStart = inPos;
me->mtc.crossEnd = inLim;
me->isBlockHeaderState_Parse = False;
me->isBlockHeaderState_Write = False;
return SZ_OK;
}
if (status != CODER_STATUS_NEEDS_MORE_INPUT)
return SZ_ERROR_FAIL;
if (me->mtc.progress)
{
UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
if (inDelta >= (1 << 22))
{
RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
inProgressPrev = me->mtc.inProcessed;
}
}
if (me->mtc.readWasFinished)
return SZ_OK;
}
}
}
}
#endif
void XzStatInfo_Clear(CXzStatInfo *p)
{ … }
static SRes XzDecMt_Decode_ST(CXzDecMt *p
#ifndef _7ZIP_ST
, BoolInt tMode
#endif
, CXzStatInfo *stat)
{ … }
static void XzStatInfo_SetStat(const CXzUnpacker *dec,
int finishMode,
UInt64 inProcessed,
SRes res,
ECoderStatus status,
BoolInt decodingTruncated,
CXzStatInfo *stat)
{ … }
SRes XzDecMt_Decode(CXzDecMtHandle pp,
const CXzDecMtProps *props,
const UInt64 *outDataSize, int finishMode,
ISeqOutStream *outStream,
ISeqInStream *inStream,
CXzStatInfo *stat,
int *isMT,
ICompressProgress *progress)
{ … }