123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663 |
- /*
- LzmaDecode.c
- LZMA Decoder
-
- LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
- http://www.7-zip.org/
- LZMA SDK is licensed under two licenses:
- 1) GNU Lesser General Public License (GNU LGPL)
- 2) Common Public License (CPL)
- It means that you can select one of these two licenses and
- follow rules of that license.
- SPECIAL EXCEPTION:
- Igor Pavlov, as the author of this code, expressly permits you to
- statically or dynamically link your code (or bind by name) to the
- interfaces of this file without subjecting your linked code to the
- terms of the CPL or GNU LGPL. Any modifications or additions
- to this file, however, are subject to the LGPL or CPL terms.
- */
- #include "LzmaDecode.h"
- #ifndef Byte
- #define Byte unsigned char
- #endif
- #define kNumTopBits 24
- #define kTopValue ((UInt32)1 << kNumTopBits)
- #define kNumBitModelTotalBits 11
- #define kBitModelTotal (1 << kNumBitModelTotalBits)
- #define kNumMoveBits 5
- typedef struct _CRangeDecoder
- {
- Byte *Buffer;
- Byte *BufferLim;
- UInt32 Range;
- UInt32 Code;
- #ifdef _LZMA_IN_CB
- ILzmaInCallback *InCallback;
- int Result;
- #endif
- int ExtraBytes;
- } CRangeDecoder;
- Byte RangeDecoderReadByte(CRangeDecoder *rd)
- {
- if (rd->Buffer == rd->BufferLim)
- {
- #ifdef _LZMA_IN_CB
- UInt32 size;
- rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
- rd->BufferLim = rd->Buffer + size;
- if (size == 0)
- #endif
- {
- rd->ExtraBytes = 1;
- return 0xFF;
- }
- }
- return (*rd->Buffer++);
- }
- /* #define ReadByte (*rd->Buffer++) */
- #define ReadByte (RangeDecoderReadByte(rd))
- void RangeDecoderInit(CRangeDecoder *rd,
- #ifdef _LZMA_IN_CB
- ILzmaInCallback *inCallback
- #else
- Byte *stream, UInt32 bufferSize
- #endif
- )
- {
- int i;
- #ifdef _LZMA_IN_CB
- rd->InCallback = inCallback;
- rd->Buffer = rd->BufferLim = 0;
- #else
- rd->Buffer = stream;
- rd->BufferLim = stream + bufferSize;
- #endif
- rd->ExtraBytes = 0;
- rd->Code = 0;
- rd->Range = (0xFFFFFFFF);
- for(i = 0; i < 5; i++)
- rd->Code = (rd->Code << 8) | ReadByte;
- }
- #define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
- #define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
- #define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
- UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
- {
- RC_INIT_VAR
- UInt32 result = 0;
- int i;
- 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
- }
- RC_FLUSH_VAR
- return result;
- }
- int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
- {
- UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
- if (rd->Code < bound)
- {
- rd->Range = bound;
- *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
- if (rd->Range < kTopValue)
- {
- rd->Code = (rd->Code << 8) | ReadByte;
- rd->Range <<= 8;
- }
- return 0;
- }
- else
- {
- rd->Range -= bound;
- rd->Code -= bound;
- *prob -= (*prob) >> kNumMoveBits;
- if (rd->Range < kTopValue)
- {
- rd->Code = (rd->Code << 8) | ReadByte;
- rd->Range <<= 8;
- }
- return 1;
- }
- }
- #define RC_GET_BIT2(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
- #define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
- int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
- {
- int mi = 1;
- int i;
- #ifdef _LZMA_LOC_OPT
- RC_INIT_VAR
- #endif
- for(i = numLevels; i > 0; i--)
- {
- #ifdef _LZMA_LOC_OPT
- CProb *prob = probs + mi;
- RC_GET_BIT(prob, mi)
- #else
- mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
- #endif
- }
- #ifdef _LZMA_LOC_OPT
- RC_FLUSH_VAR
- #endif
- return mi - (1 << numLevels);
- }
- int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
- {
- int mi = 1;
- int i;
- int symbol = 0;
- #ifdef _LZMA_LOC_OPT
- RC_INIT_VAR
- #endif
- for(i = 0; i < numLevels; i++)
- {
- #ifdef _LZMA_LOC_OPT
- CProb *prob = probs + mi;
- RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
- #else
- int bit = RangeDecoderBitDecode(probs + mi, rd);
- mi = mi + mi + bit;
- symbol |= (bit << i);
- #endif
- }
- #ifdef _LZMA_LOC_OPT
- RC_FLUSH_VAR
- #endif
- return symbol;
- }
- Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
- {
- int symbol = 1;
- #ifdef _LZMA_LOC_OPT
- RC_INIT_VAR
- #endif
- do
- {
- #ifdef _LZMA_LOC_OPT
- CProb *prob = probs + symbol;
- RC_GET_BIT(prob, symbol)
- #else
- symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
- #endif
- }
- while (symbol < 0x100);
- #ifdef _LZMA_LOC_OPT
- RC_FLUSH_VAR
- #endif
- return symbol;
- }
- Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
- {
- int symbol = 1;
- #ifdef _LZMA_LOC_OPT
- RC_INIT_VAR
- #endif
- do
- {
- int bit;
- int matchBit = (matchByte >> 7) & 1;
- matchByte <<= 1;
- #ifdef _LZMA_LOC_OPT
- {
- CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
- RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
- }
- #else
- bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
- symbol = (symbol << 1) | bit;
- #endif
- if (matchBit != bit)
- {
- while (symbol < 0x100)
- {
- #ifdef _LZMA_LOC_OPT
- CProb *prob = probs + symbol;
- RC_GET_BIT(prob, symbol)
- #else
- symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
- #endif
- }
- break;
- }
- }
- while (symbol < 0x100);
- #ifdef _LZMA_LOC_OPT
- RC_FLUSH_VAR
- #endif
- return symbol;
- }
- #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)
- int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
- {
- if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
- return RangeDecoderBitTreeDecode(p + LenLow +
- (posState << kLenNumLowBits), kLenNumLowBits, rd);
- if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
- return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
- (posState << kLenNumMidBits), kLenNumMidBits, rd);
- return kLenNumLowSymbols + kLenNumMidSymbols +
- RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
- }
- #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)
- #if Literal != LZMA_BASE_SIZE
- StopCompilingDueBUG
- #endif
- #ifdef _LZMA_OUT_READ
- typedef struct _LzmaVarState
- {
- CRangeDecoder RangeDecoder;
- Byte *Dictionary;
- UInt32 DictionarySize;
- UInt32 DictionaryPos;
- UInt32 GlobalPos;
- UInt32 Reps[4];
- int lc;
- int lp;
- int pb;
- int State;
- int PreviousIsMatch;
- int RemainLen;
- } LzmaVarState;
- int LzmaDecoderInit(
- unsigned char *buffer, UInt32 bufferSize,
- int lc, int lp, int pb,
- unsigned char *dictionary, UInt32 dictionarySize,
- #ifdef _LZMA_IN_CB
- ILzmaInCallback *inCallback
- #else
- unsigned char *inStream, UInt32 inSize
- #endif
- )
- {
- LzmaVarState *vs = (LzmaVarState *)buffer;
- CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
- UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
- UInt32 i;
- if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
- return LZMA_RESULT_NOT_ENOUGH_MEM;
- vs->Dictionary = dictionary;
- vs->DictionarySize = dictionarySize;
- vs->DictionaryPos = 0;
- vs->GlobalPos = 0;
- vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
- vs->lc = lc;
- vs->lp = lp;
- vs->pb = pb;
- vs->State = 0;
- vs->PreviousIsMatch = 0;
- vs->RemainLen = 0;
- dictionary[dictionarySize - 1] = 0;
- for (i = 0; i < numProbs; i++)
- p[i] = kBitModelTotal >> 1;
- RangeDecoderInit(&vs->RangeDecoder,
- #ifdef _LZMA_IN_CB
- inCallback
- #else
- inStream, inSize
- #endif
- );
- return LZMA_RESULT_OK;
- }
- int LzmaDecode(unsigned char *buffer,
- unsigned char *outStream, UInt32 outSize,
- UInt32 *outSizeProcessed)
- {
- LzmaVarState *vs = (LzmaVarState *)buffer;
- CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
- CRangeDecoder rd = vs->RangeDecoder;
- int state = vs->State;
- int previousIsMatch = vs->PreviousIsMatch;
- Byte previousByte;
- UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
- UInt32 nowPos = 0;
- UInt32 posStateMask = (1 << (vs->pb)) - 1;
- UInt32 literalPosMask = (1 << (vs->lp)) - 1;
- int lc = vs->lc;
- int len = vs->RemainLen;
- UInt32 globalPos = vs->GlobalPos;
- Byte *dictionary = vs->Dictionary;
- UInt32 dictionarySize = vs->DictionarySize;
- UInt32 dictionaryPos = vs->DictionaryPos;
- if (len == -1)
- {
- *outSizeProcessed = 0;
- return LZMA_RESULT_OK;
- }
- while(len > 0 && nowPos < outSize)
- {
- UInt32 pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
- if (++dictionaryPos == dictionarySize)
- dictionaryPos = 0;
- len--;
- }
- if (dictionaryPos == 0)
- previousByte = dictionary[dictionarySize - 1];
- else
- previousByte = dictionary[dictionaryPos - 1];
- #else
- int LzmaDecode(
- Byte *buffer, UInt32 bufferSize,
- int lc, int lp, int pb,
- #ifdef _LZMA_IN_CB
- ILzmaInCallback *inCallback,
- #else
- unsigned char *inStream, UInt32 inSize,
- #endif
- unsigned char *outStream, UInt32 outSize,
- UInt32 *outSizeProcessed)
- {
- UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
- CProb *p = (CProb *)buffer;
- CRangeDecoder rd;
- UInt32 i;
- int state = 0;
- int previousIsMatch = 0;
- Byte previousByte = 0;
- UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
- UInt32 nowPos = 0;
- UInt32 posStateMask = (1 << pb) - 1;
- UInt32 literalPosMask = (1 << lp) - 1;
- int len = 0;
- if (bufferSize < numProbs * sizeof(CProb))
- return LZMA_RESULT_NOT_ENOUGH_MEM;
- for (i = 0; i < numProbs; i++)
- p[i] = kBitModelTotal >> 1;
- RangeDecoderInit(&rd,
- #ifdef _LZMA_IN_CB
- inCallback
- #else
- inStream, inSize
- #endif
- );
- #endif
- *outSizeProcessed = 0;
- while(nowPos < outSize)
- {
- int posState = (int)(
- (nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos
- #endif
- )
- & posStateMask);
- #ifdef _LZMA_IN_CB
- if (rd.Result != LZMA_RESULT_OK)
- return rd.Result;
- #endif
- if (rd.ExtraBytes != 0)
- return LZMA_RESULT_DATA_ERROR;
- if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
- {
- CProb *probs = p + Literal + (LZMA_LIT_SIZE *
- (((
- (nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos
- #endif
- )
- & literalPosMask) << lc) + (previousByte >> (8 - lc))));
- if (state < 4) state = 0;
- else if (state < 10) state -= 3;
- else state -= 6;
- if (previousIsMatch)
- {
- Byte matchByte;
- #ifdef _LZMA_OUT_READ
- UInt32 pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- matchByte = dictionary[pos];
- #else
- matchByte = outStream[nowPos - rep0];
- #endif
- previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
- previousIsMatch = 0;
- }
- else
- previousByte = LzmaLiteralDecode(probs, &rd);
- outStream[nowPos++] = previousByte;
- #ifdef _LZMA_OUT_READ
- dictionary[dictionaryPos] = previousByte;
- if (++dictionaryPos == dictionarySize)
- dictionaryPos = 0;
- #endif
- }
- else
- {
- previousIsMatch = 1;
- if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
- {
- if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
- {
- if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
- {
- #ifdef _LZMA_OUT_READ
- UInt32 pos;
- #endif
- if (
- (nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos
- #endif
- )
- == 0)
- return LZMA_RESULT_DATA_ERROR;
- state = state < 7 ? 9 : 11;
- #ifdef _LZMA_OUT_READ
- pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- previousByte = dictionary[pos];
- dictionary[dictionaryPos] = previousByte;
- if (++dictionaryPos == dictionarySize)
- dictionaryPos = 0;
- #else
- previousByte = outStream[nowPos - rep0];
- #endif
- outStream[nowPos++] = previousByte;
- continue;
- }
- }
- else
- {
- UInt32 distance;
- if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
- distance = rep1;
- else
- {
- if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
- distance = rep2;
- else
- {
- distance = rep3;
- rep3 = rep2;
- }
- rep2 = rep1;
- }
- rep1 = rep0;
- rep0 = distance;
- }
- len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
- state = state < 7 ? 8 : 11;
- }
- else
- {
- int posSlot;
- rep3 = rep2;
- rep2 = rep1;
- rep1 = rep0;
- state = state < 7 ? 7 : 10;
- len = LzmaLenDecode(p + LenCoder, &rd, posState);
- posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
- ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
- kNumPosSlotBits), kNumPosSlotBits, &rd);
- if (posSlot >= kStartPosModelIndex)
- {
- int numDirectBits = ((posSlot >> 1) - 1);
- rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
- if (posSlot < kEndPosModelIndex)
- {
- rep0 += RangeDecoderReverseBitTreeDecode(
- p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
- }
- else
- {
- rep0 += RangeDecoderDecodeDirectBits(&rd,
- numDirectBits - kNumAlignBits) << kNumAlignBits;
- rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
- }
- }
- else
- rep0 = posSlot;
- rep0++;
- }
- if (rep0 == (UInt32)(0))
- {
- /* it's for stream version */
- len = -1;
- break;
- }
- if (rep0 > nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos
- #endif
- )
- {
- return LZMA_RESULT_DATA_ERROR;
- }
- len += kMatchMinLen;
- do
- {
- #ifdef _LZMA_OUT_READ
- UInt32 pos = dictionaryPos - rep0;
- if (pos >= dictionarySize)
- pos += dictionarySize;
- previousByte = dictionary[pos];
- dictionary[dictionaryPos] = previousByte;
- if (++dictionaryPos == dictionarySize)
- dictionaryPos = 0;
- #else
- previousByte = outStream[nowPos - rep0];
- #endif
- outStream[nowPos++] = previousByte;
- len--;
- }
- while(len > 0 && nowPos < outSize);
- }
- }
- #ifdef _LZMA_OUT_READ
- vs->RangeDecoder = rd;
- vs->DictionaryPos = dictionaryPos;
- vs->GlobalPos = globalPos + nowPos;
- vs->Reps[0] = rep0;
- vs->Reps[1] = rep1;
- vs->Reps[2] = rep2;
- vs->Reps[3] = rep3;
- vs->State = state;
- vs->PreviousIsMatch = previousIsMatch;
- vs->RemainLen = len;
- #endif
- *outSizeProcessed = nowPos;
- return LZMA_RESULT_OK;
- }
|