2 // (This file is the NZipLib sources with a crude benchmark class attached -
3 // 2002-15-05 Dan Lewis <dihlewis@yahoo.co.uk>)
4 // -------------------------------------------------------------------------
7 // Copyright (C) 2001 Mike Krueger
9 // This file was translated from java, it was part of the GNU Classpath
10 // Copyright (C) 2001 Free Software Foundation, Inc.
12 // This program is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU General Public License
14 // as published by the Free Software Foundation; either version 2
15 // of the License, or (at your option) any later version.
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 // As a special exception, if you link this library with other files to
27 // produce an executable, this library does not by itself cause the
28 // resulting executable to be covered by the GNU General Public License.
29 // This exception does not however invalidate any other reasons why the
30 // executable file might be covered by the GNU General Public License.
35 using NZlib
.Checksums
;
36 using NZlib
.Compression
;
39 static int Iterations
= 1000;
40 static int BlockSize
= 1024;
42 public static void Main (string [] args
)
44 if (args
.Length
== 0 || args
.Length
> 3) {
45 Console
.WriteLine ("Usage: zipmark FILE [ITERATIONS] [BLOCKSIZE]");
49 string filename
= args
[0];
50 FileInfo file
= new FileInfo (filename
);
52 Console
.WriteLine ("Couldn't find file {0}", filename
);
56 FileStream fs
= file
.OpenRead ();
58 byte [] raw
= new byte [file
.Length
];
59 int count
= fs
.Read (raw
, 0, (int)file
.Length
);
62 if (count
!= file
.Length
) {
63 Console
.WriteLine ("Couldn't read file {0}", filename
);
67 Deflater def
= new Deflater (Deflater
.BEST_COMPRESSION
, false);
68 Inflater inf
= new Inflater (false);
70 // 1. Count deflated size
72 int cooked_size
= Deflate (def
, raw
, null);
73 byte [] cooked
= new byte [cooked_size
];
75 // 2. Deflate & Inflate
78 Iterations
= Int32
.Parse (args
[1]);
80 BlockSize
= Int32
.Parse (args
[2]);
82 for (int i
= 0; i
< Iterations
; ++ i
) {
83 Deflate (def
, raw
, cooked
);
84 Inflate (inf
, cooked
, raw
);
90 static int Deflate (Deflater def
, byte [] src
, byte [] dest
)
93 int offset
, length
, remain
;
96 dest
= new byte [BlockSize
];
105 while (!def
.IsFinished
) {
106 if (def
.IsNeedingInput
)
109 remain
= Math
.Min (dest
.Length
- offset
, BlockSize
);
113 length
= def
.Deflate (dest
, offset
, remain
);
121 static int Inflate (Inflater inf
, byte [] src
, byte [] dest
)
123 int offset
, length
, remain
;
129 while (!inf
.IsNeedingInput
) {
130 remain
= Math
.Min (dest
.Length
- offset
, BlockSize
);
134 length
= inf
.Inflate (dest
, offset
, remain
);
142 // ---------------------- NZipLib sources from here on --------------------------
144 namespace NZlib
.Compression
{
147 /// This is the Deflater class. The deflater class compresses input
148 /// with the deflate algorithm described in RFC 1951. It has several
149 /// compression levels and three different strategies described below.
151 /// This class is <i>not</i> thread safe. This is inherent in the API, due
152 /// to the split of deflate and setInput.
154 /// author of the original java version : Jochen Hoenicke
156 public class Deflater
159 /// The best and slowest compression level. This tries to find very
160 /// long and distant string repetitions.
162 public static int BEST_COMPRESSION
= 9;
165 /// The worst but fastest compression level.
167 public static int BEST_SPEED
= 1;
170 /// The default compression level.
172 public static int DEFAULT_COMPRESSION
= -1;
175 /// This level won't compress at all but output uncompressed blocks.
177 public static int NO_COMPRESSION
= 0;
180 /// The default strategy.
182 public static int DEFAULT_STRATEGY
= 0;
186 /// This strategy will only allow longer string repetitions. It is
187 /// useful for random data with a small character set.
189 public static int FILTERED
= 1;
192 /// This strategy will not look for string repetitions at all. It
193 /// only encodes with Huffman trees (which means, that more common
194 /// characters get a smaller encoding.
196 public static int HUFFMAN_ONLY
= 2;
199 /// The compression method. This is the only method supported so far.
200 /// There is no need to use this constant at all.
202 public static int DEFLATED
= 8;
205 * The Deflater can do the following state transitions:
207 * (1) -> INIT_STATE ----> INIT_FINISHING_STATE ---.
210 * (3)| SETDICT_STATE ---> SETDICT_FINISHING_STATE |(3)
211 * \ | (3) | ,-------'
214 * (1) -> BUSY_STATE ----> FINISHING_STATE
218 * \_____________________________________/
223 * (1) If we should produce a header we start in INIT_STATE, otherwise
224 * we start in BUSY_STATE.
225 * (2) A dictionary may be set only when we are in INIT_STATE, then
226 * we change the state as indicated.
227 * (3) Whether a dictionary is set or not, on the first call of deflate
228 * we change to BUSY_STATE.
229 * (4) -- intentionally left blank -- :)
230 * (5) FINISHING_STATE is entered, when flush() is called to indicate that
231 * there is no more INPUT. There are also states indicating, that
232 * the header wasn't written yet.
233 * (6) FINISHED_STATE is entered, when everything has been flushed to the
234 * internal pending output buffer.
235 * (7) At any time (7)
239 private static int IS_SETDICT
= 0x01;
240 private static int IS_FLUSHING
= 0x04;
241 private static int IS_FINISHING
= 0x08;
243 private static int INIT_STATE
= 0x00;
244 private static int SETDICT_STATE
= 0x01;
245 // private static int INIT_FINISHING_STATE = 0x08;
246 // private static int SETDICT_FINISHING_STATE = 0x09;
247 private static int BUSY_STATE
= 0x10;
248 private static int FLUSHING_STATE
= 0x14;
249 private static int FINISHING_STATE
= 0x1c;
250 private static int FINISHED_STATE
= 0x1e;
251 private static int CLOSED_STATE
= 0x7f;
254 /// Compression level.
259 /// should we include a header.
261 private bool noHeader
;
264 // /// Compression strategy.
266 // private int strategy;
269 /// The current state.
274 /// The total bytes of output written.
276 private int totalOut
;
279 /// The pending output.
281 private DeflaterPending pending
;
284 /// The deflater engine.
286 private DeflaterEngine engine
;
289 /// Creates a new deflater with default compression level.
291 public Deflater() : this(DEFAULT_COMPRESSION
, false)
297 /// Creates a new deflater with given compression level.
299 /// <param name="lvl">
300 /// the compression level, a value between NO_COMPRESSION
301 /// and BEST_COMPRESSION, or DEFAULT_COMPRESSION.
303 /// <exception cref="System.ArgumentOutOfRangeException">if lvl is out of range.</exception>
304 public Deflater(int lvl
) : this(lvl
, false)
310 /// Creates a new deflater with given compression level.
312 /// <param name="lvl">
313 /// the compression level, a value between NO_COMPRESSION
314 /// and BEST_COMPRESSION.
316 /// <param name="nowrap">
317 /// true, if we should suppress the deflate header at the
318 /// beginning and the adler checksum at the end of the output. This is
319 /// useful for the GZIP format.
321 /// <exception cref="System.ArgumentOutOfRangeException">if lvl is out of range.</exception>
322 public Deflater(int lvl
, bool nowrap
)
324 if (lvl
== DEFAULT_COMPRESSION
) {
326 } else if (lvl
< NO_COMPRESSION
|| lvl
> BEST_COMPRESSION
) {
327 throw new ArgumentOutOfRangeException("lvl");
330 pending
= new DeflaterPending();
331 engine
= new DeflaterEngine(pending
);
332 this.noHeader
= nowrap
;
333 SetStrategy(DEFAULT_STRATEGY
);
340 /// Resets the deflater. The deflater acts afterwards as if it was
341 /// just created with the same compression level and strategy as it
346 state
= (noHeader
? BUSY_STATE
: INIT_STATE
);
353 /// Gets the current adler checksum of the data that was processed so far.
362 /// Gets the number of input bytes processed so far.
366 return engine
.TotalIn
;
371 /// Gets the number of output bytes so far.
373 public int TotalOut
{
380 /// Flushes the current input block. Further calls to deflate() will
381 /// produce enough output to inflate everything in the current input
382 /// block. This is not part of Sun's JDK so I have made it package
383 /// private. It is used by DeflaterOutputStream to implement
388 state
|= IS_FLUSHING
;
392 /// Finishes the deflater with the current input block. It is an error
393 /// to give more input after this method was called. This method must
394 /// be called to force all bytes to be flushed.
398 state
|= IS_FLUSHING
| IS_FINISHING
;
402 /// Returns true if the stream was finished and no more output bytes
405 public bool IsFinished
{
407 return state
== FINISHED_STATE
&& pending
.IsFlushed
;
412 /// Returns true, if the input buffer is empty.
413 /// You should then call setInput().
414 /// NOTE: This method can also return true when the stream
417 public bool IsNeedingInput
{
419 return engine
.NeedsInput();
424 /// Sets the data which should be compressed next. This should be only
425 /// called when needsInput indicates that more input is needed.
426 /// If you call setInput when needsInput() returns false, the
427 /// previous input that is still pending will be thrown away.
428 /// The given byte array should not be changed, before needsInput() returns
430 /// This call is equivalent to <code>setInput(input, 0, input.length)</code>.
432 /// <param name="input">
433 /// the buffer containing the input data.
435 /// <exception cref="System.InvalidOperationException">
436 /// if the buffer was finished() or ended().
438 public void SetInput(byte[] input
)
440 SetInput(input
, 0, input
.Length
);
444 /// Sets the data which should be compressed next. This should be
445 /// only called when needsInput indicates that more input is needed.
446 /// The given byte array should not be changed, before needsInput() returns
449 /// <param name="input">
450 /// the buffer containing the input data.
452 /// <param name="off">
453 /// the start of the data.
455 /// <param name="len">
456 /// the length of the data.
458 /// <exception cref="System.InvalidOperationException">
459 /// if the buffer was finished() or ended() or if previous input is still pending.
461 public void SetInput(byte[] input
, int off
, int len
)
463 if ((state
& IS_FINISHING
) != 0) {
464 throw new InvalidOperationException("finish()/end() already called");
466 engine
.SetInput(input
, off
, len
);
470 /// Sets the compression level. There is no guarantee of the exact
471 /// position of the change, but if you call this when needsInput is
472 /// true the change of compression level will occur somewhere near
473 /// before the end of the so far given input.
475 /// <param name="lvl">
476 /// the new compression level.
478 public void SetLevel(int lvl
)
480 if (lvl
== DEFAULT_COMPRESSION
) {
482 } else if (lvl
< NO_COMPRESSION
|| lvl
> BEST_COMPRESSION
) {
483 throw new ArgumentOutOfRangeException("lvl");
489 engine
.SetLevel(lvl
);
494 /// Sets the compression strategy. Strategy is one of
495 /// DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact
496 /// position where the strategy is changed, the same as for
497 /// setLevel() applies.
499 /// <param name="stgy">
500 /// the new compression strategy.
502 public void SetStrategy(int stgy
)
504 if (stgy
!= DEFAULT_STRATEGY
&& stgy
!= FILTERED
&& stgy
!= HUFFMAN_ONLY
) {
505 throw new Exception();
507 engine
.Strategy
= stgy
;
511 /// Deflates the current input block to the given array. It returns
512 /// the number of bytes compressed, or 0 if either
513 /// needsInput() or finished() returns true or length is zero.
515 /// <param name="output">
516 /// the buffer where to write the compressed data.
518 public int Deflate(byte[] output
)
520 return Deflate(output
, 0, output
.Length
);
524 /// Deflates the current input block to the given array. It returns
525 /// the number of bytes compressed, or 0 if either
526 /// needsInput() or finished() returns true or length is zero.
528 /// <param name="output">
529 /// the buffer where to write the compressed data.
531 /// <param name="offset">
532 /// the offset into the output array.
534 /// <param name="length">
535 /// the maximum number of bytes that may be written.
537 /// <exception cref="System.InvalidOperationException">
538 /// if end() was called.
540 /// <exception cref="System.ArgumentOutOfRangeException">
541 /// if offset and/or length don't match the array length.
543 public int Deflate(byte[] output
, int offset
, int length
)
545 int origLength
= length
;
547 if (state
== CLOSED_STATE
) {
548 throw new InvalidOperationException("Deflater closed");
551 if (state
< BUSY_STATE
) {
553 int header
= (DEFLATED
+
554 ((DeflaterConstants
.MAX_WBITS
- 8) << 4)) << 8;
555 int level_flags
= (level
- 1) >> 1;
556 if (level_flags
< 0 || level_flags
> 3) {
559 header
|= level_flags
<< 6;
560 if ((state
& IS_SETDICT
) != 0) {
561 /* Dictionary was set */
562 header
|= DeflaterConstants
.PRESET_DICT
;
564 header
+= 31 - (header
% 31);
567 pending
.WriteShortMSB(header
);
568 if ((state
& IS_SETDICT
) != 0) {
569 int chksum
= engine
.Adler
;
571 pending
.WriteShortMSB(chksum
>> 16);
572 pending
.WriteShortMSB(chksum
& 0xffff);
575 state
= BUSY_STATE
| (state
& (IS_FLUSHING
| IS_FINISHING
));
579 int count
= pending
.Flush(output
, offset
, length
);
584 if (length
== 0 || state
== FINISHED_STATE
) {
588 if (!engine
.Deflate((state
& IS_FLUSHING
) != 0, (state
& IS_FINISHING
) != 0)) {
589 if (state
== BUSY_STATE
) {
590 /* We need more input now */
591 return origLength
- length
;
592 } else if (state
== FLUSHING_STATE
) {
593 if (level
!= NO_COMPRESSION
) {
594 /* We have to supply some lookahead. 8 bit lookahead
595 * are needed by the zlib inflater, and we must fill
596 * the next byte, so that all bits are flushed.
598 int neededbits
= 8 + ((-pending
.BitCount
) & 7);
599 while (neededbits
> 0) {
600 /* write a static tree block consisting solely of
603 pending
.WriteBits(2, 10);
608 } else if (state
== FINISHING_STATE
) {
609 pending
.AlignToByte();
610 /* We have completed the stream */
612 int adler
= engine
.Adler
;
613 pending
.WriteShortMSB(adler
>> 16);
614 pending
.WriteShortMSB(adler
& 0xffff);
616 state
= FINISHED_STATE
;
620 return origLength
- length
;
624 /// Sets the dictionary which should be used in the deflate process.
625 /// This call is equivalent to <code>setDictionary(dict, 0, dict.Length)</code>.
627 /// <param name="dict">
630 /// <exception cref="System.InvalidOperationException">
631 /// if setInput () or deflate () were already called or another dictionary was already set.
633 public void SetDictionary(byte[] dict
)
635 SetDictionary(dict
, 0, dict
.Length
);
639 /// Sets the dictionary which should be used in the deflate process.
640 /// The dictionary should be a byte array containing strings that are
641 /// likely to occur in the data which should be compressed. The
642 /// dictionary is not stored in the compressed output, only a
643 /// checksum. To decompress the output you need to supply the same
644 /// dictionary again.
646 /// <param name="dict">
649 /// <param name="offset">
650 /// an offset into the dictionary.
652 /// <param name="length">
653 /// the length of the dictionary.
655 /// <exception cref="System.InvalidOperationException">
656 /// if setInput () or deflate () were already called or another dictionary was already set.
658 public void SetDictionary(byte[] dict
, int offset
, int length
)
660 if (state
!= INIT_STATE
) {
661 throw new InvalidOperationException();
664 state
= SETDICT_STATE
;
665 engine
.SetDictionary(dict
, offset
, length
);
670 namespace NZlib
.Compression
{
673 /// This class contains constants used for the deflater.
675 public class DeflaterConstants
677 public const bool DEBUGGING
= false;
679 public const int STORED_BLOCK
= 0;
680 public const int STATIC_TREES
= 1;
681 public const int DYN_TREES
= 2;
682 public const int PRESET_DICT
= 0x20;
684 public const int DEFAULT_MEM_LEVEL
= 8;
686 public const int MAX_MATCH
= 258;
687 public const int MIN_MATCH
= 3;
689 public const int MAX_WBITS
= 15;
690 public const int WSIZE
= 1 << MAX_WBITS
;
691 public const int WMASK
= WSIZE
- 1;
693 public const int HASH_BITS
= DEFAULT_MEM_LEVEL
+ 7;
694 public const int HASH_SIZE
= 1 << HASH_BITS
;
695 public const int HASH_MASK
= HASH_SIZE
- 1;
696 public const int HASH_SHIFT
= (HASH_BITS
+ MIN_MATCH
- 1) / MIN_MATCH
;
698 public const int MIN_LOOKAHEAD
= MAX_MATCH
+ MIN_MATCH
+ 1;
699 public const int MAX_DIST
= WSIZE
- MIN_LOOKAHEAD
;
701 public const int PENDING_BUF_SIZE
= 1 << (DEFAULT_MEM_LEVEL
+ 8);
702 public static int MAX_BLOCK_SIZE
= Math
.Min(65535, PENDING_BUF_SIZE
-5);
704 public const int DEFLATE_STORED
= 0;
705 public const int DEFLATE_FAST
= 1;
706 public const int DEFLATE_SLOW
= 2;
708 public static int[] GOOD_LENGTH
= { 0, 4, 4, 4, 4, 8, 8, 8, 32, 32 }
;
709 public static int[] MAX_LAZY
= { 0, 4, 5, 6, 4,16, 16, 32, 128, 258 }
;
710 public static int[] NICE_LENGTH
= { 0, 8,16,32,16,32,128,128, 258, 258 }
;
711 public static int[] MAX_CHAIN
= { 0, 4, 8,32,16,32,128,256,1024,4096 }
;
712 public static int[] COMPR_FUNC
= { 0, 1, 1, 1, 1, 2, 2, 2, 2, 2 }
;
716 namespace NZlib
.Compression
{
718 public class DeflaterEngine
: DeflaterConstants
720 private static int TOO_FAR
= 4096;
723 // private byte[] buffer;
724 private short[] head
;
725 private short[] prev
;
727 private int matchStart
, matchLen
;
728 private bool prevAvailable
;
729 private int blockStart
;
730 private int strstart
, lookahead
;
731 private byte[] window
;
733 private int strategy
, max_chain
, max_lazy
, niceLength
, goodLength
;
736 /// The current compression function.
738 private int comprFunc
;
741 /// The input data for compression.
743 private byte[] inputBuf
;
746 /// The total bytes of input read.
751 /// The offset into inputBuf, where input data starts.
753 private int inputOff
;
756 /// The end offset of the input data.
758 private int inputEnd
;
760 private DeflaterPending pending
;
761 private DeflaterHuffman huffman
;
764 /// The adler checksum
766 private Adler32 adler
;
768 public DeflaterEngine(DeflaterPending pending
)
770 this.pending
= pending
;
771 huffman
= new DeflaterHuffman(pending
);
772 adler
= new Adler32();
774 window
= new byte[2*WSIZE
];
775 head
= new short[HASH_SIZE
];
776 prev
= new short[WSIZE
];
778 /* We start at index 1, to avoid a implementation deficiency, that
779 * we cannot build a repeat pattern at index 0.
781 blockStart
= strstart
= 1;
788 blockStart
= strstart
= 1;
791 prevAvailable
= false;
792 matchLen
= MIN_MATCH
- 1;
794 for (int i
= 0; i
< HASH_SIZE
; i
++) {
798 for (int i
= 0; i
< WSIZE
; i
++) {
803 public void ResetAdler()
810 return (int)adler
.Value
;
820 public int Strategy
{
829 public void SetLevel(int lvl
)
831 goodLength
= DeflaterConstants
.GOOD_LENGTH
[lvl
];
832 max_lazy
= DeflaterConstants
.MAX_LAZY
[lvl
];
833 niceLength
= DeflaterConstants
.NICE_LENGTH
[lvl
];
834 max_chain
= DeflaterConstants
.MAX_CHAIN
[lvl
];
836 if (DeflaterConstants
.COMPR_FUNC
[lvl
] != comprFunc
) {
837 // if (DeflaterConstants.DEBUGGING) {
838 // Console.WriteLine("Change from "+comprFunc +" to "
839 // + DeflaterConstants.COMPR_FUNC[lvl]);
843 if (strstart
> blockStart
) {
844 huffman
.FlushStoredBlock(window
, blockStart
,
845 strstart
- blockStart
, false);
846 blockStart
= strstart
;
851 if (strstart
> blockStart
) {
852 huffman
.FlushBlock(window
, blockStart
, strstart
- blockStart
,
854 blockStart
= strstart
;
859 huffman
.TallyLit(window
[strstart
-1] & 0xff);
861 if (strstart
> blockStart
) {
862 huffman
.FlushBlock(window
, blockStart
, strstart
- blockStart
,
864 blockStart
= strstart
;
866 prevAvailable
= false;
867 matchLen
= MIN_MATCH
- 1;
870 comprFunc
= COMPR_FUNC
[lvl
];
874 private void UpdateHash()
877 // Console.WriteLine("updateHash: "+strstart);
879 ins_h
= (window
[strstart
] << HASH_SHIFT
) ^ window
[strstart
+ 1];
882 private int InsertString()
885 int hash
= ((ins_h
<< HASH_SHIFT
) ^ window
[strstart
+ (MIN_MATCH
-1)]) & HASH_MASK
;
888 // if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^
889 // (window[strstart + 1] << HASH_SHIFT) ^
890 // (window[strstart + 2])) & HASH_MASK)) {
891 // throw new Exception("hash inconsistent: "+hash+"/"
892 // +window[strstart]+","
893 // +window[strstart+1]+","
894 // +window[strstart+2]+","+HASH_SHIFT);
898 prev
[strstart
& WMASK
] = match
= head
[hash
];
899 head
[hash
] = (short)strstart
;
901 return match
& 0xffff;
904 public void FillWindow()
906 while (lookahead
< DeflaterConstants
.MIN_LOOKAHEAD
&& inputOff
< inputEnd
) {
907 int more
= 2*WSIZE
- lookahead
- strstart
;
909 /* If the window is almost full and there is insufficient lookahead,
910 * move the upper half to the lower one to make room in the upper half.
912 if (strstart
>= WSIZE
+ MAX_DIST
) {
913 System
.Array
.Copy(window
, WSIZE
, window
, 0, WSIZE
);
918 /* Slide the hash table (could be avoided with 32 bit values
919 * at the expense of memory usage).
921 for (int i
= 0; i
< HASH_SIZE
; i
++) {
923 head
[i
] = m
>= WSIZE
? (short) (m
- WSIZE
) : (short)0;
928 if (more
> inputEnd
- inputOff
) {
929 more
= inputEnd
- inputOff
;
932 System
.Array
.Copy(inputBuf
, inputOff
, window
, strstart
+ lookahead
, more
);
933 adler
.Update(inputBuf
, inputOff
, more
);
938 if (lookahead
>= MIN_MATCH
) {
944 private bool FindLongestMatch(int curMatch
)
946 int chainLength
= this.max_chain
;
947 int niceLength
= this.niceLength
;
948 short[] prev
= this.prev
;
949 int scan
= this.strstart
;
951 int best_end
= this.strstart
+ matchLen
;
952 int best_len
= Math
.Max(matchLen
, MIN_MATCH
- 1);
954 int limit
= Math
.Max(strstart
- MAX_DIST
, 0);
956 int strend
= strstart
+ MAX_MATCH
- 1;
957 byte scan_end1
= window
[best_end
- 1];
958 byte scan_end
= window
[best_end
];
960 /* Do not waste too much time if we already have a good match: */
961 if (best_len
>= this.goodLength
) {
965 /* Do not look for matches beyond the end of the input. This is necessary
966 * to make deflate deterministic.
968 if (niceLength
> lookahead
) {
969 niceLength
= lookahead
;
972 if (DeflaterConstants
.DEBUGGING
&& strstart
> 2*WSIZE
- MIN_LOOKAHEAD
) {
973 throw new InvalidOperationException("need lookahead");
977 if (DeflaterConstants
.DEBUGGING
&& curMatch
>= strstart
) {
978 throw new InvalidOperationException("future match");
980 if (window
[curMatch
+ best_len
] != scan_end
||
981 window
[curMatch
+ best_len
- 1] != scan_end1
||
982 window
[curMatch
] != window
[scan
] ||
983 window
[curMatch
+1] != window
[scan
+ 1]) {
987 match
= curMatch
+ 2;
990 /* We check for insufficient lookahead only every 8th comparison;
991 * the 256th check will be made at strstart+258.
993 while (window
[++scan
] == window
[++match
] &&
994 window
[++scan
] == window
[++match
] &&
995 window
[++scan
] == window
[++match
] &&
996 window
[++scan
] == window
[++match
] &&
997 window
[++scan
] == window
[++match
] &&
998 window
[++scan
] == window
[++match
] &&
999 window
[++scan
] == window
[++match
] &&
1000 window
[++scan
] == window
[++match
] && scan
< strend
) ;
1002 if (scan
> best_end
) {
1003 // if (DeflaterConstants.DEBUGGING && ins_h == 0)
1004 // System.err.println("Found match: "+curMatch+"-"+(scan-strstart));
1005 matchStart
= curMatch
;
1007 best_len
= scan
- strstart
;
1008 if (best_len
>= niceLength
) {
1012 scan_end1
= window
[best_end
-1];
1013 scan_end
= window
[best_end
];
1016 } while ((curMatch
= (prev
[curMatch
& WMASK
] & 0xffff)) > limit
&& --chainLength
!= 0);
1018 matchLen
= Math
.Min(best_len
, lookahead
);
1019 return matchLen
>= MIN_MATCH
;
1022 public void SetDictionary(byte[] buffer
, int offset
, int length
)
1024 if (DeflaterConstants
.DEBUGGING
&& strstart
!= 1) {
1025 throw new InvalidOperationException("strstart not 1");
1027 adler
.Update(buffer
, offset
, length
);
1028 if (length
< MIN_MATCH
) {
1031 if (length
> MAX_DIST
) {
1032 offset
+= length
- MAX_DIST
;
1036 System
.Array
.Copy(buffer
, offset
, window
, strstart
, length
);
1040 while (--length
> 0) {
1045 blockStart
= strstart
;
1048 private bool DeflateStored(bool flush
, bool finish
)
1050 if (!flush
&& lookahead
== 0) {
1054 strstart
+= lookahead
;
1057 int storedLen
= strstart
- blockStart
;
1059 if ((storedLen
>= DeflaterConstants
.MAX_BLOCK_SIZE
) || /* Block is full */
1060 (blockStart
< WSIZE
&& storedLen
>= MAX_DIST
) || /* Block may move out of window */
1062 bool lastBlock
= finish
;
1063 if (storedLen
> DeflaterConstants
.MAX_BLOCK_SIZE
) {
1064 storedLen
= DeflaterConstants
.MAX_BLOCK_SIZE
;
1068 // if (DeflaterConstants.DEBUGGING) {
1069 // Console.WriteLine("storedBlock["+storedLen+","+lastBlock+"]");
1072 huffman
.FlushStoredBlock(window
, blockStart
, storedLen
, lastBlock
);
1073 blockStart
+= storedLen
;
1079 private bool DeflateFast(bool flush
, bool finish
)
1081 if (lookahead
< MIN_LOOKAHEAD
&& !flush
) {
1085 while (lookahead
>= MIN_LOOKAHEAD
|| flush
) {
1086 if (lookahead
== 0) {
1087 /* We are flushing everything */
1088 huffman
.FlushBlock(window
, blockStart
, strstart
- blockStart
, finish
);
1089 blockStart
= strstart
;
1094 if (lookahead
>= MIN_MATCH
&&
1095 (hashHead
= InsertString()) != 0 &&
1096 strategy
!= Deflater
.HUFFMAN_ONLY
&&
1097 strstart
- hashHead
<= MAX_DIST
&&
1098 FindLongestMatch(hashHead
)) {
1099 /* longestMatch sets matchStart and matchLen */
1100 // if (DeflaterConstants.DEBUGGING) {
1101 // for (int i = 0 ; i < matchLen; i++) {
1102 // if (window[strstart+i] != window[matchStart + i]) {
1103 // throw new Exception();
1108 huffman
.TallyDist(strstart
- matchStart
, matchLen
);
1110 lookahead
-= matchLen
;
1111 if (matchLen
<= max_lazy
&& lookahead
>= MIN_MATCH
) {
1112 while (--matchLen
> 0) {
1118 strstart
+= matchLen
;
1119 if (lookahead
>= MIN_MATCH
- 1) {
1123 matchLen
= MIN_MATCH
- 1;
1126 /* No match found */
1127 huffman
.TallyLit(window
[strstart
] & 0xff);
1132 if (huffman
.IsFull()) {
1133 bool lastBlock
= finish
&& lookahead
== 0;
1134 huffman
.FlushBlock(window
, blockStart
, strstart
- blockStart
,
1136 blockStart
= strstart
;
1143 private bool DeflateSlow(bool flush
, bool finish
)
1145 if (lookahead
< MIN_LOOKAHEAD
&& !flush
) {
1149 while (lookahead
>= MIN_LOOKAHEAD
|| flush
) {
1150 if (lookahead
== 0) {
1151 if (prevAvailable
) {
1152 huffman
.TallyLit(window
[strstart
-1] & 0xff);
1154 prevAvailable
= false;
1156 /* We are flushing everything */
1157 if (DeflaterConstants
.DEBUGGING
&& !flush
) {
1158 throw new Exception("Not flushing, but no lookahead");
1160 huffman
.FlushBlock(window
, blockStart
, strstart
- blockStart
,
1162 blockStart
= strstart
;
1166 int prevMatch
= matchStart
;
1167 int prevLen
= matchLen
;
1168 if (lookahead
>= MIN_MATCH
) {
1169 int hashHead
= InsertString();
1170 if (strategy
!= Deflater
.HUFFMAN_ONLY
&& hashHead
!= 0 && strstart
- hashHead
<= MAX_DIST
&& FindLongestMatch(hashHead
))
1172 /* longestMatch sets matchStart and matchLen */
1174 /* Discard match if too small and too far away */
1175 if (matchLen
<= 5 && (strategy
== Deflater
.FILTERED
|| (matchLen
== MIN_MATCH
&& strstart
- matchStart
> TOO_FAR
))) {
1176 matchLen
= MIN_MATCH
- 1;
1181 /* previous match was better */
1182 if (prevLen
>= MIN_MATCH
&& matchLen
<= prevLen
) {
1183 // if (DeflaterConstants.DEBUGGING) {
1184 // for (int i = 0 ; i < matchLen; i++) {
1185 // if (window[strstart-1+i] != window[prevMatch + i])
1186 // throw new Exception();
1189 huffman
.TallyDist(strstart
- 1 - prevMatch
, prevLen
);
1194 if (lookahead
>= MIN_MATCH
) {
1197 } while (--prevLen
> 0);
1200 prevAvailable
= false;
1201 matchLen
= MIN_MATCH
- 1;
1203 if (prevAvailable
) {
1204 huffman
.TallyLit(window
[strstart
-1] & 0xff);
1206 prevAvailable
= true;
1211 if (huffman
.IsFull()) {
1212 int len
= strstart
- blockStart
;
1213 if (prevAvailable
) {
1216 bool lastBlock
= (finish
&& lookahead
== 0 && !prevAvailable
);
1217 huffman
.FlushBlock(window
, blockStart
, len
, lastBlock
);
1225 public bool Deflate(bool flush
, bool finish
)
1230 bool canFlush
= flush
&& inputOff
== inputEnd
;
1231 // if (DeflaterConstants.DEBUGGING) {
1232 // Console.WriteLine("window: ["+blockStart+","+strstart+","
1233 // +lookahead+"], "+comprFunc+","+canFlush);
1235 switch (comprFunc
) {
1236 case DEFLATE_STORED
:
1237 progress
= DeflateStored(canFlush
, finish
);
1240 progress
= DeflateFast(canFlush
, finish
);
1243 progress
= DeflateSlow(canFlush
, finish
);
1246 throw new InvalidOperationException("unknown comprFunc");
1248 } while (pending
.IsFlushed
&& progress
); /* repeat while we have no pending output and progress was made */
1252 public void SetInput(byte[] buf
, int off
, int len
)
1254 if (inputOff
< inputEnd
) {
1255 throw new InvalidOperationException("Old input was not completely processed");
1258 int end
= off
+ len
;
1260 /* We want to throw an ArrayIndexOutOfBoundsException early. The
1261 * check is very tricky: it also handles integer wrap around.
1263 if (0 > off
|| off
> end
|| end
> buf
.Length
) {
1264 throw new ArgumentOutOfRangeException();
1272 public bool NeedsInput()
1274 return inputEnd
== inputOff
;
1279 namespace NZlib
.Compression
{
1282 /// This is the DeflaterHuffman class.
1284 /// This class is <i>not</i> thread safe. This is inherent in the API, due
1285 /// to the split of deflate and setInput.
1287 /// author of the original java version : Jochen Hoenicke
1289 public class DeflaterHuffman
1291 private static int BUFSIZE
= 1 << (DeflaterConstants
.DEFAULT_MEM_LEVEL
+ 6);
1292 private static int LITERAL_NUM
= 286;
1293 private static int DIST_NUM
= 30;
1294 private static int BITLEN_NUM
= 19;
1295 private static int REP_3_6
= 16;
1296 private static int REP_3_10
= 17;
1297 private static int REP_11_138
= 18;
1298 private static int EOF_SYMBOL
= 256;
1299 private static int[] BL_ORDER
= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }
;
1301 private static byte[] bit4Reverse
= {
1323 public short[] freqs
;
1324 public short[] codes
;
1325 public byte[] length
;
1326 public int[] bl_counts
;
1327 public int minNumCodes
, numCodes
;
1328 public int maxLength
;
1331 public Tree(DeflaterHuffman dh
, int elems
, int minCodes
, int maxLength
)
1334 this.minNumCodes
= minCodes
;
1335 this.maxLength
= maxLength
;
1336 freqs
= new short[elems
];
1337 bl_counts
= new int[maxLength
];
1342 for (int i
= 0; i
< freqs
.Length
; i
++) {
1349 public void WriteSymbol(int code
)
1351 // if (DeflaterConstants.DEBUGGING) {
1353 // // Console.Write("writeSymbol("+freqs.length+","+code+"): ");
1355 dh
.pending
.WriteBits(codes
[code
] & 0xffff, length
[code
]);
1358 public void CheckEmpty()
1361 for (int i
= 0; i
< freqs
.Length
; i
++) {
1362 if (freqs
[i
] != 0) {
1363 Console
.WriteLine("freqs["+i
+"] == "+freqs
[i
]);
1368 throw new Exception();
1370 Console
.WriteLine("checkEmpty suceeded!");
1373 public void SetStaticCodes(short[] stCodes
, byte[] stLength
)
1379 public void BuildCodes()
1381 int numSymbols
= freqs
.Length
;
1382 int[] nextCode
= new int[maxLength
];
1384 codes
= new short[freqs
.Length
];
1386 // if (DeflaterConstants.DEBUGGING) {
1387 // Console.WriteLine("buildCodes: "+freqs.Length);
1390 for (int bits
= 0; bits
< maxLength
; bits
++) {
1391 nextCode
[bits
] = code
;
1392 code
+= bl_counts
[bits
] << (15 - bits
);
1393 // if (DeflaterConstants.DEBUGGING) {
1394 // Console.WriteLine("bits: "+(bits+1)+" count: "+bl_counts[bits]
1395 // +" nextCode: "+code); // HACK : Integer.toHexString(
1398 if (DeflaterConstants
.DEBUGGING
&& code
!= 65536) {
1399 throw new Exception("Inconsistent bl_counts!");
1402 for (int i
=0; i
< numCodes
; i
++) {
1403 int bits
= length
[i
];
1405 // if (DeflaterConstants.DEBUGGING) {
1406 // Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+")," // HACK : Integer.toHexString(
1409 codes
[i
] = BitReverse(nextCode
[bits
-1]);
1410 nextCode
[bits
-1] += 1 << (16 - bits
);
1415 private void BuildLength(int[] childs
)
1417 this.length
= new byte [freqs
.Length
];
1418 int numNodes
= childs
.Length
/ 2;
1419 int numLeafs
= (numNodes
+ 1) / 2;
1422 for (int i
= 0; i
< maxLength
; i
++) {
1426 /* First calculate optimal bit lengths */
1427 int[] lengths
= new int[numNodes
];
1428 lengths
[numNodes
-1] = 0;
1430 for (int i
= numNodes
- 1; i
>= 0; i
--) {
1431 if (childs
[2*i
+1] != -1) {
1432 int bitLength
= lengths
[i
] + 1;
1433 if (bitLength
> maxLength
) {
1434 bitLength
= maxLength
;
1437 lengths
[childs
[2*i
]] = lengths
[childs
[2*i
+1]] = bitLength
;
1440 int bitLength
= lengths
[i
];
1441 bl_counts
[bitLength
- 1]++;
1442 this.length
[childs
[2*i
]] = (byte) lengths
[i
];
1446 // if (DeflaterConstants.DEBUGGING) {
1447 // Console.WriteLine("Tree "+freqs.Length+" lengths:");
1448 // for (int i=0; i < numLeafs; i++) {
1449 // Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
1450 // + " len: "+length[childs[2*i]]);
1454 if (overflow
== 0) {
1458 int incrBitLen
= maxLength
- 1;
1460 /* Find the first bit length which could increase: */
1461 while (bl_counts
[--incrBitLen
] == 0)
1464 /* Move this node one down and remove a corresponding
1465 * amount of overflow nodes.
1468 bl_counts
[incrBitLen
]--;
1469 bl_counts
[++incrBitLen
]++;
1470 overflow
-= 1 << (maxLength
- 1 - incrBitLen
);
1471 } while (overflow
> 0 && incrBitLen
< maxLength
- 1);
1472 } while (overflow
> 0);
1474 /* We may have overshot above. Move some nodes from maxLength to
1475 * maxLength-1 in that case.
1477 bl_counts
[maxLength
-1] += overflow
;
1478 bl_counts
[maxLength
-2] -= overflow
;
1480 /* Now recompute all bit lengths, scanning in increasing
1481 * frequency. It is simpler to reconstruct all lengths instead of
1482 * fixing only the wrong ones. This idea is taken from 'ar'
1483 * written by Haruhiko Okumura.
1485 * The nodes were inserted with decreasing frequency into the childs
1488 int nodePtr
= 2 * numLeafs
;
1489 for (int bits
= maxLength
; bits
!= 0; bits
--) {
1490 int n
= bl_counts
[bits
-1];
1492 int childPtr
= 2*childs
[nodePtr
++];
1493 if (childs
[childPtr
+ 1] == -1) {
1494 /* We found another leaf */
1495 length
[childs
[childPtr
]] = (byte) bits
;
1500 // if (DeflaterConstants.DEBUGGING) {
1501 // Console.WriteLine("*** After overflow elimination. ***");
1502 // for (int i=0; i < numLeafs; i++) {
1503 // Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
1504 // + " len: "+length[childs[2*i]]);
1509 public void BuildTree()
1511 int numSymbols
= freqs
.Length
;
1513 /* heap is a priority queue, sorted by frequency, least frequent
1514 * nodes first. The heap is a binary tree, with the property, that
1515 * the parent node is smaller than both child nodes. This assures
1516 * that the smallest node is the first parent.
1518 * The binary tree is encoded in an array: 0 is root node and
1519 * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
1521 int[] heap
= new int[numSymbols
];
1524 for (int n
= 0; n
< numSymbols
; n
++) {
1525 int freq
= freqs
[n
];
1527 /* Insert n into heap */
1528 int pos
= heapLen
++;
1530 while (pos
> 0 && freqs
[heap
[ppos
= (pos
- 1) / 2]] > freq
) {
1531 heap
[pos
] = heap
[ppos
];
1540 /* We could encode a single literal with 0 bits but then we
1541 * don't see the literals. Therefore we force at least two
1542 * literals to avoid this case. We don't care about order in
1543 * this case, both literals get a 1 bit code.
1545 while (heapLen
< 2) {
1546 int node
= maxCode
< 2 ? ++maxCode
: 0;
1547 heap
[heapLen
++] = node
;
1550 numCodes
= Math
.Max(maxCode
+ 1, minNumCodes
);
1552 int numLeafs
= heapLen
;
1553 int[] childs
= new int[4*heapLen
- 2];
1554 int[] values
= new int[2*heapLen
- 1];
1555 int numNodes
= numLeafs
;
1556 for (int i
= 0; i
< heapLen
; i
++) {
1560 values
[i
] = freqs
[node
] << 8;
1564 /* Construct the Huffman tree by repeatedly combining the least two
1568 int first
= heap
[0];
1569 int last
= heap
[--heapLen
];
1571 /* Propagate the hole to the leafs of the heap */
1574 while (path
< heapLen
) {
1575 if (path
+ 1 < heapLen
&& values
[heap
[path
]] > values
[heap
[path
+1]]) {
1579 heap
[ppos
] = heap
[path
];
1581 path
= path
* 2 + 1;
1584 /* Now propagate the last element down along path. Normally
1585 * it shouldn't go too deep.
1587 int lastVal
= values
[last
];
1588 while ((path
= ppos
) > 0 && values
[heap
[ppos
= (path
- 1)/2]] > lastVal
) {
1589 heap
[path
] = heap
[ppos
];
1594 int second
= heap
[0];
1596 /* Create a new node father of first and second */
1598 childs
[2*last
] = first
;
1599 childs
[2*last
+1] = second
;
1600 int mindepth
= Math
.Min(values
[first
] & 0xff, values
[second
] & 0xff);
1601 values
[last
] = lastVal
= values
[first
] + values
[second
] - mindepth
+ 1;
1603 /* Again, propagate the hole to the leafs */
1606 while (path
< heapLen
) {
1607 if (path
+ 1 < heapLen
&& values
[heap
[path
]] > values
[heap
[path
+1]]) {
1611 heap
[ppos
] = heap
[path
];
1613 path
= ppos
* 2 + 1;
1616 /* Now propagate the new element down along path */
1617 while ((path
= ppos
) > 0 && values
[heap
[ppos
= (path
- 1)/2]] > lastVal
) {
1618 heap
[path
] = heap
[ppos
];
1621 } while (heapLen
> 1);
1623 if (heap
[0] != childs
.Length
/ 2 - 1) {
1624 throw new Exception("Weird!");
1626 BuildLength(childs
);
1629 public int GetEncodedLength()
1632 for (int i
= 0; i
< freqs
.Length
; i
++) {
1633 len
+= freqs
[i
] * length
[i
];
1638 public void CalcBLFreq(Tree blTree
)
1640 int max_count
; /* max repeat count */
1641 int min_count
; /* min repeat count */
1642 int count
; /* repeat count of the current code */
1643 int curlen
= -1; /* length of current code */
1646 while (i
< numCodes
) {
1648 int nextlen
= length
[i
];
1655 if (curlen
!= nextlen
) {
1656 blTree
.freqs
[nextlen
]++;
1663 while (i
< numCodes
&& curlen
== length
[i
]) {
1665 if (++count
>= max_count
) {
1670 if (count
< min_count
) {
1671 blTree
.freqs
[curlen
] += (short)count
;
1672 } else if (curlen
!= 0) {
1673 blTree
.freqs
[REP_3_6
]++;
1674 } else if (count
<= 10) {
1675 blTree
.freqs
[REP_3_10
]++;
1677 blTree
.freqs
[REP_11_138
]++;
1682 public void WriteTree(Tree blTree
)
1684 int max_count
; /* max repeat count */
1685 int min_count
; /* min repeat count */
1686 int count
; /* repeat count of the current code */
1687 int curlen
= -1; /* length of current code */
1690 while (i
< numCodes
) {
1692 int nextlen
= length
[i
];
1699 if (curlen
!= nextlen
) {
1700 blTree
.WriteSymbol(nextlen
);
1707 while (i
< numCodes
&& curlen
== length
[i
]) {
1709 if (++count
>= max_count
) {
1714 if (count
< min_count
) {
1715 while (count
-- > 0) {
1716 blTree
.WriteSymbol(curlen
);
1719 else if (curlen
!= 0) {
1720 blTree
.WriteSymbol(REP_3_6
);
1721 dh
.pending
.WriteBits(count
- 3, 2);
1722 } else if (count
<= 10) {
1723 blTree
.WriteSymbol(REP_3_10
);
1724 dh
.pending
.WriteBits(count
- 3, 3);
1726 blTree
.WriteSymbol(REP_11_138
);
1727 dh
.pending
.WriteBits(count
- 11, 7);
1733 public DeflaterPending pending
;
1734 private Tree literalTree
, distTree
, blTree
;
1736 private short[] d_buf
;
1737 private byte[] l_buf
;
1738 private int last_lit
;
1739 private int extra_bits
;
1741 private static short[] staticLCodes
;
1742 private static byte[] staticLLength
;
1743 private static short[] staticDCodes
;
1744 private static byte[] staticDLength
;
1747 /// Reverse the bits of a 16 bit value.
1749 public static short BitReverse(int value)
1751 return (short) (bit4Reverse
[value & 0xF] << 12
1752 | bit4Reverse
[(value >> 4) & 0xF] << 8
1753 | bit4Reverse
[(value >> 8) & 0xF] << 4
1754 | bit4Reverse
[value >> 12]);
1758 static DeflaterHuffman()
1760 /* See RFC 1951 3.2.6 */
1762 staticLCodes
= new short[LITERAL_NUM
];
1763 staticLLength
= new byte[LITERAL_NUM
];
1766 staticLCodes
[i
] = BitReverse((0x030 + i
) << 8);
1767 staticLLength
[i
++] = 8;
1770 staticLCodes
[i
] = BitReverse((0x190 - 144 + i
) << 7);
1771 staticLLength
[i
++] = 9;
1774 staticLCodes
[i
] = BitReverse((0x000 - 256 + i
) << 9);
1775 staticLLength
[i
++] = 7;
1777 while (i
< LITERAL_NUM
) {
1778 staticLCodes
[i
] = BitReverse((0x0c0 - 280 + i
) << 8);
1779 staticLLength
[i
++] = 8;
1783 staticDCodes
= new short[DIST_NUM
];
1784 staticDLength
= new byte[DIST_NUM
];
1785 for (i
= 0; i
< DIST_NUM
; i
++) {
1786 staticDCodes
[i
] = BitReverse(i
<< 11);
1787 staticDLength
[i
] = 5;
1791 public DeflaterHuffman(DeflaterPending pending
)
1793 this.pending
= pending
;
1795 literalTree
= new Tree(this, LITERAL_NUM
, 257, 15);
1796 distTree
= new Tree(this, DIST_NUM
, 1, 15);
1797 blTree
= new Tree(this, BITLEN_NUM
, 4, 7);
1799 d_buf
= new short[BUFSIZE
];
1800 l_buf
= new byte [BUFSIZE
];
1807 literalTree
.Reset();
1812 private int L_code(int len
)
1826 private int D_code(int distance
)
1829 while (distance
>= 4) {
1833 return code
+ distance
;
1836 public void SendAllTrees(int blTreeCodes
)
1838 blTree
.BuildCodes();
1839 literalTree
.BuildCodes();
1840 distTree
.BuildCodes();
1841 pending
.WriteBits(literalTree
.numCodes
- 257, 5);
1842 pending
.WriteBits(distTree
.numCodes
- 1, 5);
1843 pending
.WriteBits(blTreeCodes
- 4, 4);
1844 for (int rank
= 0; rank
< blTreeCodes
; rank
++) {
1845 pending
.WriteBits(blTree
.length
[BL_ORDER
[rank
]], 3);
1847 literalTree
.WriteTree(blTree
);
1848 distTree
.WriteTree(blTree
);
1849 // if (DeflaterConstants.DEBUGGING) {
1850 // blTree.CheckEmpty();
1854 public void CompressBlock()
1856 for (int i
= 0; i
< last_lit
; i
++) {
1857 int litlen
= l_buf
[i
] & 0xff;
1858 int dist
= d_buf
[i
];
1860 // if (DeflaterConstants.DEBUGGING) {
1861 // Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
1864 int lc
= L_code(litlen
);
1865 literalTree
.WriteSymbol(lc
);
1867 int bits
= (lc
- 261) / 4;
1868 if (bits
> 0 && bits
<= 5) {
1869 pending
.WriteBits(litlen
& ((1 << bits
) - 1), bits
);
1872 int dc
= D_code(dist
);
1873 distTree
.WriteSymbol(dc
);
1877 pending
.WriteBits(dist
& ((1 << bits
) - 1), bits
);
1880 // if (DeflaterConstants.DEBUGGING) {
1881 // if (litlen > 32 && litlen < 127) {
1882 // Console.Write("("+(char)litlen+"): ");
1884 // Console.Write("{"+litlen+"}: ");
1887 literalTree
.WriteSymbol(litlen
);
1890 // if (DeflaterConstants.DEBUGGING) {
1891 // Console.Write("EOF: ");
1893 literalTree
.WriteSymbol(EOF_SYMBOL
);
1894 // if (DeflaterConstants.DEBUGGING) {
1895 // literalTree.CheckEmpty();
1896 // distTree.CheckEmpty();
1900 public void FlushStoredBlock(byte[] stored
, int stored_offset
, int stored_len
, bool lastBlock
)
1902 // if (DeflaterConstants.DEBUGGING) {
1903 // Console.WriteLine("Flushing stored block "+ stored_len);
1905 pending
.WriteBits((DeflaterConstants
.STORED_BLOCK
<< 1)
1906 + (lastBlock
? 1 : 0), 3);
1907 pending
.AlignToByte();
1908 pending
.WriteShort(stored_len
);
1909 pending
.WriteShort(~stored_len
);
1910 pending
.WriteBlock(stored
, stored_offset
, stored_len
);
1914 public void FlushBlock(byte[] stored
, int stored_offset
, int stored_len
, bool lastBlock
)
1916 literalTree
.freqs
[EOF_SYMBOL
]++;
1919 literalTree
.BuildTree();
1920 distTree
.BuildTree();
1922 /* Calculate bitlen frequency */
1923 literalTree
.CalcBLFreq(blTree
);
1924 distTree
.CalcBLFreq(blTree
);
1926 /* Build bitlen tree */
1929 int blTreeCodes
= 4;
1930 for (int i
= 18; i
> blTreeCodes
; i
--) {
1931 if (blTree
.length
[BL_ORDER
[i
]] > 0) {
1935 int opt_len
= 14 + blTreeCodes
* 3 + blTree
.GetEncodedLength() +
1936 literalTree
.GetEncodedLength() + distTree
.GetEncodedLength() +
1939 int static_len
= extra_bits
;
1940 for (int i
= 0; i
< LITERAL_NUM
; i
++) {
1941 static_len
+= literalTree
.freqs
[i
] * staticLLength
[i
];
1943 for (int i
= 0; i
< DIST_NUM
; i
++) {
1944 static_len
+= distTree
.freqs
[i
] * staticDLength
[i
];
1946 if (opt_len
>= static_len
) {
1947 /* Force static trees */
1948 opt_len
= static_len
;
1951 if (stored_offset
>= 0 && stored_len
+4 < opt_len
>> 3) {
1953 // if (DeflaterConstants.DEBUGGING) {
1954 // Console.WriteLine("Storing, since " + stored_len + " < " + opt_len
1955 // + " <= " + static_len);
1957 FlushStoredBlock(stored
, stored_offset
, stored_len
, lastBlock
);
1958 } else if (opt_len
== static_len
) {
1959 /* Encode with static tree */
1960 pending
.WriteBits((DeflaterConstants
.STATIC_TREES
<< 1) + (lastBlock
? 1 : 0), 3);
1961 literalTree
.SetStaticCodes(staticLCodes
, staticLLength
);
1962 distTree
.SetStaticCodes(staticDCodes
, staticDLength
);
1966 /* Encode with dynamic tree */
1967 pending
.WriteBits((DeflaterConstants
.DYN_TREES
<< 1) + (lastBlock
? 1 : 0), 3);
1968 SendAllTrees(blTreeCodes
);
1974 public bool IsFull()
1976 return last_lit
+ 16 >= BUFSIZE
; // HACK: This was == 'last_lit == BUFSIZE', but errors occured with DeflateFast
1979 public bool TallyLit(int lit
)
1981 // if (DeflaterConstants.DEBUGGING) {
1982 // if (lit > 32 && lit < 127) {
1983 // Console.WriteLine("("+(char)lit+")");
1985 // Console.WriteLine("{"+lit+"}");
1988 d_buf
[last_lit
] = 0;
1989 l_buf
[last_lit
++] = (byte)lit
;
1990 literalTree
.freqs
[lit
]++;
1994 public bool TallyDist(int dist
, int len
)
1996 // if (DeflaterConstants.DEBUGGING) {
1997 // Console.WriteLine("["+dist+","+len+"]");
2000 d_buf
[last_lit
] = (short)dist
;
2001 l_buf
[last_lit
++] = (byte)(len
- 3);
2003 int lc
= L_code(len
- 3);
2004 literalTree
.freqs
[lc
]++;
2005 if (lc
>= 265 && lc
< 285) {
2006 extra_bits
+= (lc
- 261) / 4;
2009 int dc
= D_code(dist
- 1);
2010 distTree
.freqs
[dc
]++;
2012 extra_bits
+= dc
/ 2 - 1;
2019 namespace NZlib
.Compression
{
2022 /// This class stores the pending output of the Deflater.
2024 /// author of the original java version : Jochen Hoenicke
2026 public class DeflaterPending
: PendingBuffer
2028 public DeflaterPending() : base(DeflaterConstants
.PENDING_BUF_SIZE
)
2034 namespace NZlib
.Compression
{
2037 /// Inflater is used to decompress data that has been compressed according
2038 /// to the "deflate" standard described in rfc1950.
2040 /// The usage is as following. First you have to set some input with
2041 /// <code>setInput()</code>, then inflate() it. If inflate doesn't
2042 /// inflate any bytes there may be three reasons:
2044 /// <li>needsInput() returns true because the input buffer is empty.
2045 /// You have to provide more input with <code>setInput()</code>.
2046 /// NOTE: needsInput() also returns true when, the stream is finished.
2048 /// <li>needsDictionary() returns true, you have to provide a preset
2049 /// dictionary with <code>setDictionary()</code>.</li>
2050 /// <li>finished() returns true, the inflater has finished.</li>
2052 /// Once the first output byte is produced, a dictionary will not be
2053 /// needed at a later stage.
2055 /// author of the original java version : John Leuner, Jochen Hoenicke
2057 public class Inflater
2060 /// Copy lengths for literal codes 257..285
2062 private static int[] CPLENS
= {
2063 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
2064 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
2068 /// Extra bits for literal codes 257..285
2070 private static int[] CPLEXT
= {
2071 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
2072 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
2076 /// Copy offsets for distance codes 0..29
2078 private static int[] CPDIST
= {
2079 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
2080 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
2081 8193, 12289, 16385, 24577
2085 /// Extra bits for distance codes
2087 private static int[] CPDEXT
= {
2088 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
2089 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
2094 /// This are the state in which the inflater can be.
2096 private const int DECODE_HEADER
= 0;
2097 private const int DECODE_DICT
= 1;
2098 private const int DECODE_BLOCKS
= 2;
2099 private const int DECODE_STORED_LEN1
= 3;
2100 private const int DECODE_STORED_LEN2
= 4;
2101 private const int DECODE_STORED
= 5;
2102 private const int DECODE_DYN_HEADER
= 6;
2103 private const int DECODE_HUFFMAN
= 7;
2104 private const int DECODE_HUFFMAN_LENBITS
= 8;
2105 private const int DECODE_HUFFMAN_DIST
= 9;
2106 private const int DECODE_HUFFMAN_DISTBITS
= 10;
2107 private const int DECODE_CHKSUM
= 11;
2108 private const int FINISHED
= 12;
2111 /// This variable contains the current state.
2116 /// The adler checksum of the dictionary or of the decompressed
2117 /// stream, as it is written in the header resp. footer of the
2118 /// compressed stream.
2119 /// Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
2121 private int readAdler
;
2124 /// The number of bits needed to complete the current state. This
2125 /// is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
2126 /// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.
2128 private int neededBits
;
2129 private int repLength
, repDist
;
2130 private int uncomprLen
;
2133 /// True, if the last block flag was set in the last block of the
2134 /// inflated stream. This means that the stream ends after the
2137 private bool isLastBlock
;
2140 /// The total number of inflated bytes.
2142 private int totalOut
;
2145 /// The total number of bytes set with setInput(). This is not the
2146 /// value returned by getTotalIn(), since this also includes the
2147 /// unprocessed input.
2149 private int totalIn
;
2152 /// This variable stores the nowrap flag that was given to the constructor.
2153 /// True means, that the inflated stream doesn't contain a header nor the
2154 /// checksum in the footer.
2156 private bool nowrap
;
2158 private StreamManipulator input
;
2159 private OutputWindow outputWindow
;
2160 private InflaterDynHeader dynHeader
;
2161 private InflaterHuffmanTree litlenTree
, distTree
;
2162 private Adler32 adler
;
2165 /// Creates a new inflater.
2167 public Inflater() : this(false)
2172 /// Creates a new inflater.
2174 /// <param name="nowrap">
2175 /// true if no header and checksum field appears in the
2176 /// stream. This is used for GZIPed input. For compatibility with
2177 /// Sun JDK you should provide one byte of input more than needed in
2180 public Inflater(bool nowrap
)
2182 this.nowrap
= nowrap
;
2183 this.adler
= new Adler32();
2184 input
= new StreamManipulator();
2185 outputWindow
= new OutputWindow();
2186 mode
= nowrap
? DECODE_BLOCKS
: DECODE_HEADER
;
2190 /// Resets the inflater so that a new stream can be decompressed. All
2191 /// pending input and output will be discarded.
2195 mode
= nowrap
? DECODE_BLOCKS
: DECODE_HEADER
;
2196 totalIn
= totalOut
= 0;
2198 outputWindow
.Reset();
2202 isLastBlock
= false;
2207 /// Decodes the deflate header.
2210 /// false if more input is needed.
2212 /// <exception cref="System.FormatException">
2213 /// if header is invalid.
2215 private bool DecodeHeader()
2217 int header
= input
.PeekBits(16);
2222 /* The header is written in "wrong" byte order */
2223 header
= ((header
<< 8) | (header
>> 8)) & 0xffff;
2224 if (header
% 31 != 0) {
2225 throw new FormatException("Header checksum illegal");
2228 if ((header
& 0x0f00) != (Deflater
.DEFLATED
<< 8)) {
2229 throw new FormatException("Compression Method unknown");
2232 /* Maximum size of the backwards window in bits.
2233 * We currently ignore this, but we could use it to make the
2234 * inflater window more space efficient. On the other hand the
2235 * full window (15 bits) is needed most times, anyway.
2236 int max_wbits = ((header & 0x7000) >> 12) + 8;
2239 if ((header
& 0x0020) == 0) { // Dictionary flag?
2240 mode
= DECODE_BLOCKS
;
2249 /// Decodes the dictionary checksum after the deflate header.
2252 /// false if more input is needed.
2254 private bool DecodeDict()
2256 while (neededBits
> 0) {
2257 int dictByte
= input
.PeekBits(8);
2262 readAdler
= (readAdler
<< 8) | dictByte
;
2269 /// Decodes the huffman encoded symbols in the input stream.
2272 /// false if more input is needed, true if output window is
2273 /// full or the current block ends.
2275 /// <exception cref="System.FormatException">
2276 /// if deflated stream is invalid.
2278 private bool DecodeHuffman()
2280 int free
= outputWindow
.GetFreeSpace();
2281 while (free
>= 258) {
2284 case DECODE_HUFFMAN
:
2285 /* This is the inner loop so it is optimized a bit */
2286 while (((symbol
= litlenTree
.GetSymbol(input
)) & ~
0xff) == 0) {
2287 outputWindow
.Write(symbol
);
2296 /* symbol == 256: end of block */
2299 mode
= DECODE_BLOCKS
;
2305 repLength
= CPLENS
[symbol
- 257];
2306 neededBits
= CPLEXT
[symbol
- 257];
2307 } catch (Exception
) {
2308 throw new FormatException("Illegal rep length code");
2310 goto case DECODE_HUFFMAN_LENBITS
;/* fall through */
2311 case DECODE_HUFFMAN_LENBITS
:
2312 if (neededBits
> 0) {
2313 mode
= DECODE_HUFFMAN_LENBITS
;
2314 int i
= input
.PeekBits(neededBits
);
2318 input
.DropBits(neededBits
);
2321 mode
= DECODE_HUFFMAN_DIST
;
2322 goto case DECODE_HUFFMAN_DIST
;/* fall through */
2323 case DECODE_HUFFMAN_DIST
:
2324 symbol
= distTree
.GetSymbol(input
);
2329 repDist
= CPDIST
[symbol
];
2330 neededBits
= CPDEXT
[symbol
];
2331 } catch (Exception
) {
2332 throw new FormatException("Illegal rep dist code");
2335 goto case DECODE_HUFFMAN_DISTBITS
;/* fall through */
2336 case DECODE_HUFFMAN_DISTBITS
:
2337 if (neededBits
> 0) {
2338 mode
= DECODE_HUFFMAN_DISTBITS
;
2339 int i
= input
.PeekBits(neededBits
);
2343 input
.DropBits(neededBits
);
2346 outputWindow
.Repeat(repLength
, repDist
);
2348 mode
= DECODE_HUFFMAN
;
2351 throw new FormatException();
2358 /// Decodes the adler checksum after the deflate stream.
2361 /// false if more input is needed.
2363 /// <exception cref="System.FormatException">
2364 /// DataFormatException, if checksum doesn't match.
2366 private bool DecodeChksum()
2368 while (neededBits
> 0) {
2369 int chkByte
= input
.PeekBits(8);
2374 readAdler
= (readAdler
<< 8) | chkByte
;
2377 if ((int) adler
.Value
!= readAdler
) {
2378 throw new FormatException("Adler chksum doesn't match: "
2380 + " vs. " + readAdler
);
2387 /// Decodes the deflated stream.
2390 /// false if more input is needed, or if finished.
2392 /// <exception cref="System.FormatException">
2393 /// DataFormatException, if deflated stream is invalid.
2395 private bool Decode()
2399 return DecodeHeader();
2401 return DecodeDict();
2403 return DecodeChksum();
2411 input
.SkipToByteBoundary();
2413 mode
= DECODE_CHKSUM
;
2418 int type
= input
.PeekBits(3);
2424 if ((type
& 1) != 0) {
2427 switch (type
>> 1) {
2428 case DeflaterConstants
.STORED_BLOCK
:
2429 input
.SkipToByteBoundary();
2430 mode
= DECODE_STORED_LEN1
;
2432 case DeflaterConstants
.STATIC_TREES
:
2433 litlenTree
= InflaterHuffmanTree
.defLitLenTree
;
2434 distTree
= InflaterHuffmanTree
.defDistTree
;
2435 mode
= DECODE_HUFFMAN
;
2437 case DeflaterConstants
.DYN_TREES
:
2438 dynHeader
= new InflaterDynHeader();
2439 mode
= DECODE_DYN_HEADER
;
2442 throw new FormatException("Unknown block type "+type
);
2446 case DECODE_STORED_LEN1
: {
2447 if ((uncomprLen
= input
.PeekBits(16)) < 0) {
2451 mode
= DECODE_STORED_LEN2
;
2453 goto case DECODE_STORED_LEN2
; /* fall through */
2454 case DECODE_STORED_LEN2
: {
2455 int nlen
= input
.PeekBits(16);
2460 if (nlen
!= (uncomprLen ^
0xffff)) {
2461 throw new FormatException("broken uncompressed block");
2463 mode
= DECODE_STORED
;
2465 goto case DECODE_STORED
;/* fall through */
2466 case DECODE_STORED
: {
2467 int more
= outputWindow
.CopyStored(input
, uncomprLen
);
2469 if (uncomprLen
== 0) {
2470 mode
= DECODE_BLOCKS
;
2473 return !input
.IsNeedingInput
;
2476 case DECODE_DYN_HEADER
:
2477 if (!dynHeader
.Decode(input
)) {
2481 litlenTree
= dynHeader
.BuildLitLenTree();
2482 distTree
= dynHeader
.BuildDistTree();
2483 mode
= DECODE_HUFFMAN
;
2484 goto case DECODE_HUFFMAN
; /* fall through */
2485 case DECODE_HUFFMAN
:
2486 case DECODE_HUFFMAN_LENBITS
:
2487 case DECODE_HUFFMAN_DIST
:
2488 case DECODE_HUFFMAN_DISTBITS
:
2489 return DecodeHuffman();
2493 throw new FormatException();
2498 /// Sets the preset dictionary. This should only be called, if
2499 /// needsDictionary() returns true and it should set the same
2500 /// dictionary, that was used for deflating. The getAdler()
2501 /// function returns the checksum of the dictionary needed.
2503 /// <param name="buffer">
2506 /// <exception cref="System.InvalidOperationException">
2507 /// if no dictionary is needed.
2509 /// <exception cref="System.ArgumentException">
2510 /// if the dictionary checksum is wrong.
2512 public void SetDictionary(byte[] buffer
)
2514 SetDictionary(buffer
, 0, buffer
.Length
);
2518 /// Sets the preset dictionary. This should only be called, if
2519 /// needsDictionary() returns true and it should set the same
2520 /// dictionary, that was used for deflating. The getAdler()
2521 /// function returns the checksum of the dictionary needed.
2523 /// <param name="buffer">
2526 /// <param name="off">
2527 /// the offset into buffer where the dictionary starts.
2529 /// <param name="len">
2530 /// the length of the dictionary.
2532 /// <exception cref="System.InvalidOperationException">
2533 /// if no dictionary is needed.
2535 /// <exception cref="System.ArgumentException">
2536 /// if the dictionary checksum is wrong.
2538 /// <exception cref="System.ArgumentOutOfRangeException">
2539 /// if the off and/or len are wrong.
2541 public void SetDictionary(byte[] buffer
, int off
, int len
)
2543 if (!IsNeedingDictionary
) {
2544 throw new InvalidOperationException();
2547 adler
.Update(buffer
, off
, len
);
2548 if ((int) adler
.Value
!= readAdler
) {
2549 throw new ArgumentException("Wrong adler checksum");
2552 outputWindow
.CopyDict(buffer
, off
, len
);
2553 mode
= DECODE_BLOCKS
;
2557 /// Sets the input. This should only be called, if needsInput()
2560 /// <param name="buf">
2563 /// <exception cref="System.InvalidOperationException">
2564 /// if no input is needed.
2566 public void SetInput(byte[] buf
)
2568 SetInput(buf
, 0, buf
.Length
);
2572 /// Sets the input. This should only be called, if needsInput()
2575 /// <param name="buf">
2578 /// <param name="off">
2579 /// the offset into buffer where the input starts.
2581 /// <param name="len">
2582 /// the length of the input.
2584 /// <exception cref="System.InvalidOperationException">
2585 /// if no input is needed.
2587 /// <exception cref="System.ArgumentOutOfRangeException">
2588 /// if the off and/or len are wrong.
2590 public void SetInput(byte[] buf
, int off
, int len
)
2592 input
.SetInput(buf
, off
, len
);
2597 /// Inflates the compressed stream to the output buffer. If this
2598 /// returns 0, you should check, whether needsDictionary(),
2599 /// needsInput() or finished() returns true, to determine why no
2600 /// further output is produced.
2602 /// <param name = "buf">
2603 /// the output buffer.
2606 /// the number of bytes written to the buffer, 0 if no further
2607 /// output can be produced.
2609 /// <exception cref="System.ArgumentOutOfRangeException">
2610 /// if buf has length 0.
2612 /// <exception cref="System.FormatException">
2613 /// if deflated stream is invalid.
2615 public int Inflate(byte[] buf
)
2617 return Inflate(buf
, 0, buf
.Length
);
2621 /// Inflates the compressed stream to the output buffer. If this
2622 /// returns 0, you should check, whether needsDictionary(),
2623 /// needsInput() or finished() returns true, to determine why no
2624 /// further output is produced.
2626 /// <param name = "buf">
2627 /// the output buffer.
2629 /// <param name = "off">
2630 /// the offset into buffer where the output should start.
2632 /// <param name = "len">
2633 /// the maximum length of the output.
2636 /// the number of bytes written to the buffer, 0 if no further output can be produced.
2638 /// <exception cref="System.ArgumentOutOfRangeException">
2639 /// if len is <= 0.
2641 /// <exception cref="System.ArgumentOutOfRangeException">
2642 /// if the off and/or len are wrong.
2644 /// <exception cref="System.FormatException">
2645 /// if deflated stream is invalid.
2647 public int Inflate(byte[] buf
, int off
, int len
)
2650 throw new ArgumentOutOfRangeException("len <= 0");
2655 if (mode
!= DECODE_CHKSUM
) {
2656 /* Don't give away any output, if we are waiting for the
2657 * checksum in the input stream.
2659 * With this trick we have always:
2660 * needsInput() and not finished()
2661 * implies more output can be produced.
2663 more
= outputWindow
.CopyOutput(buf
, off
, len
);
2664 adler
.Update(buf
, off
, more
);
2673 } while (Decode() || (outputWindow
.GetAvailable() > 0 &&
2674 mode
!= DECODE_CHKSUM
));
2679 /// Returns true, if the input buffer is empty.
2680 /// You should then call setInput().
2681 /// NOTE: This method also returns true when the stream is finished.
2683 public bool IsNeedingInput
{
2685 return input
.IsNeedingInput
;
2690 /// Returns true, if a preset dictionary is needed to inflate the input.
2692 public bool IsNeedingDictionary
{
2694 return mode
== DECODE_DICT
&& neededBits
== 0;
2699 /// Returns true, if the inflater has finished. This means, that no
2700 /// input is needed and no output can be produced.
2702 public bool IsFinished
{
2704 return mode
== FINISHED
&& outputWindow
.GetAvailable() == 0;
2709 /// Gets the adler checksum. This is either the checksum of all
2710 /// uncompressed bytes returned by inflate(), or if needsDictionary()
2711 /// returns true (and thus no output was yet produced) this is the
2712 /// adler checksum of the expected dictionary.
2715 /// the adler checksum.
2719 return IsNeedingDictionary
? readAdler
: (int) adler
.Value
;
2724 /// Gets the total number of output bytes returned by inflate().
2727 /// the total number of output bytes.
2729 public int TotalOut
{
2736 /// Gets the total number of processed compressed input bytes.
2739 /// the total number of bytes of processed input bytes.
2741 public int TotalIn
{
2743 return totalIn
- RemainingInput
;
2748 /// Gets the number of unprocessed input. Useful, if the end of the
2749 /// stream is reached and you want to further process the bytes after
2750 /// the deflate stream.
2753 /// the number of bytes of the input which were not processed.
2755 public int RemainingInput
{
2757 return input
.AvailableBytes
;
2763 namespace NZlib
.Compression
{
2765 public class InflaterDynHeader
2767 private const int LNUM
= 0;
2768 private const int DNUM
= 1;
2769 private const int BLNUM
= 2;
2770 private const int BLLENS
= 3;
2771 private const int LLENS
= 4;
2772 private const int DLENS
= 5;
2773 private const int LREPS
= 6;
2774 private const int DREPS
= 7;
2775 private const int FINISH
= 8;
2777 private byte[] blLens
;
2778 private byte[] litlenLens
;
2779 private byte[] distLens
;
2781 private InflaterHuffmanTree blTree
;
2784 private int lnum
, dnum
, blnum
;
2785 private int repBits
;
2786 private byte repeatedLen
;
2789 private static int[] BL_ORDER
= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }
;
2791 public InflaterDynHeader()
2795 public bool Decode(StreamManipulator input
)
2801 lnum
= input
.PeekBits(5);
2807 litlenLens
= new byte[lnum
];
2808 // System.err.println("LNUM: "+lnum);
2810 goto case DNUM
;/* fall through */
2812 dnum
= input
.PeekBits(5);
2818 distLens
= new byte[dnum
];
2819 // System.err.println("DNUM: "+dnum);
2821 goto case BLNUM
;/* fall through */
2823 blnum
= input
.PeekBits(4);
2829 blLens
= new byte[19];
2831 // System.err.println("BLNUM: "+blnum);
2833 goto case BLLENS
;/* fall through */
2835 while (ptr
< blnum
) {
2836 int len
= input
.PeekBits(3);
2841 // System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
2842 blLens
[BL_ORDER
[ptr
]] = (byte) len
;
2845 blTree
= new InflaterHuffmanTree(blLens
);
2849 goto case LLENS
;/* fall through */
2851 while (ptr
< lnum
) {
2852 int symbol
= blTree
.GetSymbol(input
);
2858 // System.err.println("litlenLens["+ptr+"]: "+symbol);
2859 litlenLens
[ptr
++] = (byte) symbol
;
2861 case 16: /* repeat last len 3-6 times */
2863 throw new Exception("Repeating, but no prev len");
2866 // System.err.println("litlenLens["+ptr+"]: repeat");
2867 repeatedLen
= litlenLens
[ptr
-1];
2869 for (int i
= 3; i
-- > 0; ) {
2871 throw new Exception();
2873 litlenLens
[ptr
++] = repeatedLen
;
2877 case 17: /* repeat zero 3-10 times */
2878 // System.err.println("litlenLens["+ptr+"]: zero repeat");
2881 for (int i
= 3; i
-- > 0; ) {
2883 throw new Exception();
2885 litlenLens
[ptr
++] = repeatedLen
;
2889 case 18: /* repeat zero 11-138 times */
2890 // System.err.println("litlenLens["+ptr+"]: zero repeat");
2893 for (int i
= 11; i
-- > 0; ) {
2895 throw new Exception();
2897 litlenLens
[ptr
++] = repeatedLen
;
2905 goto case DLENS
;/* fall through */
2907 while (ptr
< dnum
) {
2908 int symbol
= blTree
.GetSymbol(input
);
2914 distLens
[ptr
++] = (byte) symbol
;
2915 // System.err.println("distLens["+ptr+"]: "+symbol);
2917 case 16: /* repeat last len 3-6 times */
2919 throw new Exception("Repeating, but no prev len");
2921 // System.err.println("distLens["+ptr+"]: repeat");
2922 repeatedLen
= distLens
[ptr
-1];
2924 for (int i
= 3; i
-- > 0; ) {
2926 throw new Exception();
2928 distLens
[ptr
++] = repeatedLen
;
2932 case 17: /* repeat zero 3-10 times */
2933 // System.err.println("distLens["+ptr+"]: repeat zero");
2936 for (int i
= 3; i
-- > 0; ) {
2938 throw new Exception();
2940 distLens
[ptr
++] = repeatedLen
;
2944 case 18: /* repeat zero 11-138 times */
2945 // System.err.println("distLens["+ptr+"]: repeat zero");
2948 for (int i
= 11; i
-- > 0; ) {
2950 throw new Exception();
2952 distLens
[ptr
++] = repeatedLen
;
2962 int count
= input
.PeekBits(repBits
);
2966 input
.DropBits(repBits
);
2967 // System.err.println("litlenLens repeat: "+repBits);
2968 while (count
-- > 0) {
2970 throw new Exception();
2972 litlenLens
[ptr
++] = repeatedLen
;
2979 int count
= input
.PeekBits(repBits
);
2983 input
.DropBits(repBits
);
2984 while (count
-- > 0) {
2986 throw new Exception();
2988 distLens
[ptr
++] = repeatedLen
;
2997 public InflaterHuffmanTree
BuildLitLenTree()
2999 return new InflaterHuffmanTree(litlenLens
);
3002 public InflaterHuffmanTree
BuildDistTree()
3004 return new InflaterHuffmanTree(distLens
);
3009 namespace NZlib
.Compression
{
3011 public class InflaterHuffmanTree
3013 private static int MAX_BITLEN
= 15;
3014 private short[] tree
;
3016 public static InflaterHuffmanTree defLitLenTree
, defDistTree
;
3018 static InflaterHuffmanTree()
3021 byte[] codeLengths
= new byte[288];
3024 codeLengths
[i
++] = 8;
3027 codeLengths
[i
++] = 9;
3030 codeLengths
[i
++] = 7;
3033 codeLengths
[i
++] = 8;
3035 defLitLenTree
= new InflaterHuffmanTree(codeLengths
);
3037 codeLengths
= new byte[32];
3040 codeLengths
[i
++] = 5;
3042 defDistTree
= new InflaterHuffmanTree(codeLengths
);
3043 } catch (Exception
) {
3044 throw new ApplicationException("InflaterHuffmanTree: static tree length illegal");
3049 /// Constructs a Huffman tree from the array of code lengths.
3051 /// <param name = "codeLengths">
3052 /// the array of code lengths
3054 public InflaterHuffmanTree(byte[] codeLengths
)
3056 BuildTree(codeLengths
);
3059 private void BuildTree(byte[] codeLengths
)
3061 int[] blCount
= new int[MAX_BITLEN
+ 1];
3062 int[] nextCode
= new int[MAX_BITLEN
+ 1];
3064 for (int i
= 0; i
< codeLengths
.Length
; i
++) {
3065 int bits
= codeLengths
[i
];
3072 for (int bits
= 1; bits
<= MAX_BITLEN
; bits
++) {
3073 nextCode
[bits
] = code
;
3074 code
+= blCount
[bits
] << (16 - bits
);
3076 /* We need an extra table for bit lengths >= 10. */
3077 int start
= nextCode
[bits
] & 0x1ff80;
3078 int end
= code
& 0x1ff80;
3079 treeSize
+= (end
- start
) >> (16 - bits
);
3082 if (code
!= 65536) {
3083 throw new Exception("Code lengths don't add up properly.");
3085 /* Now create and fill the extra tables from longest to shortest
3086 * bit len. This way the sub trees will be aligned.
3088 tree
= new short[treeSize
];
3090 for (int bits
= MAX_BITLEN
; bits
>= 10; bits
--) {
3091 int end
= code
& 0x1ff80;
3092 code
-= blCount
[bits
] << (16 - bits
);
3093 int start
= code
& 0x1ff80;
3094 for (int i
= start
; i
< end
; i
+= 1 << 7) {
3095 tree
[DeflaterHuffman
.BitReverse(i
)] = (short) ((-treePtr
<< 4) | bits
);
3096 treePtr
+= 1 << (bits
-9);
3100 for (int i
= 0; i
< codeLengths
.Length
; i
++) {
3101 int bits
= codeLengths
[i
];
3105 code
= nextCode
[bits
];
3106 int revcode
= DeflaterHuffman
.BitReverse(code
);
3109 tree
[revcode
] = (short) ((i
<< 4) | bits
);
3110 revcode
+= 1 << bits
;
3111 } while (revcode
< 512);
3113 int subTree
= tree
[revcode
& 511];
3114 int treeLen
= 1 << (subTree
& 15);
3115 subTree
= -(subTree
>> 4);
3117 tree
[subTree
| (revcode
>> 9)] = (short) ((i
<< 4) | bits
);
3118 revcode
+= 1 << bits
;
3119 } while (revcode
< treeLen
);
3121 nextCode
[bits
] = code
+ (1 << (16 - bits
));
3127 /// Reads the next symbol from input. The symbol is encoded using the
3130 /// <param name="input">
3131 /// input the input source.
3134 /// the next symbol, or -1 if not enough input is available.
3136 public int GetSymbol(StreamManipulator input
)
3138 int lookahead
, symbol
;
3139 if ((lookahead
= input
.PeekBits(9)) >= 0) {
3140 if ((symbol
= tree
[lookahead
]) >= 0) {
3141 input
.DropBits(symbol
& 15);
3144 int subtree
= -(symbol
>> 4);
3145 int bitlen
= symbol
& 15;
3146 if ((lookahead
= input
.PeekBits(bitlen
)) >= 0) {
3147 symbol
= tree
[subtree
| (lookahead
>> 9)];
3148 input
.DropBits(symbol
& 15);
3151 int bits
= input
.AvailableBits
;
3152 lookahead
= input
.PeekBits(bits
);
3153 symbol
= tree
[subtree
| (lookahead
>> 9)];
3154 if ((symbol
& 15) <= bits
) {
3155 input
.DropBits(symbol
& 15);
3162 int bits
= input
.AvailableBits
;
3163 lookahead
= input
.PeekBits(bits
);
3164 symbol
= tree
[lookahead
];
3165 if (symbol
>= 0 && (symbol
& 15) <= bits
) {
3166 input
.DropBits(symbol
& 15);
3176 namespace NZlib
.Compression
{
3179 /// This class is general purpose class for writing data to a buffer.
3181 /// It allows you to write bits as well as bytes
3182 /// Based on DeflaterPending.java
3184 /// author of the original java version : Jochen Hoenicke
3186 public class PendingBuffer
3188 protected byte[] buf
;
3195 public PendingBuffer() : this( 4096 )
3200 public PendingBuffer(int bufsize
)
3202 buf
= new byte[bufsize
];
3207 start
= end
= bitCount
= 0;
3210 public void WriteByte(int b
)
3212 if (DeflaterConstants
.DEBUGGING
&& start
!= 0)
3213 throw new Exception();
3214 buf
[end
++] = (byte) b
;
3217 public void WriteShort(int s
)
3219 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3220 throw new Exception();
3222 buf
[end
++] = (byte) s
;
3223 buf
[end
++] = (byte) (s
>> 8);
3226 public void WriteInt(int s
)
3228 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3229 throw new Exception();
3231 buf
[end
++] = (byte) s
;
3232 buf
[end
++] = (byte) (s
>> 8);
3233 buf
[end
++] = (byte) (s
>> 16);
3234 buf
[end
++] = (byte) (s
>> 24);
3237 public void WriteBlock(byte[] block
, int offset
, int len
)
3239 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3240 throw new Exception();
3242 System
.Array
.Copy(block
, offset
, buf
, end
, len
);
3246 public int BitCount
{
3252 public void AlignToByte()
3254 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3255 throw new Exception();
3258 buf
[end
++] = (byte) bits
;
3260 buf
[end
++] = (byte) (bits
>> 8);
3267 public void WriteBits(int b
, int count
)
3269 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3270 throw new Exception();
3272 // if (DeflaterConstants.DEBUGGING) {
3273 // Console.WriteLine("writeBits("+b+","+count+")");
3275 bits
|= (uint)(b
<< bitCount
);
3277 if (bitCount
>= 16) {
3278 buf
[end
++] = (byte) bits
;
3279 buf
[end
++] = (byte) (bits
>> 8);
3285 public void WriteShortMSB(int s
)
3287 if (DeflaterConstants
.DEBUGGING
&& start
!= 0) {
3288 throw new Exception();
3290 buf
[end
++] = (byte) (s
>> 8);
3291 buf
[end
++] = (byte) s
;
3294 public bool IsFlushed
{
3301 /// Flushes the pending buffer into the given output array. If the
3302 /// output array is to small, only a partial flush is done.
3304 /// <param name="output">
3305 /// the output array;
3307 /// <param name="offset">
3308 /// the offset into output array;
3310 /// <param name="length">
3311 /// length the maximum number of bytes to store;
3313 /// <exception name="ArgumentOutOfRangeException">
3314 /// IndexOutOfBoundsException if offset or length are invalid.
3316 public int Flush(byte[] output
, int offset
, int length
)
3318 if (bitCount
>= 8) {
3319 buf
[end
++] = (byte) bits
;
3323 if (length
> end
- start
) {
3324 length
= end
- start
;
3325 System
.Array
.Copy(buf
, start
, output
, offset
, length
);
3329 System
.Array
.Copy(buf
, start
, output
, offset
, length
);
3335 public byte[] ToByteArray()
3337 byte[] ret
= new byte[ end
- start
];
3338 System
.Array
.Copy(buf
, start
, ret
, 0, ret
.Length
);
3346 namespace NZlib
.Checksums
{
3349 /// Computes Adler32 checksum for a stream of data. An Adler32
3350 /// checksum is not as reliable as a CRC32 checksum, but a lot faster to
3353 /// The specification for Adler32 may be found in RFC 1950.
3354 /// ZLIB Compressed Data Format Specification version 3.3)
3357 /// From that document:
3359 /// "ADLER32 (Adler-32 checksum)
3360 /// This contains a checksum value of the uncompressed data
3361 /// (excluding any dictionary data) computed according to Adler-32
3362 /// algorithm. This algorithm is a 32-bit extension and improvement
3363 /// of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073
3366 /// Adler-32 is composed of two sums accumulated per byte: s1 is
3367 /// the sum of all bytes, s2 is the sum of all s1 values. Both sums
3368 /// are done modulo 65521. s1 is initialized to 1, s2 to zero. The
3369 /// Adler-32 checksum is stored as s2*65536 + s1 in most-
3370 /// significant-byte first (network) order."
3372 /// "8.2. The Adler-32 algorithm
3374 /// The Adler-32 algorithm is much faster than the CRC32 algorithm yet
3375 /// still provides an extremely low probability of undetected errors.
3377 /// The modulo on unsigned long accumulators can be delayed for 5552
3378 /// bytes, so the modulo operation time is negligible. If the bytes
3379 /// are a, b, c, the second sum is 3a + 2b + c + 3, and so is position
3380 /// and order sensitive, unlike the first sum, which is just a
3381 /// checksum. That 65521 is prime is important to avoid a possible
3382 /// large class of two-byte errors that leave the check unchanged.
3383 /// (The Fletcher checksum uses 255, which is not prime and which also
3384 /// makes the Fletcher check insensitive to single byte changes 0 -
3387 /// The sum s1 is initialized to 1 instead of zero to make the length
3388 /// of the sequence part of s2, so that the length does not have to be
3389 /// checked separately. (Any sequence of zeroes has a Fletcher
3390 /// checksum of zero.)"
3392 /// <see cref="NZlib.Streams.InflaterInputStream"/>
3393 /// <see cref="NZlib.Streams.DeflaterOutputStream"/>
3394 public sealed class Adler32
: IChecksum
3397 /// largest prime smaller than 65536
3399 readonly static uint BASE
= 65521;
3404 /// Returns the Adler32 data checksum computed so far.
3408 return (long) checksum
& 0xFFFFFFFFL
;
3413 /// Creates a new instance of the <code>Adler32</code> class.
3414 /// The checksum starts off with a value of 1.
3422 /// Resets the Adler32 checksum to the initial value.
3426 checksum
= 1; //Initialize to 1
3430 /// Updates the checksum with the byte b.
3432 /// <param name="bval">
3433 /// the data value to add. The high byte of the int is ignored.
3435 public void Update(int bval
)
3437 //We could make a length 1 byte array and call update again, but I
3438 //would rather not have that overhead
3439 uint s1
= checksum
& 0xFFFF;
3440 uint s2
= checksum
>> 16;
3442 s1
= (s1
+ ((uint)bval
& 0xFF)) % BASE
;
3443 s2
= (s1
+ s2
) % BASE
;
3445 checksum
= (s2
<< 16) + s1
;
3449 /// Updates the checksum with the bytes taken from the array.
3451 /// <param name="buffer">
3452 /// buffer an array of bytes
3454 public void Update(byte[] buffer
)
3456 Update(buffer
, 0, buffer
.Length
);
3460 /// Updates the checksum with the bytes taken from the array.
3462 /// <param name="buf">
3463 /// an array of bytes
3465 /// <param name="off">
3466 /// the start of the data used for this update
3468 /// <param name="len">
3469 /// the number of bytes to use for this update
3471 public void Update(byte[] buf
, int off
, int len
)
3474 throw new ArgumentNullException("buf");
3477 if (off
< 0 || len
< 0 || off
+ len
> buf
.Length
) {
3478 throw new ArgumentOutOfRangeException();
3482 uint s1
= checksum
& 0xFFFF;
3483 uint s2
= checksum
>> 16;
3486 // We can defer the modulo operation:
3487 // s1 maximally grows from 65521 to 65521 + 255 * 3800
3488 // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
3495 s1
= s1
+ (uint)(buf
[off
++] & 0xFF);
3502 checksum
= (s2
<< 16) | s1
;
3507 namespace NZlib
.Checksums
{
3510 /// Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
3511 /// x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
3513 /// Polynomials over GF(2) are represented in binary, one bit per coefficient,
3514 /// with the lowest powers in the most significant bit. Then adding polynomials
3515 /// is just exclusive-or, and multiplying a polynomial by x is a right shift by
3516 /// one. If we call the above polynomial p, and represent a byte as the
3517 /// polynomial q, also with the lowest power in the most significant bit (so the
3518 /// byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
3519 /// where a mod b means the remainder after dividing a by b.
3521 /// This calculation is done using the shift-register method of multiplying and
3522 /// taking the remainder. The register is initialized to zero, and for each
3523 /// incoming bit, x^32 is added mod p to the register if the bit is a one (where
3524 /// x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
3525 /// x (which is shifting right by one and adding x^32 mod p if the bit shifted
3526 /// out is a one). We start with the highest power (least significant bit) of
3527 /// q and repeat for all eight bits of q.
3529 /// The table is simply the CRC of all possible eight bit values. This is all
3530 /// the information needed to generate CRC's on data a byte at a time for all
3531 /// combinations of CRC register values and incoming bytes.
3533 public sealed class Crc32
: IChecksum
3535 readonly static uint CrcSeed
= 0xFFFFFFFF;
3537 readonly static uint[] CrcTable
= new uint[] {
3538 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
3539 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
3540 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
3541 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
3542 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856,
3543 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
3544 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
3545 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
3546 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
3547 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A,
3548 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
3549 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
3550 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190,
3551 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
3552 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
3553 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
3554 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
3555 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
3556 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
3557 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
3558 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
3559 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
3560 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
3561 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
3562 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17,
3563 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,
3564 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
3565 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
3566 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
3567 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
3568 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
3569 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
3570 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1,
3571 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
3572 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
3573 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
3574 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE,
3575 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
3576 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
3577 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
3578 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
3579 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
3580 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
3581 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
3582 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
3583 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
3584 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
3585 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
3586 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
3587 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
3588 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
3593 /// The crc data checksum so far.
3598 /// Returns the CRC32 data checksum computed so far.
3607 /// Resets the CRC32 data checksum as if no update was ever called.
3615 /// Updates the checksum with the int bval.
3617 /// <param name = "bval">
3618 /// the byte is taken as the lower 8 bits of bval
3620 public void Update(int bval
)
3623 crc
= CrcTable
[(crc ^ bval
) & 0xFF] ^
(crc
>> 8);
3628 /// Updates the checksum with the bytes taken from the array.
3630 /// <param name="buffer">
3631 /// buffer an array of bytes
3633 public void Update(byte[] buffer
)
3635 Update(buffer
, 0, buffer
.Length
);
3639 /// Adds the byte array to the data checksum.
3641 /// <param name = "buf">
3642 /// the buffer which contains the data
3644 /// <param name = "off">
3645 /// the offset in the buffer where the data starts
3647 /// <param name = "len">
3648 /// the length of the data
3650 public void Update(byte[] buf
, int off
, int len
)
3653 throw new ArgumentNullException("buf");
3656 if (off
< 0 || len
< 0 || off
+ len
> buf
.Length
) {
3657 throw new ArgumentOutOfRangeException();
3662 while (--len
>= 0) {
3663 crc
= CrcTable
[(crc ^ buf
[off
++]) & 0xFF] ^
(crc
>> 8);
3671 namespace NZlib
.Checksums
{
3674 /// Interface to compute a data checksum used by checked input/output streams.
3675 /// A data checksum can be updated by one byte or with a byte array. After each
3676 /// update the value of the current checksum can be returned by calling
3677 /// <code>getValue</code>. The complete checksum object can also be reset
3678 /// so it can be used again with new data.
3680 public interface IChecksum
3683 /// Returns the data checksum computed so far.
3690 /// Resets the data checksum as if no update was ever called.
3695 /// Adds one byte to the data checksum.
3697 /// <param name = "bval">
3698 /// the data value to add. The high byte of the int is ignored.
3700 void Update(int bval
);
3703 /// Updates the data checksum with the bytes taken from the array.
3705 /// <param name="buffer">
3706 /// buffer an array of bytes
3708 void Update(byte[] buffer
);
3711 /// Adds the byte array to the data checksum.
3713 /// <param name = "buf">
3714 /// the buffer which contains the data
3716 /// <param name = "off">
3717 /// the offset in the buffer where the data starts
3719 /// <param name = "len">
3720 /// the length of the data
3722 void Update(byte[] buf
, int off
, int len
);
3726 namespace NZlib
.Streams
{
3729 /// Contains the output from the Inflation process.
3730 /// We need to have a window so that we can refer backwards into the output stream
3731 /// to repeat stuff.
3733 /// author of the original java version : John Leuner
3735 public class OutputWindow
3737 private static int WINDOW_SIZE
= 1 << 15;
3738 private static int WINDOW_MASK
= WINDOW_SIZE
- 1;
3740 private byte[] window
= new byte[WINDOW_SIZE
]; //The window is 2^15 bytes
3741 private int window_end
= 0;
3742 private int window_filled
= 0;
3744 public void Write(int abyte
)
3746 if (window_filled
++ == WINDOW_SIZE
) {
3747 throw new InvalidOperationException("Window full");
3749 window
[window_end
++] = (byte) abyte
;
3750 window_end
&= WINDOW_MASK
;
3754 private void SlowRepeat(int rep_start
, int len
, int dist
)
3757 window
[window_end
++] = window
[rep_start
++];
3758 window_end
&= WINDOW_MASK
;
3759 rep_start
&= WINDOW_MASK
;
3763 public void Repeat(int len
, int dist
)
3765 if ((window_filled
+= len
) > WINDOW_SIZE
) {
3766 throw new InvalidOperationException("Window full");
3769 int rep_start
= (window_end
- dist
) & WINDOW_MASK
;
3770 int border
= WINDOW_SIZE
- len
;
3771 if (rep_start
<= border
&& window_end
< border
) {
3773 System
.Array
.Copy(window
, rep_start
, window
, window_end
, len
);
3776 /* We have to copy manually, since the repeat pattern overlaps.
3779 window
[window_end
++] = window
[rep_start
++];
3783 SlowRepeat(rep_start
, len
, dist
);
3787 public int CopyStored(StreamManipulator input
, int len
)
3789 len
= Math
.Min(Math
.Min(len
, WINDOW_SIZE
- window_filled
), input
.AvailableBytes
);
3792 int tailLen
= WINDOW_SIZE
- window_end
;
3793 if (len
> tailLen
) {
3794 copied
= input
.CopyBytes(window
, window_end
, tailLen
);
3795 if (copied
== tailLen
) {
3796 copied
+= input
.CopyBytes(window
, 0, len
- tailLen
);
3799 copied
= input
.CopyBytes(window
, window_end
, len
);
3802 window_end
= (window_end
+ copied
) & WINDOW_MASK
;
3803 window_filled
+= copied
;
3807 public void CopyDict(byte[] dict
, int offset
, int len
)
3809 if (window_filled
> 0) {
3810 throw new InvalidOperationException();
3813 if (len
> WINDOW_SIZE
) {
3814 offset
+= len
- WINDOW_SIZE
;
3817 System
.Array
.Copy(dict
, offset
, window
, 0, len
);
3818 window_end
= len
& WINDOW_MASK
;
3821 public int GetFreeSpace()
3823 return WINDOW_SIZE
- window_filled
;
3826 public int GetAvailable()
3828 return window_filled
;
3831 public int CopyOutput(byte[] output
, int offset
, int len
)
3833 int copy_end
= window_end
;
3834 if (len
> window_filled
) {
3835 len
= window_filled
;
3837 copy_end
= (window_end
- window_filled
+ len
) & WINDOW_MASK
;
3841 int tailLen
= len
- copy_end
;
3844 System
.Array
.Copy(window
, WINDOW_SIZE
- tailLen
,
3845 output
, offset
, tailLen
);
3849 System
.Array
.Copy(window
, copy_end
- len
, output
, offset
, len
);
3850 window_filled
-= copied
;
3851 if (window_filled
< 0) {
3852 throw new InvalidOperationException();
3859 window_filled
= window_end
= 0;
3864 namespace NZlib
.Streams
{
3867 /// This class allows us to retrieve a specified amount of bits from
3868 /// the input buffer, as well as copy big byte blocks.
3870 /// It uses an int buffer to store up to 31 bits for direct
3871 /// manipulation. This guarantees that we can get at least 16 bits,
3872 /// but we only need at most 15, so this is all safe.
3874 /// There are some optimizations in this class, for example, you must
3875 /// never peek more then 8 bits more than needed, and you must first
3876 /// peek bits before you may drop them. This is not a general purpose
3877 /// class but optimized for the behaviour of the Inflater.
3879 /// authors of the original java version : John Leuner, Jochen Hoenicke
3881 public class StreamManipulator
3883 private byte[] window
;
3884 private int window_start
= 0;
3885 private int window_end
= 0;
3887 private uint buffer
= 0;
3888 private int bits_in_buffer
= 0;
3891 /// Get the next n bits but don't increase input pointer. n must be
3892 /// less or equal 16 and if you if this call succeeds, you must drop
3893 /// at least n-8 bits in the next call.
3896 /// the value of the bits, or -1 if not enough bits available. */
3898 public int PeekBits(int n
)
3900 if (bits_in_buffer
< n
) {
3901 if (window_start
== window_end
) {
3904 buffer
|= (uint)((window
[window_start
++] & 0xff |
3905 (window
[window_start
++] & 0xff) << 8) << bits_in_buffer
);
3906 bits_in_buffer
+= 16;
3908 return (int)(buffer
& ((1 << n
) - 1));
3912 /// Drops the next n bits from the input. You should have called peekBits
3913 /// with a bigger or equal n before, to make sure that enough bits are in
3916 public void DropBits(int n
)
3919 bits_in_buffer
-= n
;
3923 /// Gets the next n bits and increases input pointer. This is equivalent
3924 /// to peekBits followed by dropBits, except for correct error handling.
3927 /// the value of the bits, or -1 if not enough bits available.
3929 public int GetBits(int n
)
3931 int bits
= PeekBits(n
);
3939 /// Gets the number of bits available in the bit buffer. This must be
3940 /// only called when a previous peekBits() returned -1.
3943 /// the number of bits available.
3945 public int AvailableBits
{
3947 return bits_in_buffer
;
3952 /// Gets the number of bytes available.
3955 /// the number of bytes available.
3957 public int AvailableBytes
{
3959 return window_end
- window_start
+ (bits_in_buffer
>> 3);
3964 /// Skips to the next byte boundary.
3966 public void SkipToByteBoundary()
3968 buffer
>>= (bits_in_buffer
& 7);
3969 bits_in_buffer
&= ~
7;
3972 public bool IsNeedingInput
{
3974 return window_start
== window_end
;
3979 /// Copies length bytes from input buffer to output buffer starting
3980 /// at output[offset]. You have to make sure, that the buffer is
3981 /// byte aligned. If not enough bytes are available, copies fewer
3984 /// <param name="output">
3987 /// <param name="offset">
3988 /// the offset in the buffer.
3990 /// <param name="length">
3991 /// the length to copy, 0 is allowed.
3994 /// the number of bytes copied, 0 if no byte is available.
3996 public int CopyBytes(byte[] output
, int offset
, int length
)
3999 throw new ArgumentOutOfRangeException("length negative");
4001 if ((bits_in_buffer
& 7) != 0) {
4002 /* bits_in_buffer may only be 0 or 8 */
4003 throw new InvalidOperationException("Bit buffer is not aligned!");
4007 while (bits_in_buffer
> 0 && length
> 0) {
4008 output
[offset
++] = (byte) buffer
;
4010 bits_in_buffer
-= 8;
4018 int avail
= window_end
- window_start
;
4019 if (length
> avail
) {
4022 System
.Array
.Copy(window
, window_start
, output
, offset
, length
);
4023 window_start
+= length
;
4025 if (((window_start
- window_end
) & 1) != 0) {
4026 /* We always want an even number of bytes in input, see peekBits */
4027 buffer
= (uint)(window
[window_start
++] & 0xff);
4030 return count
+ length
;
4033 public StreamManipulator()
4039 buffer
= (uint)(window_start
= window_end
= bits_in_buffer
= 0);
4042 public void SetInput(byte[] buf
, int off
, int len
)
4044 if (window_start
< window_end
) {
4045 throw new InvalidOperationException("Old input was not completely processed");
4048 int end
= off
+ len
;
4050 /* We want to throw an ArrayIndexOutOfBoundsException early. The
4051 * check is very tricky: it also handles integer wrap around.
4053 if (0 > off
|| off
> end
|| end
> buf
.Length
) {
4054 throw new ArgumentOutOfRangeException();
4057 if ((len
& 1) != 0) {
4058 /* We always want an even number of bytes in input, see peekBits */
4059 buffer
|= (uint)((buf
[off
++] & 0xff) << bits_in_buffer
);
4060 bits_in_buffer
+= 8;