| Index: third_party/lzma_sdk/C/7zDec.c
|
| ===================================================================
|
| --- third_party/lzma_sdk/C/7zDec.c (revision 0)
|
| +++ third_party/lzma_sdk/C/7zDec.c (revision 0)
|
| @@ -0,0 +1,470 @@
|
| +/* 7zDec.c -- Decoding from 7z folder
|
| +2010-11-02 : Igor Pavlov : Public domain */
|
| +
|
| +#include <string.h>
|
| +
|
| +/* #define _7ZIP_PPMD_SUPPPORT */
|
| +
|
| +#include "7z.h"
|
| +
|
| +#include "Bcj2.h"
|
| +#include "Bra.h"
|
| +#include "CpuArch.h"
|
| +#include "LzmaDec.h"
|
| +#include "Lzma2Dec.h"
|
| +#ifdef _7ZIP_PPMD_SUPPPORT
|
| +#include "Ppmd7.h"
|
| +#endif
|
| +
|
| +#define k_Copy 0
|
| +#define k_LZMA2 0x21
|
| +#define k_LZMA 0x30101
|
| +#define k_BCJ 0x03030103
|
| +#define k_PPC 0x03030205
|
| +#define k_ARM 0x03030501
|
| +#define k_ARMT 0x03030701
|
| +#define k_SPARC 0x03030805
|
| +#define k_BCJ2 0x0303011B
|
| +
|
| +#ifdef _7ZIP_PPMD_SUPPPORT
|
| +
|
| +#define k_PPMD 0x30401
|
| +
|
| +typedef struct
|
| +{
|
| + IByteIn p;
|
| + const Byte *cur;
|
| + const Byte *end;
|
| + const Byte *begin;
|
| + UInt64 processed;
|
| + Bool extra;
|
| + SRes res;
|
| + ILookInStream *inStream;
|
| +} CByteInToLook;
|
| +
|
| +static Byte ReadByte(void *pp)
|
| +{
|
| + CByteInToLook *p = (CByteInToLook *)pp;
|
| + if (p->cur != p->end)
|
| + return *p->cur++;
|
| + if (p->res == SZ_OK)
|
| + {
|
| + size_t size = p->cur - p->begin;
|
| + p->processed += size;
|
| + p->res = p->inStream->Skip(p->inStream, size);
|
| + size = (1 << 25);
|
| + p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
|
| + p->cur = p->begin;
|
| + p->end = p->begin + size;
|
| + if (size != 0)
|
| + return *p->cur++;;
|
| + }
|
| + p->extra = True;
|
| + return 0;
|
| +}
|
| +
|
| +static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
| + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
| +{
|
| + CPpmd7 ppmd;
|
| + CByteInToLook s;
|
| + SRes res = SZ_OK;
|
| +
|
| + s.p.Read = ReadByte;
|
| + s.inStream = inStream;
|
| + s.begin = s.end = s.cur = NULL;
|
| + s.extra = False;
|
| + s.res = SZ_OK;
|
| + s.processed = 0;
|
| +
|
| + if (coder->Props.size != 5)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| +
|
| + {
|
| + unsigned order = coder->Props.data[0];
|
| + UInt32 memSize = GetUi32(coder->Props.data + 1);
|
| + if (order < PPMD7_MIN_ORDER ||
|
| + order > PPMD7_MAX_ORDER ||
|
| + memSize < PPMD7_MIN_MEM_SIZE ||
|
| + memSize > PPMD7_MAX_MEM_SIZE)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + Ppmd7_Construct(&ppmd);
|
| + if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
| + return SZ_ERROR_MEM;
|
| + Ppmd7_Init(&ppmd, order);
|
| + }
|
| + {
|
| + CPpmd7z_RangeDec rc;
|
| + Ppmd7z_RangeDec_CreateVTable(&rc);
|
| + rc.Stream = &s.p;
|
| + if (!Ppmd7z_RangeDec_Init(&rc))
|
| + res = SZ_ERROR_DATA;
|
| + else if (s.extra)
|
| + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
| + else
|
| + {
|
| + SizeT i;
|
| + for (i = 0; i < outSize; i++)
|
| + {
|
| + int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
|
| + if (s.extra || sym < 0)
|
| + break;
|
| + outBuffer[i] = (Byte)sym;
|
| + }
|
| + if (i != outSize)
|
| + res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
| + else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
| + res = SZ_ERROR_DATA;
|
| + }
|
| + }
|
| + Ppmd7_Free(&ppmd, allocMain);
|
| + return res;
|
| +}
|
| +
|
| +#endif
|
| +
|
| +
|
| +static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
| + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
| +{
|
| + CLzmaDec state;
|
| + SRes res = SZ_OK;
|
| +
|
| + LzmaDec_Construct(&state);
|
| + RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
| + state.dic = outBuffer;
|
| + state.dicBufSize = outSize;
|
| + LzmaDec_Init(&state);
|
| +
|
| + for (;;)
|
| + {
|
| + Byte *inBuf = NULL;
|
| + size_t lookahead = (1 << 18);
|
| + if (lookahead > inSize)
|
| + lookahead = (size_t)inSize;
|
| + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
| + if (res != SZ_OK)
|
| + break;
|
| +
|
| + {
|
| + SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
| + ELzmaStatus status;
|
| + res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
| + lookahead -= inProcessed;
|
| + inSize -= inProcessed;
|
| + if (res != SZ_OK)
|
| + break;
|
| + if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
| + {
|
| + if (state.dicBufSize != outSize || lookahead != 0 ||
|
| + (status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
| + status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
| + res = SZ_ERROR_DATA;
|
| + break;
|
| + }
|
| + res = inStream->Skip((void *)inStream, inProcessed);
|
| + if (res != SZ_OK)
|
| + break;
|
| + }
|
| + }
|
| +
|
| + LzmaDec_FreeProbs(&state, allocMain);
|
| + return res;
|
| +}
|
| +
|
| +static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
| + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
| +{
|
| + CLzma2Dec state;
|
| + SRes res = SZ_OK;
|
| +
|
| + Lzma2Dec_Construct(&state);
|
| + if (coder->Props.size != 1)
|
| + return SZ_ERROR_DATA;
|
| + RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
|
| + state.decoder.dic = outBuffer;
|
| + state.decoder.dicBufSize = outSize;
|
| + Lzma2Dec_Init(&state);
|
| +
|
| + for (;;)
|
| + {
|
| + Byte *inBuf = NULL;
|
| + size_t lookahead = (1 << 18);
|
| + if (lookahead > inSize)
|
| + lookahead = (size_t)inSize;
|
| + res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
| + if (res != SZ_OK)
|
| + break;
|
| +
|
| + {
|
| + SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
| + ELzmaStatus status;
|
| + res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
| + lookahead -= inProcessed;
|
| + inSize -= inProcessed;
|
| + if (res != SZ_OK)
|
| + break;
|
| + if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
| + {
|
| + if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
| + (status != LZMA_STATUS_FINISHED_WITH_MARK))
|
| + res = SZ_ERROR_DATA;
|
| + break;
|
| + }
|
| + res = inStream->Skip((void *)inStream, inProcessed);
|
| + if (res != SZ_OK)
|
| + break;
|
| + }
|
| + }
|
| +
|
| + Lzma2Dec_FreeProbs(&state, allocMain);
|
| + return res;
|
| +}
|
| +
|
| +static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
| +{
|
| + while (inSize > 0)
|
| + {
|
| + void *inBuf;
|
| + size_t curSize = (1 << 18);
|
| + if (curSize > inSize)
|
| + curSize = (size_t)inSize;
|
| + RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
|
| + if (curSize == 0)
|
| + return SZ_ERROR_INPUT_EOF;
|
| + memcpy(outBuffer, inBuf, curSize);
|
| + outBuffer += curSize;
|
| + inSize -= curSize;
|
| + RINOK(inStream->Skip((void *)inStream, curSize));
|
| + }
|
| + return SZ_OK;
|
| +}
|
| +
|
| +static Bool IS_MAIN_METHOD(UInt32 m)
|
| +{
|
| + switch(m)
|
| + {
|
| + case k_Copy:
|
| + case k_LZMA:
|
| + case k_LZMA2:
|
| + #ifdef _7ZIP_PPMD_SUPPPORT
|
| + case k_PPMD:
|
| + #endif
|
| + return True;
|
| + }
|
| + return False;
|
| +}
|
| +
|
| +static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
| +{
|
| + return
|
| + c->NumInStreams == 1 &&
|
| + c->NumOutStreams == 1 &&
|
| + c->MethodID <= (UInt32)0xFFFFFFFF &&
|
| + IS_MAIN_METHOD((UInt32)c->MethodID);
|
| +}
|
| +
|
| +#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
| +
|
| +static SRes CheckSupportedFolder(const CSzFolder *f)
|
| +{
|
| + if (f->NumCoders < 1 || f->NumCoders > 4)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + if (!IS_SUPPORTED_CODER(&f->Coders[0]))
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + if (f->NumCoders == 1)
|
| + {
|
| + if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + return SZ_OK;
|
| + }
|
| + if (f->NumCoders == 2)
|
| + {
|
| + CSzCoderInfo *c = &f->Coders[1];
|
| + if (c->MethodID > (UInt32)0xFFFFFFFF ||
|
| + c->NumInStreams != 1 ||
|
| + c->NumOutStreams != 1 ||
|
| + f->NumPackStreams != 1 ||
|
| + f->PackStreams[0] != 0 ||
|
| + f->NumBindPairs != 1 ||
|
| + f->BindPairs[0].InIndex != 1 ||
|
| + f->BindPairs[0].OutIndex != 0)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + switch ((UInt32)c->MethodID)
|
| + {
|
| + case k_BCJ:
|
| + case k_ARM:
|
| + break;
|
| + default:
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + }
|
| + return SZ_OK;
|
| + }
|
| + if (f->NumCoders == 4)
|
| + {
|
| + if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
|
| + !IS_SUPPORTED_CODER(&f->Coders[2]) ||
|
| + !IS_BCJ2(&f->Coders[3]))
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + if (f->NumPackStreams != 4 ||
|
| + f->PackStreams[0] != 2 ||
|
| + f->PackStreams[1] != 6 ||
|
| + f->PackStreams[2] != 1 ||
|
| + f->PackStreams[3] != 0 ||
|
| + f->NumBindPairs != 3 ||
|
| + f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
| + f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
| + f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + return SZ_OK;
|
| + }
|
| + return SZ_ERROR_UNSUPPORTED;
|
| +}
|
| +
|
| +static UInt64 GetSum(const UInt64 *values, UInt32 index)
|
| +{
|
| + UInt64 sum = 0;
|
| + UInt32 i;
|
| + for (i = 0; i < index; i++)
|
| + sum += values[i];
|
| + return sum;
|
| +}
|
| +
|
| +#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
| +
|
| +static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
| + ILookInStream *inStream, UInt64 startPos,
|
| + Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
| + Byte *tempBuf[])
|
| +{
|
| + UInt32 ci;
|
| + SizeT tempSizes[3] = { 0, 0, 0};
|
| + SizeT tempSize3 = 0;
|
| + Byte *tempBuf3 = 0;
|
| +
|
| + RINOK(CheckSupportedFolder(folder));
|
| +
|
| + for (ci = 0; ci < folder->NumCoders; ci++)
|
| + {
|
| + CSzCoderInfo *coder = &folder->Coders[ci];
|
| +
|
| + if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
| + {
|
| + UInt32 si = 0;
|
| + UInt64 offset;
|
| + UInt64 inSize;
|
| + Byte *outBufCur = outBuffer;
|
| + SizeT outSizeCur = outSize;
|
| + if (folder->NumCoders == 4)
|
| + {
|
| + UInt32 indices[] = { 3, 2, 0 };
|
| + UInt64 unpackSize = folder->UnpackSizes[ci];
|
| + si = indices[ci];
|
| + if (ci < 2)
|
| + {
|
| + Byte *temp;
|
| + outSizeCur = (SizeT)unpackSize;
|
| + if (outSizeCur != unpackSize)
|
| + return SZ_ERROR_MEM;
|
| + temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
| + if (temp == 0 && outSizeCur != 0)
|
| + return SZ_ERROR_MEM;
|
| + outBufCur = tempBuf[1 - ci] = temp;
|
| + tempSizes[1 - ci] = outSizeCur;
|
| + }
|
| + else if (ci == 2)
|
| + {
|
| + if (unpackSize > outSize) /* check it */
|
| + return SZ_ERROR_PARAM;
|
| + tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
| + tempSize3 = outSizeCur = (SizeT)unpackSize;
|
| + }
|
| + else
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + }
|
| + offset = GetSum(packSizes, si);
|
| + inSize = packSizes[si];
|
| + RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
| +
|
| + if (coder->MethodID == k_Copy)
|
| + {
|
| + if (inSize != outSizeCur) /* check it */
|
| + return SZ_ERROR_DATA;
|
| + RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
| + }
|
| + else if (coder->MethodID == k_LZMA)
|
| + {
|
| + RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
| + }
|
| + else if (coder->MethodID == k_LZMA2)
|
| + {
|
| + RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
| + }
|
| + else
|
| + {
|
| + #ifdef _7ZIP_PPMD_SUPPPORT
|
| + RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
| + #else
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + #endif
|
| + }
|
| + }
|
| + else if (coder->MethodID == k_BCJ2)
|
| + {
|
| + UInt64 offset = GetSum(packSizes, 1);
|
| + UInt64 s3Size = packSizes[1];
|
| + SRes res;
|
| + if (ci != 3)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
| + tempSizes[2] = (SizeT)s3Size;
|
| + if (tempSizes[2] != s3Size)
|
| + return SZ_ERROR_MEM;
|
| + tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
| + if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
| + return SZ_ERROR_MEM;
|
| + res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
| + RINOK(res)
|
| +
|
| + res = Bcj2_Decode(
|
| + tempBuf3, tempSize3,
|
| + tempBuf[0], tempSizes[0],
|
| + tempBuf[1], tempSizes[1],
|
| + tempBuf[2], tempSizes[2],
|
| + outBuffer, outSize);
|
| + RINOK(res)
|
| + }
|
| + else
|
| + {
|
| + if (ci != 1)
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + switch(coder->MethodID)
|
| + {
|
| + case k_BCJ:
|
| + {
|
| + UInt32 state;
|
| + x86_Convert_Init(state);
|
| + x86_Convert(outBuffer, outSize, 0, &state, 0);
|
| + break;
|
| + }
|
| + CASE_BRA_CONV(ARM)
|
| + default:
|
| + return SZ_ERROR_UNSUPPORTED;
|
| + }
|
| + }
|
| + }
|
| + return SZ_OK;
|
| +}
|
| +
|
| +SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
| + ILookInStream *inStream, UInt64 startPos,
|
| + Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
| +{
|
| + Byte *tempBuf[3] = { 0, 0, 0};
|
| + int i;
|
| + SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
|
| + outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
| + for (i = 0; i < 3; i++)
|
| + IAlloc_Free(allocMain, tempBuf[i]);
|
| + return res;
|
| +}
|
|
|
| Property changes on: third_party\lzma_sdk\C\7zDec.c
|
| ___________________________________________________________________
|
| Added: svn:executable
|
| + *
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|