Source code
Revision control
Copy as Markdown
Other Tools
/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread↩
2018-03-02 : Igor Pavlov : Public domain */↩
↩
#include "Precomp.h"↩
↩
// #define SHOW_DEBUG_INFO↩
↩
#ifdef SHOW_DEBUG_INFO↩
#include <stdio.h>↩
#endif↩
↩
#ifdef SHOW_DEBUG_INFO↩
#define PRF(x) x↩
#else↩
#define PRF(x)↩
#endif↩
↩
#define PRF_STR(s) PRF(printf("\n" s "\n"))↩
#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))↩
#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))↩
↩
// #define _7ZIP_ST↩
↩
#include "Alloc.h"↩
↩
#include "Lzma2Dec.h"↩
#include "Lzma2DecMt.h"↩
↩
#ifndef _7ZIP_ST↩
#include "MtDec.h"↩
#endif↩
↩
↩
#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)↩
↩
void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)↩
{↩
p->inBufSize_ST = 1 << 20;↩
p->outStep_ST = 1 << 20;↩
↩
#ifndef _7ZIP_ST↩
p->numThreads = 1;↩
p->inBufSize_MT = 1 << 18;↩
p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;↩
p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;↩
#endif↩
}↩
↩
↩
↩
#ifndef _7ZIP_ST↩
↩
/* ---------- CLzma2DecMtThread ---------- */↩
↩
typedef struct↩
{↩
CLzma2Dec dec;↩
Byte dec_created;↩
Byte needInit;↩
↩
Byte *outBuf;↩
size_t outBufSize;↩
↩
EMtDecParseState state;↩
ELzma2ParseStatus parseStatus;↩
↩
size_t inPreSize;↩
size_t outPreSize;↩
↩
size_t inCodeSize;↩
size_t outCodeSize;↩
SRes codeRes;↩
↩
CAlignOffsetAlloc alloc;↩
↩
Byte mtPad[1 << 7];↩
} CLzma2DecMtThread;↩
↩
#endif↩
↩
↩
/* ---------- CLzma2DecMt ---------- */↩
↩
typedef struct↩
{↩
// ISzAllocPtr alloc;↩
ISzAllocPtr allocMid;↩
↩
CAlignOffsetAlloc alignOffsetAlloc;↩
CLzma2DecMtProps props;↩
Byte prop;↩
↩
ISeqInStream *inStream;↩
ISeqOutStream *outStream;↩
ICompressProgress *progress;↩
↩
Bool finishMode;↩
Bool outSize_Defined;↩
UInt64 outSize;↩
↩
UInt64 outProcessed;↩
UInt64 inProcessed;↩
Bool readWasFinished;↩
SRes readRes;↩
↩
Byte *inBuf;↩
size_t inBufSize;↩
Byte dec_created;↩
CLzma2Dec dec;↩
↩
size_t inPos;↩
size_t inLim;↩
↩
#ifndef _7ZIP_ST↩
UInt64 outProcessed_Parse;↩
Bool mtc_WasConstructed;↩
CMtDec mtc;↩
CLzma2DecMtThread coders[MTDEC__THREADS_MAX];↩
#endif↩
↩
} CLzma2DecMt;↩
↩
↩
↩
CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)↩
{↩
CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));↩
if (!p)↩
return NULL;↩
↩
// p->alloc = alloc;↩
p->allocMid = allocMid;↩
↩
AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);↩
p->alignOffsetAlloc.numAlignBits = 7;↩
p->alignOffsetAlloc.offset = 0;↩
p->alignOffsetAlloc.baseAlloc = alloc;↩
↩
p->inBuf = NULL;↩
p->inBufSize = 0;↩
p->dec_created = False;↩
↩
// Lzma2DecMtProps_Init(&p->props);↩
↩
#ifndef _7ZIP_ST↩
p->mtc_WasConstructed = False;↩
{↩
unsigned i;↩
for (i = 0; i < MTDEC__THREADS_MAX; i++)↩
{↩
CLzma2DecMtThread *t = &p->coders[i];↩
t->dec_created = False;↩
t->outBuf = NULL;↩
t->outBufSize = 0;↩
}↩
}↩
#endif↩
↩
return p;↩
}↩
↩
↩
#ifndef _7ZIP_ST↩
↩
static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)↩
{↩
unsigned i;↩
for (i = 0; i < MTDEC__THREADS_MAX; i++)↩
{↩
CLzma2DecMtThread *t = &p->coders[i];↩
if (t->outBuf)↩
{↩
ISzAlloc_Free(p->allocMid, t->outBuf);↩
t->outBuf = NULL;↩
t->outBufSize = 0;↩
}↩
}↩
}↩
↩
#endif↩
↩
↩
static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)↩
{↩
if (p->dec_created)↩
{↩
Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);↩
p->dec_created = False;↩
}↩
if (p->inBuf)↩
{↩
ISzAlloc_Free(p->allocMid, p->inBuf);↩
p->inBuf = NULL;↩
}↩
p->inBufSize = 0;↩
}↩
↩
↩
void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp)↩
{↩
CLzma2DecMt *p = (CLzma2DecMt *)pp;↩
↩
Lzma2DecMt_FreeSt(p);↩
↩
#ifndef _7ZIP_ST↩
↩
if (p->mtc_WasConstructed)↩
{↩
MtDec_Destruct(&p->mtc);↩
p->mtc_WasConstructed = False;↩
}↩
{↩
unsigned i;↩
for (i = 0; i < MTDEC__THREADS_MAX; i++)↩
{↩
CLzma2DecMtThread *t = &p->coders[i];↩
if (t->dec_created)↩
{↩
// we don't need to free dict here↩
Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!↩
t->dec_created = False;↩
}↩
}↩
}↩
Lzma2DecMt_FreeOutBufs(p);↩
↩
#endif↩
↩
ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);↩
}↩
↩
↩
↩
#ifndef _7ZIP_ST↩
↩
static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)↩
{↩
CLzma2DecMt *me = (CLzma2DecMt *)obj;↩
CLzma2DecMtThread *t = &me->coders[coderIndex];↩
↩
PRF_STR_INT_2("Parse", coderIndex, cc->srcSize);↩
↩
cc->state = MTDEC_PARSE_CONTINUE;↩
↩
if (cc->startCall)↩
{↩
if (!t->dec_created)↩
{↩
Lzma2Dec_Construct(&t->dec);↩
t->dec_created = True;↩
AlignOffsetAlloc_CreateVTable(&t->alloc);↩
{↩
/* (1 << 12) is expected size of one way in data cache.↩
We optimize alignment for cache line size of 128 bytes and smaller */↩
const unsigned kNumAlignBits = 12;↩
const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */↩
t->alloc.numAlignBits = kNumAlignBits;↩
t->alloc.offset = ((UInt32)coderIndex * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (1 << kNumCacheLineBits));↩
t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;↩
}↩
}↩
Lzma2Dec_Init(&t->dec);↩
↩
t->inPreSize = 0;↩
t->outPreSize = 0;↩
// t->blockWasFinished = False;↩
// t->finishedWithMark = False;↩
t->parseStatus = LZMA_STATUS_NOT_SPECIFIED;↩
t->state = MTDEC_PARSE_CONTINUE;↩
↩
t->inCodeSize = 0;↩
t->outCodeSize = 0;↩
t->codeRes = SZ_OK;↩
↩
// (cc->srcSize == 0) is allowed↩
}↩
↩
{↩
ELzma2ParseStatus status;↩
Bool overflow;↩
UInt32 unpackRem = 0;↩
↩
int checkFinishBlock = True;↩
size_t limit = me->props.outBlockMax;↩
if (me->outSize_Defined)↩
{↩
UInt64 rem = me->outSize - me->outProcessed_Parse;↩
if (limit >= rem)↩
{↩
limit = (size_t)rem;↩
if (!me->finishMode)↩
checkFinishBlock = False;↩
}↩
}↩
↩
// checkFinishBlock = False, if we want to decode partial data↩
// that must be finished at position <= outBlockMax.↩
↩
{↩
const SizeT srcOrig = cc->srcSize;↩
SizeT srcSize_Point = 0;↩
SizeT dicPos_Point = 0;↩
↩
cc->srcSize = 0;↩
overflow = False;↩
↩
for (;;)↩
{↩
SizeT srcCur = srcOrig - cc->srcSize;↩
↩
status = Lzma2Dec_Parse(&t->dec,↩
limit - t->dec.decoder.dicPos,↩
cc->src + cc->srcSize, &srcCur,↩
checkFinishBlock);↩
↩
cc->srcSize += srcCur;↩
↩
if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)↩
{↩
if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)↩
{↩
overflow = True;↩
break;↩
}↩
continue;↩
}↩
↩
if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)↩
{↩
if (t->dec.decoder.dicPos == 0)↩
continue;↩
// we decode small blocks in one thread↩
if (t->dec.decoder.dicPos >= (1 << 14))↩
break;↩
dicPos_Point = t->dec.decoder.dicPos;↩
srcSize_Point = cc->srcSize;↩
continue;↩
}↩
↩
if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock↩
// && limit == t->dec.decoder.dicPos↩
// && limit == me->props.outBlockMax↩
)↩
{↩
overflow = True;↩
break;↩
}↩
↩
unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);↩
break;↩
}↩
↩
if (dicPos_Point != 0↩
&& (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK↩
&& (int)status != LZMA_STATUS_FINISHED_WITH_MARK↩
&& (int)status != LZMA_STATUS_NOT_SPECIFIED)↩
{↩
// we revert to latest newBlock state↩
status = LZMA2_PARSE_STATUS_NEW_BLOCK;↩
unpackRem = 0;↩
t->dec.decoder.dicPos = dicPos_Point;↩
cc->srcSize = srcSize_Point;↩
overflow = False;↩
}↩
}↩
↩
t->inPreSize += cc->srcSize;↩
t->parseStatus = status;↩
↩
if (overflow)↩
cc->state = MTDEC_PARSE_OVERFLOW;↩
else↩
{↩
size_t dicPos = t->dec.decoder.dicPos;↩
↩
if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)↩
{↩
if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)↩
{↩
cc->state = MTDEC_PARSE_NEW;↩
cc->srcSize--; // we don't need control byte of next block↩
t->inPreSize--;↩
}↩
else↩
{↩
cc->state = MTDEC_PARSE_END;↩
if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)↩
{↩
// (status == LZMA_STATUS_NOT_SPECIFIED)↩
// (status == LZMA_STATUS_NOT_FINISHED)↩
if (unpackRem != 0)↩
{↩
/* we also reserve space for max possible number of output bytes of current LZMA chunk */↩
SizeT rem = limit - dicPos;↩
if (rem > unpackRem)↩
rem = unpackRem;↩
dicPos += rem;↩
}↩
}↩
}↩
↩
me->outProcessed_Parse += dicPos;↩
}↩
↩
cc->outPos = dicPos;↩
t->outPreSize = (size_t)dicPos;↩
}↩
↩
t->state = cc->state;↩
return;↩
}↩
}↩
↩
↩
static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)↩
{↩
CLzma2DecMt *me = (CLzma2DecMt *)pp;↩
CLzma2DecMtThread *t = &me->coders[coderIndex];↩
Byte *dest = t->outBuf;↩
↩
if (t->inPreSize == 0)↩
{↩
t->codeRes = SZ_ERROR_DATA;↩
return t->codeRes;↩
}↩
↩
if (!dest || t->outBufSize < t->outPreSize)↩
{↩
if (dest)↩
{↩
ISzAlloc_Free(me->allocMid, dest);↩
t->outBuf = NULL;↩
t->outBufSize = 0;↩
}↩
↩
dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize↩
// + (1 << 28)↩
);↩
// Sleep(200);↩
if (!dest)↩
return SZ_ERROR_MEM;↩
t->outBuf = dest;↩
t->outBufSize = t->outPreSize;↩
}↩
↩
t->dec.decoder.dic = dest;↩
t->dec.decoder.dicBufSize = t->outPreSize;↩
↩
t->needInit = True;↩
↩
return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt↩
}↩
↩
↩
static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,↩
const Byte *src, size_t srcSize, int srcFinished,↩
// int finished, int blockFinished,↩
UInt64 *inCodePos, UInt64 *outCodePos, int *stop)↩
{↩
CLzma2DecMt *me = (CLzma2DecMt *)pp;↩
CLzma2DecMtThread *t = &me->coders[coderIndex];↩
↩
UNUSED_VAR(srcFinished)↩
↩
PRF_STR_INT_2("Code", coderIndex, srcSize);↩
↩
*inCodePos = t->inCodeSize;↩
*outCodePos = 0;↩
*stop = True;↩
↩
if (t->needInit)↩
{↩
Lzma2Dec_Init(&t->dec);↩
t->needInit = False;↩
}↩
↩
{↩
ELzmaStatus status;↩
size_t srcProcessed = srcSize;↩
Bool blockWasFinished =↩
((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK↩
|| t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);↩
↩
SRes res = Lzma2Dec_DecodeToDic(&t->dec,↩
t->outPreSize,↩
src, &srcProcessed,↩
blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,↩
&status);↩
↩
t->codeRes = res;↩
↩
t->inCodeSize += srcProcessed;↩
*inCodePos = t->inCodeSize;↩
t->outCodeSize = t->dec.decoder.dicPos;↩
*outCodePos = t->dec.decoder.dicPos;↩
↩
if (res != SZ_OK)↩
return res;↩
↩
if (srcProcessed == srcSize)↩
*stop = False;↩
↩
if (blockWasFinished)↩
{↩
if (srcSize != srcProcessed)↩
return SZ_ERROR_FAIL;↩
↩
if (t->inPreSize == t->inCodeSize)↩
{↩
if (t->outPreSize != t->outCodeSize)↩
return SZ_ERROR_FAIL;↩
*stop = True;↩
}↩
}↩
else↩
{↩
if (t->outPreSize == t->outCodeSize)↩
*stop = True;↩
}↩
↩
return SZ_OK;↩
}↩
}↩
↩
↩
#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)↩
↩
static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,↩
Bool needWriteToStream,↩
const Byte *src, size_t srcSize,↩
Bool *needContinue, Bool *canRecode)↩
{↩
CLzma2DecMt *me = (CLzma2DecMt *)pp;↩
const CLzma2DecMtThread *t = &me->coders[coderIndex];↩
size_t size = t->outCodeSize;↩
const Byte *data = t->outBuf;↩
Bool needContinue2 = True;↩
↩
PRF_STR_INT_2("Write", coderIndex, srcSize);↩
↩
*needContinue = False;↩
*canRecode = True;↩
UNUSED_VAR(src)↩
UNUSED_VAR(srcSize)↩
↩
if (↩
// t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK↩
t->state == MTDEC_PARSE_OVERFLOW↩
|| t->state == MTDEC_PARSE_END)↩
needContinue2 = False;↩
↩
↩
if (!needWriteToStream)↩
return SZ_OK;↩
↩
me->mtc.inProcessed += t->inCodeSize;↩
↩
if (t->codeRes == SZ_OK)↩
if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK↩
|| t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)↩
if (t->outPreSize != t->outCodeSize↩
|| t->inPreSize != t->inCodeSize)↩
return SZ_ERROR_FAIL;↩
↩
*canRecode = False;↩
↩
if (me->outStream)↩
{↩
for (;;)↩
{↩
size_t cur = size;↩
size_t written;↩
if (cur > LZMA2DECMT_STREAM_WRITE_STEP)↩
cur = LZMA2DECMT_STREAM_WRITE_STEP;↩
↩
written = ISeqOutStream_Write(me->outStream, data, cur);↩
↩
me->outProcessed += written;↩
// me->mtc.writtenTotal += written;↩
if (written != cur)↩
return SZ_ERROR_WRITE;↩
data += cur;↩
size -= cur;↩
if (size == 0)↩
{↩
*needContinue = needContinue2;↩
return SZ_OK;↩
}↩
RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));↩
}↩
}↩
↩
return SZ_ERROR_FAIL;↩
/*↩
if (size > me->outBufSize)↩
return SZ_ERROR_OUTPUT_EOF;↩
memcpy(me->outBuf, data, size);↩
me->outBufSize -= size;↩
me->outBuf += size;↩
*needContinue = needContinue2;↩
return SZ_OK;↩
*/↩
}↩
↩
#endif↩
↩
↩
static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)↩
{↩
if (!p->dec_created)↩
{↩
Lzma2Dec_Construct(&p->dec);↩
p->dec_created = True;↩
}↩
↩
RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));↩
↩
if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)↩
{↩
ISzAlloc_Free(p->allocMid, p->inBuf);↩
p->inBufSize = 0;↩
p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);↩
if (!p->inBuf)↩
return SZ_ERROR_MEM;↩
p->inBufSize = p->props.inBufSize_ST;↩
}↩
↩
Lzma2Dec_Init(&p->dec);↩
↩
return SZ_OK;↩
}↩
↩
↩
static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p↩
#ifndef _7ZIP_ST↩
, Bool tMode↩
#endif↩
)↩
{↩
SizeT wrPos;↩
size_t inPos, inLim;↩
const Byte *inData;↩
UInt64 inPrev, outPrev;↩
↩
CLzma2Dec *dec;↩
↩
#ifndef _7ZIP_ST↩
if (tMode)↩
{↩
Lzma2DecMt_FreeOutBufs(p);↩
tMode = MtDec_PrepareRead(&p->mtc);↩
}↩
#endif↩
↩
RINOK(Lzma2Dec_Prepare_ST(p));↩
↩
dec = &p->dec;↩
↩
inPrev = p->inProcessed;↩
outPrev = p->outProcessed;↩
↩
inPos = 0;↩
inLim = 0;↩
inData = NULL;↩
wrPos = dec->decoder.dicPos;↩
↩
for (;;)↩
{↩
SizeT dicPos;↩
SizeT size;↩
ELzmaFinishMode finishMode;↩
SizeT inProcessed;↩
ELzmaStatus status;↩
SRes res;↩
↩
SizeT outProcessed;↩
Bool outFinished;↩
Bool needStop;↩
↩
if (inPos == inLim)↩
{↩
#ifndef _7ZIP_ST↩
if (tMode)↩
{↩
inData = MtDec_Read(&p->mtc, &inLim);↩
inPos = 0;↩
if (inData)↩
continue;↩
tMode = False;↩
inLim = 0;↩
}↩
#endif↩
↩
if (!p->readWasFinished)↩
{↩
inPos = 0;↩
inLim = p->inBufSize;↩
inData = p->inBuf;↩
p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);↩
// p->readProcessed += inLim;↩
// inLim -= 5; p->readWasFinished = True; // for test↩
if (inLim == 0 || p->readRes != SZ_OK)↩
p->readWasFinished = True;↩
}↩
}↩
↩
dicPos = dec->decoder.dicPos;↩
{↩
SizeT next = dec->decoder.dicBufSize;↩
if (next - wrPos > p->props.outStep_ST)↩
next = wrPos + p->props.outStep_ST;↩
size = next - dicPos;↩
}↩
↩
finishMode = LZMA_FINISH_ANY;↩
if (p->outSize_Defined)↩
{↩
const UInt64 rem = p->outSize - p->outProcessed;↩
if (size >= rem)↩
{↩
size = (SizeT)rem;↩
if (p->finishMode)↩
finishMode = LZMA_FINISH_END;↩
}↩
}↩
↩
inProcessed = inLim - inPos;↩
↩
res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);↩
↩
inPos += inProcessed;↩
p->inProcessed += inProcessed;↩
outProcessed = dec->decoder.dicPos - dicPos;↩
p->outProcessed += outProcessed;↩
↩
outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);↩
↩
needStop = (res != SZ_OK↩
|| (inProcessed == 0 && outProcessed == 0)↩
|| status == LZMA_STATUS_FINISHED_WITH_MARK↩
|| (!p->finishMode && outFinished));↩
↩
if (needStop || outProcessed >= size)↩
{↩
SRes res2;↩
{↩
size_t writeSize = dec->decoder.dicPos - wrPos;↩
size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);↩
res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;↩
}↩
↩
if (dec->decoder.dicPos == dec->decoder.dicBufSize)↩
dec->decoder.dicPos = 0;↩
wrPos = dec->decoder.dicPos;↩
↩
RINOK(res2);↩
↩
if (needStop)↩
{↩
if (res != SZ_OK)↩
return res;↩
↩
if (status == LZMA_STATUS_FINISHED_WITH_MARK)↩
{↩
if (p->finishMode)↩
{↩
if (p->outSize_Defined && p->outSize != p->outProcessed)↩
return SZ_ERROR_DATA;↩
}↩
return SZ_OK;↩
}↩
↩
if (!p->finishMode && outFinished)↩
return SZ_OK;↩
↩
if (status == LZMA_STATUS_NEEDS_MORE_INPUT)↩
return SZ_ERROR_INPUT_EOF;↩
↩
return SZ_ERROR_DATA;↩
}↩
}↩
↩
if (p->progress)↩
{↩
UInt64 inDelta = p->inProcessed - inPrev;↩
UInt64 outDelta = p->outProcessed - outPrev;↩
if (inDelta >= (1 << 22) || outDelta >= (1 << 22))↩
{↩
RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));↩
inPrev = p->inProcessed;↩
outPrev = p->outProcessed;↩
}↩
}↩
}↩
}↩
↩
↩
↩
SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,↩
Byte prop,↩
const CLzma2DecMtProps *props,↩
ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,↩
// Byte *outBuf, size_t *outBufSize,↩
ISeqInStream *inStream,↩
// const Byte *inData, size_t inDataSize,↩
UInt64 *inProcessed,↩
// UInt64 *outProcessed,↩
int *isMT,↩
ICompressProgress *progress)↩
{↩
CLzma2DecMt *p = (CLzma2DecMt *)pp;↩
#ifndef _7ZIP_ST↩
Bool tMode;↩
#endif↩
↩
*inProcessed = 0;↩
↩
if (prop > 40)↩
return SZ_ERROR_UNSUPPORTED;↩
↩
p->prop = prop;↩
p->props = *props;↩
↩
p->inStream = inStream;↩
p->outStream = outStream;↩
p->progress = progress;↩
↩
p->outSize = 0;↩
p->outSize_Defined = False;↩
if (outDataSize)↩
{↩
p->outSize_Defined = True;↩
p->outSize = *outDataSize;↩
}↩
p->finishMode = finishMode;↩
↩
p->outProcessed = 0;↩
p->inProcessed = 0;↩
↩
p->readWasFinished = False;↩
↩
*isMT = False;↩
↩
↩
#ifndef _7ZIP_ST↩
↩
tMode = False;↩
↩
// p->mtc.parseRes = SZ_OK;↩
↩
// p->mtc.numFilledThreads = 0;↩
// p->mtc.crossStart = 0;↩
// p->mtc.crossEnd = 0;↩
// p->mtc.allocError_for_Read_BlockIndex = 0;↩
// p->mtc.isAllocError = False;↩
↩
if (p->props.numThreads > 1)↩
{↩
IMtDecCallback vt;↩
↩
Lzma2DecMt_FreeSt(p);↩
↩
p->outProcessed_Parse = 0;↩
↩
if (!p->mtc_WasConstructed)↩
{↩
p->mtc_WasConstructed = True;↩
MtDec_Construct(&p->mtc);↩
}↩
↩
p->mtc.progress = progress;↩
p->mtc.inStream = inStream;↩
↩
// p->outBuf = NULL;↩
// p->outBufSize = 0;↩
/*↩
if (!outStream)↩
{↩
// p->outBuf = outBuf;↩
// p->outBufSize = *outBufSize;↩
// *outBufSize = 0;↩
return SZ_ERROR_PARAM;↩
}↩
*/↩
↩
// p->mtc.inBlockMax = p->props.inBlockMax;↩
p->mtc.alloc = &p->alignOffsetAlloc.vt;↩
// p->alignOffsetAlloc.baseAlloc;↩
// p->mtc.inData = inData;↩
// p->mtc.inDataSize = inDataSize;↩
p->mtc.mtCallback = &vt;↩
p->mtc.mtCallbackObject = p;↩
↩
p->mtc.inBufSize = p->props.inBufSize_MT;↩
↩
p->mtc.numThreadsMax = p->props.numThreads;↩
↩
*isMT = True;↩
↩
vt.Parse = Lzma2DecMt_MtCallback_Parse;↩
vt.PreCode = Lzma2DecMt_MtCallback_PreCode;↩
vt.Code = Lzma2DecMt_MtCallback_Code;↩
vt.Write = Lzma2DecMt_MtCallback_Write;↩
↩
{↩
Bool needContinue = False;↩
↩
SRes res = MtDec_Code(&p->mtc);↩
↩
/*↩
if (!outStream)↩
*outBufSize = p->outBuf - outBuf;↩
*/↩
↩
*inProcessed = p->mtc.inProcessed;↩
↩
needContinue = False;↩
↩
if (res == SZ_OK)↩
{↩
if (p->mtc.mtProgress.res != SZ_OK)↩
res = p->mtc.mtProgress.res;↩
else↩
needContinue = p->mtc.needContinue;↩
}↩
↩
if (!needContinue)↩
{↩
if (res == SZ_OK)↩
return p->mtc.readRes;↩
return res;↩
}↩
↩
tMode = True;↩
p->readRes = p->mtc.readRes;↩
p->readWasFinished = p->mtc.readWasFinished;↩
p->inProcessed = p->mtc.inProcessed;↩
↩
PRF_STR("----- decoding ST -----");↩
}↩
}↩
↩
#endif↩
↩
↩
*isMT = False;↩
↩
{↩
SRes res = Lzma2Dec_Decode_ST(p↩
#ifndef _7ZIP_ST↩
, tMode↩
#endif↩
);↩
↩
*inProcessed = p->inProcessed;↩
↩
// res = SZ_OK; // for test↩
if (res == SZ_OK && p->readRes != SZ_OK)↩
res = p->readRes;↩
↩
/*↩
#ifndef _7ZIP_ST↩
if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)↩
res = p->mtc.parseRes;↩
#endif↩
*/↩
↩
return res;↩
}↩
}↩
↩
↩
/* ---------- Read from CLzma2DecMtHandle Interface ---------- */↩
↩
SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,↩
Byte prop,↩
const CLzma2DecMtProps *props,↩
const UInt64 *outDataSize, int finishMode,↩
ISeqInStream *inStream)↩
{↩
CLzma2DecMt *p = (CLzma2DecMt *)pp;↩
↩
if (prop > 40)↩
return SZ_ERROR_UNSUPPORTED;↩
↩
p->prop = prop;↩
p->props = *props;↩
↩
p->inStream = inStream;↩
↩
p->outSize = 0;↩
p->outSize_Defined = False;↩
if (outDataSize)↩
{↩
p->outSize_Defined = True;↩
p->outSize = *outDataSize;↩
}↩
p->finishMode = finishMode;↩
↩
p->outProcessed = 0;↩
p->inProcessed = 0;↩
↩
p->inPos = 0;↩
p->inLim = 0;↩
↩
return Lzma2Dec_Prepare_ST(p);↩
}↩
↩
↩
SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,↩
Byte *data, size_t *outSize,↩
UInt64 *inStreamProcessed)↩
{↩
CLzma2DecMt *p = (CLzma2DecMt *)pp;↩
ELzmaFinishMode finishMode;↩
SRes readRes;↩
size_t size = *outSize;↩
↩
*outSize = 0;↩
*inStreamProcessed = 0;↩
↩
finishMode = LZMA_FINISH_ANY;↩
if (p->outSize_Defined)↩
{↩
const UInt64 rem = p->outSize - p->outProcessed;↩
if (size >= rem)↩
{↩
size = (size_t)rem;↩
if (p->finishMode)↩
finishMode = LZMA_FINISH_END;↩
}↩
}↩
↩
readRes = SZ_OK;↩
↩
for (;;)↩
{↩
SizeT inCur;↩
SizeT outCur;↩
ELzmaStatus status;↩
SRes res;↩
↩
if (p->inPos == p->inLim && readRes == SZ_OK)↩
{↩
p->inPos = 0;↩
p->inLim = p->props.inBufSize_ST;↩
readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);↩
}↩
↩
inCur = p->inLim - p->inPos;↩
outCur = size;↩
↩
res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,↩
p->inBuf + p->inPos, &inCur, finishMode, &status);↩
↩
p->inPos += inCur;↩
p->inProcessed += inCur;↩
*inStreamProcessed += inCur;↩
p->outProcessed += outCur;↩
*outSize += outCur;↩
size -= outCur;↩
data += outCur;↩
↩
if (res != 0)↩
return res;↩
↩
/*↩
if (status == LZMA_STATUS_FINISHED_WITH_MARK)↩
return readRes;↩
↩
if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)↩
{↩
if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)↩
return SZ_ERROR_DATA;↩
return readRes;↩
}↩
*/↩
↩
if (inCur == 0 && outCur == 0)↩
return readRes;↩
}↩
}↩