LzmaDecode.c
LZMA Decoder (optimized for Speed version)
- LZMA SDK 4.16 Copyright (c) 1999-2005 Igor Pavlov (2005-03-18)
+ LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
http://www.7-zip.org/
LZMA SDK is licensed under two licenses:
#include "LzmaDecode.h"
-#ifndef Byte
-#define Byte unsigned char
-#endif
-
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#ifdef _LZMA_IN_CB
#define RC_TEST { if (Buffer == BufferLim) \
- { UInt32 size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
+ { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) return result; \
BufferLim = Buffer + size; if (size == 0) return LZMA_RESULT_DATA_ERROR; }}
#define RC_INIT Buffer = BufferLim = 0; RC_INIT2
StopCompilingDueBUG
#endif
-#ifdef _LZMA_OUT_READ
-
-typedef struct _LzmaVarState
-{
- Byte *Buffer;
- Byte *BufferLim;
- UInt32 Range;
- UInt32 Code;
- #ifdef _LZMA_IN_CB
- ILzmaInCallback *InCallback;
- #endif
- Byte *Dictionary;
- UInt32 DictionarySize;
- UInt32 DictionaryPos;
- UInt32 GlobalPos;
- UInt32 Reps[4];
- int lc;
- int lp;
- int pb;
- int State;
- int RemainLen;
- Byte TempDictionary[4];
-} 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
- )
+int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
{
- Byte *Buffer;
- Byte *BufferLim;
- UInt32 Range;
- UInt32 Code;
- 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->RemainLen = 0;
- dictionary[dictionarySize - 1] = 0;
- for (i = 0; i < numProbs; i++)
- p[i] = kBitModelTotal >> 1;
+ unsigned char prop0;
+ if (size < LZMA_PROPERTIES_SIZE)
+ return LZMA_RESULT_DATA_ERROR;
+ prop0 = propsData[0];
+ if (prop0 >= (9 * 5 * 5))
+ return LZMA_RESULT_DATA_ERROR;
+ {
+ for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
+ for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
+ propsRes->lc = prop0;
+ /*
+ unsigned char remainder = (unsigned char)(prop0 / 9);
+ propsRes->lc = prop0 % 9;
+ propsRes->pb = remainder / 5;
+ propsRes->lp = remainder % 5;
+ */
+ }
- #ifdef _LZMA_IN_CB
- RC_INIT;
- #else
- RC_INIT(inStream, inSize);
- #endif
- vs->Buffer = Buffer;
- vs->BufferLim = BufferLim;
- vs->Range = Range;
- vs->Code = Code;
- #ifdef _LZMA_IN_CB
- vs->InCallback = InCallback;
+ #ifdef _LZMA_OUT_READ
+ {
+ int i;
+ propsRes->DictionarySize = 0;
+ for (i = 0; i < 4; i++)
+ propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8);
+ if (propsRes->DictionarySize == 0)
+ propsRes->DictionarySize = 1;
+ }
#endif
-
return LZMA_RESULT_OK;
}
-int LzmaDecode(unsigned char *buffer,
- unsigned char *outStream, UInt32 outSize,
- UInt32 *outSizeProcessed)
+#define kLzmaStreamWasFinishedId (-1)
+
+int LzmaDecode(CLzmaDecoderState *vs,
+ #ifdef _LZMA_IN_CB
+ ILzmaInCallback *InCallback,
+ #else
+ const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
+ #endif
+ unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
{
- LzmaVarState *vs = (LzmaVarState *)buffer;
- Byte *Buffer = vs->Buffer;
- Byte *BufferLim = vs->BufferLim;
+ CProb *p = vs->Probs;
+ SizeT nowPos = 0;
+ Byte previousByte = 0;
+ UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
+ UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
+ int lc = vs->Properties.lc;
+
+ #ifdef _LZMA_OUT_READ
+
UInt32 Range = vs->Range;
UInt32 Code = vs->Code;
#ifdef _LZMA_IN_CB
- ILzmaInCallback *InCallback = vs->InCallback;
+ const Byte *Buffer = vs->Buffer;
+ const Byte *BufferLim = vs->BufferLim;
+ #else
+ const Byte *Buffer = inStream;
+ const Byte *BufferLim = inStream + inSize;
#endif
- CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
int state = vs->State;
- 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;
+ UInt32 distanceLimit = vs->DistanceLimit;
Byte *dictionary = vs->Dictionary;
- UInt32 dictionarySize = vs->DictionarySize;
+ UInt32 dictionarySize = vs->Properties.DictionarySize;
UInt32 dictionaryPos = vs->DictionaryPos;
Byte tempDictionary[4];
+
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+ if (len == kLzmaStreamWasFinishedId)
+ return LZMA_RESULT_OK;
+
if (dictionarySize == 0)
{
dictionary = tempDictionary;
tempDictionary[0] = vs->TempDictionary[0];
}
- if (len == -1)
+ if (len == kLzmaNeedInitId)
{
- *outSizeProcessed = 0;
- return LZMA_RESULT_OK;
+ {
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ UInt32 i;
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ rep0 = rep1 = rep2 = rep3 = 1;
+ state = 0;
+ globalPos = 0;
+ distanceLimit = 0;
+ dictionaryPos = 0;
+ dictionary[dictionarySize - 1] = 0;
+ #ifdef _LZMA_IN_CB
+ RC_INIT;
+ #else
+ RC_INIT(inStream, inSize);
+ #endif
+ }
+ len = 0;
}
-
while(len != 0 && nowPos < outSize)
{
UInt32 pos = dictionaryPos - rep0;
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;
+ #else /* if !_LZMA_OUT_READ */
- UInt32 i;
int state = 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;
-
- Byte *Buffer;
- Byte *BufferLim;
+ const Byte *Buffer;
+ const Byte *BufferLim;
UInt32 Range;
UInt32 Code;
-
- if (bufferSize < numProbs * sizeof(CProb))
- return LZMA_RESULT_NOT_ENOUGH_MEM;
- for (i = 0; i < numProbs; i++)
- p[i] = kBitModelTotal >> 1;
-
+ #ifndef _LZMA_IN_CB
+ *inSizeProcessed = 0;
+ #endif
+ *outSizeProcessed = 0;
+
+ {
+ UInt32 i;
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
+ for (i = 0; i < numProbs; i++)
+ p[i] = kBitModelTotal >> 1;
+ }
+
#ifdef _LZMA_IN_CB
RC_INIT;
#else
RC_INIT(inStream, inSize);
#endif
-#endif
- *outSizeProcessed = 0;
+ #endif /* _LZMA_OUT_READ */
+
while(nowPos < outSize)
{
CProb *prob;
#else
matchByte = outStream[nowPos - rep0];
#endif
- // prob += 0x100;
do
{
int bit;
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
}
while (symbol < 0x100);
- // prob -= 0x100;
}
while (symbol < 0x100)
{
outStream[nowPos++] = previousByte;
#ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+
dictionary[dictionaryPos] = previousByte;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
}
else
{
- // int isItRep;
UpdateBit1(prob);
prob = p + IsRep + state;
IfBit0(prob)
UInt32 pos;
#endif
UpdateBit0(prob);
- if (nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos
- #endif
- == 0)
+
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit == 0)
+ #else
+ if (nowPos == 0)
+ #endif
return LZMA_RESULT_DATA_ERROR;
+
state = state < kNumLitStates ? 9 : 11;
#ifdef _LZMA_OUT_READ
pos = dictionaryPos - rep0;
previousByte = outStream[nowPos - rep0];
#endif
outStream[nowPos++] = previousByte;
+ #ifdef _LZMA_OUT_READ
+ if (distanceLimit < dictionarySize)
+ distanceLimit++;
+ #endif
+
continue;
}
else
if (++rep0 == (UInt32)(0))
{
/* it's for stream version */
- len = -1;
+ len = kLzmaStreamWasFinishedId;
break;
}
}
len += kMatchMinLen;
- if (rep0 > nowPos
- #ifdef _LZMA_OUT_READ
- + globalPos || rep0 > dictionarySize
- #endif
- )
+ #ifdef _LZMA_OUT_READ
+ if (rep0 > distanceLimit)
+ #else
+ if (rep0 > nowPos)
+ #endif
return LZMA_RESULT_DATA_ERROR;
+
+ #ifdef _LZMA_OUT_READ
+ if (dictionarySize - distanceLimit > (UInt32)len)
+ distanceLimit += len;
+ else
+ distanceLimit = dictionarySize;
+ #endif
+
do
{
#ifdef _LZMA_OUT_READ
RC_NORMALIZE;
#ifdef _LZMA_OUT_READ
- vs->Buffer = Buffer;
- vs->BufferLim = BufferLim;
vs->Range = Range;
vs->Code = Code;
vs->DictionaryPos = dictionaryPos;
- vs->GlobalPos = globalPos + nowPos;
+ vs->GlobalPos = globalPos + (UInt32)nowPos;
+ vs->DistanceLimit = distanceLimit;
vs->Reps[0] = rep0;
vs->Reps[1] = rep1;
vs->Reps[2] = rep2;
vs->TempDictionary[0] = tempDictionary[0];
#endif
+ #ifdef _LZMA_IN_CB
+ vs->Buffer = Buffer;
+ vs->BufferLim = BufferLim;
+ #else
+ *inSizeProcessed = (SizeT)(Buffer - inStream);
+ #endif
*outSizeProcessed = nowPos;
return LZMA_RESULT_OK;
}