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