blob: 7fd5b15cf367630b8f8da0185a2b3a825f2d56fc [file] [log] [blame]
/*
* LZMADecode.c
*
* This file is a part of LZMA compression module for NSIS.
*
* Original LZMA SDK Copyright (C) 1999-2006 Igor Pavlov
* Modifications Copyright (C) 2003-2007 Amir Szekely <kichik@netvision.net.il>
*
* Licensed under the Common Public License version 1.0 (the "License");
* you may not use this file except in compliance with the License.
*
* Licence details can be found in the file COPYING.nsis.
*
* This software is provided 'as-is', without any express or implied
* warranty.
*/
#include <stdlib.h>
#include "LZMADecode.h"
#define LEAVE { goto saveStateAndReturn; }
#define NEED_BYTE(c) case c: if (!avail_in) { mode = c; LEAVE; }
#define NEED_BYTE_ if (!avail_in) LEAVE;
#define NEXT_BYTE (avail_in--, *next_in++)
#define NEED_OUT(c) case c: if (!avail_out) { mode = c; LEAVE; }
#define PUT_BYTE_(b) { *next_out = b; next_out++; avail_out--; }
#define PUT_BYTE(b) { totalOut++; PUT_BYTE_(b) }
#define DECODE_BIT(c, x) prob = x; last = c; goto _LZMA_C_RDBD; case c:
#define DECODE_LEN(c, x) probs = x; last2 = c; goto _LZMA_C_LEND; case c:
#define DECODE_BIT_TREE(c, x, y) probs = x; numLevels = y; last3 = c; goto _LZMA_C_BTD; case c:
enum {
/* 0 */ LZMA_C_INIT = 0,
/* 1 */ LZMA_C_GETDICT,
/* 2 */ LZMA_C_BLOCK,
/* 3 */ LZMA_C_RDI, /* RangeDecoderInit */
/* 4 */ LZMA_C_RDBD, /* RangeDecoderBitDecode */
/* 5 */ LZMA_C_RDBD_IN, /* RangeDecoderBitDecode */
/* 6 */ LZMA_C_TYPE,
/* 7 */ LZMA_C_ISREP,
/* 8 */ LZMA_C_ISREPG0,
/* 9 */ LZMA_C_ISREP0LONG,
/* 10 */ LZMA_C_ISREPG1,
/* 11 */ LZMA_C_ISREPG2,
/* 12 */ LZMA_C_NORM,
/* 13 */ LZMA_C_LITDM1, /* LzmaLiteralDecodeMatch */
/* 14 */ LZMA_C_LITDM2, /* LzmaLiteralDecodeMatch */
/* 15 */ LZMA_C_LITD, /* LzmaLiteralDecode */
/* 16 */ LZMA_C_RDRBTD, /* RangeDecoderReverseBitTreeDecode */
/* 17 */ LZMA_C_LEND, /* LzmaLenDecode */
/* 18 */ LZMA_C_LEND1, /* LzmaLenDecode */
/* 19 */ LZMA_C_LEND2, /* LzmaLenDecode */
/* 20 */ LZMA_C_LEND_RES, /* LzmaLenDecode */
/* 21 */ LZMA_C_LEND_C1,
/* 22 */ LZMA_C_LEND_C2,
/* 23 */ LZMA_C_BTD, /* RangeDecoderBitTreeDecode */
/* 24 */ LZMA_C_BTD_LOOP,
/* 25 */ LZMA_C_BTD_C1,
/* 26 */ LZMA_C_OUTPUT_1,
/* 27 */ LZMA_C_OUTPUT_2,
/* 28 */ LZMA_C_OUTPUT_3
};
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
#define RC_NORMALIZE(c) if (range < kTopValue) { NEED_BYTE(c); range <<= 8; code = (code << 8) | NEXT_BYTE; }
#define RC_GET_BIT2(c, prob, mi, A0, A1) { \
UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
if (code < bound) \
{ A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
else \
{ A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
RC_NORMALIZE(c) \
}
#define RC_GET_BIT(c, prob, mi) RC_GET_BIT2(c, prob, mi, ; , ;)
#define kNumPosBitsMax 4
#define kNumPosStatesMax (1 << kNumPosBitsMax)
#define kLenNumLowBits 3
#define kLenNumLowSymbols (1 << kLenNumLowBits)
#define kLenNumMidBits 3
#define kLenNumMidSymbols (1 << kLenNumMidBits)
#define kLenNumHighBits 8
#define kLenNumHighSymbols (1 << kLenNumHighBits)
#define LenChoice 0
#define LenChoice2 (LenChoice + 1)
#define LenLow (LenChoice2 + 1)
#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
#define kNumStates 12
#define kStartPosModelIndex 4
#define kEndPosModelIndex 14
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
#define kNumPosSlotBits 6
#define kNumLenToPosStates 4
#define kNumAlignBits 4
#define kAlignTableSize (1 << kNumAlignBits)
#define kMatchMinLen 2
#define IsMatch 0
#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
#define IsRepG0 (IsRep + kNumStates)
#define IsRepG1 (IsRepG0 + kNumStates)
#define IsRepG2 (IsRepG1 + kNumStates)
#define IsRep0Long (IsRepG2 + kNumStates)
#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
#define LenCoder (Align + kAlignTableSize)
#define RepLenCoder (LenCoder + kNumLenProbs)
#define Literal (RepLenCoder + kNumLenProbs)
#define LZMA_BASE_SIZE 1846
#define LZMA_LIT_SIZE 768
#if Literal != LZMA_BASE_SIZE
StopCompilingDueBUG
#endif
void lzmaInit(lzma_stream *s)
{
/* size of lzma_stream minus the size of the two allocated buffer pointers.
we don't want to lose to pointer or else we won't be able to free them. */
size_t i = sizeof(lzma_stream) - (sizeof(unsigned char *) * 2);
while (i--)
((lzByte *)s)[i] = 0;
s->rep0 = s->rep1 = s->rep2 = s->rep3 = 1;
s->range = (0xFFFFFFFF);
}
int lzmaDecode(lzma_stream *s)
{
/* restore decoder state */
lzma_stream _s = *s;
#define mode _s.mode
#define last _s.last
#define last2 _s.last2
#define last3 _s.last3
#define p (*(CProb **) &_s.dynamicData)
#define dynamicDataSize _s.dynamicDataSize
#define state _s.state
#define isPreviousMatch _s.isPreviousMatch
#define previousByte _s.previousByte
#define rep0 _s.rep0
#define rep1 _s.rep1
#define rep2 _s.rep2
#define rep3 _s.rep3
#define lc _s.lc
#define len _s.len
#define totalOut _s.totalOut
#define dictionary _s.dictionary
#define dictionarySize _s.dictionarySize
#define dictionaryPos _s.dictionaryPos
#define posStateMask _s.posStateMask
#define literalPosMask _s.literalPosMask
#define avail_in _s.avail_in
#define next_in _s.next_in
#define avail_out _s.avail_out
#define next_out _s.next_out
#define range _s.range
#define code _s.code
#define probs _s.probs
#define prob _s.prob
#define symbol _s.temp2
#define bit _s.temp3
#define matchBit _s.temp1
#define i _s.temp1
#define result _s.temp2
#define numLevels _s.temp3
#define posSlot _s.temp2
#define newDictionarySize (*(UInt32*) &_s.temp3)
#define matchByte _s.matchByte
#define mi _s.mi
#define posState _s.posState
if (len == -1)
return LZMA_STREAM_END;
for (;;) switch (mode)
{
case LZMA_C_INIT:
{
lzByte firstByte;
UInt32 newDynamicDataSize;
UInt32 numProbs;
int lp;
int pb;
NEED_BYTE_;
firstByte = NEXT_BYTE;
if (firstByte > (9*5*5))
return LZMA_DATA_ERROR;
pb = firstByte / (9*5);
firstByte %= (9*5);
lp = firstByte / 9;
firstByte %= 9;
lc = firstByte;
posStateMask = (1 << (pb)) - 1;
literalPosMask = (1 << (lp)) - 1;
numProbs = Literal + (LZMA_LIT_SIZE << (lc + pb));
newDynamicDataSize = numProbs * sizeof(CProb);
if (newDynamicDataSize != dynamicDataSize)
{
if (p)
lzmafree(p);
p = lzmaalloc(newDynamicDataSize);
if (!p)
return LZMA_NOT_ENOUGH_MEM;
dynamicDataSize = newDynamicDataSize;
}
while (numProbs--)
p[numProbs] = kBitModelTotal >> 1;
for (i = 0, newDictionarySize = 0; i < 4; i++)
{
NEED_BYTE(LZMA_C_GETDICT);
newDictionarySize |= NEXT_BYTE << (i * 8);
}
if (newDictionarySize != dictionarySize)
{
dictionarySize = newDictionarySize;
if (dictionary)
lzmafree(dictionary);
dictionary = lzmaalloc(dictionarySize);
if (!dictionary)
return LZMA_NOT_ENOUGH_MEM;
}
dictionary[dictionarySize - 1] = 0;
i = 5;
while (i--)
{
NEED_BYTE(LZMA_C_RDI);
code = (code << 8) | NEXT_BYTE;
}
}
case LZMA_C_BLOCK:
posState = (int)(totalOut & posStateMask);
DECODE_BIT(LZMA_C_TYPE, p + IsMatch + (state << kNumPosBitsMax) + posState);
if (bit == 0)
{
probs = p + Literal + (LZMA_LIT_SIZE *
(((totalOut & literalPosMask) << lc) + (previousByte >> (8 - lc))));
if (state < 4) state = 0;
else if (state < 10) state -= 3;
else state -= 6;
if (isPreviousMatch)
{
UInt32 pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
matchByte = dictionary[pos];
{
symbol = 1;
do
{
matchBit = (matchByte >> 7) & 1;
matchByte <<= 1;
{
prob = probs + ((1 + matchBit) << 8) + symbol;
RC_GET_BIT2(LZMA_C_LITDM1, prob, symbol, bit = 0, bit = 1)
}
if (matchBit != bit)
{
while (symbol < 0x100)
{
prob = probs + symbol;
RC_GET_BIT(LZMA_C_LITDM2, prob, symbol)
}
break;
}
}
while (symbol < 0x100);
previousByte = symbol;
}
isPreviousMatch = 0;
}
else
{
symbol = 1;
do
{
prob = probs + symbol;
RC_GET_BIT(LZMA_C_LITD, prob, symbol)
}
while (symbol < 0x100);
previousByte = symbol;
}
NEED_OUT(LZMA_C_OUTPUT_1);
PUT_BYTE(previousByte);
dictionary[dictionaryPos] = previousByte;
dictionaryPos = (dictionaryPos + 1) % dictionarySize;
}
/* bit == 1 */
else
{
isPreviousMatch = 1;
DECODE_BIT(LZMA_C_ISREP, p + IsRep + state);
if (bit == 1)
{
DECODE_BIT(LZMA_C_ISREPG0, p + IsRepG0 + state);
if (bit == 0)
{
DECODE_BIT(LZMA_C_ISREP0LONG, p + IsRep0Long + (state << kNumPosBitsMax) + posState);
if (bit == 0)
{
UInt32 pos;
if (totalOut == 0)
return LZMA_DATA_ERROR;
state = state < 7 ? 9 : 11;
NEED_OUT(LZMA_C_OUTPUT_2);
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
dictionaryPos = (dictionaryPos + 1) % dictionarySize;
PUT_BYTE(previousByte);
mode = LZMA_C_BLOCK;
break;
}
}
else
{
UInt32 distance;
DECODE_BIT(LZMA_C_ISREPG1, p + IsRepG1 + state);
if (bit == 0)
{
distance = rep1;
}
else
{
DECODE_BIT(LZMA_C_ISREPG2, p + IsRepG2 + state);
if (bit == 0)
distance = rep2;
else
{
distance = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = distance;
}
DECODE_LEN(LZMA_C_LEND_C1, p + RepLenCoder);
state = state < 7 ? 8 : 11;
}
else
{
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
state = state < 7 ? 7 : 10;
DECODE_LEN(LZMA_C_LEND_C2, p + LenCoder);
DECODE_BIT_TREE(
LZMA_C_BTD_C1,
p + PosSlot + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits),
kNumPosSlotBits
);
if (posSlot >= kStartPosModelIndex)
{
int numDirectBits = ((posSlot >> 1) - 1);
rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
if (posSlot < kEndPosModelIndex)
{
probs = p + SpecPos + rep0 - posSlot - 1;
numLevels = numDirectBits;
}
else
{
int numTotalBits = numDirectBits - kNumAlignBits;
result = 0;
for (i = numTotalBits; i > 0; i--)
{
/* UInt32 t; */
range >>= 1;
result <<= 1;
if (code >= range)
{
code -= range;
result |= 1;
}
/*
t = (code - range) >> 31;
t &= 1;
code -= range & (t - 1);
result = (result + result) | (1 - t);
*/
RC_NORMALIZE(LZMA_C_NORM)
}
rep0 += result << kNumAlignBits;
probs = p + Align;
numLevels = kNumAlignBits;
}
mi = 1;
symbol = 0;
for(i = 0; i < numLevels; i++)
{
prob = probs + mi;
RC_GET_BIT2(LZMA_C_RDRBTD, prob, mi, ; , symbol |= (1 << i));
}
rep0 += symbol;
}
else
rep0 = posSlot;
rep0++;
}
if (rep0 == (UInt32)(0))
{
len = -1;
LEAVE;
}
if (rep0 > totalOut)
{
return LZMA_DATA_ERROR;
}
len += kMatchMinLen;
totalOut += len;
do
{
UInt32 pos;
NEED_OUT(LZMA_C_OUTPUT_3);
pos = dictionaryPos - rep0;
if (pos >= dictionarySize)
pos += dictionarySize;
previousByte = dictionary[pos];
dictionary[dictionaryPos] = previousByte;
dictionaryPos = (dictionaryPos + 1) % dictionarySize;
PUT_BYTE_(previousByte);
len--;
}
while(len > 0);
}
mode = LZMA_C_BLOCK;
break;
case LZMA_C_RDBD:
_LZMA_C_RDBD:
{
UInt32 bound = (range >> kNumBitModelTotalBits) * *prob;
if (code < bound)
{
range = bound;
*prob += (kBitModelTotal - *prob) >> kNumMoveBits;
bit = 0;
}
else
{
range -= bound;
code -= bound;
*prob -= (*prob) >> kNumMoveBits;
bit = 1;
}
RC_NORMALIZE(LZMA_C_RDBD_IN);
}
mode = last;
break;
case LZMA_C_LEND:
_LZMA_C_LEND:
DECODE_BIT(LZMA_C_LEND1, probs + LenChoice);
if (bit == 0)
{
len = 0;
probs += LenLow + (posState << kLenNumLowBits);
numLevels = kLenNumLowBits;
}
else {
DECODE_BIT(LZMA_C_LEND2, probs + LenChoice2);
if (bit == 0)
{
len = kLenNumLowSymbols;
probs += + LenMid + (posState << kLenNumMidBits);
numLevels = kLenNumMidBits;
}
else
{
len = kLenNumLowSymbols + kLenNumMidSymbols;
probs += LenHigh;
numLevels = kLenNumHighBits;
}
}
last3 = LZMA_C_LEND_RES;
case LZMA_C_BTD:
_LZMA_C_BTD:
mi = 1;
for(i = numLevels; i > 0; i--)
{
prob = probs + mi;
RC_GET_BIT(LZMA_C_BTD_LOOP, prob, mi)
}
result = mi - (1 << numLevels);
mode = last3;
break;
case LZMA_C_LEND_RES:
len += result;
mode = last2;
break;
default:
return LZMA_DATA_ERROR;
}
saveStateAndReturn:
/* save decoder state */
*s = _s;
return LZMA_OK;
}
/* aCaB */
void lzmaShutdown(lzma_stream *s) {
lzma_stream _s = *s;
if (p) lzmafree(p);
if (dictionary) lzmafree(dictionary);
p = NULL;
dictionary = NULL;
*s = _s;
}