Source code
Revision control
Copy as Markdown
Other Tools
/* XzDec.c -- Xz Decode↩
2018-04-24 : Igor Pavlov : Public domain */↩
↩
#include "Precomp.h"↩
↩
// #include <stdio.h>↩
↩
// #define XZ_DUMP↩
↩
/* #define XZ_DUMP */↩
↩
#ifdef XZ_DUMP↩
#include <stdio.h>↩
#endif↩
↩
// #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))↩
↩
#include <stdlib.h>↩
#include <string.h>↩
↩
#include "7zCrc.h"↩
#include "Alloc.h"↩
#include "Bra.h"↩
#include "CpuArch.h"↩
#include "Delta.h"↩
#include "Lzma2Dec.h"↩
↩
// #define USE_SUBBLOCK↩
↩
#ifdef USE_SUBBLOCK↩
#include "Bcj3Dec.c"↩
#include "SbDec.h"↩
#endif↩
↩
#include "Xz.h"↩
↩
#define XZ_CHECK_SIZE_MAX 64↩
↩
#define CODER_BUF_SIZE ((size_t)1 << 17)↩
↩
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)↩
{↩
unsigned i, limit;↩
*value = 0;↩
limit = (maxSize > 9) ? 9 : (unsigned)maxSize;↩
↩
for (i = 0; i < limit;)↩
{↩
Byte b = p[i];↩
*value |= (UInt64)(b & 0x7F) << (7 * i++);↩
if ((b & 0x80) == 0)↩
return (b == 0 && i != 1) ? 0 : i;↩
}↩
return 0;↩
}↩
↩
/* ---------- BraState ---------- */↩
↩
#define BRA_BUF_SIZE (1 << 14)↩
↩
typedef struct↩
{↩
size_t bufPos;↩
size_t bufConv;↩
size_t bufTotal;↩
↩
int encodeMode;↩
↩
UInt32 methodId;↩
UInt32 delta;↩
UInt32 ip;↩
UInt32 x86State;↩
Byte deltaState[DELTA_STATE_SIZE];↩
↩
Byte buf[BRA_BUF_SIZE];↩
} CBraState;↩
↩
static void BraState_Free(void *pp, ISzAllocPtr alloc)↩
{↩
ISzAlloc_Free(alloc, pp);↩
}↩
↩
static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)↩
{↩
CBraState *p = ((CBraState *)pp);↩
UNUSED_VAR(alloc);↩
p->ip = 0;↩
if (p->methodId == XZ_ID_Delta)↩
{↩
if (propSize != 1)↩
return SZ_ERROR_UNSUPPORTED;↩
p->delta = (unsigned)props[0] + 1;↩
}↩
else↩
{↩
if (propSize == 4)↩
{↩
UInt32 v = GetUi32(props);↩
switch (p->methodId)↩
{↩
case XZ_ID_PPC:↩
case XZ_ID_ARM:↩
case XZ_ID_SPARC:↩
if ((v & 3) != 0)↩
return SZ_ERROR_UNSUPPORTED;↩
break;↩
case XZ_ID_ARMT:↩
if ((v & 1) != 0)↩
return SZ_ERROR_UNSUPPORTED;↩
break;↩
case XZ_ID_IA64:↩
if ((v & 0xF) != 0)↩
return SZ_ERROR_UNSUPPORTED;↩
break;↩
}↩
p->ip = v;↩
}↩
else if (propSize != 0)↩
return SZ_ERROR_UNSUPPORTED;↩
}↩
return SZ_OK;↩
}↩
↩
static void BraState_Init(void *pp)↩
{↩
CBraState *p = ((CBraState *)pp);↩
p->bufPos = p->bufConv = p->bufTotal = 0;↩
x86_Convert_Init(p->x86State);↩
if (p->methodId == XZ_ID_Delta)↩
Delta_Init(p->deltaState);↩
}↩
↩
↩
#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;↩
↩
static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)↩
{↩
CBraState *p = ((CBraState *)pp);↩
switch (p->methodId)↩
{↩
case XZ_ID_Delta:↩
if (p->encodeMode)↩
Delta_Encode(p->deltaState, p->delta, data, size);↩
else↩
Delta_Decode(p->deltaState, p->delta, data, size);↩
break;↩
case XZ_ID_X86:↩
size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);↩
break;↩
CASE_BRA_CONV(PPC)↩
CASE_BRA_CONV(IA64)↩
CASE_BRA_CONV(ARM)↩
CASE_BRA_CONV(ARMT)↩
CASE_BRA_CONV(SPARC)↩
}↩
p->ip += (UInt32)size;↩
return size;↩
}↩
↩
↩
static SRes BraState_Code2(void *pp,↩
Byte *dest, SizeT *destLen,↩
const Byte *src, SizeT *srcLen, int srcWasFinished,↩
ECoderFinishMode finishMode,↩
// int *wasFinished↩
ECoderStatus *status)↩
{↩
CBraState *p = ((CBraState *)pp);↩
SizeT destRem = *destLen;↩
SizeT srcRem = *srcLen;↩
UNUSED_VAR(finishMode);↩
↩
*destLen = 0;↩
*srcLen = 0;↩
// *wasFinished = False;↩
*status = CODER_STATUS_NOT_FINISHED;↩
↩
while (destRem > 0)↩
{↩
if (p->bufPos != p->bufConv)↩
{↩
size_t size = p->bufConv - p->bufPos;↩
if (size > destRem)↩
size = destRem;↩
memcpy(dest, p->buf + p->bufPos, size);↩
p->bufPos += size;↩
*destLen += size;↩
dest += size;↩
destRem -= size;↩
continue;↩
}↩
↩
p->bufTotal -= p->bufPos;↩
memmove(p->buf, p->buf + p->bufPos, p->bufTotal);↩
p->bufPos = 0;↩
p->bufConv = 0;↩
{↩
size_t size = BRA_BUF_SIZE - p->bufTotal;↩
if (size > srcRem)↩
size = srcRem;↩
memcpy(p->buf + p->bufTotal, src, size);↩
*srcLen += size;↩
src += size;↩
srcRem -= size;↩
p->bufTotal += size;↩
}↩
if (p->bufTotal == 0)↩
break;↩
↩
p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);↩
↩
if (p->bufConv == 0)↩
{↩
if (!srcWasFinished)↩
break;↩
p->bufConv = p->bufTotal;↩
}↩
}↩
↩
if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)↩
{↩
*status = CODER_STATUS_FINISHED_WITH_MARK;↩
// *wasFinished = 1;↩
}↩
↩
return SZ_OK;↩
}↩
↩
↩
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)↩
{↩
CBraState *decoder;↩
if (id < XZ_ID_Delta || id > XZ_ID_SPARC)↩
return SZ_ERROR_UNSUPPORTED;↩
decoder = p->p;↩
if (!decoder)↩
{↩
decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));↩
if (!decoder)↩
return SZ_ERROR_MEM;↩
p->p = decoder;↩
p->Free = BraState_Free;↩
p->SetProps = BraState_SetProps;↩
p->Init = BraState_Init;↩
p->Code2 = BraState_Code2;↩
p->Filter = BraState_Filter;↩
}↩
decoder->methodId = (UInt32)id;↩
decoder->encodeMode = encodeMode;↩
return SZ_OK;↩
}↩
↩
↩
↩
/* ---------- SbState ---------- */↩
↩
#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,↩
// int *wasFinished↩
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; /* change it */↩
res = SbDec_Decode((CSbDec *)pp);↩
*destLen -= p->destLen;↩
*srcLen -= p->srcLen;↩
// *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */↩
*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↩
↩
↩
↩
/* ---------- Lzma2 ---------- */↩
↩
typedef struct↩
{↩
CLzma2Dec decoder;↩
Bool outBufMode;↩
} CLzma2Dec_Spec;↩
↩
↩
static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)↩
{↩
CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;↩
if (p->outBufMode)↩
Lzma2Dec_FreeProbs(&p->decoder, alloc);↩
else↩
Lzma2Dec_Free(&p->decoder, alloc);↩
ISzAlloc_Free(alloc, pp);↩
}↩
↩
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)↩
{↩
if (propSize != 1)↩
return SZ_ERROR_UNSUPPORTED;↩
{↩
CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;↩
if (p->outBufMode)↩
return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);↩
else↩
return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);↩
}↩
}↩
↩
static void Lzma2State_Init(void *pp)↩
{↩
Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);↩
}↩
↩
↩
/*↩
if (outBufMode), then (dest) is not used. Use NULL.↩
Data is unpacked to (spec->decoder.decoder.dic) output buffer.↩
*/↩
↩
static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,↩
int srcWasFinished, ECoderFinishMode finishMode,↩
// int *wasFinished,↩
ECoderStatus *status)↩
{↩
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;↩
ELzmaStatus status2;↩
/* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */↩
SRes res;↩
UNUSED_VAR(srcWasFinished);↩
if (spec->outBufMode)↩
{↩
SizeT dicPos = spec->decoder.decoder.dicPos;↩
SizeT dicLimit = dicPos + *destLen;↩
res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);↩
*destLen = spec->decoder.decoder.dicPos - dicPos;↩
}↩
else↩
res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);↩
// *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);↩
// ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder↩
*status = status2;↩
return res;↩
}↩
↩
↩
static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)↩
{↩
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;↩
if (!spec)↩
{↩
spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));↩
if (!spec)↩
return SZ_ERROR_MEM;↩
p->p = spec;↩
p->Free = Lzma2State_Free;↩
p->SetProps = Lzma2State_SetProps;↩
p->Init = Lzma2State_Init;↩
p->Code2 = Lzma2State_Code2;↩
p->Filter = NULL;↩
Lzma2Dec_Construct(&spec->decoder);↩
}↩
spec->outBufMode = False;↩
if (outBuf)↩
{↩
spec->outBufMode = True;↩
spec->decoder.decoder.dic = outBuf;↩
spec->decoder.decoder.dicBufSize = outBufSize;↩
}↩
return SZ_OK;↩
}↩
↩
↩
static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)↩
{↩
CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;↩
if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))↩
return SZ_ERROR_FAIL;↩
if (outBuf)↩
{↩
spec->decoder.decoder.dic = outBuf;↩
spec->decoder.decoder.dicBufSize = outBufSize;↩
}↩
return SZ_OK;↩
}↩
↩
↩
↩
static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)↩
{↩
unsigned i;↩
p->alloc = alloc;↩
p->buf = NULL;↩
p->numCoders = 0;↩
↩
p->outBufSize = 0;↩
p->outBuf = NULL;↩
// p->SingleBufMode = False;↩
↩
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)↩
p->coders[i].p = NULL;↩
}↩
↩
↩
static void MixCoder_Free(CMixCoder *p)↩
{↩
unsigned i;↩
p->numCoders = 0;↩
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)↩
{↩
IStateCoder *sc = &p->coders[i];↩
if (sc->p)↩
{↩
sc->Free(sc->p, p->alloc);↩
sc->p = NULL;↩
}↩
}↩
if (p->buf)↩
{↩
ISzAlloc_Free(p->alloc, p->buf);↩
p->buf = NULL; /* 9.31: the BUG was fixed */↩
}↩
}↩
↩
static void MixCoder_Init(CMixCoder *p)↩
{↩
unsigned i;↩
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)↩
{↩
p->size[i] = 0;↩
p->pos[i] = 0;↩
p->finished[i] = 0;↩
}↩
for (i = 0; i < p->numCoders; i++)↩
{↩
IStateCoder *coder = &p->coders[i];↩
coder->Init(coder->p);↩
p->results[i] = SZ_OK;↩
}↩
p->outWritten = 0;↩
p->wasFinished = False;↩
p->res = SZ_OK;↩
p->status = CODER_STATUS_NOT_SPECIFIED;↩
}↩
↩
↩
static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)↩
{↩
IStateCoder *sc = &p->coders[coderIndex];↩
p->ids[coderIndex] = methodId;↩
switch (methodId)↩
{↩
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);↩
#ifdef USE_SUBBLOCK↩
case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);↩
#endif↩
}↩
if (coderIndex == 0)↩
return SZ_ERROR_UNSUPPORTED;↩
return BraState_SetFromMethod(sc, methodId, 0, p->alloc);↩
}↩
↩
↩
static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)↩
{↩
IStateCoder *sc = &p->coders[coderIndex];↩
switch (methodId)↩
{↩
case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);↩
}↩
return SZ_ERROR_UNSUPPORTED;↩
}↩
↩
↩
↩
/*↩
if (destFinish) - then unpack data block is finished at (*destLen) position,↩
and we can return data that were not processed by filter↩
↩
output (status) can be :↩
CODER_STATUS_NOT_FINISHED↩
CODER_STATUS_FINISHED_WITH_MARK↩
CODER_STATUS_NEEDS_MORE_INPUT - not implemented still↩
*/↩
↩
static SRes MixCoder_Code(CMixCoder *p,↩
Byte *dest, SizeT *destLen, int destFinish,↩
const Byte *src, SizeT *srcLen, int srcWasFinished,↩
ECoderFinishMode finishMode)↩
{↩
SizeT destLenOrig = *destLen;↩
SizeT srcLenOrig = *srcLen;↩
↩
*destLen = 0;↩
*srcLen = 0;↩
↩
if (p->wasFinished)↩
return p->res;↩
↩
p->status = CODER_STATUS_NOT_FINISHED;↩
↩
// if (p->SingleBufMode)↩
if (p->outBuf)↩
{↩
SRes res;↩
SizeT destLen2, srcLen2;↩
int wasFinished;↩
↩
PRF_STR("------- MixCoder Single ----------");↩
↩
srcLen2 = srcLenOrig;↩
destLen2 = destLenOrig;↩
↩
{↩
IStateCoder *coder = &p->coders[0];↩
res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,↩
// &wasFinished,↩
&p->status);↩
wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);↩
}↩
↩
p->res = res;↩
↩
/*↩
if (wasFinished)↩
p->status = CODER_STATUS_FINISHED_WITH_MARK;↩
else↩
{↩
if (res == SZ_OK)↩
if (destLen2 != destLenOrig)↩
p->status = CODER_STATUS_NEEDS_MORE_INPUT;↩
}↩
*/↩
↩
↩
*srcLen = srcLen2;↩
src += srcLen2;↩
p->outWritten += destLen2;↩
↩
if (res != SZ_OK || srcWasFinished || wasFinished)↩
p->wasFinished = True;↩
↩
if (p->numCoders == 1)↩
*destLen = destLen2;↩
else if (p->wasFinished)↩
{↩
unsigned i;↩
size_t processed = p->outWritten;↩
↩
for (i = 1; i < p->numCoders; i++)↩
{↩
IStateCoder *coder = &p->coders[i];↩
processed = coder->Filter(coder->p, p->outBuf, processed);↩
if (wasFinished || (destFinish && p->outWritten == destLenOrig))↩
processed = p->outWritten;↩
PRF_STR_INT("filter", i);↩
}↩
*destLen = processed;↩
}↩
return res;↩
}↩
↩
PRF_STR("standard mix");↩
↩
if (p->numCoders != 1)↩
{↩
if (!p->buf)↩
{↩
p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));↩
if (!p->buf)↩
return SZ_ERROR_MEM;↩
}↩
↩
finishMode = CODER_FINISH_ANY;↩
}↩
↩
for (;;)↩
{↩
Bool processed = False;↩
Bool allFinished = True;↩
SRes resMain = SZ_OK;↩
unsigned i;↩
↩
p->status = CODER_STATUS_NOT_FINISHED;↩
/*↩
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)↩
break;↩
*/↩
↩
for (i = 0; i < p->numCoders; i++)↩
{↩
SRes res;↩
IStateCoder *coder = &p->coders[i];↩
Byte *dest2;↩
SizeT destLen2, srcLen2; // destLen2_Orig;↩
const Byte *src2;↩
int srcFinished2;↩
int encodingWasFinished;↩
ECoderStatus status2;↩
↩
if (i == 0)↩
{↩
src2 = src;↩
srcLen2 = srcLenOrig - *srcLen;↩
srcFinished2 = srcWasFinished;↩
}↩
else↩
{↩
size_t k = i - 1;↩
src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];↩
srcLen2 = p->size[k] - p->pos[k];↩
srcFinished2 = p->finished[k];↩
}↩
↩
if (i == p->numCoders - 1)↩
{↩
dest2 = dest;↩
destLen2 = destLenOrig - *destLen;↩
}↩
else↩
{↩
if (p->pos[i] != p->size[i])↩
continue;↩
dest2 = p->buf + (CODER_BUF_SIZE * i);↩
destLen2 = CODER_BUF_SIZE;↩
}↩
↩
// destLen2_Orig = destLen2;↩
↩
if (p->results[i] != SZ_OK)↩
{↩
if (resMain == SZ_OK)↩
resMain = p->results[i];↩
continue;↩
}↩
↩
res = coder->Code2(coder->p,↩
dest2, &destLen2,↩
src2, &srcLen2, srcFinished2,↩
finishMode,↩
// &encodingWasFinished,↩
&status2);↩
↩
if (res != SZ_OK)↩
{↩
p->results[i] = res;↩
if (resMain == SZ_OK)↩
resMain = res;↩
}↩
↩
encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);↩
↩
if (!encodingWasFinished)↩
{↩
allFinished = False;↩
if (p->numCoders == 1 && res == SZ_OK)↩
p->status = status2;↩
}↩
↩
if (i == 0)↩
{↩
*srcLen += srcLen2;↩
src += srcLen2;↩
}↩
else↩
p->pos[(size_t)i - 1] += srcLen2;↩
↩
if (i == p->numCoders - 1)↩
{↩
*destLen += destLen2;↩
dest += destLen2;↩
}↩
else↩
{↩
p->size[i] = destLen2;↩
p->pos[i] = 0;↩
p->finished[i] = encodingWasFinished;↩
}↩
↩
if (destLen2 != 0 || srcLen2 != 0)↩
processed = True;↩
}↩
↩
if (!processed)↩
{↩
if (allFinished)↩
p->status = CODER_STATUS_FINISHED_WITH_MARK;↩
return resMain;↩
}↩
}↩
}↩
↩
↩
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)↩
{↩
*p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);↩
if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=↩
GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))↩
return SZ_ERROR_NO_ARCHIVE;↩
return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;↩
}↩
↩
static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)↩
{↩
return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)↩
&& GetUi32(buf) == CrcCalc(buf + 4, 6)↩
&& flags == GetBe16(buf + 8)↩
&& buf[10] == XZ_FOOTER_SIG_0↩
&& buf[11] == XZ_FOOTER_SIG_1;↩
}↩
↩
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \↩
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \↩
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }↩
↩
↩
static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)↩
{↩
unsigned numFilters = XzBlock_GetNumFilters(p) - 1;↩
unsigned i;↩
{↩
const CXzFilter *f = &p->filters[numFilters];↩
if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)↩
return False;↩
}↩
↩
for (i = 0; i < numFilters; i++)↩
{↩
const CXzFilter *f = &p->filters[i];↩
if (f->id == XZ_ID_Delta)↩
{↩
if (f->propsSize != 1)↩
return False;↩
}↩
else if (f->id < XZ_ID_Delta↩
|| f->id > XZ_ID_SPARC↩
|| (f->propsSize != 0 && f->propsSize != 4))↩
return False;↩
}↩
return True;↩
}↩
↩
↩
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)↩
{↩
unsigned pos;↩
unsigned numFilters, i;↩
unsigned headerSize = (unsigned)header[0] << 2;↩
↩
/* (headerSize != 0) : another code checks */↩
↩
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))↩
return SZ_ERROR_ARCHIVE;↩
↩
pos = 1;↩
p->flags = header[pos++];↩
↩
p->packSize = (UInt64)(Int64)-1;↩
if (XzBlock_HasPackSize(p))↩
{↩
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);↩
if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)↩
return SZ_ERROR_ARCHIVE;↩
}↩
↩
p->unpackSize = (UInt64)(Int64)-1;↩
if (XzBlock_HasUnpackSize(p))↩
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);↩
↩
numFilters = XzBlock_GetNumFilters(p);↩
for (i = 0; i < numFilters; i++)↩
{↩
CXzFilter *filter = p->filters + i;↩
UInt64 size;↩
READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);↩
READ_VARINT_AND_CHECK(header, pos, headerSize, &size);↩
if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)↩
return SZ_ERROR_ARCHIVE;↩
filter->propsSize = (UInt32)size;↩
memcpy(filter->props, header + pos, (size_t)size);↩
pos += (unsigned)size;↩
↩
#ifdef XZ_DUMP↩
printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);↩
{↩
unsigned i;↩
for (i = 0; i < size; i++)↩
printf(" %2X", filter->props[i]);↩
}↩
#endif↩
}↩
↩
if (XzBlock_HasUnsupportedFlags(p))↩
return SZ_ERROR_UNSUPPORTED;↩
↩
while (pos < headerSize)↩
if (header[pos++] != 0)↩
return SZ_ERROR_ARCHIVE;↩
return SZ_OK;↩
}↩
↩
↩
↩
↩
static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)↩
{↩
unsigned i;↩
Bool needReInit = True;↩
unsigned numFilters = XzBlock_GetNumFilters(block);↩
↩
if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))↩
{↩
needReInit = False;↩
for (i = 0; i < numFilters; i++)↩
if (p->ids[i] != block->filters[numFilters - 1 - i].id)↩
{↩
needReInit = True;↩
break;↩
}↩
}↩
↩
// p->SingleBufMode = (outBuf != NULL);↩
p->outBuf = outBuf;↩
p->outBufSize = outBufSize;↩
↩
// p->SingleBufMode = False;↩
// outBuf = NULL;↩
↩
if (needReInit)↩
{↩
MixCoder_Free(p);↩
for (i = 0; i < numFilters; i++)↩
{↩
RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));↩
}↩
p->numCoders = numFilters;↩
}↩
else↩
{↩
RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));↩
}↩
↩
for (i = 0; i < numFilters; i++)↩
{↩
const CXzFilter *f = &block->filters[numFilters - 1 - i];↩
IStateCoder *sc = &p->coders[i];↩
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));↩
}↩
↩
MixCoder_Init(p);↩
return SZ_OK;↩
}↩
↩
↩
↩
void XzUnpacker_Init(CXzUnpacker *p)↩
{↩
p->state = XZ_STATE_STREAM_HEADER;↩
p->pos = 0;↩
p->numStartedStreams = 0;↩
p->numFinishedStreams = 0;↩
p->numTotalBlocks = 0;↩
p->padSize = 0;↩
p->decodeOnlyOneBlock = 0;↩
↩
p->parseMode = False;↩
p->decodeToStreamSignature = False;↩
↩
// p->outBuf = NULL;↩
// p->outBufSize = 0;↩
p->outDataWritten = 0;↩
}↩
↩
↩
void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)↩
{↩
p->outBuf = outBuf;↩
p->outBufSize = outBufSize;↩
}↩
↩
↩
void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)↩
{↩
MixCoder_Construct(&p->decoder, alloc);↩
p->outBuf = NULL;↩
p->outBufSize = 0;↩
XzUnpacker_Init(p);↩
}↩
↩
↩
void XzUnpacker_Free(CXzUnpacker *p)↩
{↩
MixCoder_Free(&p->decoder);↩
}↩
↩
↩
void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)↩
{↩
p->indexSize = 0;↩
p->numBlocks = 0;↩
Sha256_Init(&p->sha);↩
p->state = XZ_STATE_BLOCK_HEADER;↩
p->pos = 0;↩
p->decodeOnlyOneBlock = 1;↩
}↩
↩
↩
static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)↩
{↩
Byte temp[32];↩
unsigned num = Xz_WriteVarInt(temp, packSize);↩
num += Xz_WriteVarInt(temp + num, unpackSize);↩
Sha256_Update(&p->sha, temp, num);↩
p->indexSize += num;↩
p->numBlocks++;↩
}↩
↩
↩
↩
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,↩
const Byte *src, SizeT *srcLen, int srcFinished,↩
ECoderFinishMode finishMode, ECoderStatus *status)↩
{↩
SizeT destLenOrig = *destLen;↩
SizeT srcLenOrig = *srcLen;↩
*destLen = 0;↩
*srcLen = 0;↩
*status = CODER_STATUS_NOT_SPECIFIED;↩
↩
for (;;)↩
{↩
SizeT srcRem;↩
↩
if (p->state == XZ_STATE_BLOCK)↩
{↩
SizeT destLen2 = destLenOrig - *destLen;↩
SizeT srcLen2 = srcLenOrig - *srcLen;↩
SRes res;↩
↩
ECoderFinishMode finishMode2 = finishMode;↩
Bool srcFinished2 = srcFinished;↩
Bool destFinish = False;↩
↩
if (p->block.packSize != (UInt64)(Int64)-1)↩
{↩
UInt64 rem = p->block.packSize - p->packSize;↩
if (srcLen2 >= rem)↩
{↩
srcFinished2 = True;↩
srcLen2 = (SizeT)rem;↩
}↩
if (rem == 0 && p->block.unpackSize == p->unpackSize)↩
return SZ_ERROR_DATA;↩
}↩
↩
if (p->block.unpackSize != (UInt64)(Int64)-1)↩
{↩
UInt64 rem = p->block.unpackSize - p->unpackSize;↩
if (destLen2 >= rem)↩
{↩
destFinish = True;↩
finishMode2 = CODER_FINISH_END;↩
destLen2 = (SizeT)rem;↩
}↩
}↩
↩
/*↩
if (srcLen2 == 0 && destLen2 == 0)↩
{↩
*status = CODER_STATUS_NOT_FINISHED;↩
return SZ_OK;↩
}↩
*/↩
↩
{↩
res = MixCoder_Code(&p->decoder,↩
(p->outBuf ? NULL : dest), &destLen2, destFinish,↩
src, &srcLen2, srcFinished2,↩
finishMode2);↩
↩
*status = p->decoder.status;↩
XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);↩
if (!p->outBuf)↩
dest += destLen2;↩
p->outDataWritten += destLen2;↩
}↩
↩
(*srcLen) += srcLen2;↩
src += srcLen2;↩
p->packSize += srcLen2;↩
(*destLen) += destLen2;↩
p->unpackSize += destLen2;↩
↩
RINOK(res);↩
↩
if (*status != CODER_STATUS_FINISHED_WITH_MARK)↩
{↩
if (p->block.packSize == p->packSize↩
&& *status == CODER_STATUS_NEEDS_MORE_INPUT)↩
{↩
PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");↩
*status = CODER_STATUS_NOT_SPECIFIED;↩
return SZ_ERROR_DATA;↩
}↩
↩
return SZ_OK;↩
}↩
{↩
XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);↩
p->state = XZ_STATE_BLOCK_FOOTER;↩
p->pos = 0;↩
p->alignPos = 0;↩
*status = CODER_STATUS_NOT_SPECIFIED;↩
↩
if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)↩
|| (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))↩
{↩
PRF_STR("ERROR: block.size mismatch");↩
return SZ_ERROR_DATA;↩
}↩
}↩
// continue;↩
}↩
↩
srcRem = srcLenOrig - *srcLen;↩
↩
// XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes↩
if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)↩
{↩
*status = CODER_STATUS_NEEDS_MORE_INPUT;↩
return SZ_OK;↩
}↩
↩
switch (p->state)↩
{↩
case XZ_STATE_STREAM_HEADER:↩
{↩
if (p->pos < XZ_STREAM_HEADER_SIZE)↩
{↩
if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])↩
return SZ_ERROR_NO_ARCHIVE;↩
if (p->decodeToStreamSignature)↩
return SZ_OK;↩
p->buf[p->pos++] = *src++;↩
(*srcLen)++;↩
}↩
else↩
{↩
RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));↩
p->numStartedStreams++;↩
p->indexSize = 0;↩
p->numBlocks = 0;↩
Sha256_Init(&p->sha);↩
p->state = XZ_STATE_BLOCK_HEADER;↩
p->pos = 0;↩
}↩
break;↩
}↩
↩
case XZ_STATE_BLOCK_HEADER:↩
{↩
if (p->pos == 0)↩
{↩
p->buf[p->pos++] = *src++;↩
(*srcLen)++;↩
if (p->buf[0] == 0)↩
{↩
if (p->decodeOnlyOneBlock)↩
return SZ_ERROR_DATA;↩
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);↩
p->indexPos = p->indexPreSize;↩
p->indexSize += p->indexPreSize;↩
Sha256_Final(&p->sha, p->shaDigest);↩
Sha256_Init(&p->sha);↩
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);↩
p->state = XZ_STATE_STREAM_INDEX;↩
break;↩
}↩
p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;↩
break;↩
}↩
↩
if (p->pos != p->blockHeaderSize)↩
{↩
UInt32 cur = p->blockHeaderSize - p->pos;↩
if (cur > srcRem)↩
cur = (UInt32)srcRem;↩
memcpy(p->buf + p->pos, src, cur);↩
p->pos += cur;↩
(*srcLen) += cur;↩
src += cur;↩
}↩
else↩
{↩
RINOK(XzBlock_Parse(&p->block, p->buf));↩
if (!XzBlock_AreSupportedFilters(&p->block))↩
return SZ_ERROR_UNSUPPORTED;↩
p->numTotalBlocks++;↩
p->state = XZ_STATE_BLOCK;↩
p->packSize = 0;↩
p->unpackSize = 0;↩
XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));↩
if (p->parseMode)↩
{↩
p->headerParsedOk = True;↩
return SZ_OK;↩
}↩
RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));↩
}↩
break;↩
}↩
↩
case XZ_STATE_BLOCK_FOOTER:↩
{↩
if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)↩
{↩
if (srcRem == 0)↩
{↩
*status = CODER_STATUS_NEEDS_MORE_INPUT;↩
return SZ_OK;↩
}↩
(*srcLen)++;↩
p->alignPos++;↩
if (*src++ != 0)↩
return SZ_ERROR_CRC;↩
}↩
else↩
{↩
UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);↩
UInt32 cur = checkSize - p->pos;↩
if (cur != 0)↩
{↩
if (srcRem == 0)↩
{↩
*status = CODER_STATUS_NEEDS_MORE_INPUT;↩
return SZ_OK;↩
}↩
if (cur > srcRem)↩
cur = (UInt32)srcRem;↩
memcpy(p->buf + p->pos, src, cur);↩
p->pos += cur;↩
(*srcLen) += cur;↩
src += cur;↩
if (checkSize != p->pos)↩
break;↩
}↩
{↩
Byte digest[XZ_CHECK_SIZE_MAX];↩
p->state = XZ_STATE_BLOCK_HEADER;↩
p->pos = 0;↩
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)↩
return SZ_ERROR_CRC;↩
if (p->decodeOnlyOneBlock)↩
{↩
*status = CODER_STATUS_FINISHED_WITH_MARK;↩
return SZ_OK;↩
}↩
}↩
}↩
break;↩
}↩
↩
case XZ_STATE_STREAM_INDEX:↩
{↩
if (p->pos < p->indexPreSize)↩
{↩
(*srcLen)++;↩
if (*src++ != p->buf[p->pos++])↩
return SZ_ERROR_CRC;↩
}↩
else↩
{↩
if (p->indexPos < p->indexSize)↩
{↩
UInt64 cur = p->indexSize - p->indexPos;↩
if (srcRem > cur)↩
srcRem = (SizeT)cur;↩
p->crc = CrcUpdate(p->crc, src, srcRem);↩
Sha256_Update(&p->sha, src, srcRem);↩
(*srcLen) += srcRem;↩
src += srcRem;↩
p->indexPos += srcRem;↩
}↩
else if ((p->indexPos & 3) != 0)↩
{↩
Byte b = *src++;↩
p->crc = CRC_UPDATE_BYTE(p->crc, b);↩
(*srcLen)++;↩
p->indexPos++;↩
p->indexSize++;↩
if (b != 0)↩
return SZ_ERROR_CRC;↩
}↩
else↩
{↩
Byte digest[SHA256_DIGEST_SIZE];↩
p->state = XZ_STATE_STREAM_INDEX_CRC;↩
p->indexSize += 4;↩
p->pos = 0;↩
Sha256_Final(&p->sha, digest);↩
if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)↩
return SZ_ERROR_CRC;↩
}↩
}↩
break;↩
}↩
↩
case XZ_STATE_STREAM_INDEX_CRC:↩
{↩
if (p->pos < 4)↩
{↩
(*srcLen)++;↩
p->buf[p->pos++] = *src++;↩
}↩
else↩
{↩
p->state = XZ_STATE_STREAM_FOOTER;↩
p->pos = 0;↩
if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))↩
return SZ_ERROR_CRC;↩
}↩
break;↩
}↩
↩
case XZ_STATE_STREAM_FOOTER:↩
{↩
UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;↩
if (cur > srcRem)↩
cur = (UInt32)srcRem;↩
memcpy(p->buf + p->pos, src, cur);↩
p->pos += cur;↩
(*srcLen) += cur;↩
src += cur;↩
if (p->pos == XZ_STREAM_FOOTER_SIZE)↩
{↩
p->state = XZ_STATE_STREAM_PADDING;↩
p->numFinishedStreams++;↩
p->padSize = 0;↩
if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))↩
return SZ_ERROR_CRC;↩
}↩
break;↩
}↩
↩
case XZ_STATE_STREAM_PADDING:↩
{↩
if (*src != 0)↩
{↩
if (((UInt32)p->padSize & 3) != 0)↩
return SZ_ERROR_NO_ARCHIVE;↩
p->pos = 0;↩
p->state = XZ_STATE_STREAM_HEADER;↩
}↩
else↩
{↩
(*srcLen)++;↩
src++;↩
p->padSize++;↩
}↩
break;↩
}↩
↩
case XZ_STATE_BLOCK: break; /* to disable GCC warning */↩
}↩
}↩
/*↩
if (p->state == XZ_STATE_FINISHED)↩
*status = CODER_STATUS_FINISHED_WITH_MARK;↩
return SZ_OK;↩
*/↩
}↩
↩
↩
SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,↩
const Byte *src, SizeT *srcLen,↩
ECoderFinishMode finishMode, ECoderStatus *status)↩
{↩
XzUnpacker_Init(p);↩
XzUnpacker_SetOutBuf(p, dest, *destLen);↩
↩
return XzUnpacker_Code(p,↩
NULL, destLen,↩
src, srcLen, True,↩
finishMode, status);↩
}↩
↩
↩
Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)↩
{↩
return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);↩
}↩
↩
Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)↩
{↩
return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);↩
}↩
↩
UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)↩
{↩
UInt64 num = 0;↩
if (p->state == XZ_STATE_STREAM_PADDING)↩
num = p->padSize;↩
else if (p->state == XZ_STATE_STREAM_HEADER)↩
num = p->padSize + p->pos;↩
return num;↩
}↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
↩
#ifndef _7ZIP_ST↩
#include "MtDec.h"↩
#endif↩
↩
↩
void XzDecMtProps_Init(CXzDecMtProps *p)↩
{↩
p->inBufSize_ST = 1 << 18;↩
p->outStep_ST = 1 << 20;↩
p->ignoreErrors = False;↩
↩
#ifndef _7ZIP_ST↩
p->numThreads = 1;↩
p->inBufSize_MT = 1 << 18;↩
p->memUseMax = sizeof(size_t) << 28;↩
#endif↩
}↩
↩
↩
↩
#ifndef _7ZIP_ST↩
↩
/* ---------- CXzDecMtThread ---------- */↩
↩
typedef struct↩
{↩
Byte *outBuf;↩
size_t outBufSize;↩
size_t outPreSize;↩
size_t inPreSize;↩
size_t inPreHeaderSize;↩
size_t blockPackSize_for_Index; // including block header and checksum.↩
size_t blockPackTotal; // including stream header, block header and checksum.↩
size_t inCodeSize;↩
size_t outCodeSize;↩
ECoderStatus status;↩
SRes codeRes;↩
Bool skipMode;↩
// Bool finishedWithMark;↩
EMtDecParseState parseState;↩
Bool parsing_Truncated;↩
Bool atBlockHeader;↩
CXzStreamFlags streamFlags;↩
// UInt64 numFinishedStreams↩
UInt64 numStreams;↩
UInt64 numTotalBlocks;↩
UInt64 numBlocks;↩
↩
Bool dec_created;↩
CXzUnpacker dec;↩
↩
Byte mtPad[1 << 7];↩
} CXzDecMtThread;↩
↩
#endif↩
↩
↩
/* ---------- CXzDecMt ---------- */↩
↩
typedef struct↩
{↩
CAlignOffsetAlloc alignOffsetAlloc;↩
ISzAllocPtr allocMid;↩
↩
CXzDecMtProps props;↩
size_t unpackBlockMaxSize;↩
↩
ISeqInStream *inStream;↩
ISeqOutStream *outStream;↩
ICompressProgress *progress;↩
// CXzStatInfo *stat;↩
↩
Bool finishMode;↩
Bool outSize_Defined;↩
UInt64 outSize;↩
↩
UInt64 outProcessed;↩
UInt64 inProcessed;↩
UInt64 readProcessed;↩
Bool readWasFinished;↩
SRes readRes;↩
SRes writeRes;↩
↩
Byte *outBuf;↩
size_t outBufSize;↩
Byte *inBuf;↩
size_t inBufSize;↩
Bool dec_created;↩
CXzUnpacker dec;↩
↩
ECoderStatus status;↩
SRes codeRes;↩
↩
#ifndef _7ZIP_ST↩
Bool mainDecoderWasCalled;↩
// int statErrorDefined;↩
int finishedDecoderIndex;↩
↩
// global values that are used in Parse stage↩
CXzStreamFlags streamFlags;↩
// UInt64 numFinishedStreams↩
UInt64 numStreams;↩
UInt64 numTotalBlocks;↩
UInt64 numBlocks;↩
↩
// UInt64 numBadBlocks;↩
SRes mainErrorCode;↩
↩
Bool isBlockHeaderState_Parse;↩
Bool isBlockHeaderState_Write;↩
UInt64 outProcessed_Parse;↩
Bool parsing_Truncated;↩
↩
Bool mtc_WasConstructed;↩
CMtDec mtc;↩
CXzDecMtThread coders[MTDEC__THREADS_MAX];↩
#endif↩
↩
} CXzDecMt;↩
↩
↩
↩
CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)↩
{↩
CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));↩
if (!p)↩
return NULL;↩
↩
AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);↩
p->alignOffsetAlloc.baseAlloc = alloc;↩
p->alignOffsetAlloc.numAlignBits = 7;↩
p->alignOffsetAlloc.offset = 0;↩
↩
p->allocMid = allocMid;↩
↩
p->outBuf = NULL;↩
p->outBufSize = 0;↩
p->inBuf = NULL;↩
p->inBufSize = 0;↩
p->dec_created = False;↩
↩
p->unpackBlockMaxSize = 0;↩
↩
XzDecMtProps_Init(&p->props);↩
↩
#ifndef _7ZIP_ST↩
p->mtc_WasConstructed = False;↩
{↩
unsigned i;↩
for (i = 0; i < MTDEC__THREADS_MAX; i++)↩
{↩
CXzDecMtThread *coder = &p->coders[i];↩
coder->dec_created = False;↩
coder->outBuf = NULL;↩
coder->outBufSize = 0;↩
}↩
}↩
#endif↩
↩
return p;↩
}↩
↩
↩
#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)↩
{↩
if (p->dec_created)↩
{↩
XzUnpacker_Free(&p->dec);↩
p->dec_created = False;↩
}↩
↩
if (p->outBuf)↩
{↩
ISzAlloc_Free(p->allocMid, p->outBuf);↩
p->outBuf = NULL;↩
}↩
p->outBufSize = 0;↩
↩
if (p->inBuf)↩
{↩
ISzAlloc_Free(p->allocMid, p->inBuf);↩
p->inBuf = NULL;↩
}↩
p->inBufSize = 0;↩
}↩
↩
↩
void XzDecMt_Destroy(CXzDecMtHandle pp)↩
{↩
CXzDecMt *p = (CXzDecMt *)pp;↩
↩
XzDecMt_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++)↩
{↩
CXzDecMtThread *t = &p->coders[i];↩
if (t->dec_created)↩
{↩
// we don't need to free dict here↩
XzUnpacker_Free(&t->dec);↩
t->dec_created = False;↩
}↩
}↩
}↩
XzDecMt_FreeOutBufs(p);↩
↩
#endif↩
↩
ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, 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);↩
↩
// PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));↩
↩
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;↩
/*↩
if (res == SZ_ERROR_MEM)↩
return res;↩
return SZ_OK;↩
*/↩
return; // res;↩
}↩
↩
if (coder->dec.headerParsedOk)↩
{↩
const CXzBlock *block = &coder->dec.block;↩
if (XzBlock_HasUnpackSize(block)↩
// && block->unpackSize <= me->props.outBlockMax↩
&& XzBlock_HasPackSize(block))↩
{↩
{↩
if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)↩
{↩
cc->state = MTDEC_PARSE_OVERFLOW;↩
return; // SZ_OK;↩
}↩
}↩
{↩
UInt64 packSize = block->packSize;↩
UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);↩
UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);↩
UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;↩
// if (blockPackSum <= me->props.inBlockMax)↩
// unpackBlockMaxSize↩
{↩
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 (coder->inPreSize <= me->props.inBlockMax)↩
{↩
if (!cc->srcFinished)↩
return; // SZ_OK;↩
cc->state =↩
coder->parseState = MTDEC_PARSE_END;↩
return; // SZ_OK;↩
}↩
cc->state = MTDEC_PARSE_OVERFLOW;↩
return; // SZ_OK;↩
}↩
↩
// ---------- skipMode ----------↩
{↩
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; // SZ_OK;↩
cc->state = MTDEC_PARSE_END;↩
}↩
else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block↩
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)↩
{↩
// next block can be zero size↩
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; // SZ_OK;↩
↩
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; // SZ_OK;↩
}↩
}↩
↩
↩
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;↩
}↩
↩
// return SZ_ERROR_MEM;↩
↩
XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);↩
↩
{↩
SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);↩
// res = SZ_ERROR_UNSUPPORTED; // to test↩
coder->codeRes = res;↩
if (res != SZ_OK)↩
{↩
// if (res == SZ_ERROR_MEM) return res;↩
if (me->props.ignoreErrors && res != SZ_ERROR_MEM)↩
return S_OK;↩
return res;↩
}↩
}↩
↩
return SZ_OK;↩
}↩
↩
↩
static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,↩
const Byte *src, size_t srcSize, int srcFinished,↩
// int finished, int blockFinished,↩
UInt64 *inCodePos, UInt64 *outCodePos, int *stop)↩
{↩
CXzDecMt *me = (CXzDecMt *)pp;↩
CXzDecMtThread *coder = &me->coders[coderIndex];↩
↩
*inCodePos = coder->inCodeSize;↩
*outCodePos = coder->outCodeSize;↩
*stop = True;↩
↩
if (coder->inCodeSize < coder->inPreHeaderSize)↩
{↩
UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;↩
size_t step = srcSize;↩
if (step > rem)↩
step = (size_t)rem;↩
src += step;↩
srcSize -= step;↩
coder->inCodeSize += step;↩
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;↩
↩
// PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));↩
↩
res = XzUnpacker_Code(&coder->dec,↩
NULL, &outSizeCur,↩
src, &srcProcessed, srcFinished,↩
// coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,↩
CODER_FINISH_END,↩
&status);↩
↩
// PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));↩
↩
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 S_OK;↩
}↩
return coder->codeRes;↩
}↩
↩
↩
#define XZDECMT_STREAM_WRITE_STEP (1 << 24)↩
↩
static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,↩
Bool needWriteToStream,↩
const Byte *src, size_t srcSize,↩
// int srcFinished,↩
Bool *needContinue,↩
Bool *canRecode)↩
{↩
CXzDecMt *me = (CXzDecMt *)pp;↩
const CXzDecMtThread *coder = &me->coders[coderIndex];↩
↩
// PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));↩
↩
*needContinue = False;↩
*canRecode = True;↩
↩
if (!needWriteToStream)↩
return SZ_OK;↩
↩
if (!coder->dec.headerParsedOk || !coder->outBuf)↩
{↩
if (me->finishedDecoderIndex < 0)↩
me->finishedDecoderIndex = 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;↩
↩
// we use in me->dec: sha, numBlocks, indexSize↩
↩
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;↩
}↩
// me->numBadBlocks++;↩
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);↩
↩
// PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));↩
↩
me->outProcessed += written;↩
if (written != cur)↩
{↩
me->writeRes = SZ_ERROR_WRITE;↩
res = me->writeRes;↩
break;↩
}↩
data += cur;↩
size -= cur;↩
// PRF_STR_INT("Written size =", size);↩
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 = coderIndex;↩
return res;↩
}↩
↩
RINOK(res);↩
↩
if (coder->inPreSize != coder->inCodeSize↩
|| coder->blockPackTotal != coder->inCodeSize)↩
{↩
me->finishedDecoderIndex = coderIndex;↩
return SZ_OK;↩
}↩
↩
if (coder->parseState != MTDEC_PARSE_END)↩
{↩
*needContinue = True;↩
return SZ_OK;↩
}↩
}↩
↩
// (coder->state == MTDEC_PARSE_END) means that there are no other working threads↩
// so we can use mtc variables without lock↩
↩
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->decodeOnlyOneBlock = False;↩
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, // srcFinished↩
CODER_FINISH_END, // CODER_FINISH_ANY,↩
&status);↩
↩
me->status = status;↩
me->codeRes = res;↩
↩
me->mtc.inProcessed += srcProcessed;↩
me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;↩
↩
if (res != SZ_OK)↩
{↩
return S_OK;↩
// return res;↩
}↩
↩
if (dec->state == XZ_STATE_STREAM_HEADER)↩
{↩
*needContinue = True;↩
me->isBlockHeaderState_Parse = False;↩
me->isBlockHeaderState_Write = False;↩
{↩
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);↩
if (!crossBuf)↩
return SZ_ERROR_MEM;↩
memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);↩
}↩
me->mtc.crossStart = 0;↩
me->mtc.crossEnd = srcSize - srcProcessed;↩
return SZ_OK;↩
}↩
↩
if (status != CODER_STATUS_NEEDS_MORE_INPUT)↩
{↩
return E_FAIL;↩
}↩
↩
if (me->mtc.readWasFinished)↩
{↩
return SZ_OK;↩
}↩
}↩
↩
{↩
size_t inPos;↩
size_t inLim;↩
const Byte *inData;↩
UInt64 inProgressPrev = me->mtc.inProcessed;↩
↩
// XzDecMt_Prepare_InBuf_ST(p);↩
Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);↩
if (!crossBuf)↩
return SZ_ERROR_MEM;↩
↩
inPos = 0;↩
inLim = 0;↩
// outProcessed = 0;↩
↩
inData = crossBuf;↩
↩
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 *)inData, &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,↩
inData + inPos, &inProcessed,↩
(inProcessed == 0), // srcFinished↩
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 S_OK;↩
// return res;↩
}↩
↩
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 E_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)↩
{↩
p->InSize = 0;↩
p->OutSize = 0;↩
↩
p->NumStreams = 0;↩
p->NumBlocks = 0;↩
↩
p->UnpackSize_Defined = False;↩
↩
p->NumStreams_Defined = False;↩
p->NumBlocks_Defined = False;↩
↩
// p->IsArc = False;↩
// p->UnexpectedEnd = False;↩
// p->Unsupported = False;↩
// p->HeadersError = False;↩
// p->DataError = False;↩
// p->CrcError = False;↩
↩
p->DataAfterEnd = False;↩
p->DecodingTruncated = False;↩
↩
p->DecodeRes = SZ_OK;↩
p->ReadRes = SZ_OK;↩
p->ProgressRes = SZ_OK;↩
↩
p->CombinedRes = SZ_OK;↩
p->CombinedRes_Type = SZ_OK;↩
}↩
↩
↩
↩
↩
static SRes XzDecMt_Decode_ST(CXzDecMt *p↩
#ifndef _7ZIP_ST↩
, Bool tMode↩
#endif↩
, CXzStatInfo *stat)↩
{↩
size_t outPos;↩
size_t inPos, inLim;↩
const Byte *inData;↩
UInt64 inPrev, outPrev;↩
↩
CXzUnpacker *dec;↩
↩
#ifndef _7ZIP_ST↩
if (tMode)↩
{↩
XzDecMt_FreeOutBufs(p);↩
tMode = MtDec_PrepareRead(&p->mtc);↩
}↩
#endif↩
↩
if (!p->outBuf || p->outBufSize != p->props.outStep_ST)↩
{↩
ISzAlloc_Free(p->allocMid, p->outBuf);↩
p->outBufSize = 0;↩
p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);↩
if (!p->outBuf)↩
return SZ_ERROR_MEM;↩
p->outBufSize = p->props.outStep_ST;↩
}↩
↩
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;↩
}↩
↩
dec = &p->dec;↩
dec->decodeToStreamSignature = False;↩
// dec->decodeOnlyOneBlock = False;↩
↩
XzUnpacker_SetOutBuf(dec, NULL, 0);↩
↩
inPrev = p->inProcessed;↩
outPrev = p->outProcessed;↩
↩
inPos = 0;↩
inLim = 0;↩
inData = NULL;↩
outPos = 0;↩
↩
for (;;)↩
{↩
SizeT outSize;↩
Bool finished;↩
ECoderFinishMode finishMode;↩
SizeT inProcessed;↩
ECoderStatus status;↩
SRes res;↩
↩
SizeT outProcessed;↩
↩
↩
↩
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;↩
if (inLim == 0 || p->readRes != SZ_OK)↩
p->readWasFinished = True;↩
}↩
}↩
↩
outSize = p->props.outStep_ST - outPos;↩
↩
finishMode = CODER_FINISH_ANY;↩
if (p->outSize_Defined)↩
{↩
const UInt64 rem = p->outSize - p->outProcessed;↩
if (outSize >= rem)↩
{↩
outSize = (SizeT)rem;↩
if (p->finishMode)↩
finishMode = CODER_FINISH_END;↩
}↩
}↩
↩
inProcessed = inLim - inPos;↩
outProcessed = outSize;↩
↩
res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,↩
inData + inPos, &inProcessed,↩
(inPos == inLim), // srcFinished↩
finishMode, &status);↩
↩
p->codeRes = res;↩
p->status = status;↩
↩
inPos += inProcessed;↩
outPos += outProcessed;↩
p->inProcessed += inProcessed;↩
p->outProcessed += outProcessed;↩
↩
finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);↩
↩
if (finished || outProcessed >= outSize)↩
if (outPos != 0)↩
{↩
size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);↩
p->outProcessed += written;↩
if (written != outPos)↩
{↩
stat->CombinedRes_Type = SZ_ERROR_WRITE;↩
return SZ_ERROR_WRITE;↩
}↩
outPos = 0;↩
}↩
↩
if (p->progress && res == SZ_OK)↩
{↩
UInt64 inDelta = p->inProcessed - inPrev;↩
UInt64 outDelta = p->outProcessed - outPrev;↩
if (inDelta >= (1 << 22) || outDelta >= (1 << 22))↩
{↩
res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);↩
if (res != SZ_OK)↩
{↩
stat->CombinedRes_Type = SZ_ERROR_PROGRESS;↩
stat->ProgressRes = res;↩
return res;↩
}↩
inPrev = p->inProcessed;↩
outPrev = p->outProcessed;↩
}↩
}↩
↩
if (finished)↩
return res;↩
}↩
}↩
↩
static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,↩
int finishMode,↩
UInt64 readProcessed, UInt64 inProcessed,↩
SRes res, ECoderStatus status,↩
Bool decodingTruncated,↩
CXzStatInfo *stat)↩
{↩
UInt64 extraSize;↩
↩
stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);↩
stat->InSize = inProcessed;↩
stat->NumStreams = dec->numStartedStreams;↩
stat->NumBlocks = dec->numTotalBlocks;↩
↩
stat->UnpackSize_Defined = True;↩
stat->NumStreams_Defined = True;↩
stat->NumBlocks_Defined = True;↩
↩
extraSize = XzUnpacker_GetExtraSize(dec);↩
↩
if (res == SZ_OK)↩
{↩
if (status == CODER_STATUS_NEEDS_MORE_INPUT)↩
{↩
// CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams↩
extraSize = 0;↩
if (!XzUnpacker_IsStreamWasFinished(dec))↩
res = SZ_ERROR_INPUT_EOF;↩
}↩
else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)↩
res = SZ_ERROR_DATA;↩
}↩
else if (res == SZ_ERROR_NO_ARCHIVE)↩
{↩
/*↩
SZ_ERROR_NO_ARCHIVE is possible for 2 states:↩
XZ_STATE_STREAM_HEADER - if bad signature or bad CRC↩
XZ_STATE_STREAM_PADDING - if non-zero padding data↩
extraSize / inProcessed don't include "bad" byte↩
*/↩
if (inProcessed != extraSize) // if good streams before error↩
if (extraSize != 0 || readProcessed != inProcessed)↩
{↩
stat->DataAfterEnd = True;↩
// there is some good xz stream before. So we set SZ_OK↩
res = SZ_OK;↩
}↩
}↩
↩
stat->DecodeRes = res;↩
↩
stat->InSize -= extraSize;↩
return res;↩
}↩
↩
↩
SRes XzDecMt_Decode(CXzDecMtHandle pp,↩
const CXzDecMtProps *props,↩
const UInt64 *outDataSize, int finishMode,↩
ISeqOutStream *outStream,↩
// Byte *outBuf, size_t *outBufSize,↩
ISeqInStream *inStream,↩
// const Byte *inData, size_t inDataSize,↩
CXzStatInfo *stat,↩
int *isMT,↩
ICompressProgress *progress)↩
{↩
CXzDecMt *p = (CXzDecMt *)pp;↩
#ifndef _7ZIP_ST↩
Bool tMode;↩
#endif↩
↩
XzStatInfo_Clear(stat);↩
↩
p->props = *props;↩
↩
p->inStream = inStream;↩
p->outStream = outStream;↩
p->progress = progress;↩
// p->stat = stat;↩
↩
p->outSize = 0;↩
p->outSize_Defined = False;↩
if (outDataSize)↩
{↩
p->outSize_Defined = True;↩
p->outSize = *outDataSize;↩
}↩
↩
p->finishMode = finishMode;↩
↩
// p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test↩
↩
p->writeRes = SZ_OK;↩
p->outProcessed = 0;↩
p->inProcessed = 0;↩
p->readProcessed = 0;↩
p->readWasFinished = False;↩
↩
p->codeRes = 0;↩
p->status = CODER_STATUS_NOT_SPECIFIED;↩
↩
if (!p->dec_created)↩
{↩
XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);↩
p->dec_created = True;↩
}↩
XzUnpacker_Init(&p->dec);↩
↩
↩
*isMT = False;↩
↩
/*↩
p->outBuf = NULL;↩
p->outBufSize = 0;↩
if (!outStream)↩
{↩
p->outBuf = outBuf;↩
p->outBufSize = *outBufSize;↩
*outBufSize = 0;↩
}↩
*/↩
↩
↩
#ifndef _7ZIP_ST↩
↩
p->isBlockHeaderState_Parse = False;↩
p->isBlockHeaderState_Write = False;↩
// p->numBadBlocks = 0;↩
p->mainErrorCode = SZ_OK;↩
p->mainDecoderWasCalled = False;↩
↩
tMode = False;↩
↩
if (p->props.numThreads > 1)↩
{↩
IMtDecCallback vt;↩
↩
XzDecMt_FreeSt(p);↩
↩
p->outProcessed_Parse = 0;↩
p->parsing_Truncated = False;↩
↩
p->numStreams = 0;↩
p->numTotalBlocks = 0;↩
p->numBlocks = 0;↩
p->finishedDecoderIndex = -1;↩
↩
if (!p->mtc_WasConstructed)↩
{↩
p->mtc_WasConstructed = True;↩
MtDec_Construct(&p->mtc);↩
}↩
↩
p->mtc.mtCallback = &vt;↩
p->mtc.mtCallbackObject = p;↩
↩
p->mtc.progress = progress;↩
p->mtc.inStream = inStream;↩
p->mtc.alloc = &p->alignOffsetAlloc.vt;↩
// p->mtc.inData = inData;↩
// p->mtc.inDataSize = inDataSize;↩
p->mtc.inBufSize = p->props.inBufSize_MT;↩
// p->mtc.inBlockMax = p->props.inBlockMax;↩
p->mtc.numThreadsMax = p->props.numThreads;↩
↩
*isMT = True;↩
↩
vt.Parse = XzDecMt_Callback_Parse;↩
vt.PreCode = XzDecMt_Callback_PreCode;↩
vt.Code = XzDecMt_Callback_Code;↩
vt.Write = XzDecMt_Callback_Write;↩
↩
{↩
Bool needContinue;↩
↩
SRes res = MtDec_Code(&p->mtc);↩
↩
stat->InSize = p->mtc.inProcessed;↩
↩
p->inProcessed = p->mtc.inProcessed;↩
p->readRes = p->mtc.readRes;↩
p->readWasFinished = p->mtc.readWasFinished;↩
p->readProcessed = p->mtc.readProcessed;↩
↩
tMode = True;↩
needContinue = False;↩
↩
if (res == SZ_OK)↩
{↩
if (p->mtc.mtProgress.res != SZ_OK)↩
{↩
res = p->mtc.mtProgress.res;↩
stat->ProgressRes = res;↩
stat->CombinedRes_Type = SZ_ERROR_PROGRESS;↩
}↩
else↩
needContinue = p->mtc.needContinue;↩
}↩
↩
if (!needContinue)↩
{↩
SRes codeRes;↩
Bool truncated = False;↩
ECoderStatus status;↩
CXzUnpacker *dec;↩
↩
stat->OutSize = p->outProcessed;↩
↩
if (p->finishedDecoderIndex >= 0)↩
{↩
CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];↩
codeRes = coder->codeRes;↩
dec = &coder->dec;↩
status = coder->status;↩
}↩
else if (p->mainDecoderWasCalled)↩
{↩
codeRes = p->codeRes;↩
dec = &p->dec;↩
status = p->status;↩
truncated = p->parsing_Truncated;↩
}↩
else↩
return E_FAIL;↩
↩
XzStatInfo_SetStat(dec, p->finishMode,↩
p->mtc.readProcessed, p->mtc.inProcessed,↩
codeRes, status,↩
truncated,↩
stat);↩
↩
if (res == SZ_OK)↩
{↩
if (p->writeRes != SZ_OK)↩
{↩
res = p->writeRes;↩
stat->CombinedRes_Type = SZ_ERROR_WRITE;↩
}↩
else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)↩
{↩
res = p->mtc.readRes;↩
stat->ReadRes = res;↩
stat->CombinedRes_Type = SZ_ERROR_READ;↩
}↩
else if (p->mainErrorCode != SZ_OK)↩
{↩
res = p->mainErrorCode;↩
}↩
}↩
↩
stat->CombinedRes = res;↩
if (stat->CombinedRes_Type == SZ_OK)↩
stat->CombinedRes_Type = res;↩
return res;↩
}↩
↩
PRF_STR("----- decoding ST -----");↩
}↩
}↩
↩
#endif↩
↩
↩
*isMT = False;↩
↩
{↩
SRes res = XzDecMt_Decode_ST(p↩
#ifndef _7ZIP_ST↩
, tMode↩
#endif↩
, stat↩
);↩
↩
XzStatInfo_SetStat(&p->dec,↩
p->finishMode,↩
p->readProcessed, p->inProcessed,↩
p->codeRes, p->status,↩
False, // truncated↩
stat);↩
↩
if (res == SZ_OK)↩
{↩
/*↩
if (p->writeRes != SZ_OK)↩
{↩
res = p->writeRes;↩
stat->CombinedRes_Type = SZ_ERROR_WRITE;↩
}↩
else↩
*/↩
if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)↩
{↩
res = p->readRes;↩
stat->ReadRes = res;↩
stat->CombinedRes_Type = SZ_ERROR_READ;↩
}↩
#ifndef _7ZIP_ST↩
else if (p->mainErrorCode != SZ_OK)↩
res = p->mainErrorCode;↩
#endif↩
}↩
↩
stat->CombinedRes = res;↩
if (stat->CombinedRes_Type == SZ_OK)↩
stat->CombinedRes_Type = res;↩
return res;↩
}↩
}↩