1 // Rar3Decoder.cpp
2 // According to unRAR license, this code may not be used to develop
3 // a program that creates RAR archives
4
5 /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6
7 #include "StdAfx.h"
8
9 #include "../../../C/Alloc.h"
10
11 #include "../Common/StreamUtils.h"
12
13 #include "Rar3Decoder.h"
14
15 namespace NCompress {
16 namespace NRar3 {
17
18 static const UInt32 kNumAlignReps = 15;
19
20 static const unsigned kSymbolReadTable = 256;
21 static const unsigned kSymbolRep = 259;
22
23 static const Byte kDistDirectBits[kDistTableSize] =
24 {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14,15,15,
25 16,16,16,16,16,16,16,16,16,16,16,16,16,16,
26 18,18,18,18,18,18,18,18,18,18,18,18};
27
28 static const Byte kLen2DistStarts[kNumLen2Symbols] = {0,4,8,16,32,64,128,192};
29 static const Byte kLen2DistDirectBits[kNumLen2Symbols] = {2,2,3, 4, 5, 6, 6, 6};
30
31 static const UInt32 kDistLimit3 = 0x2000 - 2;
32 static const UInt32 kDistLimit4 = 0x40000 - 2;
33
34 static const UInt32 kNormalMatchMinLen = 3;
35
36 static const UInt32 kVmDataSizeMax = 1 << 16;
37 static const UInt32 kVmCodeSizeMax = 1 << 16;
38
39 extern "C" {
40
Wrap_ReadByte(IByteInPtr pp)41 static Byte Wrap_ReadByte(IByteInPtr pp) throw()
42 {
43 CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
44 return p->BitDecoder.Stream.ReadByte();
45 }
46
Wrap_ReadBits8(IByteInPtr pp)47 static Byte Wrap_ReadBits8(IByteInPtr pp) throw()
48 {
49 CByteIn *p = Z7_CONTAINER_FROM_VTBL_CLS(pp, CByteIn, IByteIn_obj);
50 return (Byte)p->BitDecoder.ReadByteFromAligned();
51 }
52
53 }
54
55
CDecoder()56 CDecoder::CDecoder():
57 _isSolid(false),
58 _solidAllowed(false),
59 _window(NULL),
60 _winPos(0),
61 _wrPtr(0),
62 _lzSize(0),
63 _writtenFileSize(0),
64 _vmData(NULL),
65 _vmCode(NULL)
66 {
67 Ppmd7_Construct(&_ppmd);
68
69 UInt32 start = 0;
70 for (UInt32 i = 0; i < kDistTableSize; i++)
71 {
72 kDistStart[i] = start;
73 start += ((UInt32)1 << kDistDirectBits[i]);
74 }
75 }
76
~CDecoder()77 CDecoder::~CDecoder()
78 {
79 InitFilters();
80 ::MidFree(_vmData);
81 ::MidFree(_window);
82 Ppmd7_Free(&_ppmd, &g_BigAlloc);
83 }
84
WriteDataToStream(const Byte * data,UInt32 size)85 HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)
86 {
87 return WriteStream(_outStream, data, size);
88 }
89
WriteData(const Byte * data,UInt32 size)90 HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)
91 {
92 HRESULT res = S_OK;
93 if (_writtenFileSize < _unpackSize)
94 {
95 UInt32 curSize = size;
96 UInt64 remain = _unpackSize - _writtenFileSize;
97 if (remain < curSize)
98 curSize = (UInt32)remain;
99 res = WriteDataToStream(data, curSize);
100 }
101 _writtenFileSize += size;
102 return res;
103 }
104
WriteArea(UInt32 startPtr,UInt32 endPtr)105 HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)
106 {
107 if (startPtr <= endPtr)
108 return WriteData(_window + startPtr, endPtr - startPtr);
109 RINOK(WriteData(_window + startPtr, kWindowSize - startPtr))
110 return WriteData(_window, endPtr);
111 }
112
ExecuteFilter(unsigned tempFilterIndex,NVm::CBlockRef & outBlockRef)113 void CDecoder::ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef)
114 {
115 CTempFilter *tempFilter = _tempFilters[tempFilterIndex];
116 tempFilter->InitR[6] = (UInt32)_writtenFileSize;
117 NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);
118 NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));
119 CFilter *filter = _filters[tempFilter->FilterIndex];
120 if (!filter->IsSupported)
121 _unsupportedFilter = true;
122 if (!_vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData))
123 _unsupportedFilter = true;
124 delete tempFilter;
125 _tempFilters[tempFilterIndex] = NULL;
126 _numEmptyTempFilters++;
127 }
128
WriteBuf()129 HRESULT CDecoder::WriteBuf()
130 {
131 UInt32 writtenBorder = _wrPtr;
132 UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;
133 FOR_VECTOR (i, _tempFilters)
134 {
135 CTempFilter *filter = _tempFilters[i];
136 if (!filter)
137 continue;
138 if (filter->NextWindow)
139 {
140 filter->NextWindow = false;
141 continue;
142 }
143 UInt32 blockStart = filter->BlockStart;
144 UInt32 blockSize = filter->BlockSize;
145 if (((blockStart - writtenBorder) & kWindowMask) < writeSize)
146 {
147 if (writtenBorder != blockStart)
148 {
149 RINOK(WriteArea(writtenBorder, blockStart))
150 writtenBorder = blockStart;
151 writeSize = (_winPos - writtenBorder) & kWindowMask;
152 }
153 if (blockSize <= writeSize)
154 {
155 UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;
156 if (blockStart < blockEnd || blockEnd == 0)
157 _vm.SetMemory(0, _window + blockStart, blockSize);
158 else
159 {
160 UInt32 tailSize = kWindowSize - blockStart;
161 _vm.SetMemory(0, _window + blockStart, tailSize);
162 _vm.SetMemory(tailSize, _window, blockEnd);
163 }
164 NVm::CBlockRef outBlockRef;
165 ExecuteFilter(i, outBlockRef);
166 while (i + 1 < _tempFilters.Size())
167 {
168 CTempFilter *nextFilter = _tempFilters[i + 1];
169 if (!nextFilter
170 || nextFilter->BlockStart != blockStart
171 || nextFilter->BlockSize != outBlockRef.Size
172 || nextFilter->NextWindow)
173 break;
174 _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
175 ExecuteFilter(++i, outBlockRef);
176 }
177 WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);
178 _writtenFileSize += outBlockRef.Size;
179 writtenBorder = blockEnd;
180 writeSize = (_winPos - writtenBorder) & kWindowMask;
181 }
182 else
183 {
184 for (unsigned j = i; j < _tempFilters.Size(); j++)
185 {
186 CTempFilter *filter2 = _tempFilters[j];
187 if (filter2 && filter2->NextWindow)
188 filter2->NextWindow = false;
189 }
190 _wrPtr = writtenBorder;
191 return S_OK; // check it
192 }
193 }
194 }
195
196 _wrPtr = _winPos;
197 return WriteArea(writtenBorder, _winPos);
198 }
199
InitFilters()200 void CDecoder::InitFilters()
201 {
202 _lastFilter = 0;
203 _numEmptyTempFilters = 0;
204 unsigned i;
205 for (i = 0; i < _tempFilters.Size(); i++)
206 delete _tempFilters[i];
207 _tempFilters.Clear();
208 for (i = 0; i < _filters.Size(); i++)
209 delete _filters[i];
210 _filters.Clear();
211 }
212
213 static const unsigned MAX_UNPACK_FILTERS = 8192;
214
AddVmCode(UInt32 firstByte,UInt32 codeSize)215 bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)
216 {
217 CMemBitDecoder inp;
218 inp.Init(_vmData, codeSize);
219
220 UInt32 filterIndex;
221
222 if (firstByte & 0x80)
223 {
224 filterIndex = inp.ReadEncodedUInt32();
225 if (filterIndex == 0)
226 InitFilters();
227 else
228 filterIndex--;
229 }
230 else
231 filterIndex = _lastFilter;
232
233 if (filterIndex > (UInt32)_filters.Size())
234 return false;
235 _lastFilter = filterIndex;
236 bool newFilter = (filterIndex == (UInt32)_filters.Size());
237
238 CFilter *filter;
239 if (newFilter)
240 {
241 // check if too many filters
242 if (filterIndex > MAX_UNPACK_FILTERS)
243 return false;
244 filter = new CFilter;
245 _filters.Add(filter);
246 }
247 else
248 {
249 filter = _filters[filterIndex];
250 filter->ExecCount++;
251 }
252
253 if (_numEmptyTempFilters != 0)
254 {
255 const unsigned num = _tempFilters.Size();
256 CTempFilter **tempFilters = _tempFilters.NonConstData();
257
258 unsigned w = 0;
259 for (unsigned i = 0; i < num; i++)
260 {
261 CTempFilter *tf = tempFilters[i];
262 if (tf)
263 tempFilters[w++] = tf;
264 }
265
266 _tempFilters.DeleteFrom(w);
267 _numEmptyTempFilters = 0;
268 }
269
270 if (_tempFilters.Size() > MAX_UNPACK_FILTERS)
271 return false;
272 CTempFilter *tempFilter = new CTempFilter;
273 _tempFilters.Add(tempFilter);
274 tempFilter->FilterIndex = filterIndex;
275
276 UInt32 blockStart = inp.ReadEncodedUInt32();
277 if (firstByte & 0x40)
278 blockStart += 258;
279 tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;
280 if (firstByte & 0x20)
281 filter->BlockSize = inp.ReadEncodedUInt32();
282 tempFilter->BlockSize = filter->BlockSize;
283 tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;
284
285 memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));
286 tempFilter->InitR[3] = NVm::kGlobalOffset;
287 tempFilter->InitR[4] = tempFilter->BlockSize;
288 tempFilter->InitR[5] = filter->ExecCount;
289 if (firstByte & 0x10)
290 {
291 UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);
292 for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
293 if (initMask & (1 << i))
294 tempFilter->InitR[i] = inp.ReadEncodedUInt32();
295 }
296
297 bool isOK = true;
298 if (newFilter)
299 {
300 UInt32 vmCodeSize = inp.ReadEncodedUInt32();
301 if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)
302 return false;
303 for (UInt32 i = 0; i < vmCodeSize; i++)
304 _vmCode[i] = (Byte)inp.ReadBits(8);
305 isOK = filter->PrepareProgram(_vmCode, vmCodeSize);
306 }
307
308 {
309 Byte *globalData = &tempFilter->GlobalData[0];
310 for (unsigned i = 0; i < NVm::kNumGpRegs; i++)
311 NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);
312 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);
313 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?
314 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], filter->ExecCount);
315 }
316
317 if (firstByte & 8)
318 {
319 UInt32 dataSize = inp.ReadEncodedUInt32();
320 if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)
321 return false;
322 CRecordVector<Byte> &globalData = tempFilter->GlobalData;
323 unsigned requiredSize = (unsigned)(dataSize + NVm::kFixedGlobalSize);
324 if (globalData.Size() < requiredSize)
325 globalData.ChangeSize_KeepData(requiredSize);
326 Byte *dest = &globalData[NVm::kFixedGlobalSize];
327 for (UInt32 i = 0; i < dataSize; i++)
328 dest[i] = (Byte)inp.ReadBits(8);
329 }
330
331 return isOK;
332 }
333
ReadVmCodeLZ()334 bool CDecoder::ReadVmCodeLZ()
335 {
336 UInt32 firstByte = ReadBits(8);
337 UInt32 len = (firstByte & 7) + 1;
338 if (len == 7)
339 len = ReadBits(8) + 7;
340 else if (len == 8)
341 len = ReadBits(16);
342 if (len > kVmDataSizeMax)
343 return false;
344 for (UInt32 i = 0; i < len; i++)
345 _vmData[i] = (Byte)ReadBits(8);
346 return AddVmCode(firstByte, len);
347 }
348
349
350 // int CDecoder::DecodePpmSymbol() { return Ppmd7a_DecodeSymbol(&_ppmd); }
351 #define DecodePpmSymbol() Ppmd7a_DecodeSymbol(&_ppmd)
352
353
ReadVmCodePPM()354 bool CDecoder::ReadVmCodePPM()
355 {
356 const int firstByte = DecodePpmSymbol();
357 if (firstByte < 0)
358 return false;
359 UInt32 len = (firstByte & 7) + 1;
360 if (len == 7)
361 {
362 const int b1 = DecodePpmSymbol();
363 if (b1 < 0)
364 return false;
365 len = (unsigned)b1 + 7;
366 }
367 else if (len == 8)
368 {
369 const int b1 = DecodePpmSymbol();
370 if (b1 < 0)
371 return false;
372 const int b2 = DecodePpmSymbol();
373 if (b2 < 0)
374 return false;
375 len = (unsigned)b1 * 256 + (unsigned)b2;
376 }
377 if (len > kVmDataSizeMax)
378 return false;
379 if (InputEofError_Fast())
380 return false;
381 for (UInt32 i = 0; i < len; i++)
382 {
383 const int b = DecodePpmSymbol();
384 if (b < 0)
385 return false;
386 _vmData[i] = (Byte)b;
387 }
388 return AddVmCode((unsigned)firstByte, len);
389 }
390
391 #define RIF(x) { if (!(x)) return S_FALSE; }
392
ReadBits(unsigned numBits)393 UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.BitDecoder.ReadBits(numBits); }
394
395 // ---------- PPM ----------
396
InitPPM()397 HRESULT CDecoder::InitPPM()
398 {
399 unsigned maxOrder = (unsigned)ReadBits(7);
400
401 const bool reset = ((maxOrder & 0x20) != 0);
402 UInt32 maxMB = 0;
403 if (reset)
404 maxMB = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
405 else
406 {
407 if (PpmError || !Ppmd7_WasAllocated(&_ppmd))
408 return S_FALSE;
409 }
410 if (maxOrder & 0x40)
411 PpmEscChar = (Byte)Wrap_ReadBits8(&m_InBitStream.IByteIn_obj);
412
413 _ppmd.rc.dec.Stream = &m_InBitStream.IByteIn_obj;
414 m_InBitStream.IByteIn_obj.Read = Wrap_ReadBits8;
415
416 Ppmd7a_RangeDec_Init(&_ppmd.rc.dec);
417
418 m_InBitStream.IByteIn_obj.Read = Wrap_ReadByte;
419
420 if (reset)
421 {
422 PpmError = true;
423 maxOrder = (maxOrder & 0x1F) + 1;
424 if (maxOrder > 16)
425 maxOrder = 16 + (maxOrder - 16) * 3;
426 if (maxOrder == 1)
427 {
428 Ppmd7_Free(&_ppmd, &g_BigAlloc);
429 return S_FALSE;
430 }
431 if (!Ppmd7_Alloc(&_ppmd, (maxMB + 1) << 20, &g_BigAlloc))
432 return E_OUTOFMEMORY;
433 Ppmd7_Init(&_ppmd, maxOrder);
434 PpmError = false;
435 }
436 return S_OK;
437 }
438
439
DecodePPM(Int32 num,bool & keepDecompressing)440 HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
441 {
442 keepDecompressing = false;
443 if (PpmError)
444 return S_FALSE;
445 do
446 {
447 if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
448 {
449 RINOK(WriteBuf())
450 if (_writtenFileSize > _unpackSize)
451 {
452 keepDecompressing = false;
453 return S_OK;
454 }
455 }
456 if (InputEofError_Fast())
457 return false;
458 const int c = DecodePpmSymbol();
459 if (c < 0)
460 {
461 PpmError = true;
462 return S_FALSE;
463 }
464 if (c == PpmEscChar)
465 {
466 const int nextCh = DecodePpmSymbol();
467 if (nextCh < 0)
468 {
469 PpmError = true;
470 return S_FALSE;
471 }
472 if (nextCh == 0)
473 return ReadTables(keepDecompressing);
474 if (nextCh == 2 || nextCh == -1)
475 return S_OK;
476 if (nextCh == 3)
477 {
478 if (!ReadVmCodePPM())
479 {
480 PpmError = true;
481 return S_FALSE;
482 }
483 continue;
484 }
485 if (nextCh == 4 || nextCh == 5)
486 {
487 UInt32 dist = 0;
488 UInt32 len = 4;
489 if (nextCh == 4)
490 {
491 for (int i = 0; i < 3; i++)
492 {
493 const int c2 = DecodePpmSymbol();
494 if (c2 < 0)
495 {
496 PpmError = true;
497 return S_FALSE;
498 }
499 dist = (dist << 8) + (Byte)c2;
500 }
501 dist++;
502 len += 28;
503 }
504 const int c2 = DecodePpmSymbol();
505 if (c2 < 0)
506 {
507 PpmError = true;
508 return S_FALSE;
509 }
510 len += (unsigned)c2;
511 if (dist >= _lzSize)
512 return S_FALSE;
513 CopyBlock(dist, len);
514 num -= (Int32)len;
515 continue;
516 }
517 }
518 PutByte((Byte)c);
519 num--;
520 }
521 while (num >= 0);
522 keepDecompressing = true;
523 return S_OK;
524 }
525
526 // ---------- LZ ----------
527
ReadTables(bool & keepDecompressing)528 HRESULT CDecoder::ReadTables(bool &keepDecompressing)
529 {
530 keepDecompressing = true;
531 m_InBitStream.BitDecoder.AlignToByte();
532 if (ReadBits(1) != 0)
533 {
534 _lzMode = false;
535 return InitPPM();
536 }
537
538 TablesRead = false;
539 TablesOK = false;
540
541 _lzMode = true;
542 PrevAlignBits = 0;
543 PrevAlignCount = 0;
544
545 const unsigned kLevelTableSize = 20;
546 Byte levelLevels[kLevelTableSize];
547 Byte lens[kTablesSizesSum];
548
549 if (ReadBits(1) == 0)
550 memset(m_LastLevels, 0, kTablesSizesSum);
551
552 unsigned i;
553
554 for (i = 0; i < kLevelTableSize; i++)
555 {
556 const UInt32 len = ReadBits(4);
557 if (len == 15)
558 {
559 UInt32 zeroCount = ReadBits(4);
560 if (zeroCount != 0)
561 {
562 zeroCount += 2;
563 while (zeroCount-- > 0 && i < kLevelTableSize)
564 levelLevels[i++]=0;
565 i--;
566 continue;
567 }
568 }
569 levelLevels[i] = (Byte)len;
570 }
571
572 NHuffman::CDecoder256<kNumHuffmanBits, kLevelTableSize, 6> m_LevelDecoder;
573 RIF(m_LevelDecoder.Build(levelLevels, NHuffman::k_BuildMode_Full))
574
575 i = 0;
576
577 do
578 {
579 const unsigned sym = m_LevelDecoder.DecodeFull(&m_InBitStream.BitDecoder);
580 if (sym < 16)
581 {
582 lens[i] = Byte((sym + m_LastLevels[i]) & 15);
583 i++;
584 }
585 #if 0
586 else if (sym > kLevelTableSize)
587 return S_FALSE;
588 #endif
589 else
590 {
591 unsigned num = ((sym /* - 16 */) & 1) * 4;
592 num += num + 3 + (unsigned)ReadBits(num + 3);
593 num += i;
594 if (num > kTablesSizesSum)
595 num = kTablesSizesSum;
596 Byte v = 0;
597 if (sym < 16 + 2)
598 {
599 if (i == 0)
600 return S_FALSE;
601 v = lens[(size_t)i - 1];
602 }
603 do
604 lens[i++] = v;
605 while (i < num);
606 }
607 }
608 while (i < kTablesSizesSum);
609
610 if (InputEofError())
611 return S_FALSE;
612
613 TablesRead = true;
614
615 // original code has check here:
616 /*
617 if (InAddr > ReadTop)
618 {
619 keepDecompressing = false;
620 return true;
621 }
622 */
623
624 RIF(m_MainDecoder.Build(&lens[0]))
625 RIF(m_DistDecoder.Build(&lens[kMainTableSize]))
626 RIF(m_AlignDecoder.Build(&lens[kMainTableSize + kDistTableSize]))
627 RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize + kAlignTableSize]))
628
629 memcpy(m_LastLevels, lens, kTablesSizesSum);
630
631 TablesOK = true;
632
633 return S_OK;
634 }
635
636 /*
637 class CCoderReleaser
638 {
639 CDecoder *m_Coder;
640 public:
641 CCoderReleaser(CDecoder *coder): m_Coder(coder) {}
642 ~CCoderReleaser()
643 {
644 m_Coder->ReleaseStreams();
645 }
646 };
647 */
648
ReadEndOfBlock(bool & keepDecompressing)649 HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)
650 {
651 if (ReadBits(1) == 0)
652 {
653 // new file
654 keepDecompressing = false;
655 TablesRead = (ReadBits(1) == 0);
656 return S_OK;
657 }
658 TablesRead = false;
659 return ReadTables(keepDecompressing);
660 }
661
662
DecodeLZ(bool & keepDecompressing)663 HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
664 {
665 UInt32 rep0 = _reps[0];
666 UInt32 rep1 = _reps[1];
667 UInt32 rep2 = _reps[2];
668 UInt32 rep3 = _reps[3];
669 UInt32 len = _lastLength;
670 for (;;)
671 {
672 if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)
673 {
674 RINOK(WriteBuf())
675 if (_writtenFileSize > _unpackSize)
676 {
677 keepDecompressing = false;
678 return S_OK;
679 }
680 }
681
682 if (InputEofError_Fast())
683 return S_FALSE;
684
685 unsigned sym = m_MainDecoder.Decode(&m_InBitStream.BitDecoder);
686 if (sym < 256)
687 {
688 PutByte((Byte)sym);
689 continue;
690 }
691 else if (sym == kSymbolReadTable)
692 {
693 RINOK(ReadEndOfBlock(keepDecompressing))
694 break;
695 }
696 else if (sym == 257)
697 {
698 if (!ReadVmCodeLZ())
699 return S_FALSE;
700 continue;
701 }
702 else if (sym == 258)
703 {
704 if (len == 0)
705 return S_FALSE;
706 }
707 else if (sym < kSymbolRep + 4)
708 {
709 if (sym != kSymbolRep)
710 {
711 UInt32 dist;
712 if (sym == kSymbolRep + 1)
713 dist = rep1;
714 else
715 {
716 if (sym == kSymbolRep + 2)
717 dist = rep2;
718 else
719 {
720 dist = rep3;
721 rep3 = rep2;
722 }
723 rep2 = rep1;
724 }
725 rep1 = rep0;
726 rep0 = dist;
727 }
728
729 const unsigned sym2 = m_LenDecoder.Decode(&m_InBitStream.BitDecoder);
730 if (sym2 >= kLenTableSize)
731 return S_FALSE;
732 len = 2 + sym2;
733 if (sym2 >= 8)
734 {
735 const unsigned num = (sym2 >> 2) - 1;
736 len = 2 + (UInt32)((4 + (sym2 & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
737 }
738 }
739 else
740 {
741 rep3 = rep2;
742 rep2 = rep1;
743 rep1 = rep0;
744 if (sym < 271)
745 {
746 sym -= 263;
747 rep0 = kLen2DistStarts[sym] + m_InBitStream.BitDecoder.ReadBits_upto8(kLen2DistDirectBits[sym]);
748 len = 2;
749 }
750 else if (sym < 299)
751 {
752 sym -= 271;
753 len = kNormalMatchMinLen + sym;
754 if (sym >= 8)
755 {
756 const unsigned num = (sym >> 2) - 1;
757 len = kNormalMatchMinLen + (UInt32)((4 + (sym & 3)) << num) + m_InBitStream.BitDecoder.ReadBits_upto8(num);
758 }
759 const unsigned sym2 = m_DistDecoder.Decode(&m_InBitStream.BitDecoder);
760 if (sym2 >= kDistTableSize)
761 return S_FALSE;
762 rep0 = kDistStart[sym2];
763 unsigned numBits = kDistDirectBits[sym2];
764 if (sym2 >= (kNumAlignBits * 2) + 2)
765 {
766 if (numBits > kNumAlignBits)
767 rep0 += (m_InBitStream.BitDecoder.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);
768 if (PrevAlignCount > 0)
769 {
770 PrevAlignCount--;
771 rep0 += PrevAlignBits;
772 }
773 else
774 {
775 const unsigned sym3 = m_AlignDecoder.Decode(&m_InBitStream.BitDecoder);
776 if (sym3 < (1 << kNumAlignBits))
777 {
778 rep0 += sym3;
779 PrevAlignBits = sym3;
780 }
781 else if (sym3 == (1 << kNumAlignBits))
782 {
783 PrevAlignCount = kNumAlignReps;
784 rep0 += PrevAlignBits;
785 }
786 else
787 return S_FALSE;
788 }
789 }
790 else
791 rep0 += m_InBitStream.BitDecoder.ReadBits_upto8(numBits);
792 len += ((UInt32)(kDistLimit4 - rep0) >> 31) + ((UInt32)(kDistLimit3 - rep0) >> 31);
793 }
794 else
795 return S_FALSE;
796 }
797 if (rep0 >= _lzSize)
798 return S_FALSE;
799 CopyBlock(rep0, len);
800 }
801 _reps[0] = rep0;
802 _reps[1] = rep1;
803 _reps[2] = rep2;
804 _reps[3] = rep3;
805 _lastLength = len;
806
807 return S_OK;
808 }
809
810
CodeReal(ICompressProgressInfo * progress)811 HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
812 {
813 _writtenFileSize = 0;
814 _unsupportedFilter = false;
815
816 if (!_isSolid)
817 {
818 _lzSize = 0;
819 _winPos = 0;
820 _wrPtr = 0;
821 for (unsigned i = 0; i < kNumReps; i++)
822 _reps[i] = 0;
823 _lastLength = 0;
824 memset(m_LastLevels, 0, kTablesSizesSum);
825 TablesRead = false;
826 PpmEscChar = 2;
827 PpmError = true;
828 InitFilters();
829 // _errorMode = false;
830 }
831
832 /*
833 if (_errorMode)
834 return S_FALSE;
835 */
836
837 if (!_isSolid || !TablesRead)
838 {
839 bool keepDecompressing;
840 RINOK(ReadTables(keepDecompressing))
841 if (!keepDecompressing)
842 {
843 _solidAllowed = true;
844 return S_OK;
845 }
846 }
847
848 for (;;)
849 {
850 bool keepDecompressing;
851 if (_lzMode)
852 {
853 if (!TablesOK)
854 return S_FALSE;
855 RINOK(DecodeLZ(keepDecompressing))
856 }
857 else
858 {
859 RINOK(DecodePPM(1 << 18, keepDecompressing))
860 }
861
862 if (InputEofError())
863 return S_FALSE;
864
865 const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
866 RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
867 if (!keepDecompressing)
868 break;
869 }
870
871 _solidAllowed = true;
872
873 RINOK(WriteBuf())
874 const UInt64 packSize = m_InBitStream.BitDecoder.GetProcessedSize();
875 RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize))
876 if (_writtenFileSize < _unpackSize)
877 return S_FALSE;
878
879 if (_unsupportedFilter)
880 return E_NOTIMPL;
881
882 return S_OK;
883 }
884
Z7_COM7F_IMF(CDecoder::Code (ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress))885 Z7_COM7F_IMF(CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
886 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress))
887 {
888 try
889 {
890 if (!inSize)
891 return E_INVALIDARG;
892
893 if (_isSolid && !_solidAllowed)
894 return S_FALSE;
895 _solidAllowed = false;
896
897 if (!_vmData)
898 {
899 _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);
900 if (!_vmData)
901 return E_OUTOFMEMORY;
902 _vmCode = _vmData + kVmDataSizeMax;
903 }
904
905 if (!_window)
906 {
907 _window = (Byte *)::MidAlloc(kWindowSize);
908 if (!_window)
909 return E_OUTOFMEMORY;
910 }
911 if (!m_InBitStream.BitDecoder.Create(1 << 20))
912 return E_OUTOFMEMORY;
913 if (!_vm.Create())
914 return E_OUTOFMEMORY;
915
916
917 m_InBitStream.BitDecoder.SetStream(inStream);
918 m_InBitStream.BitDecoder.Init();
919 _outStream = outStream;
920
921 // CCoderReleaser coderReleaser(this);
922 _unpackSize = outSize ? *outSize : (UInt64)(Int64)-1;
923 return CodeReal(progress);
924 }
925 catch(const CInBufferException &e) { /* _errorMode = true; */ return e.ErrorCode; }
926 catch(...) { /* _errorMode = true; */ return S_FALSE; }
927 // CNewException is possible here. But probably CNewException is caused
928 // by error in data stream.
929 }
930
Z7_COM7F_IMF(CDecoder::SetDecoderProperties2 (const Byte * data,UInt32 size))931 Z7_COM7F_IMF(CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size))
932 {
933 if (size < 1)
934 return E_INVALIDARG;
935 _isSolid = ((data[0] & 1) != 0);
936 return S_OK;
937 }
938
939 }}
940