5
#include "DeflateDecoder.h"
11
static const int kLenIdFinished = -1;
12
static const int kLenIdNeedInit = -2;
14
CCoder::CCoder(bool deflate64Mode, bool deflateNSIS):
15
_deflate64Mode(deflate64Mode),
16
_deflateNSIS(deflateNSIS),
17
_keepHistory(false) {}
19
UInt32 CCoder::ReadBits(int numBits)
21
return m_InBitStream.ReadBits(numBits);
24
bool CCoder::DeCodeLevelTable(Byte *values, int numSymbols)
29
UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);
30
if (number < kTableDirectLevels)
31
values[i++] = (Byte)number;
32
else if (number < kLevelTableSize)
34
if (number == kTableLevelRepNumber)
38
int num = ReadBits(2) + 3;
39
for (; num > 0 && i < numSymbols; num--, i++)
40
values[i] = values[i - 1];
45
if (number == kTableLevel0Number)
46
num = ReadBits(3) + 3;
48
num = ReadBits(7) + 11;
49
for (;num > 0 && i < numSymbols; num--)
56
while(i < numSymbols);
60
#define RIF(x) { if (!(x)) return false; }
62
bool CCoder::ReadTables(void)
64
m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
65
UInt32 blockType = ReadBits(kBlockTypeFieldSize);
66
if (blockType > NBlockType::kDynamicHuffman)
69
if (blockType == NBlockType::kStored)
72
UInt32 currentBitPosition = m_InBitStream.GetBitPosition();
73
int numBitsForAlign = (int)(currentBitPosition > 0 ? (8 - currentBitPosition): 0);
74
ReadBits(numBitsForAlign);
75
m_StoredBlockSize = ReadBits(kStoredBlockLengthFieldSize);
78
return (m_StoredBlockSize == (UInt16)~ReadBits(kStoredBlockLengthFieldSize));
84
if (blockType == NBlockType::kFixedHuffman)
86
levels.SetFixedLevels();
87
_numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
91
int numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
92
_numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
93
int numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
96
if (_numDistLevels > kDistTableSize32)
99
Byte levelLevels[kLevelTableSize];
100
for (int i = 0; i < kLevelTableSize; i++)
102
int position = kCodeLengthAlphabetOrder[i];
103
if(i < numLevelCodes)
104
levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
106
levelLevels[position] = 0;
109
RIF(m_LevelDecoder.SetCodeLengths(levelLevels));
111
Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
112
if (!DeCodeLevelTable(tmpLevels, numLitLenLevels + _numDistLevels))
116
memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
117
memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
119
RIF(m_MainDecoder.SetCodeLengths(levels.litLenLevels));
120
return m_DistDecoder.SetCodeLengths(levels.distLevels);
123
HRESULT CCoder::CodeSpec(UInt32 curSize)
125
if (_remainLen == kLenIdFinished)
127
if (_remainLen == kLenIdNeedInit)
130
if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
131
return E_OUTOFMEMORY;
132
if (!m_InBitStream.Create(1 << 17))
133
return E_OUTOFMEMORY;
134
m_OutWindowStream.Init(_keepHistory);
135
m_InBitStream.Init();
136
m_FinalBlock = false;
138
_needReadTable = true;
144
while(_remainLen > 0 && curSize > 0)
147
Byte b = m_OutWindowStream.GetByte(_rep0);
148
m_OutWindowStream.PutByte(b);
158
_remainLen = kLenIdFinished;
163
_needReadTable = false;
168
for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
169
m_OutWindowStream.PutByte((Byte)m_InBitStream.ReadBits(8));
170
_needReadTable = (m_StoredBlockSize == 0);
175
if (m_InBitStream.NumExtraBytes > 4)
178
UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);
181
m_OutWindowStream.PutByte((Byte)number);
185
else if (number == kSymbolEndOfBlock)
187
_needReadTable = true;
190
else if (number < kMainTableSize)
192
number -= kSymbolMatch;
198
len = kLenStart64[number];
199
numBits = kLenDirectBits64[number];
203
len = kLenStart32[number];
204
numBits = kLenDirectBits32[number];
206
len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
209
if (locLen > curSize)
210
locLen = (UInt32)curSize;
211
number = m_DistDecoder.DecodeSymbol(&m_InBitStream);
212
if (number >= _numDistLevels)
214
UInt32 distance = kDistStart[number] + m_InBitStream.ReadBits(kDistDirectBits[number]);
215
if (!m_OutWindowStream.CopyBlock(distance, locLen))
221
_remainLen = (Int32)len;
233
HRESULT CCoder::CodeReal(ISequentialInStream *inStream,
234
ISequentialOutStream *outStream,
235
const UInt64 *, const UInt64 *outSize,
236
ICompressProgressInfo *progress)
238
SetInStream(inStream);
239
m_OutWindowStream.SetStream(outStream);
240
SetOutStreamSize(outSize);
241
CCoderReleaser flusher(this);
243
const UInt64 start = m_OutWindowStream.GetProcessedSize();
246
UInt32 curSize = 1 << 18;
249
const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);
251
curSize = (UInt32)rem;
255
RINOK(CodeSpec(curSize));
256
if (_remainLen == kLenIdFinished)
258
if (progress != NULL)
260
const UInt64 inSize = m_InBitStream.GetProcessedSize();
261
const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
262
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
265
flusher.NeedFlush = false;
270
#ifdef _NO_EXCEPTIONS
272
#define DEFLATE_TRY_BEGIN
273
#define DEFLATE_TRY_END
277
#define DEFLATE_TRY_BEGIN try {
278
#define DEFLATE_TRY_END } \
279
catch(const CInBufferException &e) { return e.ErrorCode; } \
280
catch(const CLZOutWindowException &e) { return e.ErrorCode; } \
281
catch(...) { return S_FALSE; }
285
HRESULT CCoder::Code(ISequentialInStream *inStream,
286
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
287
ICompressProgressInfo *progress)
290
return CodeReal(inStream, outStream, inSize, outSize, progress);
294
STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
298
*value = m_InBitStream.GetProcessedSize();
302
STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
304
m_InBitStream.SetStream(inStream);
308
STDMETHODIMP CCoder::ReleaseInStream()
310
m_InBitStream.ReleaseStream();
314
STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)
316
_remainLen = kLenIdNeedInit;
317
m_OutWindowStream.Init(_keepHistory);
321
#ifndef NO_READ_FROM_CODER
323
STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
328
const UInt64 startPos = m_OutWindowStream.GetProcessedSize();
329
m_OutWindowStream.SetMemStream((Byte *)data);
330
RINOK(CodeSpec(size));
332
*processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);