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 +}}