comparison BZip2/BZip2InputStream.cs @ 1:94e25b786321

Re #311: can't read ZIP file packed by Linux app Archive Manager/File Roller Initial commit of clean SharpZipLib 0860 source. Only change is build paths.
author IBBoard <dev@ibboard.co.uk>
date Sat, 30 Oct 2010 14:03:17 +0000
parents
children
comparison
equal deleted inserted replaced
0:d16ef17fa7bb 1:94e25b786321
1 // BZip2InputStream.cs
2 //
3 // Copyright (C) 2001 Mike Krueger
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 //
19 // Linking this library statically or dynamically with other modules is
20 // making a combined work based on this library. Thus, the terms and
21 // conditions of the GNU General Public License cover the whole
22 // combination.
23 //
24 // As a special exception, the copyright holders of this library give you
25 // permission to link this library with independent modules to produce an
26 // executable, regardless of the license terms of these independent
27 // modules, and to copy and distribute the resulting executable under
28 // terms of your choice, provided that you also meet, for each linked
29 // independent module, the terms and conditions of the license of that
30 // module. An independent module is a module which is not derived from
31 // or based on this library. If you modify this library, you may extend
32 // this exception to your version of the library, but you are not
33 // obligated to do so. If you do not wish to do so, delete this
34 // exception statement from your version.
35
36 using System;
37 using System.IO;
38
39 using ICSharpCode.SharpZipLib.Checksums;
40
41 namespace ICSharpCode.SharpZipLib.BZip2
42 {
43
44 /// <summary>
45 /// An input stream that decompresses files in the BZip2 format
46 /// </summary>
47 public class BZip2InputStream : Stream
48 {
49 #region Constants
50 const int START_BLOCK_STATE = 1;
51 const int RAND_PART_A_STATE = 2;
52 const int RAND_PART_B_STATE = 3;
53 const int RAND_PART_C_STATE = 4;
54 const int NO_RAND_PART_A_STATE = 5;
55 const int NO_RAND_PART_B_STATE = 6;
56 const int NO_RAND_PART_C_STATE = 7;
57 #endregion
58 #region Constructors
59 /// <summary>
60 /// Construct instance for reading from stream
61 /// </summary>
62 /// <param name="stream">Data source</param>
63 public BZip2InputStream(Stream stream)
64 {
65 // init arrays
66 for (int i = 0; i < BZip2Constants.GroupCount; ++i)
67 {
68 limit[i] = new int[BZip2Constants.MaximumAlphaSize];
69 baseArray[i] = new int[BZip2Constants.MaximumAlphaSize];
70 perm[i] = new int[BZip2Constants.MaximumAlphaSize];
71 }
72
73 BsSetStream(stream);
74 Initialize();
75 InitBlock();
76 SetupBlock();
77 }
78
79 #endregion
80
81 /// <summary>
82 /// Get/set flag indicating ownership of underlying stream.
83 /// When the flag is true <see cref="Close"></see> will close the underlying stream also.
84 /// </summary>
85 public bool IsStreamOwner
86 {
87 get { return isStreamOwner; }
88 set { isStreamOwner = value; }
89 }
90
91
92 #region Stream Overrides
93 /// <summary>
94 /// Gets a value indicating if the stream supports reading
95 /// </summary>
96 public override bool CanRead
97 {
98 get {
99 return baseStream.CanRead;
100 }
101 }
102
103 /// <summary>
104 /// Gets a value indicating whether the current stream supports seeking.
105 /// </summary>
106 public override bool CanSeek {
107 get {
108 return baseStream.CanSeek;
109 }
110 }
111
112 /// <summary>
113 /// Gets a value indicating whether the current stream supports writing.
114 /// This property always returns false
115 /// </summary>
116 public override bool CanWrite {
117 get {
118 return false;
119 }
120 }
121
122 /// <summary>
123 /// Gets the length in bytes of the stream.
124 /// </summary>
125 public override long Length {
126 get {
127 return baseStream.Length;
128 }
129 }
130
131 /// <summary>
132 /// Gets or sets the streams position.
133 /// Setting the position is not supported and will throw a NotSupportException
134 /// </summary>
135 /// <exception cref="NotSupportedException">Any attempt to set the position</exception>
136 public override long Position {
137 get {
138 return baseStream.Position;
139 }
140 set {
141 throw new NotSupportedException("BZip2InputStream position cannot be set");
142 }
143 }
144
145 /// <summary>
146 /// Flushes the stream.
147 /// </summary>
148 public override void Flush()
149 {
150 if (baseStream != null) {
151 baseStream.Flush();
152 }
153 }
154
155 /// <summary>
156 /// Set the streams position. This operation is not supported and will throw a NotSupportedException
157 /// </summary>
158 /// <param name="offset">A byte offset relative to the <paramref name="origin"/> parameter.</param>
159 /// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
160 /// <returns>The new position of the stream.</returns>
161 /// <exception cref="NotSupportedException">Any access</exception>
162 public override long Seek(long offset, SeekOrigin origin)
163 {
164 throw new NotSupportedException("BZip2InputStream Seek not supported");
165 }
166
167 /// <summary>
168 /// Sets the length of this stream to the given value.
169 /// This operation is not supported and will throw a NotSupportedExceptionortedException
170 /// </summary>
171 /// <param name="value">The new length for the stream.</param>
172 /// <exception cref="NotSupportedException">Any access</exception>
173 public override void SetLength(long value)
174 {
175 throw new NotSupportedException("BZip2InputStream SetLength not supported");
176 }
177
178 /// <summary>
179 /// Writes a block of bytes to this stream using data from a buffer.
180 /// This operation is not supported and will throw a NotSupportedException
181 /// </summary>
182 /// <param name="buffer">The buffer to source data from.</param>
183 /// <param name="offset">The offset to start obtaining data from.</param>
184 /// <param name="count">The number of bytes of data to write.</param>
185 /// <exception cref="NotSupportedException">Any access</exception>
186 public override void Write(byte[] buffer, int offset, int count)
187 {
188 throw new NotSupportedException("BZip2InputStream Write not supported");
189 }
190
191 /// <summary>
192 /// Writes a byte to the current position in the file stream.
193 /// This operation is not supported and will throw a NotSupportedException
194 /// </summary>
195 /// <param name="value">The value to write.</param>
196 /// <exception cref="NotSupportedException">Any access</exception>
197 public override void WriteByte(byte value)
198 {
199 throw new NotSupportedException("BZip2InputStream WriteByte not supported");
200 }
201
202 /// <summary>
203 /// Read a sequence of bytes and advances the read position by one byte.
204 /// </summary>
205 /// <param name="buffer">Array of bytes to store values in</param>
206 /// <param name="offset">Offset in array to begin storing data</param>
207 /// <param name="count">The maximum number of bytes to read</param>
208 /// <returns>The total number of bytes read into the buffer. This might be less
209 /// than the number of bytes requested if that number of bytes are not
210 /// currently available or zero if the end of the stream is reached.
211 /// </returns>
212 public override int Read(byte[] buffer, int offset, int count)
213 {
214 if ( buffer == null )
215 {
216 throw new ArgumentNullException("buffer");
217 }
218
219 for (int i = 0; i < count; ++i) {
220 int rb = ReadByte();
221 if (rb == -1) {
222 return i;
223 }
224 buffer[offset + i] = (byte)rb;
225 }
226 return count;
227 }
228
229 /// <summary>
230 /// Closes the stream, releasing any associated resources.
231 /// </summary>
232 public override void Close()
233 {
234 if ( IsStreamOwner && (baseStream != null) ) {
235 baseStream.Close();
236 }
237 }
238 /// <summary>
239 /// Read a byte from stream advancing position
240 /// </summary>
241 /// <returns>byte read or -1 on end of stream</returns>
242 public override int ReadByte()
243 {
244 if (streamEnd)
245 {
246 return -1; // ok
247 }
248
249 int retChar = currentChar;
250 switch (currentState)
251 {
252 case RAND_PART_B_STATE:
253 SetupRandPartB();
254 break;
255 case RAND_PART_C_STATE:
256 SetupRandPartC();
257 break;
258 case NO_RAND_PART_B_STATE:
259 SetupNoRandPartB();
260 break;
261 case NO_RAND_PART_C_STATE:
262 SetupNoRandPartC();
263 break;
264 case START_BLOCK_STATE:
265 case NO_RAND_PART_A_STATE:
266 case RAND_PART_A_STATE:
267 break;
268 default:
269 break;
270 }
271 return retChar;
272 }
273
274 #endregion
275
276 void MakeMaps()
277 {
278 nInUse = 0;
279 for (int i = 0; i < 256; ++i) {
280 if (inUse[i]) {
281 seqToUnseq[nInUse] = (byte)i;
282 unseqToSeq[i] = (byte)nInUse;
283 nInUse++;
284 }
285 }
286 }
287
288 void Initialize()
289 {
290 char magic1 = BsGetUChar();
291 char magic2 = BsGetUChar();
292
293 char magic3 = BsGetUChar();
294 char magic4 = BsGetUChar();
295
296 if (magic1 != 'B' || magic2 != 'Z' || magic3 != 'h' || magic4 < '1' || magic4 > '9') {
297 streamEnd = true;
298 return;
299 }
300
301 SetDecompressStructureSizes(magic4 - '0');
302 computedCombinedCRC = 0;
303 }
304
305 void InitBlock()
306 {
307 char magic1 = BsGetUChar();
308 char magic2 = BsGetUChar();
309 char magic3 = BsGetUChar();
310 char magic4 = BsGetUChar();
311 char magic5 = BsGetUChar();
312 char magic6 = BsGetUChar();
313
314 if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
315 Complete();
316 return;
317 }
318
319 if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
320 BadBlockHeader();
321 streamEnd = true;
322 return;
323 }
324
325 storedBlockCRC = BsGetInt32();
326
327 blockRandomised = (BsR(1) == 1);
328
329 GetAndMoveToFrontDecode();
330
331 mCrc.Reset();
332 currentState = START_BLOCK_STATE;
333 }
334
335 void EndBlock()
336 {
337 computedBlockCRC = (int)mCrc.Value;
338
339 // -- A bad CRC is considered a fatal error. --
340 if (storedBlockCRC != computedBlockCRC) {
341 CrcError();
342 }
343
344 // 1528150659
345 computedCombinedCRC = ((computedCombinedCRC << 1) & 0xFFFFFFFF) | (computedCombinedCRC >> 31);
346 computedCombinedCRC = computedCombinedCRC ^ (uint)computedBlockCRC;
347 }
348
349 void Complete()
350 {
351 storedCombinedCRC = BsGetInt32();
352 if (storedCombinedCRC != (int)computedCombinedCRC) {
353 CrcError();
354 }
355
356 streamEnd = true;
357 }
358
359 void BsSetStream(Stream stream)
360 {
361 baseStream = stream;
362 bsLive = 0;
363 bsBuff = 0;
364 }
365
366 void FillBuffer()
367 {
368 int thech = 0;
369
370 try {
371 thech = baseStream.ReadByte();
372 } catch (Exception) {
373 CompressedStreamEOF();
374 }
375
376 if (thech == -1) {
377 CompressedStreamEOF();
378 }
379
380 bsBuff = (bsBuff << 8) | (thech & 0xFF);
381 bsLive += 8;
382 }
383
384 int BsR(int n)
385 {
386 while (bsLive < n) {
387 FillBuffer();
388 }
389
390 int v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
391 bsLive -= n;
392 return v;
393 }
394
395 char BsGetUChar()
396 {
397 return (char)BsR(8);
398 }
399
400 int BsGetIntVS(int numBits)
401 {
402 return BsR(numBits);
403 }
404
405 int BsGetInt32()
406 {
407 int result = BsR(8);
408 result = (result << 8) | BsR(8);
409 result = (result << 8) | BsR(8);
410 result = (result << 8) | BsR(8);
411 return result;
412 }
413
414 void RecvDecodingTables()
415 {
416 char[][] len = new char[BZip2Constants.GroupCount][];
417 for (int i = 0; i < BZip2Constants.GroupCount; ++i) {
418 len[i] = new char[BZip2Constants.MaximumAlphaSize];
419 }
420
421 bool[] inUse16 = new bool[16];
422
423 //--- Receive the mapping table ---
424 for (int i = 0; i < 16; i++) {
425 inUse16[i] = (BsR(1) == 1);
426 }
427
428 for (int i = 0; i < 16; i++) {
429 if (inUse16[i]) {
430 for (int j = 0; j < 16; j++) {
431 inUse[i * 16 + j] = (BsR(1) == 1);
432 }
433 } else {
434 for (int j = 0; j < 16; j++) {
435 inUse[i * 16 + j] = false;
436 }
437 }
438 }
439
440 MakeMaps();
441 int alphaSize = nInUse + 2;
442
443 //--- Now the selectors ---
444 int nGroups = BsR(3);
445 int nSelectors = BsR(15);
446
447 for (int i = 0; i < nSelectors; i++) {
448 int j = 0;
449 while (BsR(1) == 1) {
450 j++;
451 }
452 selectorMtf[i] = (byte)j;
453 }
454
455 //--- Undo the MTF values for the selectors. ---
456 byte[] pos = new byte[BZip2Constants.GroupCount];
457 for (int v = 0; v < nGroups; v++) {
458 pos[v] = (byte)v;
459 }
460
461 for (int i = 0; i < nSelectors; i++) {
462 int v = selectorMtf[i];
463 byte tmp = pos[v];
464 while (v > 0) {
465 pos[v] = pos[v - 1];
466 v--;
467 }
468 pos[0] = tmp;
469 selector[i] = tmp;
470 }
471
472 //--- Now the coding tables ---
473 for (int t = 0; t < nGroups; t++) {
474 int curr = BsR(5);
475 for (int i = 0; i < alphaSize; i++) {
476 while (BsR(1) == 1) {
477 if (BsR(1) == 0) {
478 curr++;
479 } else {
480 curr--;
481 }
482 }
483 len[t][i] = (char)curr;
484 }
485 }
486
487 //--- Create the Huffman decoding tables ---
488 for (int t = 0; t < nGroups; t++) {
489 int minLen = 32;
490 int maxLen = 0;
491 for (int i = 0; i < alphaSize; i++) {
492 maxLen = Math.Max(maxLen, len[t][i]);
493 minLen = Math.Min(minLen, len[t][i]);
494 }
495 HbCreateDecodeTables(limit[t], baseArray[t], perm[t], len[t], minLen, maxLen, alphaSize);
496 minLens[t] = minLen;
497 }
498 }
499
500 void GetAndMoveToFrontDecode()
501 {
502 byte[] yy = new byte[256];
503 int nextSym;
504
505 int limitLast = BZip2Constants.BaseBlockSize * blockSize100k;
506 origPtr = BsGetIntVS(24);
507
508 RecvDecodingTables();
509 int EOB = nInUse+1;
510 int groupNo = -1;
511 int groupPos = 0;
512
513 /*--
514 Setting up the unzftab entries here is not strictly
515 necessary, but it does save having to do it later
516 in a separate pass, and so saves a block's worth of
517 cache misses.
518 --*/
519 for (int i = 0; i <= 255; i++) {
520 unzftab[i] = 0;
521 }
522
523 for (int i = 0; i <= 255; i++) {
524 yy[i] = (byte)i;
525 }
526
527 last = -1;
528
529 if (groupPos == 0) {
530 groupNo++;
531 groupPos = BZip2Constants.GroupSize;
532 }
533
534 groupPos--;
535 int zt = selector[groupNo];
536 int zn = minLens[zt];
537 int zvec = BsR(zn);
538 int zj;
539
540 while (zvec > limit[zt][zn]) {
541 if (zn > 20) { // the longest code
542 throw new BZip2Exception("Bzip data error");
543 }
544 zn++;
545 while (bsLive < 1) {
546 FillBuffer();
547 }
548 zj = (bsBuff >> (bsLive-1)) & 1;
549 bsLive--;
550 zvec = (zvec << 1) | zj;
551 }
552 if (zvec - baseArray[zt][zn] < 0 || zvec - baseArray[zt][zn] >= BZip2Constants.MaximumAlphaSize) {
553 throw new BZip2Exception("Bzip data error");
554 }
555 nextSym = perm[zt][zvec - baseArray[zt][zn]];
556
557 while (true) {
558 if (nextSym == EOB) {
559 break;
560 }
561
562 if (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB) {
563 int s = -1;
564 int n = 1;
565 do {
566 if (nextSym == BZip2Constants.RunA) {
567 s += (0 + 1) * n;
568 } else if (nextSym == BZip2Constants.RunB) {
569 s += (1 + 1) * n;
570 }
571
572 n <<= 1;
573
574 if (groupPos == 0) {
575 groupNo++;
576 groupPos = BZip2Constants.GroupSize;
577 }
578
579 groupPos--;
580
581 zt = selector[groupNo];
582 zn = minLens[zt];
583 zvec = BsR(zn);
584
585 while (zvec > limit[zt][zn]) {
586 zn++;
587 while (bsLive < 1) {
588 FillBuffer();
589 }
590 zj = (bsBuff >> (bsLive - 1)) & 1;
591 bsLive--;
592 zvec = (zvec << 1) | zj;
593 }
594 nextSym = perm[zt][zvec - baseArray[zt][zn]];
595 } while (nextSym == BZip2Constants.RunA || nextSym == BZip2Constants.RunB);
596
597 s++;
598 byte ch = seqToUnseq[yy[0]];
599 unzftab[ch] += s;
600
601 while (s > 0) {
602 last++;
603 ll8[last] = ch;
604 s--;
605 }
606
607 if (last >= limitLast) {
608 BlockOverrun();
609 }
610 continue;
611 } else {
612 last++;
613 if (last >= limitLast) {
614 BlockOverrun();
615 }
616
617 byte tmp = yy[nextSym - 1];
618 unzftab[seqToUnseq[tmp]]++;
619 ll8[last] = seqToUnseq[tmp];
620
621 for (int j = nextSym-1; j > 0; --j) {
622 yy[j] = yy[j - 1];
623 }
624 yy[0] = tmp;
625
626 if (groupPos == 0) {
627 groupNo++;
628 groupPos = BZip2Constants.GroupSize;
629 }
630
631 groupPos--;
632 zt = selector[groupNo];
633 zn = minLens[zt];
634 zvec = BsR(zn);
635 while (zvec > limit[zt][zn]) {
636 zn++;
637 while (bsLive < 1) {
638 FillBuffer();
639 }
640 zj = (bsBuff >> (bsLive-1)) & 1;
641 bsLive--;
642 zvec = (zvec << 1) | zj;
643 }
644 nextSym = perm[zt][zvec - baseArray[zt][zn]];
645 continue;
646 }
647 }
648 }
649
650 void SetupBlock()
651 {
652 int[] cftab = new int[257];
653
654 cftab[0] = 0;
655 Array.Copy(unzftab, 0, cftab, 1, 256);
656
657 for (int i = 1; i <= 256; i++) {
658 cftab[i] += cftab[i - 1];
659 }
660
661 for (int i = 0; i <= last; i++) {
662 byte ch = ll8[i];
663 tt[cftab[ch]] = i;
664 cftab[ch]++;
665 }
666
667 cftab = null;
668
669 tPos = tt[origPtr];
670
671 count = 0;
672 i2 = 0;
673 ch2 = 256; /*-- not a char and not EOF --*/
674
675 if (blockRandomised) {
676 rNToGo = 0;
677 rTPos = 0;
678 SetupRandPartA();
679 } else {
680 SetupNoRandPartA();
681 }
682 }
683
684 void SetupRandPartA()
685 {
686 if (i2 <= last) {
687 chPrev = ch2;
688 ch2 = ll8[tPos];
689 tPos = tt[tPos];
690 if (rNToGo == 0) {
691 rNToGo = BZip2Constants.RandomNumbers[rTPos];
692 rTPos++;
693 if (rTPos == 512) {
694 rTPos = 0;
695 }
696 }
697 rNToGo--;
698 ch2 ^= (int)((rNToGo == 1) ? 1 : 0);
699 i2++;
700
701 currentChar = ch2;
702 currentState = RAND_PART_B_STATE;
703 mCrc.Update(ch2);
704 } else {
705 EndBlock();
706 InitBlock();
707 SetupBlock();
708 }
709 }
710
711 void SetupNoRandPartA()
712 {
713 if (i2 <= last) {
714 chPrev = ch2;
715 ch2 = ll8[tPos];
716 tPos = tt[tPos];
717 i2++;
718
719 currentChar = ch2;
720 currentState = NO_RAND_PART_B_STATE;
721 mCrc.Update(ch2);
722 } else {
723 EndBlock();
724 InitBlock();
725 SetupBlock();
726 }
727 }
728
729 void SetupRandPartB()
730 {
731 if (ch2 != chPrev) {
732 currentState = RAND_PART_A_STATE;
733 count = 1;
734 SetupRandPartA();
735 } else {
736 count++;
737 if (count >= 4) {
738 z = ll8[tPos];
739 tPos = tt[tPos];
740 if (rNToGo == 0) {
741 rNToGo = BZip2Constants.RandomNumbers[rTPos];
742 rTPos++;
743 if (rTPos == 512) {
744 rTPos = 0;
745 }
746 }
747 rNToGo--;
748 z ^= (byte)((rNToGo == 1) ? 1 : 0);
749 j2 = 0;
750 currentState = RAND_PART_C_STATE;
751 SetupRandPartC();
752 } else {
753 currentState = RAND_PART_A_STATE;
754 SetupRandPartA();
755 }
756 }
757 }
758
759 void SetupRandPartC()
760 {
761 if (j2 < (int)z) {
762 currentChar = ch2;
763 mCrc.Update(ch2);
764 j2++;
765 } else {
766 currentState = RAND_PART_A_STATE;
767 i2++;
768 count = 0;
769 SetupRandPartA();
770 }
771 }
772
773 void SetupNoRandPartB()
774 {
775 if (ch2 != chPrev) {
776 currentState = NO_RAND_PART_A_STATE;
777 count = 1;
778 SetupNoRandPartA();
779 } else {
780 count++;
781 if (count >= 4) {
782 z = ll8[tPos];
783 tPos = tt[tPos];
784 currentState = NO_RAND_PART_C_STATE;
785 j2 = 0;
786 SetupNoRandPartC();
787 } else {
788 currentState = NO_RAND_PART_A_STATE;
789 SetupNoRandPartA();
790 }
791 }
792 }
793
794 void SetupNoRandPartC()
795 {
796 if (j2 < (int)z) {
797 currentChar = ch2;
798 mCrc.Update(ch2);
799 j2++;
800 } else {
801 currentState = NO_RAND_PART_A_STATE;
802 i2++;
803 count = 0;
804 SetupNoRandPartA();
805 }
806 }
807
808 void SetDecompressStructureSizes(int newSize100k)
809 {
810 if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k && blockSize100k <= 9)) {
811 throw new BZip2Exception("Invalid block size");
812 }
813
814 blockSize100k = newSize100k;
815
816 if (newSize100k == 0) {
817 return;
818 }
819
820 int n = BZip2Constants.BaseBlockSize * newSize100k;
821 ll8 = new byte[n];
822 tt = new int[n];
823 }
824
825 static void CompressedStreamEOF()
826 {
827 throw new EndOfStreamException("BZip2 input stream end of compressed stream");
828 }
829
830 static void BlockOverrun()
831 {
832 throw new BZip2Exception("BZip2 input stream block overrun");
833 }
834
835 static void BadBlockHeader()
836 {
837 throw new BZip2Exception("BZip2 input stream bad block header");
838 }
839
840 static void CrcError()
841 {
842 throw new BZip2Exception("BZip2 input stream crc error");
843 }
844
845 static void HbCreateDecodeTables(int[] limit, int[] baseArray, int[] perm, char[] length, int minLen, int maxLen, int alphaSize)
846 {
847 int pp = 0;
848
849 for (int i = minLen; i <= maxLen; ++i)
850 {
851 for (int j = 0; j < alphaSize; ++j)
852 {
853 if (length[j] == i)
854 {
855 perm[pp] = j;
856 ++pp;
857 }
858 }
859 }
860
861 for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++)
862 {
863 baseArray[i] = 0;
864 }
865
866 for (int i = 0; i < alphaSize; i++)
867 {
868 ++baseArray[length[i] + 1];
869 }
870
871 for (int i = 1; i < BZip2Constants.MaximumCodeLength; i++)
872 {
873 baseArray[i] += baseArray[i - 1];
874 }
875
876 for (int i = 0; i < BZip2Constants.MaximumCodeLength; i++)
877 {
878 limit[i] = 0;
879 }
880
881 int vec = 0;
882
883 for (int i = minLen; i <= maxLen; i++)
884 {
885 vec += (baseArray[i + 1] - baseArray[i]);
886 limit[i] = vec - 1;
887 vec <<= 1;
888 }
889
890 for (int i = minLen + 1; i <= maxLen; i++)
891 {
892 baseArray[i] = ((limit[i - 1] + 1) << 1) - baseArray[i];
893 }
894 }
895
896 #region Instance Fields
897 /*--
898 index of the last char in the block, so
899 the block size == last + 1.
900 --*/
901 int last;
902
903 /*--
904 index in zptr[] of original string after sorting.
905 --*/
906 int origPtr;
907
908 /*--
909 always: in the range 0 .. 9.
910 The current block size is 100000 * this number.
911 --*/
912 int blockSize100k;
913
914 bool blockRandomised;
915
916 int bsBuff;
917 int bsLive;
918 IChecksum mCrc = new StrangeCRC();
919
920 bool[] inUse = new bool[256];
921 int nInUse;
922
923 byte[] seqToUnseq = new byte[256];
924 byte[] unseqToSeq = new byte[256];
925
926 byte[] selector = new byte[BZip2Constants.MaximumSelectors];
927 byte[] selectorMtf = new byte[BZip2Constants.MaximumSelectors];
928
929 int[] tt;
930 byte[] ll8;
931
932 /*--
933 freq table collected to save a pass over the data
934 during decompression.
935 --*/
936 int[] unzftab = new int[256];
937
938 int[][] limit = new int[BZip2Constants.GroupCount][];
939 int[][] baseArray = new int[BZip2Constants.GroupCount][];
940 int[][] perm = new int[BZip2Constants.GroupCount][];
941 int[] minLens = new int[BZip2Constants.GroupCount];
942
943 Stream baseStream;
944 bool streamEnd;
945
946 int currentChar = -1;
947
948 int currentState = START_BLOCK_STATE;
949
950 int storedBlockCRC, storedCombinedCRC;
951 int computedBlockCRC;
952 uint computedCombinedCRC;
953
954 int count, chPrev, ch2;
955 int tPos;
956 int rNToGo;
957 int rTPos;
958 int i2, j2;
959 byte z;
960 bool isStreamOwner = true;
961 #endregion
962 }
963 }
964 /* This file was derived from a file containing this license:
965 *
966 * This file is a part of bzip2 and/or libbzip2, a program and
967 * library for lossless, block-sorting data compression.
968 *
969 * Copyright (C) 1996-1998 Julian R Seward. All rights reserved.
970 *
971 * Redistribution and use in source and binary forms, with or without
972 * modification, are permitted provided that the following conditions
973 * are met:
974 *
975 * 1. Redistributions of source code must retain the above copyright
976 * notice, this list of conditions and the following disclaimer.
977 *
978 * 2. The origin of this software must not be misrepresented; you must
979 * not claim that you wrote the original software. If you use this
980 * software in a product, an acknowledgment in the product
981 * documentation would be appreciated but is not required.
982 *
983 * 3. Altered source versions must be plainly marked as such, and must
984 * not be misrepresented as being the original software.
985 *
986 * 4. The name of the author may not be used to endorse or promote
987 * products derived from this software without specific prior written
988 * permission.
989 *
990 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
991 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
992 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
993 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
994 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
995 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
996 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
997 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
998 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
999 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1000 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1001 *
1002 * Java version ported by Keiron Liddle, Aftex Software <keiron@aftexsw.com> 1999-2001
1003 */