root/trunk/BazaReklam.Updater/ICSharpCode.SharpZipLib/Zip/Compression/DeflaterEngine.cs @ 944

Wersja 597, 23.6 KB (wprowadzona przez marek, 17 years temu)

re #165

Line 
1// DeflaterEngine.cs
2//
3// Copyright (C) 2001 Mike Krueger
4// Copyright (C) 2004 John Reilly
5//
6// This file was translated from java, it was part of the GNU Classpath
7// Copyright (C) 2001 Free Software Foundation, Inc.
8//
9// This program is free software; you can redistribute it and/or
10// modify it under the terms of the GNU General Public License
11// as published by the Free Software Foundation; either version 2
12// of the License, or (at your option) any later version.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22//
23// Linking this library statically or dynamically with other modules is
24// making a combined work based on this library.  Thus, the terms and
25// conditions of the GNU General Public License cover the whole
26// combination.
27//
28// As a special exception, the copyright holders of this library give you
29// permission to link this library with independent modules to produce an
30// executable, regardless of the license terms of these independent
31// modules, and to copy and distribute the resulting executable under
32// terms of your choice, provided that you also meet, for each linked
33// independent module, the terms and conditions of the license of that
34// module.  An independent module is a module which is not derived from
35// or based on this library.  If you modify this library, you may extend
36// this exception to your version of the library, but you are not
37// obligated to do so.  If you do not wish to do so, delete this
38// exception statement from your version.
39
40using System;
41
42using ICSharpCode.SharpZipLib.Checksums;
43
44namespace ICSharpCode.SharpZipLib.Zip.Compression
45{
46       
47        /// <summary>
48        /// Strategies for deflater
49        /// </summary>
50        public enum DeflateStrategy
51        {
52                /// <summary>
53                /// The default strategy
54                /// </summary>
55                Default  = 0,
56               
57                /// <summary>
58                /// This strategy will only allow longer string repetitions.  It is
59                /// useful for random data with a small character set.
60                /// </summary>
61                Filtered = 1,
62
63                       
64                /// <summary>
65                /// This strategy will not look for string repetitions at all.  It
66                /// only encodes with Huffman trees (which means, that more common
67                /// characters get a smaller encoding.
68                /// </summary>
69                HuffmanOnly = 2
70        }
71
72        // DEFLATE ALGORITHM:
73        //
74        // The uncompressed stream is inserted into the window array.  When
75        // the window array is full the first half is thrown away and the
76        // second half is copied to the beginning.
77        //
78        // The head array is a hash table.  Three characters build a hash value
79        // and they the value points to the corresponding index in window of
80        // the last string with this hash.  The prev array implements a
81        // linked list of matches with the same hash: prev[index & WMASK] points
82        // to the previous index with the same hash.
83        //
84
85       
86        /// <summary>
87        /// Low level compression engine for deflate algorithm which uses a 32K sliding window
88        /// with secondary compression from Huffman/Shannon-Fano codes.
89        /// </summary>
90        public class DeflaterEngine : DeflaterConstants
91        {
92                #region Constants
93                const int TooFar = 4096;
94                #endregion
95               
96                #region Constructors
97                /// <summary>
98                /// Construct instance with pending buffer
99                /// </summary>
100                /// <param name="pending">
101                /// Pending buffer to use
102                /// </param>>
103                public DeflaterEngine(DeflaterPending pending)
104                {
105                        this.pending = pending;
106                        huffman = new DeflaterHuffman(pending);
107                        adler = new Adler32();
108                       
109                        window = new byte[2 * WSIZE];
110                        head   = new short[HASH_SIZE];
111                        prev   = new short[WSIZE];
112                       
113                        // We start at index 1, to avoid an implementation deficiency, that
114                        // we cannot build a repeat pattern at index 0.
115                        blockStart = strstart = 1;
116                }
117
118                #endregion
119
120                /// <summary>
121                /// Deflate drives actual compression of data
122                /// </summary>
123                /// <param name="flush">True to flush input buffers</param>
124                /// <param name="finish">Finish deflation with the current input.</param>
125                /// <returns>Returns true if progress has been made.</returns>
126                public bool Deflate(bool flush, bool finish)
127                {
128                        bool progress;
129                        do
130                        {
131                                FillWindow();
132                                bool canFlush = flush && (inputOff == inputEnd);
133
134#if DebugDeflation
135                                if (DeflaterConstants.DEBUGGING) {
136                                        Console.WriteLine("window: [" + blockStart + "," + strstart + ","
137                                                                + lookahead + "], " + compressionFunction + "," + canFlush);
138                                }
139#endif
140                                switch (compressionFunction)
141                                {
142                                        case DEFLATE_STORED:
143                                                progress = DeflateStored(canFlush, finish);
144                                                break;
145                                        case DEFLATE_FAST:
146                                                progress = DeflateFast(canFlush, finish);
147                                                break;
148                                        case DEFLATE_SLOW:
149                                                progress = DeflateSlow(canFlush, finish);
150                                                break;
151                                        default:
152                                                throw new InvalidOperationException("unknown compressionFunction");
153                                }
154                        } while (pending.IsFlushed && progress); // repeat while we have no pending output and progress was made
155                        return progress;
156                }
157
158                /// <summary>
159                /// Sets input data to be deflated.  Should only be called when <code>NeedsInput()</code>
160                /// returns true
161                /// </summary>
162                /// <param name="buffer">The buffer containing input data.</param>
163                /// <param name="offset">The offset of the first byte of data.</param>
164                /// <param name="count">The number of bytes of data to use as input.</param>
165                public void SetInput(byte[] buffer, int offset, int count)
166                {
167                        if ( buffer == null )
168                        {
169                                throw new ArgumentNullException("buffer");
170                        }
171
172                        if ( offset < 0 )
173                        {
174                                throw new ArgumentOutOfRangeException("offset");
175                        }
176
177                        if ( count < 0 )
178                        {
179                                throw new ArgumentOutOfRangeException("count");
180                        }
181
182                        if (inputOff < inputEnd)
183                        {
184                                throw new InvalidOperationException("Old input was not completely processed");
185                        }
186                       
187                        int end = offset + count;
188                       
189                        /* We want to throw an ArrayIndexOutOfBoundsException early.  The
190                        * check is very tricky: it also handles integer wrap around.
191                        */
192                        if ((offset > end) || (end > buffer.Length) )
193                        {
194                                throw new ArgumentOutOfRangeException("count");
195                        }
196                       
197                        inputBuf = buffer;
198                        inputOff = offset;
199                        inputEnd = end;
200                }
201
202                /// <summary>
203                /// Determines if more <see cref="SetInput">input</see> is needed.
204                /// </summary>         
205                /// <returns>Return true if input is needed via <see cref="SetInput">SetInput</see></returns>
206                public bool NeedsInput()
207                {
208                        return (inputEnd == inputOff);
209                }
210
211                /// <summary>
212                /// Set compression dictionary
213                /// </summary>
214                /// <param name="buffer">The buffer containing the dictionary data</param>
215                /// <param name="offset">The offset in the buffer for the first byte of data</param>
216                /// <param name="length">The length of the dictionary data.</param>
217                public void SetDictionary(byte[] buffer, int offset, int length)
218                {
219#if DebugDeflation
220                        if (DeflaterConstants.DEBUGGING && (strstart != 1) )
221                        {
222                                throw new InvalidOperationException("strstart not 1");
223                        }
224#endif
225                        adler.Update(buffer, offset, length);
226                        if (length < MIN_MATCH)
227                        {
228                                return;
229                        }
230
231                        if (length > MAX_DIST)
232                        {
233                                offset += length - MAX_DIST;
234                                length = MAX_DIST;
235                        }
236                       
237                        System.Array.Copy(buffer, offset, window, strstart, length);
238                       
239                        UpdateHash();
240                        --length;
241                        while (--length > 0)
242                        {
243                                InsertString();
244                                strstart++;
245                        }
246                        strstart += 2;
247                        blockStart = strstart;
248                }
249               
250                /// <summary>
251                /// Reset internal state
252                /// </summary>         
253                public void Reset()
254                {
255                        huffman.Reset();
256                        adler.Reset();
257                        blockStart = strstart = 1;
258                        lookahead = 0;
259                        totalIn   = 0;
260                        prevAvailable = false;
261                        matchLen = MIN_MATCH - 1;
262                       
263                        for (int i = 0; i < HASH_SIZE; i++) {
264                                head[i] = 0;
265                        }
266                       
267                        for (int i = 0; i < WSIZE; i++) {
268                                prev[i] = 0;
269                        }
270                }
271
272                /// <summary>
273                /// Reset Adler checksum
274                /// </summary>         
275                public void ResetAdler()
276                {
277                        adler.Reset();
278                }
279
280                /// <summary>
281                /// Get current value of Adler checksum
282                /// </summary>         
283                public int Adler {
284                        get {
285                                return unchecked((int)adler.Value);
286                        }
287                }
288
289                /// <summary>
290                /// Total data processed
291                /// </summary>         
292                public long TotalIn {
293                        get {
294                                return totalIn;
295                        }
296                }
297
298                /// <summary>
299                /// Get/set the <see cref="DeflateStrategy">deflate strategy</see>
300                /// </summary>         
301                public DeflateStrategy Strategy {
302                        get {
303                                return strategy;
304                        }
305                        set {
306                                strategy = value;
307                        }
308                }
309               
310                /// <summary>
311                /// Set the deflate level (0-9)
312                /// </summary>
313                /// <param name="level">The value to set the level to.</param>
314                public void SetLevel(int level)
315                {
316                        if ( (level < 0) || (level > 9) )
317                        {
318                                throw new ArgumentOutOfRangeException("level");
319                        }
320
321                        goodLength = DeflaterConstants.GOOD_LENGTH[level];
322                        max_lazy   = DeflaterConstants.MAX_LAZY[level];
323                        niceLength = DeflaterConstants.NICE_LENGTH[level];
324                        max_chain  = DeflaterConstants.MAX_CHAIN[level];
325                       
326                        if (DeflaterConstants.COMPR_FUNC[level] != compressionFunction) {
327
328#if DebugDeflation
329                                if (DeflaterConstants.DEBUGGING) {
330                                   Console.WriteLine("Change from " + compressionFunction + " to "
331                                                                                  + DeflaterConstants.COMPR_FUNC[level]);
332                                }
333#endif
334                                switch (compressionFunction) {
335                                        case DEFLATE_STORED:
336                                                if (strstart > blockStart) {
337                                                        huffman.FlushStoredBlock(window, blockStart,
338                                                                strstart - blockStart, false);
339                                                        blockStart = strstart;
340                                                }
341                                                UpdateHash();
342                                                break;
343
344                                        case DEFLATE_FAST:
345                                                if (strstart > blockStart) {
346                                                        huffman.FlushBlock(window, blockStart, strstart - blockStart,
347                                                                false);
348                                                        blockStart = strstart;
349                                                }
350                                                break;
351
352                                        case DEFLATE_SLOW:
353                                                if (prevAvailable) {
354                                                        huffman.TallyLit(window[strstart-1] & 0xff);
355                                                }
356                                                if (strstart > blockStart) {
357                                                        huffman.FlushBlock(window, blockStart, strstart - blockStart, false);
358                                                        blockStart = strstart;
359                                                }
360                                                prevAvailable = false;
361                                                matchLen = MIN_MATCH - 1;
362                                                break;
363                                }
364                                compressionFunction = COMPR_FUNC[level];
365                        }
366                }
367               
368                /// <summary>
369                /// Fill the window
370                /// </summary>
371                public void FillWindow()
372                {
373                        /* If the window is almost full and there is insufficient lookahead,
374                         * move the upper half to the lower one to make room in the upper half.
375                         */
376                        if (strstart >= WSIZE + MAX_DIST)
377                        {
378                                SlideWindow();
379                        }
380                       
381                        /* If there is not enough lookahead, but still some input left,
382                         * read in the input
383                         */
384                        while (lookahead < DeflaterConstants.MIN_LOOKAHEAD && inputOff < inputEnd)
385                        {
386                                int more = 2 * WSIZE - lookahead - strstart;
387                               
388                                if (more > inputEnd - inputOff)
389                                {
390                                        more = inputEnd - inputOff;
391                                }
392                               
393                                System.Array.Copy(inputBuf, inputOff, window, strstart + lookahead, more);
394                                adler.Update(inputBuf, inputOff, more);
395                               
396                                inputOff += more;
397                                totalIn  += more;
398                                lookahead += more;
399                        }
400                       
401                        if (lookahead >= MIN_MATCH)
402                        {
403                                UpdateHash();
404                        }
405                }
406               
407                void UpdateHash()
408                {
409/*
410                        if (DEBUGGING) {
411                                Console.WriteLine("updateHash: "+strstart);
412                        }
413*/
414                        ins_h = (window[strstart] << HASH_SHIFT) ^ window[strstart + 1];
415                }
416               
417                /// <summary>
418                /// Inserts the current string in the head hash and returns the previous
419                /// value for this hash.
420                /// </summary>
421                /// <returns>The previous hash value</returns>
422                int InsertString()
423                {
424                        short match;
425                        int hash = ((ins_h << HASH_SHIFT) ^ window[strstart + (MIN_MATCH -1)]) & HASH_MASK;
426
427#if DebugDeflation
428                        if (DeflaterConstants.DEBUGGING)
429                        {
430                                if (hash != (((window[strstart] << (2*HASH_SHIFT)) ^
431                                                                  (window[strstart + 1] << HASH_SHIFT) ^
432                                                                  (window[strstart + 2])) & HASH_MASK)) {
433                                                throw new SharpZipBaseException("hash inconsistent: " + hash + "/"
434                                                                                                +window[strstart] + ","
435                                                                                                +window[strstart + 1] + ","
436                                                                                                +window[strstart + 2] + "," + HASH_SHIFT);
437                                        }
438                        }
439#endif
440                        prev[strstart & WMASK] = match = head[hash];
441                        head[hash] = unchecked((short)strstart);
442                        ins_h = hash;
443                        return match & 0xffff;
444                }
445               
446                void SlideWindow()
447                {
448                        Array.Copy(window, WSIZE, window, 0, WSIZE);
449                        matchStart -= WSIZE;
450                        strstart   -= WSIZE;
451                        blockStart -= WSIZE;
452                       
453                        // Slide the hash table (could be avoided with 32 bit values
454                        // at the expense of memory usage).
455                        for (int i = 0; i < HASH_SIZE; ++i) {
456                                int m = head[i] & 0xffff;
457                                head[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0);
458                        }
459                       
460                        // Slide the prev table.
461                        for (int i = 0; i < WSIZE; i++) {
462                                int m = prev[i] & 0xffff;
463                                prev[i] = (short)(m >= WSIZE ? (m - WSIZE) : 0);
464                        }
465                }
466               
467                /// <summary>
468                /// Find the best (longest) string in the window matching the
469                /// string starting at strstart.
470                ///
471                /// Preconditions:
472                /// <code>
473                /// strstart + MAX_MATCH &lt;= window.length.</code>
474                /// </summary>
475                /// <param name="curMatch"></param>
476                /// <returns>True if a match greater than the minimum length is found</returns>
477                bool FindLongestMatch(int curMatch)
478                {
479                        int chainLength = this.max_chain;
480                        int niceLength  = this.niceLength;
481                        short[] prev    = this.prev;
482                        int scan        = this.strstart;
483                        int match;
484                        int best_end = this.strstart + matchLen;
485                        int best_len = Math.Max(matchLen, MIN_MATCH - 1);
486                       
487                        int limit = Math.Max(strstart - MAX_DIST, 0);
488                       
489                        int strend = strstart + MAX_MATCH - 1;
490                        byte scan_end1 = window[best_end - 1];
491                        byte scan_end  = window[best_end];
492                       
493                        // Do not waste too much time if we already have a good match:
494                        if (best_len >= this.goodLength) {
495                                chainLength >>= 2;
496                        }
497                       
498                        /* Do not look for matches beyond the end of the input. This is necessary
499                        * to make deflate deterministic.
500                        */
501                        if (niceLength > lookahead) {
502                                niceLength = lookahead;
503                        }
504                       
505#if DebugDeflation
506
507                        if (DeflaterConstants.DEBUGGING && (strstart > 2 * WSIZE - MIN_LOOKAHEAD))
508                        {
509                                throw new InvalidOperationException("need lookahead");
510                        }
511#endif                 
512       
513                        do {
514
515#if DebugDeflation
516
517                                if (DeflaterConstants.DEBUGGING && (curMatch >= strstart) )
518                                {
519                                        throw new InvalidOperationException("no future");
520                                }
521#endif           
522                                if (window[curMatch + best_len] != scan_end      ||
523                                        window[curMatch + best_len - 1] != scan_end1 ||
524                                        window[curMatch] != window[scan]             ||
525                                        window[curMatch + 1] != window[scan + 1]) {
526                                        continue;
527                                }
528                               
529                                match = curMatch + 2;
530                                scan += 2;
531                               
532                                /* We check for insufficient lookahead only every 8th comparison;
533                                * the 256th check will be made at strstart + 258.
534                                */
535                                while (
536                                        window[++scan] == window[++match] &&
537                                        window[++scan] == window[++match] &&
538                                        window[++scan] == window[++match] &&
539                                        window[++scan] == window[++match] &&
540                                        window[++scan] == window[++match] &&
541                                        window[++scan] == window[++match] &&
542                                        window[++scan] == window[++match] &&
543                                        window[++scan] == window[++match] &&
544                                        (scan < strend))
545                                {
546                                        // Do nothing
547                                }
548                               
549                                if (scan > best_end) {
550#if DebugDeflation
551                                        if (DeflaterConstants.DEBUGGING && (ins_h == 0) )
552                                                Console.Error.WriteLine("Found match: " + curMatch + "-" + (scan - strstart));
553#endif
554                                        matchStart = curMatch;
555                                        best_end = scan;
556                                        best_len = scan - strstart;
557                                       
558                                        if (best_len >= niceLength) {
559                                                break;
560                                        }
561                                       
562                                        scan_end1  = window[best_end - 1];
563                                        scan_end   = window[best_end];
564                                }
565                                scan = strstart;
566                        } while ((curMatch = (prev[curMatch & WMASK] & 0xffff)) > limit && --chainLength != 0);
567                       
568                        matchLen = Math.Min(best_len, lookahead);
569                        return matchLen >= MIN_MATCH;
570                }
571               
572                bool DeflateStored(bool flush, bool finish)
573                {
574                        if (!flush && (lookahead == 0)) {
575                                return false;
576                        }
577                       
578                        strstart += lookahead;
579                        lookahead = 0;
580                       
581                        int storedLength = strstart - blockStart;
582                       
583                        if ((storedLength >= DeflaterConstants.MAX_BLOCK_SIZE) || // Block is full
584                                (blockStart < WSIZE && storedLength >= MAX_DIST) ||   // Block may move out of window
585                                flush) {
586                                bool lastBlock = finish;
587                                if (storedLength > DeflaterConstants.MAX_BLOCK_SIZE) {
588                                        storedLength = DeflaterConstants.MAX_BLOCK_SIZE;
589                                        lastBlock = false;
590                                }
591                               
592#if DebugDeflation
593                                if (DeflaterConstants.DEBUGGING)
594                                {
595                                   Console.WriteLine("storedBlock[" + storedLength + "," + lastBlock + "]");
596                                }
597#endif
598
599                                huffman.FlushStoredBlock(window, blockStart, storedLength, lastBlock);
600                                blockStart += storedLength;
601                                return !lastBlock;
602                        }
603                        return true;
604                }
605               
606                bool DeflateFast(bool flush, bool finish)
607                {
608                        if (lookahead < MIN_LOOKAHEAD && !flush) {
609                                return false;
610                        }
611                       
612                        while (lookahead >= MIN_LOOKAHEAD || flush) {
613                                if (lookahead == 0) {
614                                        // We are flushing everything
615                                        huffman.FlushBlock(window, blockStart, strstart - blockStart, finish);
616                                        blockStart = strstart;
617                                        return false;
618                                }
619                               
620                                if (strstart > 2 * WSIZE - MIN_LOOKAHEAD) {
621                                        /* slide window, as FindLongestMatch needs this.
622                                         * This should only happen when flushing and the window
623                                         * is almost full.
624                                         */
625                                        SlideWindow();
626                                }
627                               
628                                int hashHead;
629                                if (lookahead >= MIN_MATCH &&
630                                        (hashHead = InsertString()) != 0 &&
631                                        strategy != DeflateStrategy.HuffmanOnly &&
632                                        strstart - hashHead <= MAX_DIST &&
633                                        FindLongestMatch(hashHead)) {
634                                        // longestMatch sets matchStart and matchLen
635#if DebugDeflation
636                                        if (DeflaterConstants.DEBUGGING)
637                                        {
638                                                for (int i = 0 ; i < matchLen; i++) {
639                                                        if (window[strstart + i] != window[matchStart + i]) {
640                                                                throw new SharpZipBaseException("Match failure");
641                                                        }
642                                                }
643                                        }
644#endif                                 
645
646                                        bool full = huffman.TallyDist(strstart - matchStart, matchLen);
647
648                                        lookahead -= matchLen;
649                                        if (matchLen <= max_lazy && lookahead >= MIN_MATCH) {
650                                                while (--matchLen > 0) {
651                                                        ++strstart;
652                                                        InsertString();
653                                                }
654                                                ++strstart;
655                                        } else {
656                                                strstart += matchLen;
657                                                if (lookahead >= MIN_MATCH - 1) {
658                                                        UpdateHash();
659                                                }
660                                        }
661                                        matchLen = MIN_MATCH - 1;
662                                        if (!full) {
663                                                continue;
664                                        }
665                                } else {
666                                        // No match found
667                                        huffman.TallyLit(window[strstart] & 0xff);
668                                        ++strstart;
669                                        --lookahead;
670                                }
671                               
672                                if (huffman.IsFull()) {
673                                        bool lastBlock = finish && (lookahead == 0);
674                                        huffman.FlushBlock(window, blockStart, strstart - blockStart, lastBlock);
675                                        blockStart = strstart;
676                                        return !lastBlock;
677                                }
678                        }
679                        return true;
680                }
681               
682                bool DeflateSlow(bool flush, bool finish)
683                {
684                        if (lookahead < MIN_LOOKAHEAD && !flush) {
685                                return false;
686                        }
687                       
688                        while (lookahead >= MIN_LOOKAHEAD || flush) {
689                                if (lookahead == 0) {
690                                        if (prevAvailable) {
691                                                huffman.TallyLit(window[strstart-1] & 0xff);
692                                        }
693                                        prevAvailable = false;
694                                       
695                                        // We are flushing everything
696#if DebugDeflation
697                                        if (DeflaterConstants.DEBUGGING && !flush)
698                                        {
699                                                throw new SharpZipBaseException("Not flushing, but no lookahead");
700                                        }
701#endif               
702                                        huffman.FlushBlock(window, blockStart, strstart - blockStart,
703                                                finish);
704                                        blockStart = strstart;
705                                        return false;
706                                }
707                               
708                                if (strstart >= 2 * WSIZE - MIN_LOOKAHEAD) {
709                                        /* slide window, as FindLongestMatch needs this.
710                                         * This should only happen when flushing and the window
711                                         * is almost full.
712                                         */
713                                        SlideWindow();
714                                }
715                               
716                                int prevMatch = matchStart;
717                                int prevLen = matchLen;
718                                if (lookahead >= MIN_MATCH) {
719
720                                        int hashHead = InsertString();
721
722                                        if (strategy != DeflateStrategy.HuffmanOnly &&
723                                                hashHead != 0 &&
724                                                strstart - hashHead <= MAX_DIST &&
725                                                FindLongestMatch(hashHead)) {
726                                               
727                                                // longestMatch sets matchStart and matchLen
728                                                       
729                                                // Discard match if too small and too far away
730                                                if (matchLen <= 5 && (strategy == DeflateStrategy.Filtered || (matchLen == MIN_MATCH && strstart - matchStart > TooFar))) {
731                                                        matchLen = MIN_MATCH - 1;
732                                                }
733                                        }
734                                }
735                               
736                                // previous match was better
737                                if ((prevLen >= MIN_MATCH) && (matchLen <= prevLen) ) {
738#if DebugDeflation
739                                        if (DeflaterConstants.DEBUGGING)
740                                        {
741                                           for (int i = 0 ; i < matchLen; i++) {
742                                                  if (window[strstart-1+i] != window[prevMatch + i])
743                                                         throw new SharpZipBaseException();
744                                                }
745                                        }
746#endif
747                                        huffman.TallyDist(strstart - 1 - prevMatch, prevLen);
748                                        prevLen -= 2;
749                                        do {
750                                                strstart++;
751                                                lookahead--;
752                                                if (lookahead >= MIN_MATCH) {
753                                                        InsertString();
754                                                }
755                                        } while (--prevLen > 0);
756
757                                        strstart ++;
758                                        lookahead--;
759                                        prevAvailable = false;
760                                        matchLen = MIN_MATCH - 1;
761                                } else {
762                                        if (prevAvailable) {
763                                                huffman.TallyLit(window[strstart-1] & 0xff);
764                                        }
765                                        prevAvailable = true;
766                                        strstart++;
767                                        lookahead--;
768                                }
769                               
770                                if (huffman.IsFull()) {
771                                        int len = strstart - blockStart;
772                                        if (prevAvailable) {
773                                                len--;
774                                        }
775                                        bool lastBlock = (finish && (lookahead == 0) && !prevAvailable);
776                                        huffman.FlushBlock(window, blockStart, len, lastBlock);
777                                        blockStart += len;
778                                        return !lastBlock;
779                                }
780                        }
781                        return true;
782                }
783               
784                #region Instance Fields
785
786                // Hash index of string to be inserted
787                int ins_h;
788
789                /// <summary>
790                /// Hashtable, hashing three characters to an index for window, so
791                /// that window[index]..window[index+2] have this hash code. 
792                /// Note that the array should really be unsigned short, so you need
793                /// to and the values with 0xffff.
794                /// </summary>
795                short[] head;
796
797                /// <summary>
798                /// <code>prev[index &amp; WMASK]</code> points to the previous index that has the
799                /// same hash code as the string starting at index.  This way
800                /// entries with the same hash code are in a linked list.
801                /// Note that the array should really be unsigned short, so you need
802                /// to and the values with 0xffff.
803                /// </summary>
804                short[] prev;
805               
806                int    matchStart;
807                // Length of best match
808                int    matchLen;
809                // Set if previous match exists
810                bool   prevAvailable;
811                int    blockStart;
812
813                /// <summary>
814                /// Points to the current character in the window.
815                /// </summary>
816                int    strstart;
817
818                /// <summary>
819                /// lookahead is the number of characters starting at strstart in
820                /// window that are valid.
821                /// So window[strstart] until window[strstart+lookahead-1] are valid
822                /// characters.
823                /// </summary>
824                int    lookahead;
825
826                /// <summary>
827                /// This array contains the part of the uncompressed stream that
828                /// is of relevance.  The current character is indexed by strstart.
829                /// </summary>
830                byte[] window;
831               
832                DeflateStrategy strategy;
833                int max_chain, max_lazy, niceLength, goodLength;
834               
835                /// <summary>
836                /// The current compression function.
837                /// </summary>
838                int compressionFunction;
839               
840                /// <summary>
841                /// The input data for compression.
842                /// </summary>
843                byte[] inputBuf;
844               
845                /// <summary>
846                /// The total bytes of input read.
847                /// </summary>
848                long totalIn;
849               
850                /// <summary>
851                /// The offset into inputBuf, where input data starts.
852                /// </summary>
853                int inputOff;
854               
855                /// <summary>
856                /// The end offset of the input data.
857                /// </summary>
858                int inputEnd;
859               
860                DeflaterPending pending;
861                DeflaterHuffman huffman;
862               
863                /// <summary>
864                /// The adler checksum
865                /// </summary>
866                Adler32 adler;
867                #endregion
868        }
869}
Notatka: Zobacz TracBrowser aby uzyskać więcej informacji.