| Index: third_party/lzma_sdk/C/XzDec.c
|
| ===================================================================
|
| --- third_party/lzma_sdk/C/XzDec.c (revision 0)
|
| +++ third_party/lzma_sdk/C/XzDec.c (revision 0)
|
| @@ -0,0 +1,875 @@
|
| +/* XzDec.c -- Xz Decode
|
| +2010-04-16 : Igor Pavlov : Public domain */
|
| +
|
| +/* #define XZ_DUMP */
|
| +
|
| +#ifdef XZ_DUMP
|
| +#include <stdio.h>
|
| +#endif
|
| +
|
| +#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 "SbDec.h"
|
| +#endif
|
| +
|
| +#include "Xz.h"
|
| +
|
| +#define XZ_CHECK_SIZE_MAX 64
|
| +
|
| +#define CODER_BUF_SIZE (1 << 17)
|
| +
|
| +unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
|
| +{
|
| + int i, limit;
|
| + *value = 0;
|
| + limit = (maxSize > 9) ? 9 : (int)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;
|
| +
|
| + UInt32 methodId;
|
| + int encodeMode;
|
| + UInt32 delta;
|
| + UInt32 ip;
|
| + UInt32 x86State;
|
| + Byte deltaState[DELTA_STATE_SIZE];
|
| +
|
| + Byte buf[BRA_BUF_SIZE];
|
| +} CBraState;
|
| +
|
| +void BraState_Free(void *pp, ISzAlloc *alloc)
|
| +{
|
| + alloc->Free(alloc, pp);
|
| +}
|
| +
|
| +SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
| +{
|
| + CBraState *p = ((CBraState *)pp);
|
| + alloc = alloc;
|
| + p->encodeMode = 0;
|
| + 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;
|
| +}
|
| +
|
| +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: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
|
| +
|
| +static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
| + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
|
| +{
|
| + CBraState *p = ((CBraState *)pp);
|
| + SizeT destLenOrig = *destLen;
|
| + SizeT srcLenOrig = *srcLen;
|
| + *destLen = 0;
|
| + *srcLen = 0;
|
| + finishMode = finishMode;
|
| + *wasFinished = 0;
|
| + while (destLenOrig > 0)
|
| + {
|
| + if (p->bufPos != p->bufConv)
|
| + {
|
| + size_t curSize = p->bufConv - p->bufPos;
|
| + if (curSize > destLenOrig)
|
| + curSize = destLenOrig;
|
| + memcpy(dest, p->buf + p->bufPos, curSize);
|
| + p->bufPos += curSize;
|
| + *destLen += curSize;
|
| + dest += curSize;
|
| + destLenOrig -= curSize;
|
| + continue;
|
| + }
|
| + p->bufTotal -= p->bufPos;
|
| + memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
|
| + p->bufPos = 0;
|
| + p->bufConv = 0;
|
| + {
|
| + size_t curSize = BRA_BUF_SIZE - p->bufTotal;
|
| + if (curSize > srcLenOrig)
|
| + curSize = srcLenOrig;
|
| + memcpy(p->buf + p->bufTotal, src, curSize);
|
| + *srcLen += curSize;
|
| + src += curSize;
|
| + srcLenOrig -= curSize;
|
| + p->bufTotal += curSize;
|
| + }
|
| + if (p->bufTotal == 0)
|
| + break;
|
| + switch(p->methodId)
|
| + {
|
| + case XZ_ID_Delta:
|
| + if (p->encodeMode)
|
| + Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
|
| + else
|
| + Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
|
| + p->bufConv = p->bufTotal;
|
| + break;
|
| + case XZ_ID_X86:
|
| + p->bufConv = x86_Convert(p->buf, p->bufTotal, 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)
|
| + default:
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + }
|
| + p->ip += (UInt32)p->bufConv;
|
| +
|
| + if (p->bufConv == 0)
|
| + {
|
| + if (!srcWasFinished)
|
| + break;
|
| + p->bufConv = p->bufTotal;
|
| + }
|
| + }
|
| + if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
|
| + *wasFinished = 1;
|
| + return SZ_OK;
|
| +}
|
| +
|
| +SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
|
| +{
|
| + CBraState *decoder;
|
| + if (id != XZ_ID_Delta &&
|
| + id != XZ_ID_X86 &&
|
| + id != XZ_ID_PPC &&
|
| + id != XZ_ID_IA64 &&
|
| + id != XZ_ID_ARM &&
|
| + id != XZ_ID_ARMT &&
|
| + id != XZ_ID_SPARC)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + p->p = 0;
|
| + decoder = alloc->Alloc(alloc, sizeof(CBraState));
|
| + if (decoder == 0)
|
| + return SZ_ERROR_MEM;
|
| + decoder->methodId = (UInt32)id;
|
| + p->p = decoder;
|
| + p->Free = BraState_Free;
|
| + p->SetProps = BraState_SetProps;
|
| + p->Init = BraState_Init;
|
| + p->Code = BraState_Code;
|
| + return SZ_OK;
|
| +}
|
| +
|
| +/* ---------- SbState ---------- */
|
| +
|
| +#ifdef USE_SUBBLOCK
|
| +
|
| +static void SbState_Free(void *pp, ISzAlloc *alloc)
|
| +{
|
| + CSubblockDec *p = (CSubblockDec *)pp;
|
| + SubblockDec_Free(p, alloc);
|
| + alloc->Free(alloc, pp);
|
| +}
|
| +
|
| +static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
| +{
|
| + pp = pp;
|
| + props = props;
|
| + alloc = alloc;
|
| + return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
|
| +}
|
| +
|
| +static void SbState_Init(void *pp)
|
| +{
|
| + SubblockDec_Init((CSubblockDec *)pp);
|
| +}
|
| +
|
| +static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
| + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
|
| +{
|
| + ECoderStatus status;
|
| + SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);
|
| + srcWasFinished = srcWasFinished;
|
| + *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
|
| + return res;
|
| +}
|
| +
|
| +SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
|
| +{
|
| + CSubblockDec *decoder;
|
| + p->p = 0;
|
| + decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));
|
| + if (decoder == 0)
|
| + return SZ_ERROR_MEM;
|
| + p->p = decoder;
|
| + p->Free = SbState_Free;
|
| + p->SetProps = SbState_SetProps;
|
| + p->Init = SbState_Init;
|
| + p->Code = SbState_Code;
|
| + SubblockDec_Construct(decoder);
|
| + return SZ_OK;
|
| +}
|
| +#endif
|
| +
|
| +/* ---------- Lzma2State ---------- */
|
| +
|
| +static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
|
| +{
|
| + Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
|
| + alloc->Free(alloc, pp);
|
| +}
|
| +
|
| +static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
| +{
|
| + if (propSize != 1)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
|
| +}
|
| +
|
| +static void Lzma2State_Init(void *pp)
|
| +{
|
| + Lzma2Dec_Init((CLzma2Dec *)pp);
|
| +}
|
| +
|
| +static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
| + int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
|
| +{
|
| + ELzmaStatus status;
|
| + /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
|
| + SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);
|
| + srcWasFinished = srcWasFinished;
|
| + *wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
|
| + return res;
|
| +}
|
| +
|
| +static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
|
| +{
|
| + CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));
|
| + p->p = decoder;
|
| + if (decoder == 0)
|
| + return SZ_ERROR_MEM;
|
| + p->Free = Lzma2State_Free;
|
| + p->SetProps = Lzma2State_SetProps;
|
| + p->Init = Lzma2State_Init;
|
| + p->Code = Lzma2State_Code;
|
| + Lzma2Dec_Construct(decoder);
|
| + return SZ_OK;
|
| +}
|
| +
|
| +
|
| +void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
|
| +{
|
| + int i;
|
| + p->alloc = alloc;
|
| + p->buf = 0;
|
| + p->numCoders = 0;
|
| + for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
|
| + p->coders[i].p = NULL;
|
| +}
|
| +
|
| +void MixCoder_Free(CMixCoder *p)
|
| +{
|
| + int i;
|
| + for (i = 0; i < p->numCoders; i++)
|
| + {
|
| + IStateCoder *sc = &p->coders[i];
|
| + if (p->alloc && sc->p)
|
| + sc->Free(sc->p, p->alloc);
|
| + }
|
| + p->numCoders = 0;
|
| + if (p->buf)
|
| + p->alloc->Free(p->alloc, p->buf);
|
| +}
|
| +
|
| +void MixCoder_Init(CMixCoder *p)
|
| +{
|
| + int i;
|
| + for (i = 0; i < p->numCoders - 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);
|
| + }
|
| +}
|
| +
|
| +SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
|
| +{
|
| + IStateCoder *sc = &p->coders[coderIndex];
|
| + p->ids[coderIndex] = methodId;
|
| + switch(methodId)
|
| + {
|
| + case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, 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, p->alloc);
|
| +}
|
| +
|
| +SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
|
| + const Byte *src, SizeT *srcLen, int srcWasFinished,
|
| + ECoderFinishMode finishMode, ECoderStatus *status)
|
| +{
|
| + SizeT destLenOrig = *destLen;
|
| + SizeT srcLenOrig = *srcLen;
|
| + Bool allFinished = True;
|
| + *destLen = 0;
|
| + *srcLen = 0;
|
| + *status = CODER_STATUS_NOT_FINISHED;
|
| +
|
| + if (p->buf == 0)
|
| + {
|
| + p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
|
| + if (p->buf == 0)
|
| + return SZ_ERROR_MEM;
|
| + }
|
| +
|
| + if (p->numCoders != 1)
|
| + finishMode = CODER_FINISH_ANY;
|
| +
|
| + for (;;)
|
| + {
|
| + Bool processed = False;
|
| + int i;
|
| + /*
|
| + 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 *destCur;
|
| + SizeT destLenCur, srcLenCur;
|
| + const Byte *srcCur;
|
| + int srcFinishedCur;
|
| + int encodingWasFinished;
|
| +
|
| + if (i == 0)
|
| + {
|
| + srcCur = src;
|
| + srcLenCur = srcLenOrig - *srcLen;
|
| + srcFinishedCur = srcWasFinished;
|
| + }
|
| + else
|
| + {
|
| + srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
|
| + srcLenCur = p->size[i - 1] - p->pos[i - 1];
|
| + srcFinishedCur = p->finished[i - 1];
|
| + }
|
| +
|
| + if (i == p->numCoders - 1)
|
| + {
|
| + destCur = dest;
|
| + destLenCur = destLenOrig - *destLen;
|
| + }
|
| + else
|
| + {
|
| + if (p->pos[i] != p->size[i])
|
| + continue;
|
| + destCur = p->buf + (CODER_BUF_SIZE * i);
|
| + destLenCur = CODER_BUF_SIZE;
|
| + }
|
| +
|
| + res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
|
| +
|
| + if (!encodingWasFinished)
|
| + allFinished = False;
|
| +
|
| + if (i == 0)
|
| + {
|
| + *srcLen += srcLenCur;
|
| + src += srcLenCur;
|
| + }
|
| + else
|
| + {
|
| + p->pos[i - 1] += srcLenCur;
|
| + }
|
| +
|
| + if (i == p->numCoders - 1)
|
| + {
|
| + *destLen += destLenCur;
|
| + dest += destLenCur;
|
| + }
|
| + else
|
| + {
|
| + p->size[i] = destLenCur;
|
| + p->pos[i] = 0;
|
| + p->finished[i] = encodingWasFinished;
|
| + }
|
| +
|
| + if (res != SZ_OK)
|
| + return res;
|
| +
|
| + if (destLenCur != 0 || srcLenCur != 0)
|
| + processed = True;
|
| + }
|
| + if (!processed)
|
| + break;
|
| + }
|
| + if (allFinished)
|
| + *status = CODER_STATUS_FINISHED_WITH_MARK;
|
| + return SZ_OK;
|
| +}
|
| +
|
| +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) &&
|
| + memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
|
| +}
|
| +
|
| +#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; }
|
| +
|
| +
|
| +SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
|
| +{
|
| + unsigned pos;
|
| + int numFilters, i;
|
| + UInt32 headerSize = (UInt32)header[0] << 2;
|
| +
|
| + if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
|
| + return SZ_ERROR_ARCHIVE;
|
| +
|
| + pos = 1;
|
| + if (pos == headerSize)
|
| + return SZ_ERROR_ARCHIVE;
|
| + p->flags = header[pos++];
|
| +
|
| + 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;
|
| + }
|
| +
|
| + 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[%d] = %2X: ", i, filter->id);
|
| + {
|
| + int i;
|
| + for (i = 0; i < size; i++)
|
| + printf(" %2X", filter->props[i]);
|
| + }
|
| + #endif
|
| + }
|
| +
|
| + while (pos < headerSize)
|
| + if (header[pos++] != 0)
|
| + return SZ_ERROR_ARCHIVE;
|
| + return SZ_OK;
|
| +}
|
| +
|
| +SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
|
| +{
|
| + int i;
|
| + Bool needReInit = True;
|
| + int numFilters = XzBlock_GetNumFilters(block);
|
| + if (numFilters == p->numCoders)
|
| + {
|
| + for (i = 0; i < numFilters; i++)
|
| + if (p->ids[i] != block->filters[numFilters - 1 - i].id)
|
| + break;
|
| + needReInit = (i != numFilters);
|
| + }
|
| + if (needReInit)
|
| + {
|
| + MixCoder_Free(p);
|
| + p->numCoders = numFilters;
|
| + for (i = 0; i < numFilters; i++)
|
| + {
|
| + const CXzFilter *f = &block->filters[numFilters - 1 - i];
|
| + RINOK(MixCoder_SetFromMethod(p, i, f->id));
|
| + }
|
| + }
|
| + 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;
|
| +}
|
| +
|
| +SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)
|
| +{
|
| + MixCoder_Construct(&p->decoder, alloc);
|
| + p->state = XZ_STATE_STREAM_HEADER;
|
| + p->pos = 0;
|
| + p->numStreams = 0;
|
| + return SZ_OK;
|
| +}
|
| +
|
| +void XzUnpacker_Free(CXzUnpacker *p)
|
| +{
|
| + MixCoder_Free(&p->decoder);
|
| +}
|
| +
|
| +SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
| + const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)
|
| +{
|
| + SizeT destLenOrig = *destLen;
|
| + SizeT srcLenOrig = *srcLen;
|
| + *destLen = 0;
|
| + *srcLen = 0;
|
| + *status = CODER_STATUS_NOT_SPECIFIED;
|
| + for (;;)
|
| + {
|
| + SizeT srcRem = srcLenOrig - *srcLen;
|
| +
|
| + if (p->state == XZ_STATE_BLOCK)
|
| + {
|
| + SizeT destLen2 = destLenOrig - *destLen;
|
| + SizeT srcLen2 = srcLenOrig - *srcLen;
|
| + SRes res;
|
| + if (srcLen2 == 0 && destLen2 == 0)
|
| + {
|
| + *status = CODER_STATUS_NOT_FINISHED;
|
| + return SZ_OK;
|
| + }
|
| +
|
| + res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
|
| + XzCheck_Update(&p->check, dest, destLen2);
|
| +
|
| + (*srcLen) += srcLen2;
|
| + src += srcLen2;
|
| + p->packSize += srcLen2;
|
| +
|
| + (*destLen) += destLen2;
|
| + dest += destLen2;
|
| + p->unpackSize += destLen2;
|
| +
|
| + RINOK(res);
|
| +
|
| + if (*status == CODER_STATUS_FINISHED_WITH_MARK)
|
| + {
|
| + Byte temp[32];
|
| + unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
|
| + num += Xz_WriteVarInt(temp + num, p->unpackSize);
|
| + Sha256_Update(&p->sha, temp, num);
|
| + p->indexSize += num;
|
| + p->numBlocks++;
|
| +
|
| + p->state = XZ_STATE_BLOCK_FOOTER;
|
| + p->pos = 0;
|
| + p->alignPos = 0;
|
| + }
|
| + else if (srcLen2 == 0 && destLen2 == 0)
|
| + return SZ_OK;
|
| +
|
| + continue;
|
| + }
|
| +
|
| + if (srcRem == 0)
|
| + {
|
| + *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;
|
| + p->buf[p->pos++] = *src++;
|
| + (*srcLen)++;
|
| + }
|
| + else
|
| + {
|
| + RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
|
| + p->state = XZ_STATE_BLOCK_HEADER;
|
| + Sha256_Init(&p->sha);
|
| + p->indexSize = 0;
|
| + p->numBlocks = 0;
|
| + p->pos = 0;
|
| + }
|
| + break;
|
| + }
|
| +
|
| + case XZ_STATE_BLOCK_HEADER:
|
| + {
|
| + if (p->pos == 0)
|
| + {
|
| + p->buf[p->pos++] = *src++;
|
| + (*srcLen)++;
|
| + if (p->buf[0] == 0)
|
| + {
|
| + 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;
|
| + }
|
| + p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
|
| + }
|
| + else 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));
|
| + p->state = XZ_STATE_BLOCK;
|
| + p->packSize = 0;
|
| + p->unpackSize = 0;
|
| + XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
|
| + RINOK(XzDec_Init(&p->decoder, &p->block));
|
| + }
|
| + break;
|
| + }
|
| +
|
| + case XZ_STATE_BLOCK_FOOTER:
|
| + {
|
| + if (((p->packSize + p->alignPos) & 3) != 0)
|
| + {
|
| + (*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 (cur > srcRem)
|
| + cur = (UInt32)srcRem;
|
| + memcpy(p->buf + p->pos, src, cur);
|
| + p->pos += cur;
|
| + (*srcLen) += cur;
|
| + src += cur;
|
| + }
|
| + else
|
| + {
|
| + 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;
|
| + }
|
| + }
|
| + 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->numStreams++;
|
| + 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;
|
| + */
|
| +}
|
| +
|
| +Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
|
| +{
|
| + return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
|
| +}
|
|
|
| Property changes on: third_party\lzma_sdk\C\XzDec.c
|
| ___________________________________________________________________
|
| Added: svn:executable
|
| + *
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|