Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/Rar3Decoder.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // Rar3Decoder.cpp2 // According to unRAR license, this code may not be used to develop3 // a program that creates RAR archives5 #include "StdAfx.h"7 #include "../Common/StreamUtils.h"9 #include "Rar3Decoder.h"11 namespace NCompress {12 namespace NRar3 {14 static const UInt32 kNumAlignReps = 15;16 static const UInt32 kSymbolReadTable = 256;17 static const UInt32 kSymbolRep = 259;18 static const UInt32 kSymbolLen2 = kSymbolRep + kNumReps;20 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};21 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};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};28 static const Byte kLevelDirectBits[kLevelTableSize] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};30 static const Byte kLen2DistStarts[kNumLen2Symbols]={0,4,8,16,32,64,128,192};31 static const Byte kLen2DistDirectBits[kNumLen2Symbols]={2,2,3, 4, 5, 6, 6, 6};33 static const UInt32 kDistLimit3 = 0x2000 - 2;34 static const UInt32 kDistLimit4 = 0x40000 - 2;36 static const UInt32 kNormalMatchMinLen = 3;38 static const UInt32 kVmDataSizeMax = 1 << 16;39 static const UInt32 kVmCodeSizeMax = 1 << 16;41 CDecoder::CDecoder():42 _window(0),43 _winPos(0),44 _wrPtr(0),45 _lzSize(0),46 _writtenFileSize(0),47 _vmData(0),48 _vmCode(0),49 m_IsSolid(false)50 {51 }53 CDecoder::~CDecoder()54 {55 InitFilters();56 ::MidFree(_vmData);57 ::MidFree(_window);58 }60 HRESULT CDecoder::WriteDataToStream(const Byte *data, UInt32 size)61 {62 return WriteStream(_outStream, data, size);63 }65 HRESULT CDecoder::WriteData(const Byte *data, UInt32 size)66 {67 HRESULT res = S_OK;68 if (_writtenFileSize < _unpackSize)69 {70 UInt32 curSize = size;71 UInt64 remain = _unpackSize - _writtenFileSize;72 if (remain < curSize)73 curSize = (UInt32)remain;74 res = WriteDataToStream(data, curSize);75 }76 _writtenFileSize += size;77 return res;78 }80 HRESULT CDecoder::WriteArea(UInt32 startPtr, UInt32 endPtr)81 {82 if (startPtr <= endPtr)83 return WriteData(_window + startPtr, endPtr - startPtr);84 RINOK(WriteData(_window + startPtr, kWindowSize - startPtr));85 return WriteData(_window, endPtr);86 }88 void CDecoder::ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef)89 {90 CTempFilter *tempFilter = _tempFilters[tempFilterIndex];91 tempFilter->InitR[6] = (UInt32)_writtenFileSize;92 NVm::SetValue32(&tempFilter->GlobalData[0x24], (UInt32)_writtenFileSize);93 NVm::SetValue32(&tempFilter->GlobalData[0x28], (UInt32)(_writtenFileSize >> 32));94 CFilter *filter = _filters[tempFilter->FilterIndex];95 _vm.Execute(filter, tempFilter, outBlockRef, filter->GlobalData);96 delete tempFilter;97 _tempFilters[tempFilterIndex] = 0;98 }100 HRESULT CDecoder::WriteBuf()101 {102 UInt32 writtenBorder = _wrPtr;103 UInt32 writeSize = (_winPos - writtenBorder) & kWindowMask;104 for (int i = 0; i < _tempFilters.Size(); i++)105 {106 CTempFilter *filter = _tempFilters[i];107 if (filter == NULL)108 continue;109 if (filter->NextWindow)110 {111 filter->NextWindow = false;112 continue;113 }114 UInt32 blockStart = filter->BlockStart;115 UInt32 blockSize = filter->BlockSize;116 if (((blockStart - writtenBorder) & kWindowMask) < writeSize)117 {118 if (writtenBorder != blockStart)119 {120 RINOK(WriteArea(writtenBorder, blockStart));121 writtenBorder = blockStart;122 writeSize = (_winPos - writtenBorder) & kWindowMask;123 }124 if (blockSize <= writeSize)125 {126 UInt32 blockEnd = (blockStart + blockSize) & kWindowMask;127 if (blockStart < blockEnd || blockEnd == 0)128 _vm.SetMemory(0, _window + blockStart, blockSize);129 else130 {131 UInt32 tailSize = kWindowSize - blockStart;132 _vm.SetMemory(0, _window + blockStart, tailSize);133 _vm.SetMemory(tailSize, _window, blockEnd);134 }135 NVm::CBlockRef outBlockRef;136 ExecuteFilter(i, outBlockRef);137 while (i + 1 < _tempFilters.Size())138 {139 CTempFilter *nextFilter = _tempFilters[i + 1];140 if (nextFilter == NULL || nextFilter->BlockStart != blockStart ||141 nextFilter->BlockSize != outBlockRef.Size || nextFilter->NextWindow)142 break;143 _vm.SetMemory(0, _vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);144 ExecuteFilter(++i, outBlockRef);145 }146 WriteDataToStream(_vm.GetDataPointer(outBlockRef.Offset), outBlockRef.Size);147 _writtenFileSize += outBlockRef.Size;148 writtenBorder = blockEnd;149 writeSize = (_winPos - writtenBorder) & kWindowMask;150 }151 else152 {153 for (int j = i; j < _tempFilters.Size(); j++)154 {155 CTempFilter *filter = _tempFilters[j];156 if (filter != NULL && filter->NextWindow)157 filter->NextWindow = false;158 }159 _wrPtr = writtenBorder;160 return S_OK; // check it161 }162 }163 }165 _wrPtr = _winPos;166 return WriteArea(writtenBorder, _winPos);167 }169 void CDecoder::InitFilters()170 {171 _lastFilter = 0;172 int i;173 for (i = 0; i < _tempFilters.Size(); i++)174 delete _tempFilters[i];175 _tempFilters.Clear();176 for (i = 0; i < _filters.Size(); i++)177 delete _filters[i];178 _filters.Clear();179 }181 bool CDecoder::AddVmCode(UInt32 firstByte, UInt32 codeSize)182 {183 CMemBitDecoder inp;184 inp.Init(_vmData, codeSize);186 UInt32 filterIndex;187 if (firstByte & 0x80)188 {189 filterIndex = NVm::ReadEncodedUInt32(inp);190 if (filterIndex == 0)191 InitFilters();192 else193 filterIndex--;194 }195 else196 filterIndex = _lastFilter;197 if (filterIndex > (UInt32)_filters.Size())198 return false;199 _lastFilter = filterIndex;200 bool newFilter = (filterIndex == (UInt32)_filters.Size());202 CFilter *filter;203 if (newFilter)204 {205 // check if too many filters206 if (filterIndex > 1024)207 return false;208 filter = new CFilter;209 _filters.Add(filter);210 }211 else212 {213 filter = _filters[filterIndex];214 filter->ExecCount++;215 }217 int numEmptyItems = 0;218 int i;219 for (i = 0; i < _tempFilters.Size(); i++)220 {221 _tempFilters[i - numEmptyItems] = _tempFilters[i];222 if (_tempFilters[i] == NULL)223 numEmptyItems++;224 if (numEmptyItems > 0)225 _tempFilters[i] = NULL;226 }227 if (numEmptyItems == 0)228 {229 _tempFilters.Add(NULL);230 numEmptyItems = 1;231 }232 CTempFilter *tempFilter = new CTempFilter;233 _tempFilters[_tempFilters.Size() - numEmptyItems] = tempFilter;234 tempFilter->FilterIndex = filterIndex;235 tempFilter->ExecCount = filter->ExecCount;237 UInt32 blockStart = NVm::ReadEncodedUInt32(inp);238 if (firstByte & 0x40)239 blockStart += 258;240 tempFilter->BlockStart = (blockStart + _winPos) & kWindowMask;241 if (firstByte & 0x20)242 filter->BlockSize = NVm::ReadEncodedUInt32(inp);243 tempFilter->BlockSize = filter->BlockSize;244 tempFilter->NextWindow = _wrPtr != _winPos && ((_wrPtr - _winPos) & kWindowMask) <= blockStart;246 memset(tempFilter->InitR, 0, sizeof(tempFilter->InitR));247 tempFilter->InitR[3] = NVm::kGlobalOffset;248 tempFilter->InitR[4] = tempFilter->BlockSize;249 tempFilter->InitR[5] = tempFilter->ExecCount;250 if (firstByte & 0x10)251 {252 UInt32 initMask = inp.ReadBits(NVm::kNumGpRegs);253 for (int i = 0; i < NVm::kNumGpRegs; i++)254 if (initMask & (1 << i))255 tempFilter->InitR[i] = NVm::ReadEncodedUInt32(inp);256 }257 if (newFilter)258 {259 UInt32 vmCodeSize = NVm::ReadEncodedUInt32(inp);260 if (vmCodeSize >= kVmCodeSizeMax || vmCodeSize == 0)261 return false;262 for (UInt32 i = 0; i < vmCodeSize; i++)263 _vmCode[i] = (Byte)inp.ReadBits(8);264 _vm.PrepareProgram(_vmCode, vmCodeSize, filter);265 }267 tempFilter->AllocateEmptyFixedGlobal();269 Byte *globalData = &tempFilter->GlobalData[0];270 for (i = 0; i < NVm::kNumGpRegs; i++)271 NVm::SetValue32(&globalData[i * 4], tempFilter->InitR[i]);272 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockSize], tempFilter->BlockSize);273 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kBlockPos], 0); // It was commented. why?274 NVm::SetValue32(&globalData[NVm::NGlobalOffset::kExecCount], tempFilter->ExecCount);276 if (firstByte & 8)277 {278 UInt32 dataSize = NVm::ReadEncodedUInt32(inp);279 if (dataSize > NVm::kGlobalSize - NVm::kFixedGlobalSize)280 return false;281 CRecordVector<Byte> &globalData = tempFilter->GlobalData;282 int requredSize = (int)(dataSize + NVm::kFixedGlobalSize);283 if (globalData.Size() < requredSize)284 {285 globalData.Reserve(requredSize);286 for (; globalData.Size() < requredSize; i++)287 globalData.Add(0);288 }289 for (UInt32 i = 0; i < dataSize; i++)290 globalData[NVm::kFixedGlobalSize + i] = (Byte)inp.ReadBits(8);291 }292 return true;293 }295 bool CDecoder::ReadVmCodeLZ()296 {297 UInt32 firstByte = m_InBitStream.ReadBits(8);298 UInt32 length = (firstByte & 7) + 1;299 if (length == 7)300 length = m_InBitStream.ReadBits(8) + 7;301 else if (length == 8)302 length = m_InBitStream.ReadBits(16);303 if (length > kVmDataSizeMax)304 return false;305 for (UInt32 i = 0; i < length; i++)306 _vmData[i] = (Byte)m_InBitStream.ReadBits(8);307 return AddVmCode(firstByte, length);308 }310 bool CDecoder::ReadVmCodePPM()311 {312 int firstByte = DecodePpmSymbol();313 if (firstByte == -1)314 return false;315 UInt32 length = (firstByte & 7) + 1;316 if (length == 7)317 {318 int b1 = DecodePpmSymbol();319 if (b1 == -1)320 return false;321 length = b1 + 7;322 }323 else if (length == 8)324 {325 int b1 = DecodePpmSymbol();326 if (b1 == -1)327 return false;328 int b2 = DecodePpmSymbol();329 if (b2 == -1)330 return false;331 length = b1 * 256 + b2;332 }333 if (length > kVmDataSizeMax)334 return false;335 for (UInt32 i = 0; i < length; i++)336 {337 int b = DecodePpmSymbol();338 if (b == -1)339 return false;340 _vmData[i] = (Byte)b;341 }342 return AddVmCode(firstByte, length);343 }345 #define RIF(x) { if (!(x)) return S_FALSE; }347 UInt32 CDecoder::ReadBits(int numBits) { return m_InBitStream.ReadBits(numBits); }349 /////////////////////////////////////////////////350 // PPM352 HRESULT CDecoder::InitPPM()353 {354 Byte maxOrder = (Byte)ReadBits(7);356 bool reset = ((maxOrder & 0x20) != 0);357 int maxMB = 0;358 if (reset)359 maxMB = (Byte)ReadBits(8);360 else361 {362 if (_ppm.SubAllocator.GetSubAllocatorSize()== 0)363 return S_FALSE;364 }365 if (maxOrder & 0x40)366 PpmEscChar = (Byte)ReadBits(8);367 m_InBitStream.InitRangeCoder();368 /*369 if (m_InBitStream.m_BitPos != 0)370 return S_FALSE;371 */372 if (reset)373 {374 maxOrder = (maxOrder & 0x1F) + 1;375 if (maxOrder > 16)376 maxOrder = 16 + (maxOrder - 16) * 3;377 if (maxOrder == 1)378 {379 // SubAlloc.StopSubAllocator();380 _ppm.SubAllocator.StopSubAllocator();381 return S_FALSE;382 }383 // SubAlloc.StartSubAllocator(MaxMB+1);384 // StartModelRare(maxOrder);386 if (!_ppm.SubAllocator.StartSubAllocator((maxMB + 1) << 20))387 return E_OUTOFMEMORY;388 _ppm.MaxOrder = 0;389 _ppm.StartModelRare(maxOrder);391 }392 // return (minContext != NULL);394 return S_OK;395 }397 int CDecoder::DecodePpmSymbol() { return _ppm.DecodeSymbol(&m_InBitStream); }399 HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)400 {401 keepDecompressing = false;402 do403 {404 if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)405 {406 RINOK(WriteBuf());407 if (_writtenFileSize > _unpackSize)408 {409 keepDecompressing = false;410 return S_OK;411 }412 }413 int c = DecodePpmSymbol();414 if (c == -1)415 {416 // Original code sets PPMError=true here and then it returns S_OK. Why ???417 // return S_OK;418 return S_FALSE;419 }420 if (c == PpmEscChar)421 {422 int nextCh = DecodePpmSymbol();423 if (nextCh == 0)424 return ReadTables(keepDecompressing);425 if (nextCh == 2 || nextCh == -1)426 return S_OK;427 if (nextCh == 3)428 {429 if (!ReadVmCodePPM())430 return S_FALSE;431 continue;432 }433 if (nextCh == 4 || nextCh == 5)434 {435 UInt32 distance = 0;436 UInt32 length = 4;437 if (nextCh == 4)438 {439 for (int i = 0; i < 3; i++)440 {441 int c = DecodePpmSymbol();442 if (c == -1)443 return S_OK;444 distance = (distance << 8) + (Byte)c;445 }446 distance++;447 length += 28;448 }449 int c = DecodePpmSymbol();450 if (c == -1)451 return S_OK;452 length += c;453 if (distance >= _lzSize)454 return S_FALSE;455 CopyBlock(distance, length);456 num -= (Int32)length;457 continue;458 }459 }460 PutByte((Byte)c);461 num--;462 }463 while (num >= 0);464 keepDecompressing = true;465 return S_OK;466 }468 /////////////////////////////////////////////////469 // LZ471 HRESULT CDecoder::ReadTables(bool &keepDecompressing)472 {473 keepDecompressing = true;474 ReadBits((8 - m_InBitStream.GetBitPosition()) & 7);475 if (ReadBits(1) != 0)476 {477 _lzMode = false;478 return InitPPM();479 }481 _lzMode = true;482 PrevAlignBits = 0;483 PrevAlignCount = 0;485 Byte levelLevels[kLevelTableSize];486 Byte newLevels[kTablesSizesSum];488 if (ReadBits(1) == 0)489 memset(m_LastLevels, 0, kTablesSizesSum);491 int i;492 for (i = 0; i < kLevelTableSize; i++)493 {494 UInt32 length = ReadBits(4);495 if (length == 15)496 {497 UInt32 zeroCount = ReadBits(4);498 if (zeroCount != 0)499 {500 zeroCount += 2;501 while (zeroCount-- > 0 && i < kLevelTableSize)502 levelLevels[i++]=0;503 i--;504 continue;505 }506 }507 levelLevels[i] = (Byte)length;508 }509 RIF(m_LevelDecoder.SetCodeLengths(levelLevels));510 i = 0;511 while (i < kTablesSizesSum)512 {513 UInt32 number = m_LevelDecoder.DecodeSymbol(&m_InBitStream);514 if (number < 16)515 {516 newLevels[i] = Byte((number + m_LastLevels[i]) & 15);517 i++;518 }519 else if (number > kLevelTableSize)520 return S_FALSE;521 else522 {523 int num;524 if (((number - 16) & 1) == 0)525 num = ReadBits(3) + 3;526 else527 num = ReadBits(7) + 11;528 if (number < 18)529 {530 if (i == 0)531 return S_FALSE;532 for (; num > 0 && i < kTablesSizesSum; num--, i++)533 newLevels[i] = newLevels[i - 1];534 }535 else536 {537 for (; num > 0 && i < kTablesSizesSum; num--)538 newLevels[i++] = 0;539 }540 }541 }542 TablesRead = true;544 // original code has check here:545 /*546 if (InAddr > ReadTop)547 {548 keepDecompressing = false;549 return true;550 }551 */553 RIF(m_MainDecoder.SetCodeLengths(&newLevels[0]));554 RIF(m_DistDecoder.SetCodeLengths(&newLevels[kMainTableSize]));555 RIF(m_AlignDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize]));556 RIF(m_LenDecoder.SetCodeLengths(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize]));558 memcpy(m_LastLevels, newLevels, kTablesSizesSum);559 return S_OK;560 }562 class CCoderReleaser563 {564 CDecoder *m_Coder;565 public:566 CCoderReleaser(CDecoder *coder): m_Coder(coder) {}567 ~CCoderReleaser()568 {569 // m_Coder->m_OutWindowStream.Flush();570 m_Coder->ReleaseStreams();571 }572 };574 HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)575 {576 if (ReadBits(1) != 0)577 {578 // old file579 TablesRead = false;580 return ReadTables(keepDecompressing);581 }582 // new file583 keepDecompressing = false;584 TablesRead = (ReadBits(1) == 0);585 return S_OK;586 }588 UInt32 kDistStart[kDistTableSize];590 class CDistInit591 {592 public:593 CDistInit() { Init(); }594 void Init()595 {596 UInt32 start = 0;597 for (UInt32 i = 0; i < kDistTableSize; i++)598 {599 kDistStart[i] = start;600 start += (1 << kDistDirectBits[i]);601 }602 }603 } g_DistInit;605 HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)606 {607 UInt32 rep0 = _reps[0];608 UInt32 rep1 = _reps[1];609 UInt32 rep2 = _reps[2];610 UInt32 rep3 = _reps[3];611 UInt32 length = _lastLength;612 for (;;)613 {614 if (((_wrPtr - _winPos) & kWindowMask) < 260 && _wrPtr != _winPos)615 {616 RINOK(WriteBuf());617 if (_writtenFileSize > _unpackSize)618 {619 keepDecompressing = false;620 return S_OK;621 }622 }623 UInt32 number = m_MainDecoder.DecodeSymbol(&m_InBitStream);624 if (number < 256)625 {626 PutByte(Byte(number));628 continue;629 }630 else if (number == kSymbolReadTable)631 {632 RINOK(ReadEndOfBlock(keepDecompressing));633 break;634 }635 else if (number == 257)636 {637 if (!ReadVmCodeLZ())638 return S_FALSE;639 continue;640 }641 else if (number == 258)642 {643 }644 else if (number < kSymbolRep + 4)645 {646 if (number != kSymbolRep)647 {648 UInt32 distance;649 if (number == kSymbolRep + 1)650 distance = rep1;651 else652 {653 if (number == kSymbolRep + 2)654 distance = rep2;655 else656 {657 distance = rep3;658 rep3 = rep2;659 }660 rep2 = rep1;661 }662 rep1 = rep0;663 rep0 = distance;664 }666 UInt32 number = m_LenDecoder.DecodeSymbol(&m_InBitStream);667 if (number >= kLenTableSize)668 return S_FALSE;669 length = 2 + kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);670 }671 else672 {673 rep3 = rep2;674 rep2 = rep1;675 rep1 = rep0;676 if (number < 271)677 {678 number -= 263;679 rep0 = kLen2DistStarts[number] + m_InBitStream.ReadBits(kLen2DistDirectBits[number]);680 length = 2;681 }682 else if (number < 299)683 {684 number -= 271;685 length = kNormalMatchMinLen + (UInt32)kLenStart[number] + m_InBitStream.ReadBits(kLenDirectBits[number]);686 UInt32 number = m_DistDecoder.DecodeSymbol(&m_InBitStream);687 if (number >= kDistTableSize)688 return S_FALSE;689 rep0 = kDistStart[number];690 int numBits = kDistDirectBits[number];691 if (number >= (kNumAlignBits * 2) + 2)692 {693 if (numBits > kNumAlignBits)694 rep0 += (m_InBitStream.ReadBits(numBits - kNumAlignBits) << kNumAlignBits);695 if (PrevAlignCount > 0)696 {697 PrevAlignCount--;698 rep0 += PrevAlignBits;699 }700 else701 {702 UInt32 number = m_AlignDecoder.DecodeSymbol(&m_InBitStream);703 if (number < (1 << kNumAlignBits))704 {705 rep0 += number;706 PrevAlignBits = number;707 }708 else if (number == (1 << kNumAlignBits))709 {710 PrevAlignCount = kNumAlignReps;711 rep0 += PrevAlignBits;712 }713 else714 return S_FALSE;715 }716 }717 else718 rep0 += m_InBitStream.ReadBits(numBits);719 length += ((kDistLimit4 - rep0) >> 31) + ((kDistLimit3 - rep0) >> 31);720 }721 else722 return S_FALSE;723 }724 if (rep0 >= _lzSize)725 return S_FALSE;726 CopyBlock(rep0, length);727 }728 _reps[0] = rep0;729 _reps[1] = rep1;730 _reps[2] = rep2;731 _reps[3] = rep3;732 _lastLength = length;734 return S_OK;735 }737 HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)738 {739 _writtenFileSize = 0;740 if (!m_IsSolid)741 {742 _lzSize = 0;743 _winPos = 0;744 _wrPtr = 0;745 for (int i = 0; i < kNumReps; i++)746 _reps[i] = 0;747 _lastLength = 0;748 memset(m_LastLevels, 0, kTablesSizesSum);749 TablesRead = false;750 PpmEscChar = 2;751 InitFilters();752 }753 if (!m_IsSolid || !TablesRead)754 {755 bool keepDecompressing;756 RINOK(ReadTables(keepDecompressing));757 if (!keepDecompressing)758 return S_OK;759 }761 for(;;)762 {763 bool keepDecompressing;764 if (_lzMode)765 {766 RINOK(DecodeLZ(keepDecompressing))767 }768 else769 {770 RINOK(DecodePPM(1 << 18, keepDecompressing))771 }772 UInt64 packSize = m_InBitStream.GetProcessedSize();773 RINOK(progress->SetRatioInfo(&packSize, &_writtenFileSize));774 if (!keepDecompressing)775 break;776 }777 RINOK(WriteBuf());778 if (_writtenFileSize < _unpackSize)779 return S_FALSE;780 // return m_OutWindowStream.Flush();781 return S_OK;782 }784 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,785 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)786 {787 try788 {789 if (inSize == NULL || outSize == NULL)790 return E_INVALIDARG;792 if (_vmData == 0)793 {794 _vmData = (Byte *)::MidAlloc(kVmDataSizeMax + kVmCodeSizeMax);795 if (_vmData == 0)796 return E_OUTOFMEMORY;797 _vmCode = _vmData + kVmDataSizeMax;798 }800 if (_window == 0)801 {802 _window = (Byte *)::MidAlloc(kWindowSize);803 if (_window == 0)804 return E_OUTOFMEMORY;805 }806 if (!m_InBitStream.Create(1 << 20))807 return E_OUTOFMEMORY;808 if (!_vm.Create())809 return E_OUTOFMEMORY;812 m_InBitStream.SetStream(inStream);813 m_InBitStream.Init();814 _outStream = outStream;816 CCoderReleaser coderReleaser(this);817 _unpackSize = *outSize;818 return CodeReal(progress);819 }820 catch(const CInBufferException &e) { return e.ErrorCode; }821 catch(...) { return S_FALSE; }822 // CNewException is possible here. But probably CNewException is caused823 // by error in data stream.824 }826 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)827 {828 if (size < 1)829 return E_INVALIDARG;830 m_IsSolid = (data[0] != 0);831 return S_OK;832 }834 }}