1 // DeflateDecoder.cpp
2
3 #include "StdAfx.h"
4
5 #include "DeflateDecoder.h"
6
7 namespace NCompress {
8 namespace NDeflate {
9 namespace NDecoder {
10
CCoder(bool deflate64Mode)11 CCoder::CCoder(bool deflate64Mode):
12 _deflateNSIS(false),
13 _deflate64Mode(deflate64Mode),
14 _keepHistory(false),
15 _needFinishInput(false),
16 _needInitInStream(true),
17 _outSizeDefined(false),
18 _outStartPos(0),
19 ZlibMode(false) {}
20
ReadBits(unsigned numBits)21 UInt32 CCoder::ReadBits(unsigned numBits)
22 {
23 return m_InBitStream.ReadBits(numBits);
24 }
25
ReadAlignedByte()26 Byte CCoder::ReadAlignedByte()
27 {
28 return m_InBitStream.ReadAlignedByte();
29 }
30
DecodeLevels(Byte * levels,unsigned numSymbols)31 bool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols)
32 {
33 unsigned i = 0;
34
35 do
36 {
37 UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream);
38 if (sym < kTableDirectLevels)
39 levels[i++] = (Byte)sym;
40 else
41 {
42 if (sym >= kLevelTableSize)
43 return false;
44
45 unsigned num;
46 unsigned numBits;
47 Byte symbol;
48
49 if (sym == kTableLevelRepNumber)
50 {
51 if (i == 0)
52 return false;
53 numBits = 2;
54 num = 0;
55 symbol = levels[(size_t)i - 1];
56 }
57 else
58 {
59 sym -= kTableLevel0Number;
60 sym <<= 2;
61 numBits = 3 + (unsigned)sym;
62 num = ((unsigned)sym << 1);
63 symbol = 0;
64 }
65
66 num += i + 3 + ReadBits(numBits);
67 if (num > numSymbols)
68 return false;
69 do
70 levels[i++] = symbol;
71 while (i < num);
72 }
73 }
74 while (i < numSymbols);
75
76 return true;
77 }
78
79 #define RIF(x) { if (!(x)) return false; }
80
ReadTables(void)81 bool CCoder::ReadTables(void)
82 {
83 m_FinalBlock = (ReadBits(kFinalBlockFieldSize) == NFinalBlockField::kFinalBlock);
84 if (m_InBitStream.ExtraBitsWereRead())
85 return false;
86 UInt32 blockType = ReadBits(kBlockTypeFieldSize);
87 if (blockType > NBlockType::kDynamicHuffman)
88 return false;
89 if (m_InBitStream.ExtraBitsWereRead())
90 return false;
91
92 if (blockType == NBlockType::kStored)
93 {
94 m_StoredMode = true;
95 m_InBitStream.AlignToByte();
96 m_StoredBlockSize = ReadAligned_UInt16(); // ReadBits(kStoredBlockLengthFieldSize)
97 if (_deflateNSIS)
98 return true;
99 return (m_StoredBlockSize == (UInt16)~ReadAligned_UInt16());
100 }
101
102 m_StoredMode = false;
103
104 CLevels levels;
105 if (blockType == NBlockType::kFixedHuffman)
106 {
107 levels.SetFixedLevels();
108 _numDistLevels = _deflate64Mode ? kDistTableSize64 : kDistTableSize32;
109 }
110 else
111 {
112 unsigned numLitLenLevels = ReadBits(kNumLenCodesFieldSize) + kNumLitLenCodesMin;
113 _numDistLevels = ReadBits(kNumDistCodesFieldSize) + kNumDistCodesMin;
114 unsigned numLevelCodes = ReadBits(kNumLevelCodesFieldSize) + kNumLevelCodesMin;
115
116 if (!_deflate64Mode)
117 if (_numDistLevels > kDistTableSize32)
118 return false;
119
120 Byte levelLevels[kLevelTableSize];
121 for (unsigned i = 0; i < kLevelTableSize; i++)
122 {
123 unsigned position = kCodeLengthAlphabetOrder[i];
124 if (i < numLevelCodes)
125 levelLevels[position] = (Byte)ReadBits(kLevelFieldSize);
126 else
127 levelLevels[position] = 0;
128 }
129
130 if (m_InBitStream.ExtraBitsWereRead())
131 return false;
132
133 RIF(m_LevelDecoder.Build(levelLevels));
134
135 Byte tmpLevels[kFixedMainTableSize + kFixedDistTableSize];
136 if (!DecodeLevels(tmpLevels, numLitLenLevels + _numDistLevels))
137 return false;
138
139 if (m_InBitStream.ExtraBitsWereRead())
140 return false;
141
142 levels.SubClear();
143 memcpy(levels.litLenLevels, tmpLevels, numLitLenLevels);
144 memcpy(levels.distLevels, tmpLevels + numLitLenLevels, _numDistLevels);
145 }
146 RIF(m_MainDecoder.Build(levels.litLenLevels));
147 return m_DistDecoder.Build(levels.distLevels);
148 }
149
150
InitInStream(bool needInit)151 HRESULT CCoder::InitInStream(bool needInit)
152 {
153 if (needInit)
154 {
155 // for HDD-Windows:
156 // (1 << 15) - best for reading only prefetch
157 // (1 << 22) - best for real reading / writing
158 if (!m_InBitStream.Create(1 << 20))
159 return E_OUTOFMEMORY;
160 m_InBitStream.Init();
161 _needInitInStream = false;
162 }
163 return S_OK;
164 }
165
166
CodeSpec(UInt32 curSize,bool finishInputStream,UInt32 inputProgressLimit)167 HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit)
168 {
169 if (_remainLen == kLenIdFinished)
170 return S_OK;
171
172 if (_remainLen == kLenIdNeedInit)
173 {
174 if (!_keepHistory)
175 if (!m_OutWindowStream.Create(_deflate64Mode ? kHistorySize64: kHistorySize32))
176 return E_OUTOFMEMORY;
177 RINOK(InitInStream(_needInitInStream));
178 m_OutWindowStream.Init(_keepHistory);
179
180 m_FinalBlock = false;
181 _remainLen = 0;
182 _needReadTable = true;
183 }
184
185 while (_remainLen > 0 && curSize > 0)
186 {
187 _remainLen--;
188 Byte b = m_OutWindowStream.GetByte(_rep0);
189 m_OutWindowStream.PutByte(b);
190 curSize--;
191 }
192
193 UInt64 inputStart = 0;
194 if (inputProgressLimit != 0)
195 inputStart = m_InBitStream.GetProcessedSize();
196
197 while (curSize > 0 || finishInputStream)
198 {
199 if (m_InBitStream.ExtraBitsWereRead())
200 return S_FALSE;
201
202 if (_needReadTable)
203 {
204 if (m_FinalBlock)
205 {
206 _remainLen = kLenIdFinished;
207 break;
208 }
209
210 if (inputProgressLimit != 0)
211 if (m_InBitStream.GetProcessedSize() - inputStart >= inputProgressLimit)
212 return S_OK;
213
214 if (!ReadTables())
215 return S_FALSE;
216 if (m_InBitStream.ExtraBitsWereRead())
217 return S_FALSE;
218 _needReadTable = false;
219 }
220
221 if (m_StoredMode)
222 {
223 if (finishInputStream && curSize == 0 && m_StoredBlockSize != 0)
224 return S_FALSE;
225 /* NSIS version contains some bits in bitl bits buffer.
226 So we must read some first bytes via ReadAlignedByte */
227 for (; m_StoredBlockSize > 0 && curSize > 0 && m_InBitStream.ThereAreDataInBitsBuffer(); m_StoredBlockSize--, curSize--)
228 m_OutWindowStream.PutByte(ReadAlignedByte());
229 for (; m_StoredBlockSize > 0 && curSize > 0; m_StoredBlockSize--, curSize--)
230 m_OutWindowStream.PutByte(m_InBitStream.ReadDirectByte());
231 _needReadTable = (m_StoredBlockSize == 0);
232 continue;
233 }
234
235 while (curSize > 0)
236 {
237 if (m_InBitStream.ExtraBitsWereRead_Fast())
238 return S_FALSE;
239
240 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream);
241
242 if (sym < 0x100)
243 {
244 m_OutWindowStream.PutByte((Byte)sym);
245 curSize--;
246 continue;
247 }
248 else if (sym == kSymbolEndOfBlock)
249 {
250 _needReadTable = true;
251 break;
252 }
253 else if (sym < kMainTableSize)
254 {
255 sym -= kSymbolMatch;
256 UInt32 len;
257 {
258 unsigned numBits;
259 if (_deflate64Mode)
260 {
261 len = kLenStart64[sym];
262 numBits = kLenDirectBits64[sym];
263 }
264 else
265 {
266 len = kLenStart32[sym];
267 numBits = kLenDirectBits32[sym];
268 }
269 len += kMatchMinLen + m_InBitStream.ReadBits(numBits);
270 }
271 UInt32 locLen = len;
272 if (locLen > curSize)
273 locLen = (UInt32)curSize;
274 sym = m_DistDecoder.Decode(&m_InBitStream);
275 if (sym >= _numDistLevels)
276 return S_FALSE;
277 sym = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);
278 /*
279 if (sym >= 4)
280 {
281 // sym &= 31;
282 const unsigned numDirectBits = (unsigned)(((sym >> 1) - 1));
283 sym = (2 | (sym & 1)) << numDirectBits;
284 sym += m_InBitStream.ReadBits(numDirectBits);
285 }
286 */
287 if (!m_OutWindowStream.CopyBlock(sym, locLen))
288 return S_FALSE;
289 curSize -= locLen;
290 len -= locLen;
291 if (len != 0)
292 {
293 _remainLen = (Int32)len;
294 _rep0 = sym;
295 break;
296 }
297 }
298 else
299 return S_FALSE;
300 }
301
302 if (finishInputStream && curSize == 0)
303 {
304 if (m_MainDecoder.Decode(&m_InBitStream) != kSymbolEndOfBlock)
305 return S_FALSE;
306 _needReadTable = true;
307 }
308 }
309
310 if (m_InBitStream.ExtraBitsWereRead())
311 return S_FALSE;
312
313 return S_OK;
314 }
315
316
317 #ifdef _NO_EXCEPTIONS
318
319 #define DEFLATE_TRY_BEGIN
320 #define DEFLATE_TRY_END(res)
321
322 #else
323
324 #define DEFLATE_TRY_BEGIN try {
325 #define DEFLATE_TRY_END(res) } \
326 catch(const CSystemException &e) { res = e.ErrorCode; } \
327 catch(...) { res = S_FALSE; }
328
329 // catch(const CInBufferException &e) { res = e.ErrorCode; }
330 // catch(const CLzOutWindowException &e) { res = e.ErrorCode; }
331
332 #endif
333
334
CodeReal(ISequentialOutStream * outStream,ICompressProgressInfo * progress)335 HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress)
336 {
337 HRESULT res;
338
339 DEFLATE_TRY_BEGIN
340
341 m_OutWindowStream.SetStream(outStream);
342 CCoderReleaser flusher(this);
343
344 const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize();
345
346 for (;;)
347 {
348 const UInt32 kInputProgressLimit = 1 << 21;
349 UInt32 curSize = 1 << 20;
350 bool finishInputStream = false;
351 if (_outSizeDefined)
352 {
353 const UInt64 rem = _outSize - GetOutProcessedCur();
354 if (curSize >= rem)
355 {
356 curSize = (UInt32)rem;
357 if (ZlibMode || _needFinishInput)
358 finishInputStream = true;
359 }
360 }
361 if (!finishInputStream && curSize == 0)
362 break;
363
364 RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0));
365
366 if (_remainLen == kLenIdFinished)
367 break;
368
369 if (progress)
370 {
371 const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart;
372 const UInt64 nowPos64 = GetOutProcessedCur();
373 RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
374 }
375 }
376
377 if (_remainLen == kLenIdFinished && ZlibMode)
378 {
379 m_InBitStream.AlignToByte();
380 for (unsigned i = 0; i < 4; i++)
381 ZlibFooter[i] = ReadAlignedByte();
382 }
383
384 flusher.NeedFlush = false;
385 res = Flush();
386 if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())
387 return S_FALSE;
388
389 DEFLATE_TRY_END(res)
390
391 return res;
392 }
393
394
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 *,const UInt64 * outSize,ICompressProgressInfo * progress)395 HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
396 const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
397 {
398 SetInStream(inStream);
399 SetOutStreamSize(outSize);
400 HRESULT res = CodeReal(outStream, progress);
401 ReleaseInStream();
402 /*
403 if (res == S_OK)
404 if (_needFinishInput && inSize && *inSize != m_InBitStream.GetProcessedSize())
405 res = S_FALSE;
406 */
407 return res;
408 }
409
410
SetFinishMode(UInt32 finishMode)411 STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode)
412 {
413 Set_NeedFinishInput(finishMode != 0);
414 return S_OK;
415 }
416
417
GetInStreamProcessedSize(UInt64 * value)418 STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
419 {
420 *value = m_InBitStream.GetStreamSize();
421 return S_OK;
422 }
423
424
ReadUnusedFromInBuf(void * data,UInt32 size,UInt32 * processedSize)425 STDMETHODIMP CCoder::ReadUnusedFromInBuf(void *data, UInt32 size, UInt32 *processedSize)
426 {
427 AlignToByte();
428 UInt32 i = 0;
429 if (!m_InBitStream.ExtraBitsWereRead())
430 {
431 for (i = 0; i < size; i++)
432 {
433 if (!m_InBitStream.ReadAlignedByte_FromBuf(((Byte *)data)[i]))
434 break;
435 }
436 }
437 if (processedSize)
438 *processedSize = i;
439 return S_OK;
440 }
441
442
SetInStream(ISequentialInStream * inStream)443 STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
444 {
445 m_InStreamRef = inStream;
446 m_InBitStream.SetStream(inStream);
447 return S_OK;
448 }
449
450
ReleaseInStream()451 STDMETHODIMP CCoder::ReleaseInStream()
452 {
453 m_InStreamRef.Release();
454 return S_OK;
455 }
456
457
SetOutStreamSizeResume(const UInt64 * outSize)458 void CCoder::SetOutStreamSizeResume(const UInt64 *outSize)
459 {
460 _outSizeDefined = (outSize != NULL);
461 _outSize = 0;
462 if (_outSizeDefined)
463 _outSize = *outSize;
464
465 m_OutWindowStream.Init(_keepHistory);
466 _outStartPos = m_OutWindowStream.GetProcessedSize();
467
468 _remainLen = kLenIdNeedInit;
469 }
470
471
SetOutStreamSize(const UInt64 * outSize)472 STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 *outSize)
473 {
474 /*
475 18.06:
476 We want to support GetInputProcessedSize() before CCoder::Read()
477 So we call m_InBitStream.Init() even before buffer allocations
478 m_InBitStream.Init() just sets variables to default values
479 But later we will call m_InBitStream.Init() again with real buffer pointers
480 */
481 m_InBitStream.Init();
482 _needInitInStream = true;
483 SetOutStreamSizeResume(outSize);
484 return S_OK;
485 }
486
487
488 #ifndef NO_READ_FROM_CODER
489
Read(void * data,UInt32 size,UInt32 * processedSize)490 STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
491 {
492 HRESULT res;
493
494 if (processedSize)
495 *processedSize = 0;
496 const UInt64 outPos = GetOutProcessedCur();
497
498 bool finishInputStream = false;
499 if (_outSizeDefined)
500 {
501 const UInt64 rem = _outSize - outPos;
502 if (size >= rem)
503 {
504 size = (UInt32)rem;
505 if (ZlibMode || _needFinishInput)
506 finishInputStream = true;
507 }
508 }
509 if (!finishInputStream && size == 0)
510 return S_OK;
511
512 DEFLATE_TRY_BEGIN
513
514 m_OutWindowStream.SetMemStream((Byte *)data);
515
516 res = CodeSpec(size, finishInputStream);
517
518 DEFLATE_TRY_END(res)
519
520 {
521 HRESULT res2 = Flush();
522 if (res2 != S_OK)
523 res = res2;
524 }
525
526 if (processedSize)
527 *processedSize = (UInt32)(GetOutProcessedCur() - outPos);
528
529 m_OutWindowStream.SetMemStream(NULL);
530 return res;
531 }
532
533 #endif
534
535
CodeResume(ISequentialOutStream * outStream,const UInt64 * outSize,ICompressProgressInfo * progress)536 HRESULT CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
537 {
538 SetOutStreamSizeResume(outSize);
539 return CodeReal(outStream, progress);
540 }
541
542 }}}
543