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 |