Summary

Class:ICSharpCode.SharpZipLib.BZip2.BZip2InputStream
Assembly:ICSharpCode.SharpZipLib
File(s):C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\BZip2\BZip2InputStream.cs
Covered lines:111
Uncovered lines:315
Coverable lines:426
Total lines:909
Line coverage:26%
Branch coverage:15.7%

Metrics

MethodCyclomatic ComplexitySequence CoverageBranch Coverage
.ctor(...)2100100
Flush()200
Seek(...)100
SetLength(...)100
Write(...)100
WriteByte(...)100
Read(...)46057.14
Close()310060
ReadByte()716.6718.18
MakeMaps()300
Initialize()68054.55
InitBlock()1347.3728
EndBlock()200
Complete()28066.67
BsSetStream(...)1100100
FillBuffer()263.6466.67
BsR(...)2100100
BsGetUChar()1100100
BsGetIntVS(...)100
BsGetInt32()1100100
RecvDecodingTables()1800
GetAndMoveToFrontDecode()2600
SetupBlock()48485.71
SetupRandPartA()600
SetupNoRandPartA()269.2366.67
SetupRandPartB()700
SetupRandPartC()200
SetupNoRandPartB()300
SetupNoRandPartC()200
SetDecompressStructureSizes(...)677.7854.55
CompressedStreamEOF()100
BlockOverrun()100
BadBlockHeader()100
CrcError()100
HbCreateDecodeTables(...)1000

File(s)

C:\Users\Neil\Documents\Visual Studio 2015\Projects\icsharpcode\SZL_master\ICSharpCode.SharpZipLib\BZip2\BZip2InputStream.cs

#LineLine coverage
 1using System;
 2using System.IO;
 3using ICSharpCode.SharpZipLib.Checksum;
 4
 5namespace ICSharpCode.SharpZipLib.BZip2
 6{
 7  /// <summary>
 8  /// An input stream that decompresses files in the BZip2 format
 9  /// </summary>
 10  public class BZip2InputStream : Stream
 11  {
 12    #region Constants
 13    const int START_BLOCK_STATE = 1;
 14    const int RAND_PART_A_STATE = 2;
 15    const int RAND_PART_B_STATE = 3;
 16    const int RAND_PART_C_STATE = 4;
 17    const int NO_RAND_PART_A_STATE = 5;
 18    const int NO_RAND_PART_B_STATE = 6;
 19    const int NO_RAND_PART_C_STATE = 7;
 20    #endregion
 21    #region Constructors
 22    /// <summary>
 23    /// Construct instance for reading from stream
 24    /// </summary>
 25    /// <param name="stream">Data source</param>
 126    public BZip2InputStream(Stream stream)
 27    {
 28      // init arrays
 1429       for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
 630        limit[i] = new int[BZip2Constants.MaximumAlphaSize];
 631        baseArray[i] = new int[BZip2Constants.MaximumAlphaSize];
 632        perm[i] = new int[BZip2Constants.MaximumAlphaSize];
 33      }
 34
 135      BsSetStream(stream);
 136      Initialize();
 137      InitBlock();
 138      SetupBlock();
 139    }
 40
 41    #endregion
 42
 43    /// <summary>
 44    /// Get/set flag indicating ownership of underlying stream.
 45    /// When the flag is true <see cref="Close"></see> will close the underlying stream also.
 46    /// </summary>
 47    public bool IsStreamOwner {
 148      get { return isStreamOwner; }
 049      set { isStreamOwner = value; }
 50    }
 51
 52
 53    #region Stream Overrides
 54    /// <summary>
 55    /// Gets a value indicating if the stream supports reading
 56    /// </summary>
 57    public override bool CanRead {
 58      get {
 059        return baseStream.CanRead;
 60      }
 61    }
 62
 63    /// <summary>
 64    /// Gets a value indicating whether the current stream supports seeking.
 65    /// </summary>
 66    public override bool CanSeek {
 67      get {
 068        return baseStream.CanSeek;
 69      }
 70    }
 71
 72    /// <summary>
 73    /// Gets a value indicating whether the current stream supports writing.
 74    /// This property always returns false
 75    /// </summary>
 76    public override bool CanWrite {
 77      get {
 078        return false;
 79      }
 80    }
 81
 82    /// <summary>
 83    /// Gets the length in bytes of the stream.
 84    /// </summary>
 85    public override long Length {
 86      get {
 087        return baseStream.Length;
 88      }
 89    }
 90
 91    /// <summary>
 92    /// Gets or sets the streams position.
 93    /// Setting the position is not supported and will throw a NotSupportException
 94    /// </summary>
 95    /// <exception cref="NotSupportedException">Any attempt to set the position</exception>
 96    public override long Position {
 97      get {
 098        return baseStream.Position;
 99      }
 100      set {
 0101        throw new NotSupportedException("BZip2InputStream position cannot be set");
 102      }
 103    }
 104
 105    /// <summary>
 106    /// Flushes the stream.
 107    /// </summary>
 108    public override void Flush()
 109    {
 0110       if (baseStream != null) {
 0111        baseStream.Flush();
 112      }
 0113    }
 114
 115    /// <summary>
 116    /// Set the streams position.  This operation is not supported and will throw a NotSupportedException
 117    /// </summary>
 118    /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
 119    /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the 
 120    /// <returns>The new position of the stream.</returns>
 121    /// <exception cref="NotSupportedException">Any access</exception>
 122    public override long Seek(long offset, SeekOrigin origin)
 123    {
 0124      throw new NotSupportedException("BZip2InputStream Seek not supported");
 125    }
 126
 127    /// <summary>
 128    /// Sets the length of this stream to the given value.
 129    /// This operation is not supported and will throw a NotSupportedExceptionortedException
 130    /// </summary>
 131    /// <param name="value">The new length for the stream.</param>
 132    /// <exception cref="NotSupportedException">Any access</exception>
 133    public override void SetLength(long value)
 134    {
 0135      throw new NotSupportedException("BZip2InputStream SetLength not supported");
 136    }
 137
 138    /// <summary>
 139    /// Writes a block of bytes to this stream using data from a buffer.
 140    /// This operation is not supported and will throw a NotSupportedException
 141    /// </summary>
 142    /// <param name="buffer">The buffer to source data from.</param>
 143    /// <param name="offset">The offset to start obtaining data from.</param>
 144    /// <param name="count">The number of bytes of data to write.</param>
 145    /// <exception cref="NotSupportedException">Any access</exception>
 146    public override void Write(byte[] buffer, int offset, int count)
 147    {
 0148      throw new NotSupportedException("BZip2InputStream Write not supported");
 149    }
 150
 151    /// <summary>
 152    /// Writes a byte to the current position in the file stream.
 153    /// This operation is not supported and will throw a NotSupportedException
 154    /// </summary>
 155    /// <param name="value">The value to write.</param>
 156    /// <exception cref="NotSupportedException">Any access</exception>
 157    public override void WriteByte(byte value)
 158    {
 0159      throw new NotSupportedException("BZip2InputStream WriteByte not supported");
 160    }
 161
 162    /// <summary>
 163    /// Read a sequence of bytes and advances the read position by one byte.
 164    /// </summary>
 165    /// <param name="buffer">Array of bytes to store values in</param>
 166    /// <param name="offset">Offset in array to begin storing data</param>
 167    /// <param name="count">The maximum number of bytes to read</param>
 168    /// <returns>The total number of bytes read into the buffer. This might be less
 169    /// than the number of bytes requested if that number of bytes are not
 170    /// currently available or zero if the end of the stream is reached.
 171    /// </returns>
 172    public override int Read(byte[] buffer, int offset, int count)
 173    {
 1174       if (buffer == null) {
 0175        throw new ArgumentNullException(nameof(buffer));
 176      }
 177
 2178       for (int i = 0; i < count; ++i) {
 1179        int rb = ReadByte();
 1180         if (rb == -1) {
 1181          return i;
 182        }
 0183        buffer[offset + i] = (byte)rb;
 184      }
 0185      return count;
 186    }
 187
 188    /// <summary>
 189    /// Closes the stream, releasing any associated resources.
 190    /// </summary>
 191    public override void Close()
 192    {
 1193       if (IsStreamOwner && (baseStream != null)) {
 1194        baseStream.Close();
 195      }
 1196    }
 197    /// <summary>
 198    /// Read a byte from stream advancing position
 199    /// </summary>
 200    /// <returns>byte read or -1 on end of stream</returns>
 201    public override int ReadByte()
 202    {
 1203       if (streamEnd) {
 1204        return -1; // ok
 205      }
 206
 0207      int retChar = currentChar;
 0208       switch (currentState) {
 209        case RAND_PART_B_STATE:
 0210          SetupRandPartB();
 0211          break;
 212        case RAND_PART_C_STATE:
 0213          SetupRandPartC();
 0214          break;
 215        case NO_RAND_PART_B_STATE:
 0216          SetupNoRandPartB();
 0217          break;
 218        case NO_RAND_PART_C_STATE:
 0219          SetupNoRandPartC();
 220          break;
 221        case START_BLOCK_STATE:
 222        case NO_RAND_PART_A_STATE:
 223        case RAND_PART_A_STATE:
 224          break;
 225      }
 0226      return retChar;
 227    }
 228
 229    #endregion
 230
 231    void MakeMaps()
 232    {
 0233      nInUse = 0;
 0234       for (int i = 0; i < 256; ++i) {
 0235         if (inUse[i]) {
 0236          seqToUnseq[nInUse] = (byte)i;
 0237          unseqToSeq[i] = (byte)nInUse;
 0238          nInUse++;
 239        }
 240      }
 0241    }
 242
 243    void Initialize()
 244    {
 1245      char magic1 = BsGetUChar();
 1246      char magic2 = BsGetUChar();
 247
 1248      char magic3 = BsGetUChar();
 1249      char magic4 = BsGetUChar();
 250
 1251       if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {
 0252        streamEnd = true;
 0253        return;
 254      }
 255
 1256      SetDecompressStructureSizes(magic4 - '0');
 1257      computedCombinedCRC = 0;
 1258    }
 259
 260    void InitBlock()
 261    {
 1262      char magic1 = BsGetUChar();
 1263      char magic2 = BsGetUChar();
 1264      char magic3 = BsGetUChar();
 1265      char magic4 = BsGetUChar();
 1266      char magic5 = BsGetUChar();
 1267      char magic6 = BsGetUChar();
 268
 1269       if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
 1270        Complete();
 1271        return;
 272      }
 273
 0274       if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
 0275        BadBlockHeader();
 0276        streamEnd = true;
 0277        return;
 278      }
 279
 0280      storedBlockCRC = BsGetInt32();
 281
 0282      blockRandomised = (BsR(1) == 1);
 283
 0284      GetAndMoveToFrontDecode();
 285
 0286      mCrc.Reset();
 0287      currentState = START_BLOCK_STATE;
 0288    }
 289
 290    void EndBlock()
 291    {
 0292      computedBlockCRC = (int)mCrc.Value;
 293
 294      // -- A bad CRC is considered a fatal error. --
 0295       if (storedBlockCRC != computedBlockCRC) {
 0296        CrcError();
 297      }
 298
 299      // 1528150659
 0300      computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
 0301      computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
 0302    }
 303
 304    void Complete()
 305    {
 1306      storedCombinedCRC = BsGetInt32();
 1307       if (storedCombinedCRC != (int)computedCombinedCRC) {
 0308        CrcError();
 309      }
 310
 1311      streamEnd = true;
 1312    }
 313
 314    void BsSetStream(Stream stream)
 315    {
 1316      baseStream = stream;
 1317      bsLive = 0;
 1318      bsBuff = 0;
 1319    }
 320
 321    void FillBuffer()
 322    {
 14323      int thech = 0;
 324
 325      try {
 14326        thech = baseStream.ReadByte();
 14327      } catch (Exception) {
 0328        CompressedStreamEOF();
 0329      }
 330
 14331       if (thech == -1) {
 0332        CompressedStreamEOF();
 333      }
 334
 14335      bsBuff = (bsBuff << 8) | (thech & 0xFF);
 14336      bsLive += 8;
 14337    }
 338
 339    int BsR(int n)
 340    {
 28341       while (bsLive < n) {
 14342        FillBuffer();
 343      }
 344
 14345      int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
 14346      bsLive -= n;
 14347      return v;
 348    }
 349
 350    char BsGetUChar()
 351    {
 10352      return (char)BsR(8);
 353    }
 354
 355    int BsGetIntVS(int numBits)
 356    {
 0357      return BsR(numBits);
 358    }
 359
 360    int BsGetInt32()
 361    {
 1362      int result = BsR(8);
 1363      result = (result << 8) | BsR(8);
 1364      result = (result << 8) | BsR(8);
 1365      result = (result << 8) | BsR(8);
 1366      return result;
 367    }
 368
 369    void RecvDecodingTables()
 370    {
 0371      char[][] len = new char[BZip2Constants.GroupCount][];
 0372       for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
 0373        len[i] = new char[BZip2Constants.MaximumAlphaSize];
 374      }
 375
 0376      bool[] inUse16 = new bool[16];
 377
 378      //--- Receive the mapping table ---
 0379       for (int i = 0; i < 16; i++) {
 0380        inUse16[i] = (BsR(1) == 1);
 381      }
 382
 0383       for (int i = 0; i < 16; i++) {
 0384         if (inUse16[i]) {
 0385           for (int j = 0; j < 16; j++) {
 0386            inUse[i * 16 + j] = (BsR(1) == 1);
 387          }
 0388        } else {
 0389           for (int j = 0; j < 16; j++) {
 0390            inUse[i * 16 + j] = false;
 391          }
 392        }
 393      }
 394
 0395      MakeMaps();
 0396      int alphaSize = nInUse + 2;
 397
 398      //--- Now the selectors ---
 0399      int nGroups = BsR(3);
 0400      int nSelectors = BsR(15);
 401
 0402       for (int i = 0; i < nSelectors; i++) {
 0403        int j = 0;
 0404         while (BsR(1) == 1) {
 0405          j++;
 406        }
 0407        selectorMtf[i] = (byte)j;
 408      }
 409
 410      //--- Undo the MTF values for the selectors. ---
 0411      byte[] pos = new byte[BZip2Constants.GroupCount];
 0412       for (int v = 0; v < nGroups; v++) {
 0413        pos[v] = (byte)v;
 414      }
 415
 0416       for (int i = 0; i < nSelectors; i++) {
 0417        int v = selectorMtf[i];
 0418        byte tmp = pos[v];
 0419         while (v > 0) {
 0420          pos[v] = pos[v - 1];
 0421          v--;
 422        }
 0423        pos[0] = tmp;
 0424        selector[i] = tmp;
 425      }
 426
 427      //--- Now the coding tables ---
 0428       for (int t = 0; t < nGroups; t++) {
 0429        int curr = BsR(5);
 0430         for (int i = 0; i < alphaSize; i++) {
 0431           while (BsR(1) == 1) {
 0432             if (BsR(1) == 0) {
 0433              curr++;
 0434            } else {
 0435              curr--;
 436            }
 437          }
 0438          len[t][i] = (char)curr;
 439        }
 440      }
 441
 442      //--- Create the Huffman decoding tables ---
 0443       for (int t = 0; t < nGroups; t++) {
 0444        int minLen = 32;
 0445        int maxLen = 0;
 0446         for (int i = 0; i < alphaSize; i++) {
 0447          maxLen = Math.Max(maxLen, len[t][i]);
 0448          minLen = Math.Min(minLen, len[t][i]);
 449        }
 0450        HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
 0451        minLens[t] = minLen;
 452      }
 0453    }
 454
 455    void GetAndMoveToFrontDecode()
 456    {
 0457      byte[] yy = new byte[256];
 458      int nextSym;
 459
 0460      int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
 0461      origPtr = BsGetIntVS(24);
 462
 0463      RecvDecodingTables();
 0464      int EOB = nInUse + 1;
 0465      int groupNo = -1;
 0466      int groupPos = 0;
 467
 468      /*--
 469      Setting up the unzftab entries here is not strictly
 470      necessary, but it does save having to do it later
 471      in a separate pass, and so saves a block's worth of
 472      cache misses.
 473      --*/
 0474       for (int i = 0; i <= 255; i++) {
 0475        unzftab[i] = 0;
 476      }
 477
 0478       for (int i = 0; i <= 255; i++) {
 0479        yy[i] = (byte)i;
 480      }
 481
 0482      last = -1;
 483
 0484       if (groupPos == 0) {
 0485        groupNo++;
 0486        groupPos = BZip2Constants.GroupSize;
 487      }
 488
 0489      groupPos--;
 0490      int zt = selector[groupNo];
 0491      int zn = minLens[zt];
 0492      int zvec = BsR(zn);
 493      int zj;
 494
 0495       while (zvec > limit[zt][zn]) {
 0496         if (zn > 20) { // the longest code
 0497          throw new BZip2Exception("Bzip data error");
 498        }
 0499        zn++;
 0500         while (bsLive < 1) {
 0501          FillBuffer();
 502        }
 0503        zj = (bsBuff >> (bsLive - 1)) & 1;
 0504        bsLive--;
 0505        zvec = (zvec << 1) | zj;
 506      }
 0507       if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) {
 0508        throw new BZip2Exception("Bzip data error");
 509      }
 0510      nextSym = perm[zt][zvec - baseArray[zt][zn]];
 511
 512      while (true) {
 0513         if (nextSym == EOB) {
 514          break;
 515        }
 516
 0517         if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) {
 0518          int s = -1;
 0519          int n = 1;
 520          do {
 0521             if (nextSym == BZip2Constants.RunA) {
 0522              s += (0 + 1) * n;
 0523             } else if (nextSym == BZip2Constants.RunB) {
 0524              s += (1 + 1) * n;
 525            }
 526
 0527            n <<= 1;
 528
 0529             if (groupPos == 0) {
 0530              groupNo++;
 0531              groupPos = BZip2Constants.GroupSize;
 532            }
 533
 0534            groupPos--;
 535
 0536            zt = selector[groupNo];
 0537            zn = minLens[zt];
 0538            zvec = BsR(zn);
 539
 0540             while (zvec > limit[zt][zn]) {
 0541              zn++;
 0542               while (bsLive < 1) {
 0543                FillBuffer();
 544              }
 0545              zj = (bsBuff >> (bsLive - 1)) & 1;
 0546              bsLive--;
 0547              zvec = (zvec << 1) | zj;
 548            }
 0549            nextSym = perm[zt][zvec - baseArray[zt][zn]];
 0550           } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
 551
 0552          s++;
 0553          byte ch = seqToUnseq[yy[0]];
 0554          unzftab[ch] += s;
 555
 0556           while (s > 0) {
 0557            last++;
 0558            ll8[last] = ch;
 0559            s--;
 560          }
 561
 0562           if (last >= limitLast) {
 0563            BlockOverrun();
 564          }
 0565          continue;
 566        } else {
 0567          last++;
 0568           if (last >= limitLast) {
 0569            BlockOverrun();
 570          }
 571
 0572          byte tmp = yy[nextSym - 1];
 0573          unzftab[seqToUnseq[tmp]]++;
 0574          ll8[last] = seqToUnseq[tmp];
 575
 0576           for (int j = nextSym - 1; j > 0; --j) {
 0577            yy[j] = yy[j - 1];
 578          }
 0579          yy[0] = tmp;
 580
 0581           if (groupPos == 0) {
 0582            groupNo++;
 0583            groupPos = BZip2Constants.GroupSize;
 584          }
 585
 0586          groupPos--;
 0587          zt = selector[groupNo];
 0588          zn = minLens[zt];
 0589          zvec = BsR(zn);
 0590           while (zvec > limit[zt][zn]) {
 0591            zn++;
 0592             while (bsLive < 1) {
 0593              FillBuffer();
 594            }
 0595            zj = (bsBuff >> (bsLive - 1)) & 1;
 0596            bsLive--;
 0597            zvec = (zvec << 1) | zj;
 598          }
 0599          nextSym = perm[zt][zvec - baseArray[zt][zn]];
 0600          continue;
 601        }
 602      }
 0603    }
 604
 605    void SetupBlock()
 606    {
 1607      int[] cftab = new int[257];
 608
 1609      cftab[0] = 0;
 1610      Array.Copy(unzftab, 0, cftab, 1, 256);
 611
 514612       for (int i = 1; i <= 256; i++) {
 256613        cftab[i] += cftab[i - 1];
 614      }
 615
 4616       for (int i = 0; i <= last; i++) {
 1617        byte ch = ll8[i];
 1618        tt[cftab[ch]] = i;
 1619        cftab[ch]++;
 620      }
 621
 1622      cftab = null;
 623
 1624      tPos = tt[origPtr];
 625
 1626      count = 0;
 1627      i2 = 0;
 1628      ch2 = 256;   /*-- not a char and not EOF --*/
 629
 1630       if (blockRandomised) {
 0631        rNToGo = 0;
 0632        rTPos = 0;
 0633        SetupRandPartA();
 0634      } else {
 1635        SetupNoRandPartA();
 636      }
 1637    }
 638
 639    void SetupRandPartA()
 640    {
 0641       if (i2 <= last) {
 0642        chPrev = ch2;
 0643        ch2 = ll8[tPos];
 0644        tPos = tt[tPos];
 0645         if (rNToGo == 0) {
 0646          rNToGo = BZip2Constants.RandomNumbers[rTPos];
 0647          rTPos++;
 0648           if (rTPos == 512) {
 0649            rTPos = 0;
 650          }
 651        }
 0652        rNToGo--;
 0653         ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
 0654        i2++;
 655
 0656        currentChar = ch2;
 0657        currentState = RAND_PART_B_STATE;
 0658        mCrc.Update(ch2);
 0659      } else {
 0660        EndBlock();
 0661        InitBlock();
 0662        SetupBlock();
 663      }
 0664    }
 665
 666    void SetupNoRandPartA()
 667    {
 1668       if (i2 <= last) {
 1669        chPrev = ch2;
 1670        ch2 = ll8[tPos];
 1671        tPos = tt[tPos];
 1672        i2++;
 673
 1674        currentChar = ch2;
 1675        currentState = NO_RAND_PART_B_STATE;
 1676        mCrc.Update(ch2);
 1677      } else {
 0678        EndBlock();
 0679        InitBlock();
 0680        SetupBlock();
 681      }
 0682    }
 683
 684    void SetupRandPartB()
 685    {
 0686       if (ch2 != chPrev) {
 0687        currentState = RAND_PART_A_STATE;
 0688        count = 1;
 0689        SetupRandPartA();
 0690      } else {
 0691        count++;
 0692         if (count >= 4) {
 0693          z = ll8[tPos];
 0694          tPos = tt[tPos];
 0695           if (rNToGo == 0) {
 0696            rNToGo = BZip2Constants.RandomNumbers[rTPos];
 0697            rTPos++;
 0698             if (rTPos == 512) {
 0699              rTPos = 0;
 700            }
 701          }
 0702          rNToGo--;
 0703           z ^= (byte)((rNToGo == 1) ? 1 : 0);
 0704          j2 = 0;
 0705          currentState = RAND_PART_C_STATE;
 0706          SetupRandPartC();
 0707        } else {
 0708          currentState = RAND_PART_A_STATE;
 0709          SetupRandPartA();
 710        }
 711      }
 0712    }
 713
 714    void SetupRandPartC()
 715    {
 0716       if (j2 < (int)z) {
 0717        currentChar = ch2;
 0718        mCrc.Update(ch2);
 0719        j2++;
 0720      } else {
 0721        currentState = RAND_PART_A_STATE;
 0722        i2++;
 0723        count = 0;
 0724        SetupRandPartA();
 725      }
 0726    }
 727
 728    void SetupNoRandPartB()
 729    {
 0730       if (ch2 != chPrev) {
 0731        currentState = NO_RAND_PART_A_STATE;
 0732        count = 1;
 0733        SetupNoRandPartA();
 0734      } else {
 0735        count++;
 0736         if (count >= 4) {
 0737          z = ll8[tPos];
 0738          tPos = tt[tPos];
 0739          currentState = NO_RAND_PART_C_STATE;
 0740          j2 = 0;
 0741          SetupNoRandPartC();
 0742        } else {
 0743          currentState = NO_RAND_PART_A_STATE;
 0744          SetupNoRandPartA();
 745        }
 746      }
 0747    }
 748
 749    void SetupNoRandPartC()
 750    {
 0751       if (j2 < (int)z) {
 0752        currentChar = ch2;
 0753        mCrc.Update(ch2);
 0754        j2++;
 0755      } else {
 0756        currentState = NO_RAND_PART_A_STATE;
 0757        i2++;
 0758        count = 0;
 0759        SetupNoRandPartA();
 760      }
 0761    }
 762
 763    void SetDecompressStructureSizes(int newSize100k)
 764    {
 1765       if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {
 0766        throw new BZip2Exception("Invalid block size");
 767      }
 768
 1769      blockSize100k = newSize100k;
 770
 1771       if (newSize100k == 0) {
 0772        return;
 773      }
 774
 1775      int n = BZip2Constants.BaseBlockSize * newSize100k;
 1776      ll8 = new byte[n];
 1777      tt = new int[n];
 1778    }
 779
 780    static void CompressedStreamEOF()
 781    {
 0782      throw new EndOfStreamException("BZip2 input stream end of compressed stream");
 783    }
 784
 785    static void BlockOverrun()
 786    {
 0787      throw new BZip2Exception("BZip2 input stream block overrun");
 788    }
 789
 790    static void BadBlockHeader()
 791    {
 0792      throw new BZip2Exception("BZip2 input stream bad block header");
 793    }
 794
 795    static void CrcError()
 796    {
 0797      throw new BZip2Exception("BZip2 input stream crc error");
 798    }
 799
 800    static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, in
 801    {
 0802      int pp = 0;
 803
 0804       for (int i = minLen; i <= maxLen; ++i) {
 0805         for (int j = 0; j < alphaSize; ++j) {
 0806           if (length[j] == i) {
 0807            perm[pp] = j;
 0808            ++pp;
 809          }
 810        }
 811      }
 812
 0813       for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
 0814        baseArray[i] = 0;
 815      }
 816
 0817       for (int i = 0; i < alphaSize; i++) {
 0818        ++baseArray[length[i] + 1];
 819      }
 820
 0821       for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) {
 0822        baseArray[i] += baseArray[i - 1];
 823      }
 824
 0825       for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
 0826        limit[i] = 0;
 827      }
 828
 0829      int vec = 0;
 830
 0831       for (int i = minLen; i <= maxLen; i++) {
 0832        vec += (baseArray[i + 1] - baseArray[i]);
 0833        limit[i] = vec - 1;
 0834        vec <<= 1;
 835      }
 836
 0837       for (int i = minLen + 1; i <= maxLen; i++) {
 0838        baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
 839      }
 0840    }
 841
 842    #region Instance Fields
 843    /*--
 844    index of the last char in the block, so
 845    the block size == last + 1.
 846    --*/
 847    int last;
 848
 849    /*--
 850    index in zptr[] of original string after sorting.
 851    --*/
 852    int origPtr;
 853
 854    /*--
 855    always: in the range 0 .. 9.
 856    The current block size is 100000 * this number.
 857    --*/
 858    int blockSize100k;
 859
 860    bool blockRandomised;
 861
 862    int bsBuff;
 863    int bsLive;
 1864    IChecksum mCrc = new BZip2Crc();
 865
 1866    bool[] inUse = new bool[256];
 867    int nInUse;
 868
 1869    byte[] seqToUnseq = new byte[256];
 1870    byte[] unseqToSeq = new byte[256];
 871
 1872    byte[] selector = new byte[BZip2Constants.MaximumSelectors];
 1873    byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors];
 874
 875    int[] tt;
 876    byte[] ll8;
 877
 878    /*--
 879    freq table collected to save a pass over the data
 880    during decompression.
 881    --*/
 1882    int[] unzftab = new int[256];
 883
 1884    int[][] limit = new int[BZip2Constants.GroupCount][];
 1885    int[][] baseArray = new int[BZip2Constants.GroupCount][];
 1886    int[][] perm = new int[BZip2Constants.GroupCount][];
 1887    int[] minLens = new int[BZip2Constants.GroupCount];
 888
 889    Stream baseStream;
 890    bool streamEnd;
 891
 1892    int currentChar = -1;
 893
 1894    int currentState = START_BLOCK_STATE;
 895
 896    int storedBlockCRC, storedCombinedCRC;
 897    int computedBlockCRC;
 898    uint computedCombinedCRC;
 899
 900    int count, chPrev, ch2;
 901    int tPos;
 902    int rNToGo;
 903    int rTPos;
 904    int i2, j2;
 905    byte z;
 1906    bool isStreamOwner = true;
 907    #endregion
 908  }
 909}