1 using System;
2 using System.IO;
3 using ICSharpCode.SharpZipLib.Checksum;
4 
5 namespace 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>
BZip2InputStream(Stream stream)26 		public BZip2InputStream(Stream stream)
27 		{
28 			// init arrays
29 			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
30 				limit[i] = new int[BZip2Constants.MaximumAlphaSize];
31 				baseArray[i] = new int[BZip2Constants.MaximumAlphaSize];
32 				perm[i] = new int[BZip2Constants.MaximumAlphaSize];
33 			}
34 
35 			BsSetStream(stream);
36 			Initialize();
37 			InitBlock();
38 			SetupBlock();
39 		}
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 {
48 			get { return isStreamOwner; }
49 			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 {
59 				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 {
68 				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 {
78 				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 {
87 				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 {
98 				return baseStream.Position;
99 			}
100 			set {
101 				throw new NotSupportedException("BZip2InputStream position cannot be set");
102 			}
103 		}
104 
105 		/// <summary>
106 		/// Flushes the stream.
107 		/// </summary>
Flush()108 		public override void Flush()
109 		{
110 			if (baseStream != null) {
111 				baseStream.Flush();
112 			}
113 		}
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 new position.</param>
120 		/// <returns>The new position of the stream.</returns>
121 		/// <exception cref="NotSupportedException">Any access</exception>
Seek(long offset, SeekOrigin origin)122 		public override long Seek(long offset, SeekOrigin origin)
123 		{
124 			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>
SetLength(long value)133 		public override void SetLength(long value)
134 		{
135 			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>
Write(byte[] buffer, int offset, int count)146 		public override void Write(byte[] buffer, int offset, int count)
147 		{
148 			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>
WriteByte(byte value)157 		public override void WriteByte(byte value)
158 		{
159 			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>
Read(byte[] buffer, int offset, int count)172 		public override int Read(byte[] buffer, int offset, int count)
173 		{
174 			if (buffer == null) {
175 				throw new ArgumentNullException(nameof(buffer));
176 			}
177 
178 			for (int i = 0; i < count; ++i) {
179 				int rb = ReadByte();
180 				if (rb == -1) {
181 					return i;
182 				}
183 				buffer[offset + i] = (byte)rb;
184 			}
185 			return count;
186 		}
187 
188 		/// <summary>
189 		/// Closes the stream, releasing any associated resources.
190 		/// </summary>
Dispose(bool disposing)191 		protected override void Dispose(bool disposing)
192 		{
193 			if (disposing && IsStreamOwner && (baseStream != null)) {
194 				baseStream.Dispose();
195 			}
196 		}
197 		/// <summary>
198 		/// Read a byte from stream advancing position
199 		/// </summary>
200 		/// <returns>byte read or -1 on end of stream</returns>
ReadByte()201 		public override int ReadByte()
202 		{
203 			if (streamEnd) {
204 				return -1; // ok
205 			}
206 
207 			int retChar = currentChar;
208 			switch (currentState) {
209 				case RAND_PART_B_STATE:
210 					SetupRandPartB();
211 					break;
212 				case RAND_PART_C_STATE:
213 					SetupRandPartC();
214 					break;
215 				case NO_RAND_PART_B_STATE:
216 					SetupNoRandPartB();
217 					break;
218 				case NO_RAND_PART_C_STATE:
219 					SetupNoRandPartC();
220 					break;
221 				case START_BLOCK_STATE:
222 				case NO_RAND_PART_A_STATE:
223 				case RAND_PART_A_STATE:
224 					break;
225 			}
226 			return retChar;
227 		}
228 
229 		#endregion
230 
MakeMaps()231 		void MakeMaps()
232 		{
233 			nInUse = 0;
234 			for (int i = 0; i < 256; ++i) {
235 				if (inUse[i]) {
236 					seqToUnseq[nInUse] = (byte)i;
237 					unseqToSeq[i] = (byte)nInUse;
238 					nInUse++;
239 				}
240 			}
241 		}
242 
Initialize()243 		void Initialize()
244 		{
245 			char magic1 = BsGetUChar();
246 			char magic2 = BsGetUChar();
247 
248 			char magic3 = BsGetUChar();
249 			char magic4 = BsGetUChar();
250 
251 			if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {
252 				streamEnd = true;
253 				return;
254 			}
255 
256 			SetDecompressStructureSizes(magic4 - '0');
257 			computedCombinedCRC = 0;
258 		}
259 
InitBlock()260 		void InitBlock()
261 		{
262 			char magic1 = BsGetUChar();
263 			char magic2 = BsGetUChar();
264 			char magic3 = BsGetUChar();
265 			char magic4 = BsGetUChar();
266 			char magic5 = BsGetUChar();
267 			char magic6 = BsGetUChar();
268 
269 			if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
270 				Complete();
271 				return;
272 			}
273 
274 			if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
275 				BadBlockHeader();
276 				streamEnd = true;
277 				return;
278 			}
279 
280 			storedBlockCRC = BsGetInt32();
281 
282 			blockRandomised = (BsR(1) == 1);
283 
284 			GetAndMoveToFrontDecode();
285 
286 			mCrc.Reset();
287 			currentState = START_BLOCK_STATE;
288 		}
289 
EndBlock()290 		void EndBlock()
291 		{
292 			computedBlockCRC = (int)mCrc.Value;
293 
294 			// -- A bad CRC is considered a fatal error. --
295 			if (storedBlockCRC != computedBlockCRC) {
296 				CrcError();
297 			}
298 
299 			// 1528150659
300 			computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
301 			computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
302 		}
303 
Complete()304 		void Complete()
305 		{
306 			storedCombinedCRC = BsGetInt32();
307 			if (storedCombinedCRC != (int)computedCombinedCRC) {
308 				CrcError();
309 			}
310 
311 			streamEnd = true;
312 		}
313 
BsSetStream(Stream stream)314 		void BsSetStream(Stream stream)
315 		{
316 			baseStream = stream;
317 			bsLive = 0;
318 			bsBuff = 0;
319 		}
320 
FillBuffer()321 		void FillBuffer()
322 		{
323 			int thech = 0;
324 
325 			try {
326 				thech = baseStream.ReadByte();
327 			} catch (Exception) {
328 				CompressedStreamEOF();
329 			}
330 
331 			if (thech == -1) {
332 				CompressedStreamEOF();
333 			}
334 
335 			bsBuff = (bsBuff << 8) | (thech & 0xFF);
336 			bsLive += 8;
337 		}
338 
BsR(int n)339 		int BsR(int n)
340 		{
341 			while (bsLive < n) {
342 				FillBuffer();
343 			}
344 
345 			int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
346 			bsLive -= n;
347 			return v;
348 		}
349 
BsGetUChar()350 		char BsGetUChar()
351 		{
352 			return (char)BsR(8);
353 		}
354 
BsGetIntVS(int numBits)355 		int BsGetIntVS(int numBits)
356 		{
357 			return BsR(numBits);
358 		}
359 
BsGetInt32()360 		int BsGetInt32()
361 		{
362 			int result = BsR(8);
363 			result = (result << 8) | BsR(8);
364 			result = (result << 8) | BsR(8);
365 			result = (result << 8) | BsR(8);
366 			return result;
367 		}
368 
RecvDecodingTables()369 		void RecvDecodingTables()
370 		{
371 			char[][] len = new char[BZip2Constants.GroupCount][];
372 			for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
373 				len[i] = new char[BZip2Constants.MaximumAlphaSize];
374 			}
375 
376 			bool[] inUse16 = new bool[16];
377 
378 			//--- Receive the mapping table ---
379 			for (int i = 0; i < 16; i++) {
380 				inUse16[i] = (BsR(1) == 1);
381 			}
382 
383 			for (int i = 0; i < 16; i++) {
384 				if (inUse16[i]) {
385 					for (int j = 0; j < 16; j++) {
386 						inUse[i * 16 + j] = (BsR(1) == 1);
387 					}
388 				} else {
389 					for (int j = 0; j < 16; j++) {
390 						inUse[i * 16 + j] = false;
391 					}
392 				}
393 			}
394 
395 			MakeMaps();
396 			int alphaSize = nInUse + 2;
397 
398 			//--- Now the selectors ---
399 			int nGroups = BsR(3);
400 			int nSelectors = BsR(15);
401 
402 			for (int i = 0; i < nSelectors; i++) {
403 				int j = 0;
404 				while (BsR(1) == 1) {
405 					j++;
406 				}
407 				selectorMtf[i] = (byte)j;
408 			}
409 
410 			//--- Undo the MTF values for the selectors. ---
411 			byte[] pos = new byte[BZip2Constants.GroupCount];
412 			for (int v = 0; v < nGroups; v++) {
413 				pos[v] = (byte)v;
414 			}
415 
416 			for (int i = 0; i < nSelectors; i++) {
417 				int v = selectorMtf[i];
418 				byte tmp = pos[v];
419 				while (v > 0) {
420 					pos[v] = pos[v - 1];
421 					v--;
422 				}
423 				pos[0] = tmp;
424 				selector[i] = tmp;
425 			}
426 
427 			//--- Now the coding tables ---
428 			for (int t = 0; t < nGroups; t++) {
429 				int curr = BsR(5);
430 				for (int i = 0; i < alphaSize; i++) {
431 					while (BsR(1) == 1) {
432 						if (BsR(1) == 0) {
433 							curr++;
434 						} else {
435 							curr--;
436 						}
437 					}
438 					len[t][i] = (char)curr;
439 				}
440 			}
441 
442 			//--- Create the Huffman decoding tables ---
443 			for (int t = 0; t < nGroups; t++) {
444 				int minLen = 32;
445 				int maxLen = 0;
446 				for (int i = 0; i < alphaSize; i++) {
447 					maxLen = Math.Max(maxLen, len[t][i]);
448 					minLen = Math.Min(minLen, len[t][i]);
449 				}
450 				HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
451 				minLens[t] = minLen;
452 			}
453 		}
454 
GetAndMoveToFrontDecode()455 		void GetAndMoveToFrontDecode()
456 		{
457 			byte[] yy = new byte[256];
458 			int nextSym;
459 
460 			int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
461 			origPtr = BsGetIntVS(24);
462 
463 			RecvDecodingTables();
464 			int EOB = nInUse + 1;
465 			int groupNo = -1;
466 			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 			--*/
474 			for (int i = 0; i <= 255; i++) {
475 				unzftab[i] = 0;
476 			}
477 
478 			for (int i = 0; i <= 255; i++) {
479 				yy[i] = (byte)i;
480 			}
481 
482 			last = -1;
483 
484 			if (groupPos == 0) {
485 				groupNo++;
486 				groupPos = BZip2Constants.GroupSize;
487 			}
488 
489 			groupPos--;
490 			int zt = selector[groupNo];
491 			int zn = minLens[zt];
492 			int zvec = BsR(zn);
493 			int zj;
494 
495 			while (zvec > limit[zt][zn]) {
496 				if (zn > 20) { // the longest code
497 					throw new BZip2Exception("Bzip data error");
498 				}
499 				zn++;
500 				while (bsLive < 1) {
501 					FillBuffer();
502 				}
503 				zj = (bsBuff >> (bsLive - 1)) & 1;
504 				bsLive--;
505 				zvec = (zvec << 1) | zj;
506 			}
507 			if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) {
508 				throw new BZip2Exception("Bzip data error");
509 			}
510 			nextSym = perm[zt][zvec - baseArray[zt][zn]];
511 
512 			while (true) {
513 				if (nextSym == EOB) {
514 					break;
515 				}
516 
517 				if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) {
518 					int s = -1;
519 					int n = 1;
520 					do {
521 						if (nextSym == BZip2Constants.RunA) {
522 							s += (0 + 1) * n;
523 						} else if (nextSym == BZip2Constants.RunB) {
524 							s += (1 + 1) * n;
525 						}
526 
527 						n <<= 1;
528 
529 						if (groupPos == 0) {
530 							groupNo++;
531 							groupPos = BZip2Constants.GroupSize;
532 						}
533 
534 						groupPos--;
535 
536 						zt = selector[groupNo];
537 						zn = minLens[zt];
538 						zvec = BsR(zn);
539 
540 						while (zvec > limit[zt][zn]) {
541 							zn++;
542 							while (bsLive < 1) {
543 								FillBuffer();
544 							}
545 							zj = (bsBuff >> (bsLive - 1)) & 1;
546 							bsLive--;
547 							zvec = (zvec << 1) | zj;
548 						}
549 						nextSym = perm[zt][zvec - baseArray[zt][zn]];
550 					} while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
551 
552 					s++;
553 					byte ch = seqToUnseq[yy[0]];
554 					unzftab[ch] += s;
555 
556 					while (s > 0) {
557 						last++;
558 						ll8[last] = ch;
559 						s--;
560 					}
561 
562 					if (last >= limitLast) {
563 						BlockOverrun();
564 					}
565 					continue;
566 				} else {
567 					last++;
568 					if (last >= limitLast) {
569 						BlockOverrun();
570 					}
571 
572 					byte tmp = yy[nextSym - 1];
573 					unzftab[seqToUnseq[tmp]]++;
574 					ll8[last] = seqToUnseq[tmp];
575 
576 					for (int j = nextSym - 1; j > 0; --j) {
577 						yy[j] = yy[j - 1];
578 					}
579 					yy[0] = tmp;
580 
581 					if (groupPos == 0) {
582 						groupNo++;
583 						groupPos = BZip2Constants.GroupSize;
584 					}
585 
586 					groupPos--;
587 					zt = selector[groupNo];
588 					zn = minLens[zt];
589 					zvec = BsR(zn);
590 					while (zvec > limit[zt][zn]) {
591 						zn++;
592 						while (bsLive < 1) {
593 							FillBuffer();
594 						}
595 						zj = (bsBuff >> (bsLive - 1)) & 1;
596 						bsLive--;
597 						zvec = (zvec << 1) | zj;
598 					}
599 					nextSym = perm[zt][zvec - baseArray[zt][zn]];
600 					continue;
601 				}
602 			}
603 		}
604 
SetupBlock()605 		void SetupBlock()
606 		{
607 			int[] cftab = new int[257];
608 
609 			cftab[0] = 0;
610 			Array.Copy(unzftab, 0, cftab, 1, 256);
611 
612 			for (int i = 1; i <= 256; i++) {
613 				cftab[i] += cftab[i - 1];
614 			}
615 
616 			for (int i = 0; i <= last; i++) {
617 				byte ch = ll8[i];
618 				tt[cftab[ch]] = i;
619 				cftab[ch]++;
620 			}
621 
622 			cftab = null;
623 
624 			tPos = tt[origPtr];
625 
626 			count = 0;
627 			i2 = 0;
628 			ch2 = 256;   /*-- not a char and not EOF --*/
629 
630 			if (blockRandomised) {
631 				rNToGo = 0;
632 				rTPos = 0;
633 				SetupRandPartA();
634 			} else {
635 				SetupNoRandPartA();
636 			}
637 		}
638 
SetupRandPartA()639 		void SetupRandPartA()
640 		{
641 			if (i2 <= last) {
642 				chPrev = ch2;
643 				ch2 = ll8[tPos];
644 				tPos = tt[tPos];
645 				if (rNToGo == 0) {
646 					rNToGo = BZip2Constants.RandomNumbers[rTPos];
647 					rTPos++;
648 					if (rTPos == 512) {
649 						rTPos = 0;
650 					}
651 				}
652 				rNToGo--;
653 				ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
654 				i2++;
655 
656 				currentChar = ch2;
657 				currentState = RAND_PART_B_STATE;
658 				mCrc.Update(ch2);
659 			} else {
660 				EndBlock();
661 				InitBlock();
662 				SetupBlock();
663 			}
664 		}
665 
SetupNoRandPartA()666 		void SetupNoRandPartA()
667 		{
668 			if (i2 <= last) {
669 				chPrev = ch2;
670 				ch2 = ll8[tPos];
671 				tPos = tt[tPos];
672 				i2++;
673 
674 				currentChar = ch2;
675 				currentState = NO_RAND_PART_B_STATE;
676 				mCrc.Update(ch2);
677 			} else {
678 				EndBlock();
679 				InitBlock();
680 				SetupBlock();
681 			}
682 		}
683 
SetupRandPartB()684 		void SetupRandPartB()
685 		{
686 			if (ch2 != chPrev) {
687 				currentState = RAND_PART_A_STATE;
688 				count = 1;
689 				SetupRandPartA();
690 			} else {
691 				count++;
692 				if (count >= 4) {
693 					z = ll8[tPos];
694 					tPos = tt[tPos];
695 					if (rNToGo == 0) {
696 						rNToGo = BZip2Constants.RandomNumbers[rTPos];
697 						rTPos++;
698 						if (rTPos == 512) {
699 							rTPos = 0;
700 						}
701 					}
702 					rNToGo--;
703 					z ^= (byte)((rNToGo == 1) ? 1 : 0);
704 					j2 = 0;
705 					currentState = RAND_PART_C_STATE;
706 					SetupRandPartC();
707 				} else {
708 					currentState = RAND_PART_A_STATE;
709 					SetupRandPartA();
710 				}
711 			}
712 		}
713 
SetupRandPartC()714 		void SetupRandPartC()
715 		{
716 			if (j2 < (int)z) {
717 				currentChar = ch2;
718 				mCrc.Update(ch2);
719 				j2++;
720 			} else {
721 				currentState = RAND_PART_A_STATE;
722 				i2++;
723 				count = 0;
724 				SetupRandPartA();
725 			}
726 		}
727 
SetupNoRandPartB()728 		void SetupNoRandPartB()
729 		{
730 			if (ch2 != chPrev) {
731 				currentState = NO_RAND_PART_A_STATE;
732 				count = 1;
733 				SetupNoRandPartA();
734 			} else {
735 				count++;
736 				if (count >= 4) {
737 					z = ll8[tPos];
738 					tPos = tt[tPos];
739 					currentState = NO_RAND_PART_C_STATE;
740 					j2 = 0;
741 					SetupNoRandPartC();
742 				} else {
743 					currentState = NO_RAND_PART_A_STATE;
744 					SetupNoRandPartA();
745 				}
746 			}
747 		}
748 
SetupNoRandPartC()749 		void SetupNoRandPartC()
750 		{
751 			if (j2 < (int)z) {
752 				currentChar = ch2;
753 				mCrc.Update(ch2);
754 				j2++;
755 			} else {
756 				currentState = NO_RAND_PART_A_STATE;
757 				i2++;
758 				count = 0;
759 				SetupNoRandPartA();
760 			}
761 		}
762 
SetDecompressStructureSizes(int newSize100k)763 		void SetDecompressStructureSizes(int newSize100k)
764 		{
765 			if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {
766 				throw new BZip2Exception("Invalid block size");
767 			}
768 
769 			blockSize100k = newSize100k;
770 
771 			if (newSize100k == 0) {
772 				return;
773 			}
774 
775 			int n = BZip2Constants.BaseBlockSize * newSize100k;
776 			ll8 = new byte[n];
777 			tt = new int[n];
778 		}
779 
CompressedStreamEOF()780 		static void CompressedStreamEOF()
781 		{
782 			throw new EndOfStreamException("BZip2 input stream end of compressed stream");
783 		}
784 
BlockOverrun()785 		static void BlockOverrun()
786 		{
787 			throw new BZip2Exception("BZip2 input stream block overrun");
788 		}
789 
BadBlockHeader()790 		static void BadBlockHeader()
791 		{
792 			throw new BZip2Exception("BZip2 input stream bad block header");
793 		}
794 
CrcError()795 		static void CrcError()
796 		{
797 			throw new BZip2Exception("BZip2 input stream crc error");
798 		}
799 
HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize)800 		static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize)
801 		{
802 			int pp = 0;
803 
804 			for (int i = minLen; i <= maxLen; ++i) {
805 				for (int j = 0; j < alphaSize; ++j) {
806 					if (length[j] == i) {
807 						perm[pp] = j;
808 						++pp;
809 					}
810 				}
811 			}
812 
813 			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
814 				baseArray[i] = 0;
815 			}
816 
817 			for (int i = 0; i < alphaSize; i++) {
818 				++baseArray[length[i] + 1];
819 			}
820 
821 			for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++) {
822 				baseArray[i] += baseArray[i - 1];
823 			}
824 
825 			for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++) {
826 				limit[i] = 0;
827 			}
828 
829 			int vec = 0;
830 
831 			for (int i = minLen; i <= maxLen; i++) {
832 				vec += (baseArray[i + 1] - baseArray[i]);
833 				limit[i] = vec - 1;
834 				vec <<= 1;
835 			}
836 
837 			for (int i = minLen + 1; i <= maxLen; i++) {
838 				baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
839 			}
840 		}
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;
864 		IChecksum mCrc = new BZip2Crc();
865 
866 		bool[] inUse = new bool[256];
867 		int nInUse;
868 
869 		byte[] seqToUnseq = new byte[256];
870 		byte[] unseqToSeq = new byte[256];
871 
872 		byte[] selector = new byte[BZip2Constants.MaximumSelectors];
873 		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 		--*/
882 		int[] unzftab = new int[256];
883 
884 		int[][] limit = new int[BZip2Constants.GroupCount][];
885 		int[][] baseArray = new int[BZip2Constants.GroupCount][];
886 		int[][] perm = new int[BZip2Constants.GroupCount][];
887 		int[] minLens = new int[BZip2Constants.GroupCount];
888 
889 		Stream baseStream;
890 		bool streamEnd;
891 
892 		int currentChar = -1;
893 
894 		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;
906 		bool isStreamOwner = true;
907 		#endregion
908 	}
909 }
910