Mercurial > vba-linux
view src/win32/7zip/7z/CPP/7zip/Compress/BZip2Decoder.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 // BZip2Decoder.cpp3 #include "StdAfx.h"5 extern "C"6 {7 #include "../../../C/Alloc.h"8 }10 #include "../../Common/Defs.h"12 #include "BZip2Crc.h"13 #include "BZip2Decoder.h"14 #include "Mtf8.h"16 namespace NCompress {17 namespace NBZip2 {19 #define NO_INLINE MY_FAST_CALL21 const UInt32 kNumThreadsMax = 4;23 static const UInt32 kBufferSize = (1 << 17);25 static Int16 kRandNums[512] = {26 619, 720, 127, 481, 931, 816, 813, 233, 566, 247,27 985, 724, 205, 454, 863, 491, 741, 242, 949, 214,28 733, 859, 335, 708, 621, 574, 73, 654, 730, 472,29 419, 436, 278, 496, 867, 210, 399, 680, 480, 51,30 878, 465, 811, 169, 869, 675, 611, 697, 867, 561,31 862, 687, 507, 283, 482, 129, 807, 591, 733, 623,32 150, 238, 59, 379, 684, 877, 625, 169, 643, 105,33 170, 607, 520, 932, 727, 476, 693, 425, 174, 647,34 73, 122, 335, 530, 442, 853, 695, 249, 445, 515,35 909, 545, 703, 919, 874, 474, 882, 500, 594, 612,36 641, 801, 220, 162, 819, 984, 589, 513, 495, 799,37 161, 604, 958, 533, 221, 400, 386, 867, 600, 782,38 382, 596, 414, 171, 516, 375, 682, 485, 911, 276,39 98, 553, 163, 354, 666, 933, 424, 341, 533, 870,40 227, 730, 475, 186, 263, 647, 537, 686, 600, 224,41 469, 68, 770, 919, 190, 373, 294, 822, 808, 206,42 184, 943, 795, 384, 383, 461, 404, 758, 839, 887,43 715, 67, 618, 276, 204, 918, 873, 777, 604, 560,44 951, 160, 578, 722, 79, 804, 96, 409, 713, 940,45 652, 934, 970, 447, 318, 353, 859, 672, 112, 785,46 645, 863, 803, 350, 139, 93, 354, 99, 820, 908,47 609, 772, 154, 274, 580, 184, 79, 626, 630, 742,48 653, 282, 762, 623, 680, 81, 927, 626, 789, 125,49 411, 521, 938, 300, 821, 78, 343, 175, 128, 250,50 170, 774, 972, 275, 999, 639, 495, 78, 352, 126,51 857, 956, 358, 619, 580, 124, 737, 594, 701, 612,52 669, 112, 134, 694, 363, 992, 809, 743, 168, 974,53 944, 375, 748, 52, 600, 747, 642, 182, 862, 81,54 344, 805, 988, 739, 511, 655, 814, 334, 249, 515,55 897, 955, 664, 981, 649, 113, 974, 459, 893, 228,56 433, 837, 553, 268, 926, 240, 102, 654, 459, 51,57 686, 754, 806, 760, 493, 403, 415, 394, 687, 700,58 946, 670, 656, 610, 738, 392, 760, 799, 887, 653,59 978, 321, 576, 617, 626, 502, 894, 679, 243, 440,60 680, 879, 194, 572, 640, 724, 926, 56, 204, 700,61 707, 151, 457, 449, 797, 195, 791, 558, 945, 679,62 297, 59, 87, 824, 713, 663, 412, 693, 342, 606,63 134, 108, 571, 364, 631, 212, 174, 643, 304, 329,64 343, 97, 430, 751, 497, 314, 983, 374, 822, 928,65 140, 206, 73, 263, 980, 736, 876, 478, 430, 305,66 170, 514, 364, 692, 829, 82, 855, 953, 676, 246,67 369, 970, 294, 750, 807, 827, 150, 790, 288, 923,68 804, 378, 215, 828, 592, 281, 565, 555, 710, 82,69 896, 831, 547, 261, 524, 462, 293, 465, 502, 56,70 661, 821, 976, 991, 658, 869, 905, 758, 745, 193,71 768, 550, 608, 933, 378, 286, 215, 979, 792, 961,72 61, 688, 793, 644, 986, 403, 106, 366, 905, 644,73 372, 567, 466, 434, 645, 210, 389, 550, 919, 135,74 780, 773, 635, 389, 707, 100, 626, 958, 165, 504,75 920, 176, 193, 713, 857, 265, 203, 50, 668, 108,76 645, 990, 626, 197, 510, 357, 358, 850, 858, 364,77 936, 63878 };80 bool CState::Alloc()81 {82 if (Counters == 0)83 Counters = (UInt32 *)BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32));84 return (Counters != 0);85 }87 void CState::Free()88 {89 ::BigFree(Counters);90 Counters = 0;91 }93 UInt32 CDecoder::ReadBits(int numBits) { return m_InStream.ReadBits(numBits); }94 Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); }95 bool CDecoder::ReadBit() { return ReadBits(1) != 0; }97 UInt32 CDecoder::ReadCrc()98 {99 UInt32 crc = 0;100 for (int i = 0; i < 4; i++)101 {102 crc <<= 8;103 crc |= ReadByte();104 }105 return crc;106 }108 UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, int num)109 {110 return m_InStream->ReadBits(num);111 }113 UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream)114 {115 return m_InStream->ReadBits(1);116 }118 static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream,119 UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders,120 UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes)121 {122 *randRes = ReadBit(m_InStream) ? true : false;123 *origPtrRes = ReadBits(m_InStream, kNumOrigBits);125 // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ?126 if (*origPtrRes >= blockSizeMax)127 return S_FALSE;129 CMtf8Decoder mtf;130 mtf.StartInit();132 int numInUse = 0;133 {134 Byte inUse16[16];135 int i;136 for (i = 0; i < 16; i++)137 inUse16[i] = (Byte)ReadBit(m_InStream);138 for (i = 0; i < 256; i++)139 if (inUse16[i >> 4])140 {141 if (ReadBit(m_InStream))142 mtf.Add(numInUse++, (Byte)i);143 }144 if (numInUse == 0)145 return S_FALSE;146 // mtf.Init(numInUse);147 }148 int alphaSize = numInUse + 2;150 int numTables = ReadBits(m_InStream, kNumTablesBits);151 if (numTables < kNumTablesMin || numTables > kNumTablesMax)152 return S_FALSE;154 UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits);155 if (numSelectors < 1 || numSelectors > kNumSelectorsMax)156 return S_FALSE;158 {159 Byte mtfPos[kNumTablesMax];160 int t = 0;161 do162 mtfPos[t] = (Byte)t;163 while(++t < numTables);164 UInt32 i = 0;165 do166 {167 int j = 0;168 while (ReadBit(m_InStream))169 if (++j >= numTables)170 return S_FALSE;171 Byte tmp = mtfPos[j];172 for (;j > 0; j--)173 mtfPos[j] = mtfPos[j - 1];174 m_Selectors[i] = mtfPos[0] = tmp;175 }176 while(++i < numSelectors);177 }179 int t = 0;180 do181 {182 Byte lens[kMaxAlphaSize];183 int len = (int)ReadBits(m_InStream, kNumLevelsBits);184 int i;185 for (i = 0; i < alphaSize; i++)186 {187 for (;;)188 {189 if (len < 1 || len > kMaxHuffmanLen)190 return S_FALSE;191 if (!ReadBit(m_InStream))192 break;193 len += 1 - (int)(ReadBit(m_InStream) << 1);194 }195 lens[i] = (Byte)len;196 }197 for (; i < kMaxAlphaSize; i++)198 lens[i] = 0;199 if(!m_HuffmanDecoders[t].SetCodeLengths(lens))200 return S_FALSE;201 }202 while(++t < numTables);204 {205 for (int i = 0; i < 256; i++)206 CharCounters[i] = 0;207 }209 UInt32 blockSize = 0;210 {211 UInt32 groupIndex = 0;212 UInt32 groupSize = 0;213 CHuffmanDecoder *huffmanDecoder = 0;214 int runPower = 0;215 UInt32 runCounter = 0;217 for (;;)218 {219 if (groupSize == 0)220 {221 if (groupIndex >= numSelectors)222 return S_FALSE;223 groupSize = kGroupSize;224 huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]];225 }226 groupSize--;228 UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream);230 if (nextSym < 2)231 {232 runCounter += ((UInt32)(nextSym + 1) << runPower++);233 if (blockSizeMax - blockSize < runCounter)234 return S_FALSE;235 continue;236 }237 if (runCounter != 0)238 {239 UInt32 b = (UInt32)mtf.GetHead();240 CharCounters[b] += runCounter;241 do242 CharCounters[256 + blockSize++] = b;243 while(--runCounter != 0);244 runPower = 0;245 }246 if (nextSym <= (UInt32)numInUse)247 {248 UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1);249 if (blockSize >= blockSizeMax)250 return S_FALSE;251 CharCounters[b]++;252 CharCounters[256 + blockSize++] = b;253 }254 else if (nextSym == (UInt32)numInUse + 1)255 break;256 else257 return S_FALSE;258 }259 }260 *blockSizeRes = blockSize;261 return (*origPtrRes < blockSize) ? S_OK : S_FALSE;262 }264 void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize)265 {266 {267 UInt32 sum = 0;268 for (UInt32 i = 0; i < 256; i++)269 {270 sum += charCounters[i];271 charCounters[i] = sum - charCounters[i];272 }273 }275 UInt32 *tt = charCounters + 256;276 // Compute the T^(-1) vector277 UInt32 i = 0;278 do279 tt[charCounters[tt[i] & 0xFF]++] |= (i << 8);280 while(++i < blockSize);281 }283 static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)284 {285 CBZip2Crc crc;287 // it's for speed optimization: prefetch & prevByte_init;288 UInt32 tPos = tt[tt[OrigPtr] >> 8];289 unsigned int prevByte = (unsigned int)(tPos & 0xFF);291 int numReps = 0;293 do294 {295 unsigned int b = (unsigned int)(tPos & 0xFF);296 tPos = tt[tPos >> 8];298 if (numReps == kRleModeRepSize)299 {300 for (; b > 0; b--)301 {302 crc.UpdateByte(prevByte);303 m_OutStream.WriteByte((Byte)prevByte);304 }305 numReps = 0;306 continue;307 }308 if (b != prevByte)309 numReps = 0;310 numReps++;311 prevByte = b;312 crc.UpdateByte(b);313 m_OutStream.WriteByte((Byte)b);315 /*316 prevByte = b;317 crc.UpdateByte(b);318 m_OutStream.WriteByte((Byte)b);319 for (; --blockSize != 0;)320 {321 b = (unsigned int)(tPos & 0xFF);322 tPos = tt[tPos >> 8];323 crc.UpdateByte(b);324 m_OutStream.WriteByte((Byte)b);325 if (b != prevByte)326 {327 prevByte = b;328 continue;329 }330 if (--blockSize == 0)331 break;333 b = (unsigned int)(tPos & 0xFF);334 tPos = tt[tPos >> 8];335 crc.UpdateByte(b);336 m_OutStream.WriteByte((Byte)b);337 if (b != prevByte)338 {339 prevByte = b;340 continue;341 }342 if (--blockSize == 0)343 break;345 b = (unsigned int)(tPos & 0xFF);346 tPos = tt[tPos >> 8];347 crc.UpdateByte(b);348 m_OutStream.WriteByte((Byte)b);349 if (b != prevByte)350 {351 prevByte = b;352 continue;353 }354 --blockSize;355 break;356 }357 if (blockSize == 0)358 break;360 b = (unsigned int)(tPos & 0xFF);361 tPos = tt[tPos >> 8];363 for (; b > 0; b--)364 {365 crc.UpdateByte(prevByte);366 m_OutStream.WriteByte((Byte)prevByte);367 }368 */369 }370 while(--blockSize != 0);371 return crc.GetDigest();372 }374 static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream)375 {376 CBZip2Crc crc;378 UInt32 randIndex = 1;379 UInt32 randToGo = kRandNums[0] - 2;381 int numReps = 0;383 // it's for speed optimization: prefetch & prevByte_init;384 UInt32 tPos = tt[tt[OrigPtr] >> 8];385 unsigned int prevByte = (unsigned int)(tPos & 0xFF);387 do388 {389 unsigned int b = (unsigned int)(tPos & 0xFF);390 tPos = tt[tPos >> 8];392 {393 if (randToGo == 0)394 {395 b ^= 1;396 randToGo = kRandNums[randIndex++];397 randIndex &= 0x1FF;398 }399 randToGo--;400 }402 if (numReps == kRleModeRepSize)403 {404 for (; b > 0; b--)405 {406 crc.UpdateByte(prevByte);407 m_OutStream.WriteByte((Byte)prevByte);408 }409 numReps = 0;410 continue;411 }412 if (b != prevByte)413 numReps = 0;414 numReps++;415 prevByte = b;416 crc.UpdateByte(b);417 m_OutStream.WriteByte((Byte)b);418 }419 while(--blockSize != 0);420 return crc.GetDigest();421 }423 #ifdef COMPRESS_BZIP2_MT425 CDecoder::CDecoder():426 m_States(0)427 {428 m_NumThreadsPrev = 0;429 NumThreads = 1;430 }432 CDecoder::~CDecoder()433 {434 Free();435 }437 #define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; }439 HRESULT CDecoder::Create()440 {441 RINOK_THREAD(CanProcessEvent.CreateIfNotCreated());442 RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated());443 if (m_States != 0 && m_NumThreadsPrev == NumThreads)444 return S_OK;445 Free();446 MtMode = (NumThreads > 1);447 m_NumThreadsPrev = NumThreads;448 try449 {450 m_States = new CState[NumThreads];451 if (m_States == 0)452 return E_OUTOFMEMORY;453 }454 catch(...) { return E_OUTOFMEMORY; }455 for (UInt32 t = 0; t < NumThreads; t++)456 {457 CState &ti = m_States[t];458 ti.Decoder = this;459 if (MtMode)460 {461 HRESULT res = ti.Create();462 if (res != S_OK)463 {464 NumThreads = t;465 Free();466 return res;467 }468 }469 }470 return S_OK;471 }473 void CDecoder::Free()474 {475 if (!m_States)476 return;477 CloseThreads = true;478 CanProcessEvent.Set();479 for (UInt32 t = 0; t < NumThreads; t++)480 {481 CState &s = m_States[t];482 if (MtMode)483 s.Thread.Wait();484 s.Free();485 }486 delete []m_States;487 m_States = 0;488 }489 #endif491 HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc)492 {493 wasFinished = false;494 Byte s[6];495 for (int i = 0; i < 6; i++)496 s[i] = ReadByte();497 crc = ReadCrc();498 if (s[0] == kFinSig0)499 {500 if (s[1] != kFinSig1 ||501 s[2] != kFinSig2 ||502 s[3] != kFinSig3 ||503 s[4] != kFinSig4 ||504 s[5] != kFinSig5)505 return S_FALSE;507 wasFinished = true;508 return (crc == CombinedCrc.GetDigest()) ? S_OK : S_FALSE;509 }510 if (s[0] != kBlockSig0 ||511 s[1] != kBlockSig1 ||512 s[2] != kBlockSig2 ||513 s[3] != kBlockSig3 ||514 s[4] != kBlockSig4 ||515 s[5] != kBlockSig5)516 return S_FALSE;517 CombinedCrc.Update(crc);518 return S_OK;519 }521 HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress)522 {523 #ifdef COMPRESS_BZIP2_MT524 Progress = progress;525 RINOK(Create());526 for (UInt32 t = 0; t < NumThreads; t++)527 {528 CState &s = m_States[t];529 if (!s.Alloc())530 return E_OUTOFMEMORY;531 if (MtMode)532 {533 RINOK(s.StreamWasFinishedEvent.Reset());534 RINOK(s.WaitingWasStartedEvent.Reset());535 RINOK(s.CanWriteEvent.Reset());536 }537 }538 #else539 if (!m_States[0].Alloc())540 return E_OUTOFMEMORY;541 #endif543 isBZ = false;544 Byte s[6];545 int i;546 for (i = 0; i < 4; i++)547 s[i] = ReadByte();548 if (s[0] != kArSig0 ||549 s[1] != kArSig1 ||550 s[2] != kArSig2 ||551 s[3] <= kArSig3 ||552 s[3] > kArSig3 + kBlockSizeMultMax)553 return S_OK;554 isBZ = true;555 UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep;557 CombinedCrc.Init();558 #ifdef COMPRESS_BZIP2_MT559 if (MtMode)560 {561 NextBlockIndex = 0;562 StreamWasFinished1 = StreamWasFinished2 = false;563 CloseThreads = false;564 CanStartWaitingEvent.Reset();565 m_States[0].CanWriteEvent.Set();566 BlockSizeMax = dicSize;567 Result1 = Result2 = S_OK;568 CanProcessEvent.Set();569 UInt32 t;570 for (t = 0; t < NumThreads; t++)571 m_States[t].StreamWasFinishedEvent.Lock();572 CanProcessEvent.Reset();573 CanStartWaitingEvent.Set();574 for (t = 0; t < NumThreads; t++)575 m_States[t].WaitingWasStartedEvent.Lock();576 CanStartWaitingEvent.Reset();577 RINOK(Result2);578 RINOK(Result1);579 }580 else581 #endif582 {583 CState &state = m_States[0];584 for (;;)585 {586 if (progress)587 {588 UInt64 packSize = m_InStream.GetProcessedSize();589 UInt64 unpackSize = m_OutStream.GetProcessedSize();590 RINOK(progress->SetRatioInfo(&packSize, &unpackSize));591 }592 bool wasFinished;593 UInt32 crc;594 RINOK(ReadSignatures(wasFinished, crc));595 if (wasFinished)596 return S_OK;598 UInt32 blockSize, origPtr;599 bool randMode;600 RINOK(ReadBlock(&m_InStream, state.Counters, dicSize,601 m_Selectors, m_HuffmanDecoders,602 &blockSize, &origPtr, &randMode));603 DecodeBlock1(state.Counters, blockSize);604 if ((randMode ?605 DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) :606 DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc)607 return S_FALSE;608 }609 }610 return S_OK;611 }613 HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,614 const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)615 {616 if (!m_InStream.Create(kBufferSize))617 return E_OUTOFMEMORY;618 if (!m_OutStream.Create(kBufferSize))619 return E_OUTOFMEMORY;621 m_InStream.SetStream(inStream);622 m_InStream.Init();624 m_OutStream.SetStream(outStream);625 m_OutStream.Init();627 CDecoderFlusher flusher(this);629 bool isBZ;630 RINOK(DecodeFile(isBZ, progress));631 return isBZ ? S_OK: S_FALSE;632 }634 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,635 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)636 {637 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }638 catch(const CInBufferException &e) { return e.ErrorCode; }639 catch(const COutBufferException &e) { return e.ErrorCode; }640 catch(...) { return E_FAIL; }641 }643 STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)644 {645 if (value == NULL)646 return E_INVALIDARG;647 *value = m_InStream.GetProcessedSize();648 return S_OK;649 }651 #ifdef COMPRESS_BZIP2_MT653 static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; }655 HRESULT CState::Create()656 {657 RINOK_THREAD(StreamWasFinishedEvent.CreateIfNotCreated());658 RINOK_THREAD(WaitingWasStartedEvent.CreateIfNotCreated());659 RINOK_THREAD(CanWriteEvent.CreateIfNotCreated());660 RINOK_THREAD(Thread.Create(MFThread, this));661 return S_OK;662 }664 void CState::FinishStream()665 {666 Decoder->StreamWasFinished1 = true;667 StreamWasFinishedEvent.Set();668 Decoder->CS.Leave();669 Decoder->CanStartWaitingEvent.Lock();670 WaitingWasStartedEvent.Set();671 }673 void CState::ThreadFunc()674 {675 for (;;)676 {677 Decoder->CanProcessEvent.Lock();678 Decoder->CS.Enter();679 if (Decoder->CloseThreads)680 {681 Decoder->CS.Leave();682 return;683 }684 if (Decoder->StreamWasFinished1)685 {686 FinishStream();687 continue;688 }689 HRESULT res = S_OK;691 UInt32 blockIndex = Decoder->NextBlockIndex;692 UInt32 nextBlockIndex = blockIndex + 1;693 if (nextBlockIndex == Decoder->NumThreads)694 nextBlockIndex = 0;695 Decoder->NextBlockIndex = nextBlockIndex;696 UInt32 crc;697 UInt64 packSize;698 UInt32 blockSize = 0, origPtr = 0;699 bool randMode = false;701 try702 {703 bool wasFinished;704 res = Decoder->ReadSignatures(wasFinished, crc);705 if (res != S_OK)706 {707 Decoder->Result1 = res;708 FinishStream();709 continue;710 }711 if (wasFinished)712 {713 Decoder->Result1 = res;714 FinishStream();715 continue;716 }718 res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax,719 Decoder->m_Selectors, Decoder->m_HuffmanDecoders,720 &blockSize, &origPtr, &randMode);721 if (res != S_OK)722 {723 Decoder->Result1 = res;724 FinishStream();725 continue;726 }727 packSize = Decoder->m_InStream.GetProcessedSize();728 }729 catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }730 catch(...) { res = E_FAIL; }731 if (res != S_OK)732 {733 Decoder->Result1 = res;734 FinishStream();735 continue;736 }738 Decoder->CS.Leave();740 DecodeBlock1(Counters, blockSize);742 bool needFinish = true;743 try744 {745 Decoder->m_States[blockIndex].CanWriteEvent.Lock();746 needFinish = Decoder->StreamWasFinished2;747 if (!needFinish)748 {749 if ((randMode ?750 DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) :751 DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc)752 {753 if (Decoder->Progress)754 {755 UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize();756 res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize);757 }758 }759 else760 res = S_FALSE;761 }762 }763 catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }764 catch(...) { res = E_FAIL; }765 if (res != S_OK)766 {767 Decoder->Result2 = res;768 Decoder->StreamWasFinished2 = true;769 }770 Decoder->m_States[nextBlockIndex].CanWriteEvent.Set();771 if (res != S_OK || needFinish)772 {773 StreamWasFinishedEvent.Set();774 Decoder->CanStartWaitingEvent.Lock();775 WaitingWasStartedEvent.Set();776 }777 }778 }780 STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads)781 {782 NumThreads = numThreads;783 if (NumThreads < 1)784 NumThreads = 1;785 if (NumThreads > kNumThreadsMax)786 NumThreads = kNumThreadsMax;787 return S_OK;788 }789 #endif791 }}