|
|
|
@ -2,7 +2,7 @@ |
|
|
|
|
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: |
|
|
|
@ -21,10 +21,6 @@ |
|
|
|
|
|
|
|
|
|
#include "LzmaDecode.h" |
|
|
|
|
|
|
|
|
|
#ifndef Byte |
|
|
|
|
#define Byte unsigned char |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#define kNumTopBits 24 |
|
|
|
|
#define kTopValue ((UInt32)1 << kNumTopBits) |
|
|
|
|
|
|
|
|
@ -40,7 +36,7 @@ |
|
|
|
|
#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 |
|
|
|
@ -121,109 +117,86 @@ |
|
|
|
|
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; |
|
|
|
@ -231,12 +204,27 @@ int LzmaDecode(unsigned char *buffer, |
|
|
|
|
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; |
|
|
|
@ -251,50 +239,37 @@ int LzmaDecode(unsigned char *buffer, |
|
|
|
|
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; |
|
|
|
@ -332,7 +307,6 @@ int LzmaDecode( |
|
|
|
|
#else |
|
|
|
|
matchByte = outStream[nowPos - rep0]; |
|
|
|
|
#endif |
|
|
|
|
// prob += 0x100;
|
|
|
|
|
do |
|
|
|
|
{ |
|
|
|
|
int bit; |
|
|
|
@ -343,7 +317,6 @@ int LzmaDecode( |
|
|
|
|
RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) |
|
|
|
|
} |
|
|
|
|
while (symbol < 0x100); |
|
|
|
|
// prob -= 0x100;
|
|
|
|
|
} |
|
|
|
|
while (symbol < 0x100) |
|
|
|
|
{ |
|
|
|
@ -354,6 +327,9 @@ int LzmaDecode( |
|
|
|
|
|
|
|
|
|
outStream[nowPos++] = previousByte; |
|
|
|
|
#ifdef _LZMA_OUT_READ |
|
|
|
|
if (distanceLimit < dictionarySize) |
|
|
|
|
distanceLimit++; |
|
|
|
|
|
|
|
|
|
dictionary[dictionaryPos] = previousByte; |
|
|
|
|
if (++dictionaryPos == dictionarySize) |
|
|
|
|
dictionaryPos = 0; |
|
|
|
@ -364,7 +340,6 @@ int LzmaDecode( |
|
|
|
|
} |
|
|
|
|
else
|
|
|
|
|
{ |
|
|
|
|
// int isItRep;
|
|
|
|
|
UpdateBit1(prob); |
|
|
|
|
prob = p + IsRep + state; |
|
|
|
|
IfBit0(prob) |
|
|
|
@ -390,12 +365,14 @@ int LzmaDecode( |
|
|
|
|
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; |
|
|
|
@ -409,6 +386,11 @@ int LzmaDecode( |
|
|
|
|
previousByte = outStream[nowPos - rep0]; |
|
|
|
|
#endif |
|
|
|
|
outStream[nowPos++] = previousByte; |
|
|
|
|
#ifdef _LZMA_OUT_READ |
|
|
|
|
if (distanceLimit < dictionarySize) |
|
|
|
|
distanceLimit++; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
@ -535,18 +517,26 @@ int LzmaDecode( |
|
|
|
|
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 |
|
|
|
@ -569,12 +559,11 @@ int LzmaDecode( |
|
|
|
|
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; |
|
|
|
@ -584,6 +573,12 @@ int LzmaDecode( |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|