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.cpp
3 #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_CALL
21 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, 638
78 };
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 do
162 mtfPos[t] = (Byte)t;
163 while(++t < numTables);
164 UInt32 i = 0;
165 do
166 {
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 do
181 {
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 do
242 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 else
257 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) vector
277 UInt32 i = 0;
278 do
279 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 do
294 {
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 do
388 {
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_MT
425 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 try
449 {
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 #endif
491 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_MT
524 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 #else
539 if (!m_States[0].Alloc())
540 return E_OUTOFMEMORY;
541 #endif
543 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_MT
559 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 else
581 #endif
582 {
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_MT
653 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 try
702 {
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 try
744 {
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 else
760 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 #endif
791 }}