LzmaDec.c revision 4fd606d1f5abe38e1f42c38de1d2e895166bd0f4
/** @file
Based on LZMA SDK 4.65:
LzmaDec.c -- LZMA Decoder
2008-11-06 : Igor Pavlov : Public domain
Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "LzmaDec.h"
#ifndef EFIAPI
#include <string.h>
#endif // !EFIAPI
#define kNumTopBits 24
#define kNumBitModelTotalBits 11
#define kNumMoveBits 5
#define RC_INIT_SIZE 5
#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
/* #define _LZMA_SIZE_OPT */
#ifdef _LZMA_SIZE_OPT
#else
#define TREE_6_DECODE(probs, i) \
{ i = 1; \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
TREE_GET_BIT(probs, i); \
i -= 0x40; }
#endif
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
{ UPDATE_0_CHECK; i = (i + i); A0; } else \
#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
#define kNumPosBitsMax 4
#define kLenNumLowBits 3
#define kLenNumMidBits 3
#define kLenNumHighBits 8
#define LenChoice 0
#define kNumStates 12
#define kNumLitStates 7
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kMatchMinLen 2
#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
#define IsMatch 0
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#if Literal != LZMA_BASE_SIZE
#endif
{
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
};
/* First LZMA-symbol is always decoded.
And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
Out:
Result:
SZ_OK - OK
SZ_ERROR_DATA - Error
p->remainLen:
< kMatchSpecLenStart : normal remain
= kMatchSpecLenStart : finished
= kMatchSpecLenStart + 1 : Flush marker
= kMatchSpecLenStart + 2 : State Init Marker
*/
{
unsigned len = 0;
do
{
unsigned ttt;
{
unsigned symbol;
if (checkDicSize != 0 || processedPos != 0)
if (state < kNumLitStates)
{
symbol = 1;
}
else
{
unsigned offs = 0x100;
symbol = 1;
do
{
unsigned bit;
matchByte <<= 1;
}
while (symbol < 0x100);
}
processedPos++;
/* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
continue;
}
else
{
{
state += kNumStates;
}
else
{
if (checkDicSize == 0 && processedPos == 0)
return SZ_ERROR_DATA;
{
{
dicPos++;
processedPos++;
continue;
}
}
else
{
{
}
else
{
{
}
else
{
}
}
}
}
{
{
offset = 0;
}
else
{
{
}
else
{
}
}
}
if (state >= kNumStates)
{
if (distance >= kStartPosModelIndex)
{
if (posSlot < kEndPosModelIndex)
{
distance <<= numDirectBits;
{
unsigned i = 1;
do
{
mask <<= 1;
}
while (--numDirectBits != 0);
}
}
else
{
do
{
range >>= 1;
{
UInt32 t;
}
/*
distance <<= 1;
if (code >= range)
{
code -= range;
distance |= 1;
}
*/
}
while (--numDirectBits != 0);
distance <<= kNumAlignBits;
{
unsigned i = 1;
}
{
state -= kNumStates;
break;
}
}
}
if (checkDicSize == 0)
{
if (distance >= processedPos)
return SZ_ERROR_DATA;
}
else if (distance >= checkDicSize)
return SZ_ERROR_DATA;
/* state = kLiteralNextStates[state]; */
}
len += kMatchMinLen;
return SZ_ERROR_DATA;
{
processedPos += curLen;
{
do
}
else
{
do
{
if (++pos == dicBufSize)
pos = 0;
}
while (--curLen != 0);
}
}
}
}
p->processedPos = processedPos;
return SZ_OK;
}
{
{
p->processedPos += len;
while (len-- != 0)
{
dicPos++;
}
}
}
{
do
{
if (p->checkDicSize == 0)
{
}
LzmaDec_WriteRem(p, limit);
}
if (p->remainLen > kMatchSpecLenStart)
{
p->remainLen = kMatchSpecLenStart;
}
return 0;
}
typedef enum
{
DUMMY_ERROR, /* unexpected end of input stream */
} ELzmaDummy;
{
{
unsigned ttt;
{
/* if (bufLimit - buf >= 7) return DUMMY_LIT; */
if (p->checkDicSize != 0 || p->processedPos != 0)
prob += (LZMA_LIT_SIZE *
if (state < kNumLitStates)
{
unsigned symbol = 1;
}
else
{
unsigned offs = 0x100;
unsigned symbol = 1;
do
{
unsigned bit;
matchByte <<= 1;
}
while (symbol < 0x100);
}
}
else
{
unsigned len;
{
state = 0;
res = DUMMY_MATCH;
}
else
{
{
{
return DUMMY_REP;
}
else
{
}
}
else
{
{
}
else
{
{
}
else
{
}
}
}
state = kNumStates;
}
{
{
offset = 0;
}
else
{
{
}
else
{
}
}
}
if (state < 4)
{
unsigned posSlot;
if (posSlot >= kStartPosModelIndex)
{
/* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
if (posSlot < kEndPosModelIndex)
{
}
else
{
do
{
range >>= 1;
/* if (code >= range) code -= range; */
}
while (--numDirectBits != 0);
}
{
unsigned i = 1;
do
{
GET_BIT_CHECK(prob + i, i);
}
while (--numDirectBits != 0);
}
}
}
}
}
return res;
}
{
p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
p->range = 0xFFFFFFFF;
p->needFlush = 0;
}
{
p->needFlush = 1;
p->remainLen = 0;
p->tempBufSize = 0;
if (initDic)
{
p->processedPos = 0;
p->checkDicSize = 0;
p->needInitState = 1;
}
if (initState)
p->needInitState = 1;
}
void LzmaDec_Init(CLzmaDec *p)
{
p->dicPos = 0;
}
static void LzmaDec_InitStateReal(CLzmaDec *p)
{
UInt32 i;
for (i = 0; i < numProbs; i++)
p->state = 0;
p->needInitState = 0;
}
{
(*srcLen) = 0;
LzmaDec_WriteRem(p, dicLimit);
while (p->remainLen != kMatchSpecLenStart)
{
int checkEndMarkNow;
if (p->needFlush != 0)
{
if (p->tempBufSize < RC_INIT_SIZE)
{
return SZ_OK;
}
if (p->tempBuf[0] != 0)
return SZ_ERROR_DATA;
LzmaDec_InitRc(p, p->tempBuf);
p->tempBufSize = 0;
}
checkEndMarkNow = 0;
{
{
return SZ_OK;
}
if (finishMode == LZMA_FINISH_ANY)
{
return SZ_OK;
}
if (p->remainLen != 0)
{
return SZ_ERROR_DATA;
}
checkEndMarkNow = 1;
}
if (p->needInitState)
if (p->tempBufSize == 0)
{
{
if (dummyRes == DUMMY_ERROR)
{
p->tempBufSize = (unsigned)inSize;
return SZ_OK;
}
{
return SZ_ERROR_DATA;
}
}
else
return SZ_ERROR_DATA;
}
else
{
p->tempBufSize = rem;
{
if (dummyRes == DUMMY_ERROR)
{
return SZ_OK;
}
{
return SZ_ERROR_DATA;
}
}
return SZ_ERROR_DATA;
p->tempBufSize = 0;
}
}
if (p->code == 0)
}
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{
for (;;)
{
if (p->dicPos == p->dicBufSize)
p->dicPos = 0;
{
outSizeCur = p->dicBufSize;
}
else
{
}
dest += outSizeCur;
outSize -= outSizeCur;
*destLen += outSizeCur;
if (res != 0)
return res;
if (outSizeCur == 0 || outSize == 0)
return SZ_OK;
}
}
{
p->probs = 0;
}
{
p->dic = 0;
}
{
LzmaDec_FreeProbs(p, alloc);
LzmaDec_FreeDict(p, alloc);
}
{
Byte d;
if (size < LZMA_PROPS_SIZE)
return SZ_ERROR_UNSUPPORTED;
else
if (dicSize < LZMA_DIC_MIN)
d = data[0];
if (d >= (9 * 5 * 5))
return SZ_ERROR_UNSUPPORTED;
p->lc = d % 9;
d /= 9;
p->pb = d / 5;
p->lp = d % 5;
return SZ_OK;
}
{
{
LzmaDec_FreeProbs(p, alloc);
if (p->probs == 0)
return SZ_ERROR_MEM;
}
return SZ_OK;
}
{
return SZ_OK;
}
{
{
LzmaDec_FreeDict(p, alloc);
if (p->dic == 0)
{
LzmaDec_FreeProbs(p, alloc);
return SZ_ERROR_MEM;
}
}
p->dicBufSize = dicBufSize;
return SZ_OK;
}
{
CLzmaDec p;
if (inSize < RC_INIT_SIZE)
return SZ_ERROR_INPUT_EOF;
LzmaDec_Construct(&p);
if (res != 0)
return res;
p.dicBufSize = outSize;
LzmaDec_Init(&p);
LzmaDec_FreeProbs(&p, alloc);
return res;
}