5
#include "LzxDecoder.h"
7
#include "Common/Defs.h"
10
#include "../../../../C/Alloc.h"
12
#include "Windows/Defs.h"
17
const int kLenIdNeedInit = -2;
19
CDecoder::CDecoder(bool wimMode):
24
m_x86ConvertOutStreamSpec = new Cx86ConvertOutStream;
25
m_x86ConvertOutStream = m_x86ConvertOutStreamSpec;
28
void CDecoder::ReleaseStreams()
30
m_OutWindowStream.ReleaseStream();
31
m_InBitStream.ReleaseStream();
32
m_x86ConvertOutStreamSpec->ReleaseStream();
35
STDMETHODIMP CDecoder::Flush()
37
RINOK(m_OutWindowStream.Flush());
38
return m_x86ConvertOutStreamSpec->Flush();
41
UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }
43
#define RIF(x) { if (!(x)) return false; }
45
bool CDecoder::ReadTable(Byte *lastLevels, Byte *newLevels, UInt32 numSymbols)
47
Byte levelLevels[kLevelTableSize];
49
for (i = 0; i < kLevelTableSize; i++)
50
levelLevels[i] = (Byte)ReadBits(kNumBitsForPreTreeLevel);
51
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
54
for (i = 0; i < numSymbols;)
58
lastLevels[i] = newLevels[i] = symbol;
63
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
64
if (number == kLevelSymbolZeros)
66
num = kLevelSymbolZerosStartValue + (int)ReadBits(kLevelSymbolZerosNumBits);
69
else if (number == kLevelSymbolZerosBig)
71
num = kLevelSymbolZerosBigStartValue + (int)ReadBits(kLevelSymbolZerosBigNumBits);
74
else if (number == kLevelSymbolSame || number <= kNumHuffmanBits)
76
if (number <= kNumHuffmanBits)
80
num = kLevelSymbolSameStartValue + (int)ReadBits(kLevelSymbolSameNumBits);
81
number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
82
if (number > kNumHuffmanBits)
85
symbol = Byte((17 + lastLevels[i] - number) % (kNumHuffmanBits + 1));
93
bool CDecoder::ReadTables(void)
95
Byte newLevels[kMaxTableSize];
98
m_InBitStream.DirectReadByte();
99
m_InBitStream.Normalize();
101
int blockType = (int)ReadBits(kNumBlockTypeBits);
102
if (blockType > kBlockTypeUncompressed)
105
if (ReadBits(1) == 1)
106
m_UnCompressedBlockSize = (1 << 15);
108
m_UnCompressedBlockSize = ReadBits(16);
110
m_UnCompressedBlockSize = m_InBitStream.ReadBitsBig(kUncompressedBlockSizeNumBits);
112
m_IsUncompressedBlock = (blockType == kBlockTypeUncompressed);
114
_skipByte = (m_IsUncompressedBlock && ((m_UnCompressedBlockSize & 1) != 0));
116
if (m_IsUncompressedBlock)
118
ReadBits(16 - m_InBitStream.GetBitPosition());
119
if (!m_InBitStream.ReadUInt32(m_RepDistances[0]))
122
for (int i = 1; i < kNumRepDistances; i++)
125
for (int j = 0; j < 4; j++)
126
rep |= (UInt32)m_InBitStream.DirectReadByte() << (8 * j);
127
m_RepDistances[i] = rep - 1;
131
m_AlignIsUsed = (blockType == kBlockTypeAligned);
134
for(int i = 0; i < kAlignTableSize; i++)
135
newLevels[i] = (Byte)ReadBits(kNumBitsForAlignLevel);
136
RIF(m_AlignDecoder.SetCodeLengths(newLevels));
140
RIF(ReadTable(m_LastMainLevels, newLevels, 256));
141
RIF(ReadTable(m_LastMainLevels + 256, newLevels + 256, m_NumPosLenSlots));
142
for (UInt32 i = 256 + m_NumPosLenSlots; i < kMainTableSize; i++)
144
RIF(m_MainDecoder.SetCodeLengths(newLevels));
146
RIF(ReadTable(m_LastLenLevels, newLevels, kNumLenSymbols));
147
return m_LenDecoder.SetCodeLengths(newLevels);
150
class CDecoderFlusher
155
CDecoderFlusher(CDecoder *decoder): m_Decoder(decoder), NeedFlush(true) {}
160
m_Decoder->ReleaseStreams();
165
void CDecoder::ClearPrevLevels()
168
for (i = 0; i < kMainTableSize; i++)
169
m_LastMainLevels[i] = 0;
170
for (i = 0; i < kNumLenSymbols; i++)
171
m_LastLenLevels[i] = 0;
175
HRESULT CDecoder::CodeSpec(UInt32 curSize)
177
if (_remainLen == kLenIdNeedInit)
180
m_InBitStream.Init();
181
if (!_keepHistory || !m_IsUncompressedBlock)
182
m_InBitStream.Normalize();
186
m_UnCompressedBlockSize = 0;
188
UInt32 i86TranslationSize = 12000000;
189
bool translationMode = true;
192
translationMode = (ReadBits(1) != 0);
195
i86TranslationSize = ReadBits(16) << 16;
196
i86TranslationSize |= ReadBits(16);
199
m_x86ConvertOutStreamSpec->Init(translationMode, i86TranslationSize);
201
for(int i = 0 ; i < kNumRepDistances; i++)
202
m_RepDistances[i] = 0;
206
while(_remainLen > 0 && curSize > 0)
208
m_OutWindowStream.PutByte(m_OutWindowStream.GetByte(m_RepDistances[0]));
215
if (m_UnCompressedBlockSize == 0)
218
UInt32 next = (Int32)MyMin(m_UnCompressedBlockSize, curSize);
220
m_UnCompressedBlockSize -= next;
221
if (m_IsUncompressedBlock)
225
m_OutWindowStream.PutByte(m_InBitStream.DirectReadByte());
231
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
234
m_OutWindowStream.PutByte((Byte)number);
239
UInt32 posLenSlot = number - 256;
240
if (posLenSlot >= m_NumPosLenSlots)
242
UInt32 posSlot = posLenSlot / kNumLenSlots;
243
UInt32 lenSlot = posLenSlot % kNumLenSlots;
244
UInt32 len = kMatchMinLen + lenSlot;
245
if (lenSlot == kNumLenSlots - 1)
247
UInt32 lenTemp = m_LenDecoder.DecodeSymbol(&m_InBitStream);
248
if (lenTemp >= kNumLenSymbols)
253
if (posSlot < kNumRepDistances)
255
UInt32 distance = m_RepDistances[posSlot];
256
m_RepDistances[posSlot] = m_RepDistances[0];
257
m_RepDistances[0] = distance;
263
if (posSlot < kNumPowerPosSlots)
265
numDirectBits = (int)(posSlot >> 1) - 1;
266
distance = ((2 | (posSlot & 1)) << numDirectBits);
270
numDirectBits = kNumLinearPosSlotBits;
271
distance = ((posSlot - 0x22) << kNumLinearPosSlotBits);
274
if (m_AlignIsUsed && numDirectBits >= kNumAlignBits)
276
distance += (m_InBitStream.ReadBits(numDirectBits - kNumAlignBits) << kNumAlignBits);
277
UInt32 alignTemp = m_AlignDecoder.DecodeSymbol(&m_InBitStream);
278
if (alignTemp >= kAlignTableSize)
280
distance += alignTemp;
283
distance += m_InBitStream.ReadBits(numDirectBits);
284
m_RepDistances[2] = m_RepDistances[1];
285
m_RepDistances[1] = m_RepDistances[0];
286
m_RepDistances[0] = distance - kNumRepDistances;
293
if (!m_OutWindowStream.CopyBlock(m_RepDistances[0], locLen))
300
_remainLen = (int)len;
309
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream,
310
ISequentialOutStream *outStream,
311
const UInt64 *, const UInt64 *outSize,
312
ICompressProgressInfo *progress)
316
UInt64 size = *outSize;
318
RINOK(SetInStream(inStream));
319
m_x86ConvertOutStreamSpec->SetStream(outStream);
320
m_OutWindowStream.SetStream(m_x86ConvertOutStream);
321
RINOK(SetOutStreamSize(outSize));
323
CDecoderFlusher flusher(this);
325
const UInt64 start = m_OutWindowStream.GetProcessedSize();
328
UInt32 curSize = 1 << 18;
329
UInt64 rem = size - (m_OutWindowStream.GetProcessedSize() - start);
331
curSize = (UInt32)rem;
334
RINOK(CodeSpec(curSize));
335
if (progress != NULL)
337
UInt64 inSize = m_InBitStream.GetProcessedSize();
338
UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
339
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
342
flusher.NeedFlush = false;
346
HRESULT CDecoder::Code(ISequentialInStream *inStream,
347
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
348
ICompressProgressInfo *progress)
350
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
351
catch(const CLZOutWindowException &e) { return e.ErrorCode; }
352
catch(...) { return S_FALSE; }
355
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
357
m_InBitStream.SetStream(inStream);
361
STDMETHODIMP CDecoder::ReleaseInStream()
363
m_InBitStream.ReleaseStream();
367
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
371
_remainLen = kLenIdNeedInit;
372
m_OutWindowStream.Init(_keepHistory);
376
HRESULT CDecoder::SetParams(int numDictBits)
378
if (numDictBits < kNumDictionaryBitsMin || numDictBits > kNumDictionaryBitsMax)
381
if (numDictBits < 20)
382
numPosSlots = 30 + (numDictBits - 15) * 2;
383
else if (numDictBits == 20)
387
m_NumPosLenSlots = numPosSlots * kNumLenSlots;
388
if (!m_OutWindowStream.Create(kDictionarySizeMax))
389
return E_OUTOFMEMORY;
390
if (!m_InBitStream.Create(1 << 16))
391
return E_OUTOFMEMORY;