| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902 | 
							- using System;
 
- using System.IO;
 
- using ICSharpCode.SharpZipLib.Checksum;
 
- namespace ICSharpCode.SharpZipLib.BZip2
 
- {
 
- 	/// <summary>
 
- 	/// An input stream that decompresses files in the BZip2 format
 
- 	/// </summary>
 
- 	public class BZip2InputStream : Stream
 
- 	{
 
- 		#region Constants
 
- 		const int START_BLOCK_STATE = 1;
 
- 		const int RAND_PART_A_STATE = 2;
 
- 		const int RAND_PART_B_STATE = 3;
 
- 		const int RAND_PART_C_STATE = 4;
 
- 		const int NO_RAND_PART_A_STATE = 5;
 
- 		const int NO_RAND_PART_B_STATE = 6;
 
- 		const int NO_RAND_PART_C_STATE = 7;
 
- 		#endregion
 
- 		#region Instance Fields
 
- 		/*--
 
- 		index of the last char in the block, so
 
- 		the block size == last + 1.
 
- 		--*/
 
- 		int last;
 
- 		/*--
 
- 		index in zptr[] of original string after sorting.
 
- 		--*/
 
- 		int origPtr;
 
- 		/*--
 
- 		always: in the range 0 .. 9.
 
- 		The current block size is 100000 * this number.
 
- 		--*/
 
- 		int blockSize100k;
 
- 		bool blockRandomised;
 
- 		int bsBuff;
 
- 		int bsLive;
 
- 		IChecksum mCrc = new BZip2Crc();
 
- 		bool[] inUse = new bool[256];
 
- 		int nInUse;
 
- 		byte[] seqToUnseq = new byte[256];
 
- 		byte[] unseqToSeq = new byte[256];
 
- 		byte[] selector = new byte[BZip2Constants.MaximumSelectors];
 
- 		byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors];
 
- 		int[] tt;
 
- 		byte[] ll8;
 
- 		/*--
 
- 		freq table collected to save a pass over the data
 
- 		during decompression.
 
- 		--*/
 
- 		int[] unzftab = new int[256];
 
- 		int[][] limit = new int[BZip2Constants.GroupCount][];
 
- 		int[][] baseArray = new int[BZip2Constants.GroupCount][];
 
- 		int[][] perm = new int[BZip2Constants.GroupCount][];
 
- 		int[] minLens = new int[BZip2Constants.GroupCount];
 
- 		readonly Stream baseStream;
 
- 		bool streamEnd;
 
- 		int currentChar = -1;
 
- 		int currentState = START_BLOCK_STATE;
 
- 		int storedBlockCRC, storedCombinedCRC;
 
- 		int computedBlockCRC;
 
- 		uint computedCombinedCRC;
 
- 		int count, chPrev, ch2;
 
- 		int tPos;
 
- 		int rNToGo;
 
- 		int rTPos;
 
- 		int i2, j2;
 
- 		byte z;
 
- 		#endregion
 
- 		/// <summary>
 
- 		/// Construct instance for reading from stream
 
- 		/// </summary>
 
- 		/// <param name="stream">Data source</param>
 
- 		public BZip2InputStream(Stream stream)
 
- 		{
 
- 			if (stream == null)
 
- 				throw new ArgumentNullException("nameof(stream)");
 
- 			// init arrays
 
- 			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
 
- 				limit[i] = new int[BZip2Constants.MaximumAlphaSize];
 
- 				baseArray[i] = new int[BZip2Constants.MaximumAlphaSize];
 
- 				perm[i] = new int[BZip2Constants.MaximumAlphaSize];
 
- 			}
 
- 			baseStream = stream;
 
- 			bsLive = 0;
 
- 			bsBuff = 0;
 
- 			Initialize();
 
- 			InitBlock();
 
- 			SetupBlock();
 
- 		}
 
- 		/// <summary>
 
- 		/// Get/set flag indicating ownership of underlying stream.
 
- 		/// When the flag is true <see cref="Stream.Dispose()" /> will close the underlying stream also.
 
- 		/// </summary>
 
- 		private bool isStreamOwner = true;
 
- 		public bool IsStreamOwner
 
- 		{
 
- 			get { return isStreamOwner; }
 
- 			set { isStreamOwner = value; }
 
- 		}
 
- 		#region Stream Overrides
 
- 		/// <summary>
 
- 		/// Gets a value indicating if the stream supports reading
 
- 		/// </summary>
 
- 		public override bool CanRead {
 
- 			get {
 
- 				return baseStream.CanRead;
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Gets a value indicating whether the current stream supports seeking.
 
- 		/// </summary>
 
- 		public override bool CanSeek {
 
- 			get {
 
- 				return false;
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Gets a value indicating whether the current stream supports writing.
 
- 		/// This property always returns false
 
- 		/// </summary>
 
- 		public override bool CanWrite {
 
- 			get {
 
- 				return false;
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Gets the length in bytes of the stream.
 
- 		/// </summary>
 
- 		public override long Length {
 
- 			get {
 
- 				return baseStream.Length;
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Gets the current position of the stream.
 
- 		/// Setting the position is not supported and will throw a NotSupportException.
 
- 		/// </summary>
 
- 		/// <exception cref="NotSupportedException">Any attempt to set the position.</exception>
 
- 		public override long Position {
 
- 			get {
 
- 				return baseStream.Position;
 
- 			}
 
- 			set {
 
- 				throw new NotSupportedException("BZip2InputStream position cannot be set");
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Flushes the stream.
 
- 		/// </summary>
 
- 		public override void Flush()
 
- 		{
 
- 			baseStream.Flush();
 
- 		}
 
- 		/// <summary>
 
- 		/// Set the streams position.  This operation is not supported and will throw a NotSupportedException
 
- 		/// </summary>
 
- 		/// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
 
- 		/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
 
- 		/// <returns>The new position of the stream.</returns>
 
- 		/// <exception cref="NotSupportedException">Any access</exception>
 
- 		public override long Seek(long offset, SeekOrigin origin)
 
- 		{
 
- 			throw new NotSupportedException("BZip2InputStream Seek not supported");
 
- 		}
 
- 		/// <summary>
 
- 		/// Sets the length of this stream to the given value.
 
- 		/// This operation is not supported and will throw a NotSupportedExceptionortedException
 
- 		/// </summary>
 
- 		/// <param name="value">The new length for the stream.</param>
 
- 		/// <exception cref="NotSupportedException">Any access</exception>
 
- 		public override void SetLength(long value)
 
- 		{
 
- 			throw new NotSupportedException("BZip2InputStream SetLength not supported");
 
- 		}
 
- 		/// <summary>
 
- 		/// Writes a block of bytes to this stream using data from a buffer.
 
- 		/// This operation is not supported and will throw a NotSupportedException
 
- 		/// </summary>
 
- 		/// <param name="buffer">The buffer to source data from.</param>
 
- 		/// <param name="offset">The offset to start obtaining data from.</param>
 
- 		/// <param name="count">The number of bytes of data to write.</param>
 
- 		/// <exception cref="NotSupportedException">Any access</exception>
 
- 		public override void Write(byte[] buffer, int offset, int count)
 
- 		{
 
- 			throw new NotSupportedException("BZip2InputStream Write not supported");
 
- 		}
 
- 		/// <summary>
 
- 		/// Writes a byte to the current position in the file stream.
 
- 		/// This operation is not supported and will throw a NotSupportedException
 
- 		/// </summary>
 
- 		/// <param name="value">The value to write.</param>
 
- 		/// <exception cref="NotSupportedException">Any access</exception>
 
- 		public override void WriteByte(byte value)
 
- 		{
 
- 			throw new NotSupportedException("BZip2InputStream WriteByte not supported");
 
- 		}
 
- 		/// <summary>
 
- 		/// Read a sequence of bytes and advances the read position by one byte.
 
- 		/// </summary>
 
- 		/// <param name="buffer">Array of bytes to store values in</param>
 
- 		/// <param name="offset">Offset in array to begin storing data</param>
 
- 		/// <param name="count">The maximum number of bytes to read</param>
 
- 		/// <returns>The total number of bytes read into the buffer. This might be less
 
- 		/// than the number of bytes requested if that number of bytes are not
 
- 		/// currently available or zero if the end of the stream is reached.
 
- 		/// </returns>
 
- 		public override int Read(byte[] buffer, int offset, int count)
 
- 		{
 
- 			if (buffer == null) {
 
- 				throw new ArgumentNullException("nameof(buffer)");
 
- 			}
 
- 			for (int i = 0; i < count; ++i) {
 
- 				int rb = ReadByte();
 
- 				if (rb == -1) {
 
- 					return i;
 
- 				}
 
- 				buffer[offset + i] = (byte)rb;
 
- 			}
 
- 			return count;
 
- 		}
 
- 		/// <summary>
 
- 		/// Closes the stream, releasing any associated resources.
 
- 		/// </summary>
 
- 		protected override void Dispose(bool disposing)
 
- 		{
 
- 			if (disposing && IsStreamOwner) {
 
- 				baseStream.Dispose();
 
- 			}
 
- 		}
 
- 		/// <summary>
 
- 		/// Read a byte from stream advancing position
 
- 		/// </summary>
 
- 		/// <returns>byte read or -1 on end of stream</returns>
 
- 		public override int ReadByte()
 
- 		{
 
- 			if (streamEnd) {
 
- 				return -1; // ok
 
- 			}
 
- 			int retChar = currentChar;
 
- 			switch (currentState) {
 
- 				case RAND_PART_B_STATE:
 
- 					SetupRandPartB();
 
- 					break;
 
- 				case RAND_PART_C_STATE:
 
- 					SetupRandPartC();
 
- 					break;
 
- 				case NO_RAND_PART_B_STATE:
 
- 					SetupNoRandPartB();
 
- 					break;
 
- 				case NO_RAND_PART_C_STATE:
 
- 					SetupNoRandPartC();
 
- 					break;
 
- 				case START_BLOCK_STATE:
 
- 				case NO_RAND_PART_A_STATE:
 
- 				case RAND_PART_A_STATE:
 
- 					break;
 
- 			}
 
- 			return retChar;
 
- 		}
 
- 		#endregion
 
- 		void MakeMaps()
 
- 		{
 
- 			nInUse = 0;
 
- 			for (int i = 0; i < 256; ++i) {
 
- 				if (inUse[i]) {
 
- 					seqToUnseq[nInUse] = (byte)i;
 
- 					unseqToSeq[i] = (byte)nInUse;
 
- 					nInUse++;
 
- 				}
 
- 			}
 
- 		}
 
- 		void Initialize()
 
- 		{
 
- 			char magic1 = BsGetUChar();
 
- 			char magic2 = BsGetUChar();
 
- 			char magic3 = BsGetUChar();
 
- 			char magic4 = BsGetUChar();
 
- 			if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {
 
- 				streamEnd = true;
 
- 				return;
 
- 			}
 
- 			SetDecompressStructureSizes(magic4 - '0');
 
- 			computedCombinedCRC = 0;
 
- 		}
 
- 		void InitBlock()
 
- 		{
 
- 			char magic1 = BsGetUChar();
 
- 			char magic2 = BsGetUChar();
 
- 			char magic3 = BsGetUChar();
 
- 			char magic4 = BsGetUChar();
 
- 			char magic5 = BsGetUChar();
 
- 			char magic6 = BsGetUChar();
 
- 			if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
 
- 				Complete();
 
- 				return;
 
- 			}
 
- 			if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
 
- 				BadBlockHeader();
 
- 				streamEnd = true;
 
- 				return;
 
- 			}
 
- 			storedBlockCRC = BsGetInt32();
 
- 			blockRandomised = (BsR(1) == 1);
 
- 			GetAndMoveToFrontDecode();
 
- 			mCrc.Reset();
 
- 			currentState = START_BLOCK_STATE;
 
- 		}
 
- 		void EndBlock()
 
- 		{
 
- 			computedBlockCRC = (int)mCrc.Value;
 
- 			// -- A bad CRC is considered a fatal error. --
 
- 			if (storedBlockCRC != computedBlockCRC) {
 
- 				CrcError();
 
- 			}
 
- 			// 1528150659
 
- 			computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
 
- 			computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
 
- 		}
 
- 		void Complete()
 
- 		{
 
- 			storedCombinedCRC = BsGetInt32();
 
- 			if (storedCombinedCRC != (int)computedCombinedCRC) {
 
- 				CrcError();
 
- 			}
 
- 			streamEnd = true;
 
- 		}
 
- 		void FillBuffer()
 
- 		{
 
- 			int thech = 0;
 
- 			try {
 
- 				thech = baseStream.ReadByte();
 
- 			} catch (Exception) {
 
- 				CompressedStreamEOF();
 
- 			}
 
- 			if (thech == -1) {
 
- 				CompressedStreamEOF();
 
- 			}
 
- 			bsBuff = (bsBuff << 8) | (thech & 0xFF);
 
- 			bsLive += 8;
 
- 		}
 
- 		int BsR(int n)
 
- 		{
 
- 			while (bsLive < n) {
 
- 				FillBuffer();
 
- 			}
 
- 			int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
 
- 			bsLive -= n;
 
- 			return v;
 
- 		}
 
- 		char BsGetUChar()
 
- 		{
 
- 			return (char)BsR(8);
 
- 		}
 
- 		int BsGetIntVS(int numBits)
 
- 		{
 
- 			return BsR(numBits);
 
- 		}
 
- 		int BsGetInt32()
 
- 		{
 
- 			int result = BsR(8);
 
- 			result = (result << 8) | BsR(8);
 
- 			result = (result << 8) | BsR(8);
 
- 			result = (result << 8) | BsR(8);
 
- 			return result;
 
- 		}
 
- 		void RecvDecodingTables()
 
- 		{
 
- 			char[][] len = new char[BZip2Constants.GroupCount][];
 
- 			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
 
- 				len[i] = new char[BZip2Constants.MaximumAlphaSize];
 
- 			}
 
- 			bool[] inUse16 = new bool[16];
 
- 			//--- Receive the mapping table ---
 
- 			for (int i = 0; i < 16; i++) {
 
- 				inUse16[i] = (BsR(1) == 1);
 
- 			}
 
- 			for (int i = 0; i < 16; i++) {
 
- 				if (inUse16[i]) {
 
- 					for (int j = 0; j < 16; j++) {
 
- 						inUse[i * 16 + j] = (BsR(1) == 1);
 
- 					}
 
- 				} else {
 
- 					for (int j = 0; j < 16; j++) {
 
- 						inUse[i * 16 + j] = false;
 
- 					}
 
- 				}
 
- 			}
 
- 			MakeMaps();
 
- 			int alphaSize = nInUse + 2;
 
- 			//--- Now the selectors ---
 
- 			int nGroups = BsR(3);
 
- 			int nSelectors = BsR(15);
 
- 			for (int i = 0; i < nSelectors; i++) {
 
- 				int j = 0;
 
- 				while (BsR(1) == 1) {
 
- 					j++;
 
- 				}
 
- 				selectorMtf[i] = (byte)j;
 
- 			}
 
- 			//--- Undo the MTF values for the selectors. ---
 
- 			byte[] pos = new byte[BZip2Constants.GroupCount];
 
- 			for (int v = 0; v < nGroups; v++) {
 
- 				pos[v] = (byte)v;
 
- 			}
 
- 			for (int i = 0; i < nSelectors; i++) {
 
- 				int v = selectorMtf[i];
 
- 				byte tmp = pos[v];
 
- 				while (v > 0) {
 
- 					pos[v] = pos[v - 1];
 
- 					v--;
 
- 				}
 
- 				pos[0] = tmp;
 
- 				selector[i] = tmp;
 
- 			}
 
- 			//--- Now the coding tables ---
 
- 			for (int t = 0; t < nGroups; t++) {
 
- 				int curr = BsR(5);
 
- 				for (int i = 0; i < alphaSize; i++) {
 
- 					while (BsR(1) == 1) {
 
- 						if (BsR(1) == 0) {
 
- 							curr++;
 
- 						} else {
 
- 							curr--;
 
- 						}
 
- 					}
 
- 					len[t][i] = (char)curr;
 
- 				}
 
- 			}
 
- 			//--- Create the Huffman decoding tables ---
 
- 			for (int t = 0; t < nGroups; t++) {
 
- 				int minLen = 32;
 
- 				int maxLen = 0;
 
- 				for (int i = 0; i < alphaSize; i++) {
 
- 					maxLen = Math.Max(maxLen, len[t][i]);
 
- 					minLen = Math.Min(minLen, len[t][i]);
 
- 				}
 
- 				HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
 
- 				minLens[t] = minLen;
 
- 			}
 
- 		}
 
- 		void GetAndMoveToFrontDecode()
 
- 		{
 
- 			byte[] yy = new byte[256];
 
- 			int nextSym;
 
- 			int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
 
- 			origPtr = BsGetIntVS(24);
 
- 			RecvDecodingTables();
 
- 			int EOB = nInUse + 1;
 
- 			int groupNo = -1;
 
- 			int groupPos = 0;
 
- 			/*--
 
- 			Setting up the unzftab entries here is not strictly
 
- 			necessary, but it does save having to do it later
 
- 			in a separate pass, and so saves a block's worth of
 
- 			cache misses.
 
- 			--*/
 
- 			for (int i = 0; i <= 255; i++) {
 
- 				unzftab[i] = 0;
 
- 			}
 
- 			for (int i = 0; i <= 255; i++) {
 
- 				yy[i] = (byte)i;
 
- 			}
 
- 			last = -1;
 
- 			if (groupPos == 0) {
 
- 				groupNo++;
 
- 				groupPos = BZip2Constants.GroupSize;
 
- 			}
 
- 			groupPos--;
 
- 			int zt = selector[groupNo];
 
- 			int zn = minLens[zt];
 
- 			int zvec = BsR(zn);
 
- 			int zj;
 
- 			while (zvec > limit[zt][zn]) {
 
- 				if (zn > 20) { // the longest code
 
- 					throw new BZip2Exception("Bzip data error");
 
- 				}
 
- 				zn++;
 
- 				while (bsLive < 1) {
 
- 					FillBuffer();
 
- 				}
 
- 				zj = (bsBuff >> (bsLive - 1)) & 1;
 
- 				bsLive--;
 
- 				zvec = (zvec << 1) | zj;
 
- 			}
 
- 			if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) {
 
- 				throw new BZip2Exception("Bzip data error");
 
- 			}
 
- 			nextSym = perm[zt][zvec - baseArray[zt][zn]];
 
- 			while (true) {
 
- 				if (nextSym == EOB) {
 
- 					break;
 
- 				}
 
- 				if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) {
 
- 					int s = -1;
 
- 					int n = 1;
 
- 					do {
 
- 						if (nextSym == BZip2Constants.RunA) {
 
- 							s += (0 + 1) * n;
 
- 						} else if (nextSym == BZip2Constants.RunB) {
 
- 							s += (1 + 1) * n;
 
- 						}
 
- 						n <<= 1;
 
- 						if (groupPos == 0) {
 
- 							groupNo++;
 
- 							groupPos = BZip2Constants.GroupSize;
 
- 						}
 
- 						groupPos--;
 
- 						zt = selector[groupNo];
 
- 						zn = minLens[zt];
 
- 						zvec = BsR(zn);
 
- 						while (zvec > limit[zt][zn]) {
 
- 							zn++;
 
- 							while (bsLive < 1) {
 
- 								FillBuffer();
 
- 							}
 
- 							zj = (bsBuff >> (bsLive - 1)) & 1;
 
- 							bsLive--;
 
- 							zvec = (zvec << 1) | zj;
 
- 						}
 
- 						nextSym = perm[zt][zvec - baseArray[zt][zn]];
 
- 					} while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
 
- 					s++;
 
- 					byte ch = seqToUnseq[yy[0]];
 
- 					unzftab[ch] += s;
 
- 					while (s > 0) {
 
- 						last++;
 
- 						ll8[last] = ch;
 
- 						s--;
 
- 					}
 
- 					if (last >= limitLast) {
 
- 						BlockOverrun();
 
- 					}
 
- 					continue;
 
- 				} else {
 
- 					last++;
 
- 					if (last >= limitLast) {
 
- 						BlockOverrun();
 
- 					}
 
- 					byte tmp = yy[nextSym - 1];
 
- 					unzftab[seqToUnseq[tmp]]++;
 
- 					ll8[last] = seqToUnseq[tmp];
 
- 					for (int j = nextSym - 1; j > 0; --j) {
 
- 						yy[j] = yy[j - 1];
 
- 					}
 
- 					yy[0] = tmp;
 
- 					if (groupPos == 0) {
 
- 						groupNo++;
 
- 						groupPos = BZip2Constants.GroupSize;
 
- 					}
 
- 					groupPos--;
 
- 					zt = selector[groupNo];
 
- 					zn = minLens[zt];
 
- 					zvec = BsR(zn);
 
- 					while (zvec > limit[zt][zn]) {
 
- 						zn++;
 
- 						while (bsLive < 1) {
 
- 							FillBuffer();
 
- 						}
 
- 						zj = (bsBuff >> (bsLive - 1)) & 1;
 
- 						bsLive--;
 
- 						zvec = (zvec << 1) | zj;
 
- 					}
 
- 					nextSym = perm[zt][zvec - baseArray[zt][zn]];
 
- 					continue;
 
- 				}
 
- 			}
 
- 		}
 
- 		void SetupBlock()
 
- 		{
 
- 			int[] cftab = new int[257];
 
- 			cftab[0] = 0;
 
- 			Array.Copy(unzftab, 0, cftab, 1, 256);
 
- 			for (int i = 1; i <= 256; i++) {
 
- 				cftab[i] += cftab[i - 1];
 
- 			}
 
- 			for (int i = 0; i <= last; i++) {
 
- 				byte ch = ll8[i];
 
- 				tt[cftab[ch]] = i;
 
- 				cftab[ch]++;
 
- 			}
 
- 			cftab = null;
 
- 			tPos = tt[origPtr];
 
- 			count = 0;
 
- 			i2 = 0;
 
- 			ch2 = 256;   /*-- not a char and not EOF --*/
 
- 			if (blockRandomised) {
 
- 				rNToGo = 0;
 
- 				rTPos = 0;
 
- 				SetupRandPartA();
 
- 			} else {
 
- 				SetupNoRandPartA();
 
- 			}
 
- 		}
 
- 		void SetupRandPartA()
 
- 		{
 
- 			if (i2 <= last) {
 
- 				chPrev = ch2;
 
- 				ch2 = ll8[tPos];
 
- 				tPos = tt[tPos];
 
- 				if (rNToGo == 0) {
 
- 					rNToGo = BZip2Constants.RandomNumbers[rTPos];
 
- 					rTPos++;
 
- 					if (rTPos == 512) {
 
- 						rTPos = 0;
 
- 					}
 
- 				}
 
- 				rNToGo--;
 
- 				ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
 
- 				i2++;
 
- 				currentChar = ch2;
 
- 				currentState = RAND_PART_B_STATE;
 
- 				mCrc.Update(ch2);
 
- 			} else {
 
- 				EndBlock();
 
- 				InitBlock();
 
- 				SetupBlock();
 
- 			}
 
- 		}
 
- 		void SetupNoRandPartA()
 
- 		{
 
- 			if (i2 <= last) {
 
- 				chPrev = ch2;
 
- 				ch2 = ll8[tPos];
 
- 				tPos = tt[tPos];
 
- 				i2++;
 
- 				currentChar = ch2;
 
- 				currentState = NO_RAND_PART_B_STATE;
 
- 				mCrc.Update(ch2);
 
- 			} else {
 
- 				EndBlock();
 
- 				InitBlock();
 
- 				SetupBlock();
 
- 			}
 
- 		}
 
- 		void SetupRandPartB()
 
- 		{
 
- 			if (ch2 != chPrev) {
 
- 				currentState = RAND_PART_A_STATE;
 
- 				count = 1;
 
- 				SetupRandPartA();
 
- 			} else {
 
- 				count++;
 
- 				if (count >= 4) {
 
- 					z = ll8[tPos];
 
- 					tPos = tt[tPos];
 
- 					if (rNToGo == 0) {
 
- 						rNToGo = BZip2Constants.RandomNumbers[rTPos];
 
- 						rTPos++;
 
- 						if (rTPos == 512) {
 
- 							rTPos = 0;
 
- 						}
 
- 					}
 
- 					rNToGo--;
 
- 					z ^= (byte)((rNToGo == 1) ? 1 : 0);
 
- 					j2 = 0;
 
- 					currentState = RAND_PART_C_STATE;
 
- 					SetupRandPartC();
 
- 				} else {
 
- 					currentState = RAND_PART_A_STATE;
 
- 					SetupRandPartA();
 
- 				}
 
- 			}
 
- 		}
 
- 		void SetupRandPartC()
 
- 		{
 
- 			if (j2 < (int)z) {
 
- 				currentChar = ch2;
 
- 				mCrc.Update(ch2);
 
- 				j2++;
 
- 			} else {
 
- 				currentState = RAND_PART_A_STATE;
 
- 				i2++;
 
- 				count = 0;
 
- 				SetupRandPartA();
 
- 			}
 
- 		}
 
- 		void SetupNoRandPartB()
 
- 		{
 
- 			if (ch2 != chPrev) {
 
- 				currentState = NO_RAND_PART_A_STATE;
 
- 				count = 1;
 
- 				SetupNoRandPartA();
 
- 			} else {
 
- 				count++;
 
- 				if (count >= 4) {
 
- 					z = ll8[tPos];
 
- 					tPos = tt[tPos];
 
- 					currentState = NO_RAND_PART_C_STATE;
 
- 					j2 = 0;
 
- 					SetupNoRandPartC();
 
- 				} else {
 
- 					currentState = NO_RAND_PART_A_STATE;
 
- 					SetupNoRandPartA();
 
- 				}
 
- 			}
 
- 		}
 
- 		void SetupNoRandPartC()
 
- 		{
 
- 			if (j2 < (int)z) {
 
- 				currentChar = ch2;
 
- 				mCrc.Update(ch2);
 
- 				j2++;
 
- 			} else {
 
- 				currentState = NO_RAND_PART_A_STATE;
 
- 				i2++;
 
- 				count = 0;
 
- 				SetupNoRandPartA();
 
- 			}
 
- 		}
 
- 		void SetDecompressStructureSizes(int newSize100k)
 
- 		{
 
- 			if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {
 
- 				throw new BZip2Exception("Invalid block size");
 
- 			}
 
- 			blockSize100k = newSize100k;
 
- 			if (newSize100k == 0) {
 
- 				return;
 
- 			}
 
- 			int n = BZip2Constants.BaseBlockSize * newSize100k;
 
- 			ll8 = new byte[n];
 
- 			tt = new int[n];
 
- 		}
 
- 		static void CompressedStreamEOF()
 
- 		{
 
- 			throw new EndOfStreamException("BZip2 input stream end of compressed stream");
 
- 		}
 
- 		static void BlockOverrun()
 
- 		{
 
- 			throw new BZip2Exception("BZip2 input stream block overrun");
 
- 		}
 
- 		static void BadBlockHeader()
 
- 		{
 
- 			throw new BZip2Exception("BZip2 input stream bad block header");
 
- 		}
 
- 		static void CrcError()
 
- 		{
 
- 			throw new BZip2Exception("BZip2 input stream crc error");
 
- 		}
 
- 		static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize)
 
- 		{
 
- 			int pp = 0;
 
- 			for (int i = minLen; i <= maxLen; ++i) {
 
- 				for (int j = 0; j < alphaSize; ++j) {
 
- 					if (length[j] == i) {
 
- 						perm[pp] = j;
 
- 						++pp;
 
- 					}
 
- 				}
 
- 			}
 
- 			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
 
- 				baseArray[i] = 0;
 
- 			}
 
- 			for (int i = 0; i < alphaSize; i++) {
 
- 				++baseArray[length[i] + 1];
 
- 			}
 
- 			for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) {
 
- 				baseArray[i] += baseArray[i - 1];
 
- 			}
 
- 			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
 
- 				limit[i] = 0;
 
- 			}
 
- 			int vec = 0;
 
- 			for (int i = minLen; i <= maxLen; i++) {
 
- 				vec += (baseArray[i + 1] - baseArray[i]);
 
- 				limit[i] = vec - 1;
 
- 				vec <<= 1;
 
- 			}
 
- 			for (int i = minLen + 1; i <= maxLen; i++) {
 
- 				baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
 
- 			}
 
- 		}
 
- 	}
 
- }
 
 
  |