Mercurial > vba-linux
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Compress/BZip2Decoder.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,791 @@ 1.4 +// BZip2Decoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +extern "C" 1.9 +{ 1.10 +#include "../../../C/Alloc.h" 1.11 +} 1.12 + 1.13 +#include "../../Common/Defs.h" 1.14 + 1.15 +#include "BZip2Crc.h" 1.16 +#include "BZip2Decoder.h" 1.17 +#include "Mtf8.h" 1.18 + 1.19 +namespace NCompress { 1.20 +namespace NBZip2 { 1.21 + 1.22 +#define NO_INLINE MY_FAST_CALL 1.23 + 1.24 +const UInt32 kNumThreadsMax = 4; 1.25 + 1.26 +static const UInt32 kBufferSize = (1 << 17); 1.27 + 1.28 +static Int16 kRandNums[512] = { 1.29 + 619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 1.30 + 985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 1.31 + 733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 1.32 + 419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 1.33 + 878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 1.34 + 862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 1.35 + 150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 1.36 + 170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 1.37 + 73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 1.38 + 909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 1.39 + 641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 1.40 + 161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 1.41 + 382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 1.42 + 98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 1.43 + 227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 1.44 + 469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 1.45 + 184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 1.46 + 715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 1.47 + 951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 1.48 + 652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 1.49 + 645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 1.50 + 609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 1.51 + 653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 1.52 + 411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 1.53 + 170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 1.54 + 857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 1.55 + 669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 1.56 + 944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 1.57 + 344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 1.58 + 897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 1.59 + 433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 1.60 + 686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 1.61 + 946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 1.62 + 978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 1.63 + 680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 1.64 + 707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 1.65 + 297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 1.66 + 134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 1.67 + 343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 1.68 + 140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 1.69 + 170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 1.70 + 369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 1.71 + 804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 1.72 + 896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 1.73 + 661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 1.74 + 768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 1.75 + 61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 1.76 + 372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 1.77 + 780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 1.78 + 920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 1.79 + 645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 1.80 + 936, 638 1.81 +}; 1.82 + 1.83 +bool CState::Alloc() 1.84 +{ 1.85 + if (Counters == 0) 1.86 + Counters = (UInt32 *)BigAlloc((256 + kBlockSizeMax) * sizeof(UInt32)); 1.87 + return (Counters != 0); 1.88 +} 1.89 + 1.90 +void CState::Free() 1.91 +{ 1.92 + ::BigFree(Counters); 1.93 + Counters = 0; 1.94 +} 1.95 + 1.96 +UInt32 CDecoder::ReadBits(int numBits) { return m_InStream.ReadBits(numBits); } 1.97 +Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); } 1.98 +bool CDecoder::ReadBit() { return ReadBits(1) != 0; } 1.99 + 1.100 +UInt32 CDecoder::ReadCrc() 1.101 +{ 1.102 + UInt32 crc = 0; 1.103 + for (int i = 0; i < 4; i++) 1.104 + { 1.105 + crc <<= 8; 1.106 + crc |= ReadByte(); 1.107 + } 1.108 + return crc; 1.109 +} 1.110 + 1.111 +UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, int num) 1.112 +{ 1.113 + return m_InStream->ReadBits(num); 1.114 +} 1.115 + 1.116 +UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream) 1.117 +{ 1.118 + return m_InStream->ReadBits(1); 1.119 +} 1.120 + 1.121 +static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, 1.122 + UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders, 1.123 + UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes) 1.124 +{ 1.125 + *randRes = ReadBit(m_InStream) ? true : false; 1.126 + *origPtrRes = ReadBits(m_InStream, kNumOrigBits); 1.127 + 1.128 + // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? 1.129 + if (*origPtrRes >= blockSizeMax) 1.130 + return S_FALSE; 1.131 + 1.132 + CMtf8Decoder mtf; 1.133 + mtf.StartInit(); 1.134 + 1.135 + int numInUse = 0; 1.136 + { 1.137 + Byte inUse16[16]; 1.138 + int i; 1.139 + for (i = 0; i < 16; i++) 1.140 + inUse16[i] = (Byte)ReadBit(m_InStream); 1.141 + for (i = 0; i < 256; i++) 1.142 + if (inUse16[i >> 4]) 1.143 + { 1.144 + if (ReadBit(m_InStream)) 1.145 + mtf.Add(numInUse++, (Byte)i); 1.146 + } 1.147 + if (numInUse == 0) 1.148 + return S_FALSE; 1.149 + // mtf.Init(numInUse); 1.150 + } 1.151 + int alphaSize = numInUse + 2; 1.152 + 1.153 + int numTables = ReadBits(m_InStream, kNumTablesBits); 1.154 + if (numTables < kNumTablesMin || numTables > kNumTablesMax) 1.155 + return S_FALSE; 1.156 + 1.157 + UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits); 1.158 + if (numSelectors < 1 || numSelectors > kNumSelectorsMax) 1.159 + return S_FALSE; 1.160 + 1.161 + { 1.162 + Byte mtfPos[kNumTablesMax]; 1.163 + int t = 0; 1.164 + do 1.165 + mtfPos[t] = (Byte)t; 1.166 + while(++t < numTables); 1.167 + UInt32 i = 0; 1.168 + do 1.169 + { 1.170 + int j = 0; 1.171 + while (ReadBit(m_InStream)) 1.172 + if (++j >= numTables) 1.173 + return S_FALSE; 1.174 + Byte tmp = mtfPos[j]; 1.175 + for (;j > 0; j--) 1.176 + mtfPos[j] = mtfPos[j - 1]; 1.177 + m_Selectors[i] = mtfPos[0] = tmp; 1.178 + } 1.179 + while(++i < numSelectors); 1.180 + } 1.181 + 1.182 + int t = 0; 1.183 + do 1.184 + { 1.185 + Byte lens[kMaxAlphaSize]; 1.186 + int len = (int)ReadBits(m_InStream, kNumLevelsBits); 1.187 + int i; 1.188 + for (i = 0; i < alphaSize; i++) 1.189 + { 1.190 + for (;;) 1.191 + { 1.192 + if (len < 1 || len > kMaxHuffmanLen) 1.193 + return S_FALSE; 1.194 + if (!ReadBit(m_InStream)) 1.195 + break; 1.196 + len += 1 - (int)(ReadBit(m_InStream) << 1); 1.197 + } 1.198 + lens[i] = (Byte)len; 1.199 + } 1.200 + for (; i < kMaxAlphaSize; i++) 1.201 + lens[i] = 0; 1.202 + if(!m_HuffmanDecoders[t].SetCodeLengths(lens)) 1.203 + return S_FALSE; 1.204 + } 1.205 + while(++t < numTables); 1.206 + 1.207 + { 1.208 + for (int i = 0; i < 256; i++) 1.209 + CharCounters[i] = 0; 1.210 + } 1.211 + 1.212 + UInt32 blockSize = 0; 1.213 + { 1.214 + UInt32 groupIndex = 0; 1.215 + UInt32 groupSize = 0; 1.216 + CHuffmanDecoder *huffmanDecoder = 0; 1.217 + int runPower = 0; 1.218 + UInt32 runCounter = 0; 1.219 + 1.220 + for (;;) 1.221 + { 1.222 + if (groupSize == 0) 1.223 + { 1.224 + if (groupIndex >= numSelectors) 1.225 + return S_FALSE; 1.226 + groupSize = kGroupSize; 1.227 + huffmanDecoder = &m_HuffmanDecoders[m_Selectors[groupIndex++]]; 1.228 + } 1.229 + groupSize--; 1.230 + 1.231 + UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream); 1.232 + 1.233 + if (nextSym < 2) 1.234 + { 1.235 + runCounter += ((UInt32)(nextSym + 1) << runPower++); 1.236 + if (blockSizeMax - blockSize < runCounter) 1.237 + return S_FALSE; 1.238 + continue; 1.239 + } 1.240 + if (runCounter != 0) 1.241 + { 1.242 + UInt32 b = (UInt32)mtf.GetHead(); 1.243 + CharCounters[b] += runCounter; 1.244 + do 1.245 + CharCounters[256 + blockSize++] = b; 1.246 + while(--runCounter != 0); 1.247 + runPower = 0; 1.248 + } 1.249 + if (nextSym <= (UInt32)numInUse) 1.250 + { 1.251 + UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1); 1.252 + if (blockSize >= blockSizeMax) 1.253 + return S_FALSE; 1.254 + CharCounters[b]++; 1.255 + CharCounters[256 + blockSize++] = b; 1.256 + } 1.257 + else if (nextSym == (UInt32)numInUse + 1) 1.258 + break; 1.259 + else 1.260 + return S_FALSE; 1.261 + } 1.262 + } 1.263 + *blockSizeRes = blockSize; 1.264 + return (*origPtrRes < blockSize) ? S_OK : S_FALSE; 1.265 +} 1.266 + 1.267 +void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) 1.268 +{ 1.269 + { 1.270 + UInt32 sum = 0; 1.271 + for (UInt32 i = 0; i < 256; i++) 1.272 + { 1.273 + sum += charCounters[i]; 1.274 + charCounters[i] = sum - charCounters[i]; 1.275 + } 1.276 + } 1.277 + 1.278 + UInt32 *tt = charCounters + 256; 1.279 + // Compute the T^(-1) vector 1.280 + UInt32 i = 0; 1.281 + do 1.282 + tt[charCounters[tt[i] & 0xFF]++] |= (i << 8); 1.283 + while(++i < blockSize); 1.284 +} 1.285 + 1.286 +static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) 1.287 +{ 1.288 + CBZip2Crc crc; 1.289 + 1.290 + // it's for speed optimization: prefetch & prevByte_init; 1.291 + UInt32 tPos = tt[tt[OrigPtr] >> 8]; 1.292 + unsigned int prevByte = (unsigned int)(tPos & 0xFF); 1.293 + 1.294 + int numReps = 0; 1.295 + 1.296 + do 1.297 + { 1.298 + unsigned int b = (unsigned int)(tPos & 0xFF); 1.299 + tPos = tt[tPos >> 8]; 1.300 + 1.301 + if (numReps == kRleModeRepSize) 1.302 + { 1.303 + for (; b > 0; b--) 1.304 + { 1.305 + crc.UpdateByte(prevByte); 1.306 + m_OutStream.WriteByte((Byte)prevByte); 1.307 + } 1.308 + numReps = 0; 1.309 + continue; 1.310 + } 1.311 + if (b != prevByte) 1.312 + numReps = 0; 1.313 + numReps++; 1.314 + prevByte = b; 1.315 + crc.UpdateByte(b); 1.316 + m_OutStream.WriteByte((Byte)b); 1.317 + 1.318 + /* 1.319 + prevByte = b; 1.320 + crc.UpdateByte(b); 1.321 + m_OutStream.WriteByte((Byte)b); 1.322 + for (; --blockSize != 0;) 1.323 + { 1.324 + b = (unsigned int)(tPos & 0xFF); 1.325 + tPos = tt[tPos >> 8]; 1.326 + crc.UpdateByte(b); 1.327 + m_OutStream.WriteByte((Byte)b); 1.328 + if (b != prevByte) 1.329 + { 1.330 + prevByte = b; 1.331 + continue; 1.332 + } 1.333 + if (--blockSize == 0) 1.334 + break; 1.335 + 1.336 + b = (unsigned int)(tPos & 0xFF); 1.337 + tPos = tt[tPos >> 8]; 1.338 + crc.UpdateByte(b); 1.339 + m_OutStream.WriteByte((Byte)b); 1.340 + if (b != prevByte) 1.341 + { 1.342 + prevByte = b; 1.343 + continue; 1.344 + } 1.345 + if (--blockSize == 0) 1.346 + break; 1.347 + 1.348 + b = (unsigned int)(tPos & 0xFF); 1.349 + tPos = tt[tPos >> 8]; 1.350 + crc.UpdateByte(b); 1.351 + m_OutStream.WriteByte((Byte)b); 1.352 + if (b != prevByte) 1.353 + { 1.354 + prevByte = b; 1.355 + continue; 1.356 + } 1.357 + --blockSize; 1.358 + break; 1.359 + } 1.360 + if (blockSize == 0) 1.361 + break; 1.362 + 1.363 + b = (unsigned int)(tPos & 0xFF); 1.364 + tPos = tt[tPos >> 8]; 1.365 + 1.366 + for (; b > 0; b--) 1.367 + { 1.368 + crc.UpdateByte(prevByte); 1.369 + m_OutStream.WriteByte((Byte)prevByte); 1.370 + } 1.371 + */ 1.372 + } 1.373 + while(--blockSize != 0); 1.374 + return crc.GetDigest(); 1.375 +} 1.376 + 1.377 +static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) 1.378 +{ 1.379 + CBZip2Crc crc; 1.380 + 1.381 + UInt32 randIndex = 1; 1.382 + UInt32 randToGo = kRandNums[0] - 2; 1.383 + 1.384 + int numReps = 0; 1.385 + 1.386 + // it's for speed optimization: prefetch & prevByte_init; 1.387 + UInt32 tPos = tt[tt[OrigPtr] >> 8]; 1.388 + unsigned int prevByte = (unsigned int)(tPos & 0xFF); 1.389 + 1.390 + do 1.391 + { 1.392 + unsigned int b = (unsigned int)(tPos & 0xFF); 1.393 + tPos = tt[tPos >> 8]; 1.394 + 1.395 + { 1.396 + if (randToGo == 0) 1.397 + { 1.398 + b ^= 1; 1.399 + randToGo = kRandNums[randIndex++]; 1.400 + randIndex &= 0x1FF; 1.401 + } 1.402 + randToGo--; 1.403 + } 1.404 + 1.405 + if (numReps == kRleModeRepSize) 1.406 + { 1.407 + for (; b > 0; b--) 1.408 + { 1.409 + crc.UpdateByte(prevByte); 1.410 + m_OutStream.WriteByte((Byte)prevByte); 1.411 + } 1.412 + numReps = 0; 1.413 + continue; 1.414 + } 1.415 + if (b != prevByte) 1.416 + numReps = 0; 1.417 + numReps++; 1.418 + prevByte = b; 1.419 + crc.UpdateByte(b); 1.420 + m_OutStream.WriteByte((Byte)b); 1.421 + } 1.422 + while(--blockSize != 0); 1.423 + return crc.GetDigest(); 1.424 +} 1.425 + 1.426 +#ifdef COMPRESS_BZIP2_MT 1.427 + 1.428 +CDecoder::CDecoder(): 1.429 + m_States(0) 1.430 +{ 1.431 + m_NumThreadsPrev = 0; 1.432 + NumThreads = 1; 1.433 +} 1.434 + 1.435 +CDecoder::~CDecoder() 1.436 +{ 1.437 + Free(); 1.438 +} 1.439 + 1.440 +#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } 1.441 + 1.442 +HRESULT CDecoder::Create() 1.443 +{ 1.444 + RINOK_THREAD(CanProcessEvent.CreateIfNotCreated()); 1.445 + RINOK_THREAD(CanStartWaitingEvent.CreateIfNotCreated()); 1.446 + if (m_States != 0 && m_NumThreadsPrev == NumThreads) 1.447 + return S_OK; 1.448 + Free(); 1.449 + MtMode = (NumThreads > 1); 1.450 + m_NumThreadsPrev = NumThreads; 1.451 + try 1.452 + { 1.453 + m_States = new CState[NumThreads]; 1.454 + if (m_States == 0) 1.455 + return E_OUTOFMEMORY; 1.456 + } 1.457 + catch(...) { return E_OUTOFMEMORY; } 1.458 + for (UInt32 t = 0; t < NumThreads; t++) 1.459 + { 1.460 + CState &ti = m_States[t]; 1.461 + ti.Decoder = this; 1.462 + if (MtMode) 1.463 + { 1.464 + HRESULT res = ti.Create(); 1.465 + if (res != S_OK) 1.466 + { 1.467 + NumThreads = t; 1.468 + Free(); 1.469 + return res; 1.470 + } 1.471 + } 1.472 + } 1.473 + return S_OK; 1.474 +} 1.475 + 1.476 +void CDecoder::Free() 1.477 +{ 1.478 + if (!m_States) 1.479 + return; 1.480 + CloseThreads = true; 1.481 + CanProcessEvent.Set(); 1.482 + for (UInt32 t = 0; t < NumThreads; t++) 1.483 + { 1.484 + CState &s = m_States[t]; 1.485 + if (MtMode) 1.486 + s.Thread.Wait(); 1.487 + s.Free(); 1.488 + } 1.489 + delete []m_States; 1.490 + m_States = 0; 1.491 +} 1.492 +#endif 1.493 + 1.494 +HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc) 1.495 +{ 1.496 + wasFinished = false; 1.497 + Byte s[6]; 1.498 + for (int i = 0; i < 6; i++) 1.499 + s[i] = ReadByte(); 1.500 + crc = ReadCrc(); 1.501 + if (s[0] == kFinSig0) 1.502 + { 1.503 + if (s[1] != kFinSig1 || 1.504 + s[2] != kFinSig2 || 1.505 + s[3] != kFinSig3 || 1.506 + s[4] != kFinSig4 || 1.507 + s[5] != kFinSig5) 1.508 + return S_FALSE; 1.509 + 1.510 + wasFinished = true; 1.511 + return (crc == CombinedCrc.GetDigest()) ? S_OK : S_FALSE; 1.512 + } 1.513 + if (s[0] != kBlockSig0 || 1.514 + s[1] != kBlockSig1 || 1.515 + s[2] != kBlockSig2 || 1.516 + s[3] != kBlockSig3 || 1.517 + s[4] != kBlockSig4 || 1.518 + s[5] != kBlockSig5) 1.519 + return S_FALSE; 1.520 + CombinedCrc.Update(crc); 1.521 + return S_OK; 1.522 +} 1.523 + 1.524 +HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) 1.525 +{ 1.526 + #ifdef COMPRESS_BZIP2_MT 1.527 + Progress = progress; 1.528 + RINOK(Create()); 1.529 + for (UInt32 t = 0; t < NumThreads; t++) 1.530 + { 1.531 + CState &s = m_States[t]; 1.532 + if (!s.Alloc()) 1.533 + return E_OUTOFMEMORY; 1.534 + if (MtMode) 1.535 + { 1.536 + RINOK(s.StreamWasFinishedEvent.Reset()); 1.537 + RINOK(s.WaitingWasStartedEvent.Reset()); 1.538 + RINOK(s.CanWriteEvent.Reset()); 1.539 + } 1.540 + } 1.541 + #else 1.542 + if (!m_States[0].Alloc()) 1.543 + return E_OUTOFMEMORY; 1.544 + #endif 1.545 + 1.546 + isBZ = false; 1.547 + Byte s[6]; 1.548 + int i; 1.549 + for (i = 0; i < 4; i++) 1.550 + s[i] = ReadByte(); 1.551 + if (s[0] != kArSig0 || 1.552 + s[1] != kArSig1 || 1.553 + s[2] != kArSig2 || 1.554 + s[3] <= kArSig3 || 1.555 + s[3] > kArSig3 + kBlockSizeMultMax) 1.556 + return S_OK; 1.557 + isBZ = true; 1.558 + UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; 1.559 + 1.560 + CombinedCrc.Init(); 1.561 + #ifdef COMPRESS_BZIP2_MT 1.562 + if (MtMode) 1.563 + { 1.564 + NextBlockIndex = 0; 1.565 + StreamWasFinished1 = StreamWasFinished2 = false; 1.566 + CloseThreads = false; 1.567 + CanStartWaitingEvent.Reset(); 1.568 + m_States[0].CanWriteEvent.Set(); 1.569 + BlockSizeMax = dicSize; 1.570 + Result1 = Result2 = S_OK; 1.571 + CanProcessEvent.Set(); 1.572 + UInt32 t; 1.573 + for (t = 0; t < NumThreads; t++) 1.574 + m_States[t].StreamWasFinishedEvent.Lock(); 1.575 + CanProcessEvent.Reset(); 1.576 + CanStartWaitingEvent.Set(); 1.577 + for (t = 0; t < NumThreads; t++) 1.578 + m_States[t].WaitingWasStartedEvent.Lock(); 1.579 + CanStartWaitingEvent.Reset(); 1.580 + RINOK(Result2); 1.581 + RINOK(Result1); 1.582 + } 1.583 + else 1.584 + #endif 1.585 + { 1.586 + CState &state = m_States[0]; 1.587 + for (;;) 1.588 + { 1.589 + if (progress) 1.590 + { 1.591 + UInt64 packSize = m_InStream.GetProcessedSize(); 1.592 + UInt64 unpackSize = m_OutStream.GetProcessedSize(); 1.593 + RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); 1.594 + } 1.595 + bool wasFinished; 1.596 + UInt32 crc; 1.597 + RINOK(ReadSignatures(wasFinished, crc)); 1.598 + if (wasFinished) 1.599 + return S_OK; 1.600 + 1.601 + UInt32 blockSize, origPtr; 1.602 + bool randMode; 1.603 + RINOK(ReadBlock(&m_InStream, state.Counters, dicSize, 1.604 + m_Selectors, m_HuffmanDecoders, 1.605 + &blockSize, &origPtr, &randMode)); 1.606 + DecodeBlock1(state.Counters, blockSize); 1.607 + if ((randMode ? 1.608 + DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) : 1.609 + DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc) 1.610 + return S_FALSE; 1.611 + } 1.612 + } 1.613 + return S_OK; 1.614 +} 1.615 + 1.616 +HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.617 + const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) 1.618 +{ 1.619 + if (!m_InStream.Create(kBufferSize)) 1.620 + return E_OUTOFMEMORY; 1.621 + if (!m_OutStream.Create(kBufferSize)) 1.622 + return E_OUTOFMEMORY; 1.623 + 1.624 + m_InStream.SetStream(inStream); 1.625 + m_InStream.Init(); 1.626 + 1.627 + m_OutStream.SetStream(outStream); 1.628 + m_OutStream.Init(); 1.629 + 1.630 + CDecoderFlusher flusher(this); 1.631 + 1.632 + bool isBZ; 1.633 + RINOK(DecodeFile(isBZ, progress)); 1.634 + return isBZ ? S_OK: S_FALSE; 1.635 +} 1.636 + 1.637 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, 1.638 + const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress) 1.639 +{ 1.640 + try { return CodeReal(inStream, outStream, inSize, outSize, progress); } 1.641 + catch(const CInBufferException &e) { return e.ErrorCode; } 1.642 + catch(const COutBufferException &e) { return e.ErrorCode; } 1.643 + catch(...) { return E_FAIL; } 1.644 +} 1.645 + 1.646 +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) 1.647 +{ 1.648 + if (value == NULL) 1.649 + return E_INVALIDARG; 1.650 + *value = m_InStream.GetProcessedSize(); 1.651 + return S_OK; 1.652 +} 1.653 + 1.654 +#ifdef COMPRESS_BZIP2_MT 1.655 + 1.656 +static THREAD_FUNC_DECL MFThread(void *p) { ((CState *)p)->ThreadFunc(); return 0; } 1.657 + 1.658 +HRESULT CState::Create() 1.659 +{ 1.660 + RINOK_THREAD(StreamWasFinishedEvent.CreateIfNotCreated()); 1.661 + RINOK_THREAD(WaitingWasStartedEvent.CreateIfNotCreated()); 1.662 + RINOK_THREAD(CanWriteEvent.CreateIfNotCreated()); 1.663 + RINOK_THREAD(Thread.Create(MFThread, this)); 1.664 + return S_OK; 1.665 +} 1.666 + 1.667 +void CState::FinishStream() 1.668 +{ 1.669 + Decoder->StreamWasFinished1 = true; 1.670 + StreamWasFinishedEvent.Set(); 1.671 + Decoder->CS.Leave(); 1.672 + Decoder->CanStartWaitingEvent.Lock(); 1.673 + WaitingWasStartedEvent.Set(); 1.674 +} 1.675 + 1.676 +void CState::ThreadFunc() 1.677 +{ 1.678 + for (;;) 1.679 + { 1.680 + Decoder->CanProcessEvent.Lock(); 1.681 + Decoder->CS.Enter(); 1.682 + if (Decoder->CloseThreads) 1.683 + { 1.684 + Decoder->CS.Leave(); 1.685 + return; 1.686 + } 1.687 + if (Decoder->StreamWasFinished1) 1.688 + { 1.689 + FinishStream(); 1.690 + continue; 1.691 + } 1.692 + HRESULT res = S_OK; 1.693 + 1.694 + UInt32 blockIndex = Decoder->NextBlockIndex; 1.695 + UInt32 nextBlockIndex = blockIndex + 1; 1.696 + if (nextBlockIndex == Decoder->NumThreads) 1.697 + nextBlockIndex = 0; 1.698 + Decoder->NextBlockIndex = nextBlockIndex; 1.699 + UInt32 crc; 1.700 + UInt64 packSize; 1.701 + UInt32 blockSize = 0, origPtr = 0; 1.702 + bool randMode = false; 1.703 + 1.704 + try 1.705 + { 1.706 + bool wasFinished; 1.707 + res = Decoder->ReadSignatures(wasFinished, crc); 1.708 + if (res != S_OK) 1.709 + { 1.710 + Decoder->Result1 = res; 1.711 + FinishStream(); 1.712 + continue; 1.713 + } 1.714 + if (wasFinished) 1.715 + { 1.716 + Decoder->Result1 = res; 1.717 + FinishStream(); 1.718 + continue; 1.719 + } 1.720 + 1.721 + res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax, 1.722 + Decoder->m_Selectors, Decoder->m_HuffmanDecoders, 1.723 + &blockSize, &origPtr, &randMode); 1.724 + if (res != S_OK) 1.725 + { 1.726 + Decoder->Result1 = res; 1.727 + FinishStream(); 1.728 + continue; 1.729 + } 1.730 + packSize = Decoder->m_InStream.GetProcessedSize(); 1.731 + } 1.732 + catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } 1.733 + catch(...) { res = E_FAIL; } 1.734 + if (res != S_OK) 1.735 + { 1.736 + Decoder->Result1 = res; 1.737 + FinishStream(); 1.738 + continue; 1.739 + } 1.740 + 1.741 + Decoder->CS.Leave(); 1.742 + 1.743 + DecodeBlock1(Counters, blockSize); 1.744 + 1.745 + bool needFinish = true; 1.746 + try 1.747 + { 1.748 + Decoder->m_States[blockIndex].CanWriteEvent.Lock(); 1.749 + needFinish = Decoder->StreamWasFinished2; 1.750 + if (!needFinish) 1.751 + { 1.752 + if ((randMode ? 1.753 + DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) : 1.754 + DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc) 1.755 + { 1.756 + if (Decoder->Progress) 1.757 + { 1.758 + UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize(); 1.759 + res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize); 1.760 + } 1.761 + } 1.762 + else 1.763 + res = S_FALSE; 1.764 + } 1.765 + } 1.766 + catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } 1.767 + catch(...) { res = E_FAIL; } 1.768 + if (res != S_OK) 1.769 + { 1.770 + Decoder->Result2 = res; 1.771 + Decoder->StreamWasFinished2 = true; 1.772 + } 1.773 + Decoder->m_States[nextBlockIndex].CanWriteEvent.Set(); 1.774 + if (res != S_OK || needFinish) 1.775 + { 1.776 + StreamWasFinishedEvent.Set(); 1.777 + Decoder->CanStartWaitingEvent.Lock(); 1.778 + WaitingWasStartedEvent.Set(); 1.779 + } 1.780 + } 1.781 +} 1.782 + 1.783 +STDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads) 1.784 +{ 1.785 + NumThreads = numThreads; 1.786 + if (NumThreads < 1) 1.787 + NumThreads = 1; 1.788 + if (NumThreads > kNumThreadsMax) 1.789 + NumThreads = kNumThreadsMax; 1.790 + return S_OK; 1.791 +} 1.792 +#endif 1.793 + 1.794 +}}