public override int Read()

in src/ICSharpCode.SharpZipLib/Lzw/LzwInputStream.cs [89:311]


		public override int Read(byte[] buffer, int offset, int count)
		{
			if (!headerParsed)
				ParseHeader();

			if (eof)
				return 0;

			int start = offset;

			/* Using local copies of various variables speeds things up by as
	         * much as 30% in Java! Performance not tested in C#.
	         */
			int[] lTabPrefix = tabPrefix;
			byte[] lTabSuffix = tabSuffix;
			byte[] lStack = stack;
			int lNBits = nBits;
			int lMaxCode = maxCode;
			int lMaxMaxCode = maxMaxCode;
			int lBitMask = bitMask;
			int lOldCode = oldCode;
			byte lFinChar = finChar;
			int lStackP = stackP;
			int lFreeEnt = freeEnt;
			byte[] lData = data;
			int lBitPos = bitPos;

			// empty stack if stuff still left
			int sSize = lStack.Length - lStackP;
			if (sSize > 0)
			{
				int num = (sSize >= count) ? count : sSize;
				Array.Copy(lStack, lStackP, buffer, offset, num);
				offset += num;
				count -= num;
				lStackP += num;
			}

			if (count == 0)
			{
				stackP = lStackP;
				return offset - start;
			}

		// loop, filling local buffer until enough data has been decompressed
		MainLoop:
			do
			{
				if (end < EXTRA)
				{
					Fill();
				}

				int bitIn = (got > 0) ? (end - end % lNBits) << 3 :
										(end << 3) - (lNBits - 1);

				while (lBitPos < bitIn)
				{
					#region A

					// handle 1-byte reads correctly
					if (count == 0)
					{
						nBits = lNBits;
						maxCode = lMaxCode;
						maxMaxCode = lMaxMaxCode;
						bitMask = lBitMask;
						oldCode = lOldCode;
						finChar = lFinChar;
						stackP = lStackP;
						freeEnt = lFreeEnt;
						bitPos = lBitPos;

						return offset - start;
					}

					// check for code-width expansion
					if (lFreeEnt > lMaxCode)
					{
						int nBytes = lNBits << 3;
						lBitPos = (lBitPos - 1) +
						nBytes - (lBitPos - 1 + nBytes) % nBytes;

						lNBits++;
						lMaxCode = (lNBits == maxBits) ? lMaxMaxCode :
														(1 << lNBits) - 1;

						lBitMask = (1 << lNBits) - 1;
						lBitPos = ResetBuf(lBitPos);
						goto MainLoop;
					}

					#endregion A

					#region B

					// read next code
					int pos = lBitPos >> 3;
					int code = (((lData[pos] & 0xFF) |
						((lData[pos + 1] & 0xFF) << 8) |
						((lData[pos + 2] & 0xFF) << 16)) >>
						(lBitPos & 0x7)) & lBitMask;

					lBitPos += lNBits;

					// handle first iteration
					if (lOldCode == -1)
					{
						if (code >= 256)
							throw new LzwException("corrupt input: " + code + " > 255");

						lFinChar = (byte)(lOldCode = code);
						buffer[offset++] = lFinChar;
						count--;
						continue;
					}

					// handle CLEAR code
					if (code == TBL_CLEAR && blockMode)
					{
						Array.Copy(zeros, 0, lTabPrefix, 0, zeros.Length);
						lFreeEnt = TBL_FIRST - 1;

						int nBytes = lNBits << 3;
						lBitPos = (lBitPos - 1) + nBytes - (lBitPos - 1 + nBytes) % nBytes;
						lNBits = LzwConstants.INIT_BITS;
						lMaxCode = (1 << lNBits) - 1;
						lBitMask = lMaxCode;

						// Code tables reset

						lBitPos = ResetBuf(lBitPos);
						goto MainLoop;
					}

					#endregion B

					#region C

					// setup
					int inCode = code;
					lStackP = lStack.Length;

					// Handle KwK case
					if (code >= lFreeEnt)
					{
						if (code > lFreeEnt)
						{
							throw new LzwException("corrupt input: code=" + code +
								", freeEnt=" + lFreeEnt);
						}

						lStack[--lStackP] = lFinChar;
						code = lOldCode;
					}

					// Generate output characters in reverse order
					while (code >= 256)
					{
						lStack[--lStackP] = lTabSuffix[code];
						code = lTabPrefix[code];
					}

					lFinChar = lTabSuffix[code];
					buffer[offset++] = lFinChar;
					count--;

					// And put them out in forward order
					sSize = lStack.Length - lStackP;
					int num = (sSize >= count) ? count : sSize;
					Array.Copy(lStack, lStackP, buffer, offset, num);
					offset += num;
					count -= num;
					lStackP += num;

					#endregion C

					#region D

					// generate new entry in table
					if (lFreeEnt < lMaxMaxCode)
					{
						lTabPrefix[lFreeEnt] = lOldCode;
						lTabSuffix[lFreeEnt] = lFinChar;
						lFreeEnt++;
					}

					// Remember previous code
					lOldCode = inCode;

					// if output buffer full, then return
					if (count == 0)
					{
						nBits = lNBits;
						maxCode = lMaxCode;
						bitMask = lBitMask;
						oldCode = lOldCode;
						finChar = lFinChar;
						stackP = lStackP;
						freeEnt = lFreeEnt;
						bitPos = lBitPos;

						return offset - start;
					}

					#endregion D
				}   // while

				lBitPos = ResetBuf(lBitPos);
			} while (got > 0);  // do..while

			nBits = lNBits;
			maxCode = lMaxCode;
			bitMask = lBitMask;
			oldCode = lOldCode;
			finChar = lFinChar;
			stackP = lStackP;
			freeEnt = lFreeEnt;
			bitPos = lBitPos;

			eof = true;
			return offset - start;
		}