root/branches/Abonament/BazaReklam.Updater/ICSharpCode.SharpZipLib/Zip/Compression/DeflaterHuffman.cs @ 876

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

re #165

Line 
1// DeflaterHuffman.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
42namespace ICSharpCode.SharpZipLib.Zip.Compression
43{
44       
45        /// <summary>
46        /// This is the DeflaterHuffman class.
47        ///
48        /// This class is <i>not</i> thread safe.  This is inherent in the API, due
49        /// to the split of Deflate and SetInput.
50        ///
51        /// author of the original java version : Jochen Hoenicke
52        /// </summary>
53        public class DeflaterHuffman
54        {
55                const  int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
56                const  int LITERAL_NUM = 286;
57
58                // Number of distance codes
59                const  int DIST_NUM = 30;
60                // Number of codes used to transfer bit lengths
61                const  int BITLEN_NUM = 19;
62
63                // repeat previous bit length 3-6 times (2 bits of repeat count)
64                const  int REP_3_6    = 16;
65                // repeat a zero length 3-10 times  (3 bits of repeat count)
66                const  int REP_3_10   = 17;
67                // repeat a zero length 11-138 times  (7 bits of repeat count)
68                const  int REP_11_138 = 18;
69
70                const  int EOF_SYMBOL = 256;
71
72                // The lengths of the bit length codes are sent in order of decreasing
73                // probability, to avoid transmitting the lengths for unused bit length codes.
74                static readonly int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
75               
76                static readonly byte[] bit4Reverse = {
77                        0,
78                        8,
79                        4,
80                        12,
81                        2,
82                        10,
83                        6,
84                        14,
85                        1,
86                        9,
87                        5,
88                        13,
89                        3,
90                        11,
91                        7,
92                        15
93                };
94
95                static short[] staticLCodes;
96                static byte[]  staticLLength;
97                static short[] staticDCodes;
98                static byte[]  staticDLength;
99               
100                class Tree
101                {
102                        #region Instance Fields
103                        public short[] freqs;
104                       
105                        public byte[]  length;
106                       
107                        public int     minNumCodes;
108                       
109                        public int     numCodes;
110                       
111                        short[] codes;
112                        int[]   bl_counts;
113                        int     maxLength;
114                        DeflaterHuffman dh;
115                        #endregion
116
117                        #region Constructors
118                        public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
119                        {
120                                this.dh =  dh;
121                                this.minNumCodes = minCodes;
122                                this.maxLength  = maxLength;
123                                freqs  = new short[elems];
124                                bl_counts = new int[maxLength];
125                        }
126                       
127                        #endregion
128
129                        /// <summary>
130                        /// Resets the internal state of the tree
131                        /// </summary>
132                        public void Reset()
133                        {
134                                for (int i = 0; i < freqs.Length; i++) {
135                                        freqs[i] = 0;
136                                }
137                                codes = null;
138                                length = null;
139                        }
140                       
141                        public void WriteSymbol(int code)
142                        {
143                                //                              if (DeflaterConstants.DEBUGGING) {
144                                //                                      freqs[code]--;
145                                //                                      //        Console.Write("writeSymbol("+freqs.length+","+code+"): ");
146                                //                              }
147                                dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
148                        }
149                       
150                        /// <summary>
151                        /// Check that all frequencies are zero
152                        /// </summary>
153                        /// <exception cref="SharpZipBaseException">
154                        /// At least one frequency is non-zero
155                        /// </exception>
156                        public void CheckEmpty()
157                        {
158                                bool empty = true;
159                                for (int i = 0; i < freqs.Length; i++) {
160                                        if (freqs[i] != 0) {
161                                                //Console.WriteLine("freqs[" + i + "] == " + freqs[i]);
162                                                empty = false;
163                                        }
164                                }
165                               
166                                if (!empty) {
167                                        throw new SharpZipBaseException("!Empty");
168                                }
169                        }
170
171                        /// <summary>
172                        /// Set static codes and length
173                        /// </summary>
174                        /// <param name="staticCodes">new codes</param>
175                        /// <param name="staticLengths">length for new codes</param>
176                        public void SetStaticCodes(short[] staticCodes, byte[] staticLengths)
177                        {
178                                codes = staticCodes;
179                                length = staticLengths;
180                        }
181                       
182                        /// <summary>
183                        /// Build dynamic codes and lengths
184                        /// </summary>
185                        public void BuildCodes()
186                        {
187                                int numSymbols = freqs.Length;
188                                int[] nextCode = new int[maxLength];
189                                int code = 0;
190
191                                codes = new short[freqs.Length];
192                               
193                                //                              if (DeflaterConstants.DEBUGGING) {
194                                //                                      //Console.WriteLine("buildCodes: "+freqs.Length);
195                                //                              }
196                               
197                                for (int bits = 0; bits < maxLength; bits++) {
198                                        nextCode[bits] = code;
199                                        code += bl_counts[bits] << (15 - bits);
200
201                                        //                                      if (DeflaterConstants.DEBUGGING) {
202                                        //                                              //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits]
203                                        //                                                                +" nextCode: "+code);
204                                        //                                      }
205                                }
206
207#if DebugDeflation
208                                if ( DeflaterConstants.DEBUGGING && (code != 65536) )
209                                {
210                                        throw new SharpZipBaseException("Inconsistent bl_counts!");
211                                }
212#endif                         
213                                for (int i=0; i < numCodes; i++) {
214                                        int bits = length[i];
215                                        if (bits > 0) {
216
217                                                //                                              if (DeflaterConstants.DEBUGGING) {
218                                                //                                                              //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"),
219                                                //                                                                                +bits);
220                                                //                                              }
221
222                                                codes[i] = BitReverse(nextCode[bits-1]);
223                                                nextCode[bits-1] += 1 << (16 - bits);
224                                        }
225                                }
226                        }
227                       
228                        public void BuildTree()
229                        {
230                                int numSymbols = freqs.Length;
231                               
232                                /* heap is a priority queue, sorted by frequency, least frequent
233                                * nodes first.  The heap is a binary tree, with the property, that
234                                * the parent node is smaller than both child nodes.  This assures
235                                * that the smallest node is the first parent.
236                                *
237                                * The binary tree is encoded in an array:  0 is root node and
238                                * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
239                                */
240                                int[] heap = new int[numSymbols];
241                                int heapLen = 0;
242                                int maxCode = 0;
243                                for (int n = 0; n < numSymbols; n++) {
244                                        int freq = freqs[n];
245                                        if (freq != 0) {
246                                                // Insert n into heap
247                                                int pos = heapLen++;
248                                                int ppos;
249                                                while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) {
250                                                        heap[pos] = heap[ppos];
251                                                        pos = ppos;
252                                                }
253                                                heap[pos] = n;
254                                               
255                                                maxCode = n;
256                                        }
257                                }
258                               
259                                /* We could encode a single literal with 0 bits but then we
260                                * don't see the literals.  Therefore we force at least two
261                                * literals to avoid this case.  We don't care about order in
262                                * this case, both literals get a 1 bit code.
263                                */
264                                while (heapLen < 2) {
265                                        int node = maxCode < 2 ? ++maxCode : 0;
266                                        heap[heapLen++] = node;
267                                }
268                               
269                                numCodes = Math.Max(maxCode + 1, minNumCodes);
270                               
271                                int numLeafs = heapLen;
272                                int[] childs = new int[4 * heapLen - 2];
273                                int[] values = new int[2 * heapLen - 1];
274                                int numNodes = numLeafs;
275                                for (int i = 0; i < heapLen; i++) {
276                                        int node = heap[i];
277                                        childs[2 * i]   = node;
278                                        childs[2 * i + 1] = -1;
279                                        values[i] = freqs[node] << 8;
280                                        heap[i] = i;
281                                }
282                               
283                                /* Construct the Huffman tree by repeatedly combining the least two
284                                * frequent nodes.
285                                */
286                                do {
287                                        int first = heap[0];
288                                        int last  = heap[--heapLen];
289                                       
290                                        // Propagate the hole to the leafs of the heap
291                                        int ppos = 0;
292                                        int path = 1;
293                                       
294                                        while (path < heapLen) {
295                                                if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
296                                                        path++;
297                                                }
298                                                       
299                                                heap[ppos] = heap[path];
300                                                ppos = path;
301                                                path = path * 2 + 1;
302                                        }
303                                               
304                                        /* Now propagate the last element down along path.  Normally
305                                        * it shouldn't go too deep.
306                                        */
307                                        int lastVal = values[last];
308                                        while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
309                                                heap[path] = heap[ppos];
310                                        }
311                                        heap[path] = last;
312                                       
313                                       
314                                        int second = heap[0];
315                                       
316                                        // Create a new node father of first and second
317                                        last = numNodes++;
318                                        childs[2 * last] = first;
319                                        childs[2 * last + 1] = second;
320                                        int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
321                                        values[last] = lastVal = values[first] + values[second] - mindepth + 1;
322                                       
323                                        // Again, propagate the hole to the leafs
324                                        ppos = 0;
325                                        path = 1;
326                                       
327                                        while (path < heapLen) {
328                                                if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
329                                                        path++;
330                                                }
331                                                       
332                                                heap[ppos] = heap[path];
333                                                ppos = path;
334                                                path = ppos * 2 + 1;
335                                        }
336                                               
337                                        // Now propagate the new element down along path
338                                        while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
339                                                heap[path] = heap[ppos];
340                                        }
341                                        heap[path] = last;
342                                } while (heapLen > 1);
343                               
344                                if (heap[0] != childs.Length / 2 - 1) {
345                                        throw new SharpZipBaseException("Heap invariant violated");
346                                }
347                               
348                                BuildLength(childs);
349                        }
350                       
351                        /// <summary>
352                        /// Get encoded length
353                        /// </summary>
354                        /// <returns>Encoded length, the sum of frequencies * lengths</returns>
355                        public int GetEncodedLength()
356                        {
357                                int len = 0;
358                                for (int i = 0; i < freqs.Length; i++) {
359                                        len += freqs[i] * length[i];
360                                }
361                                return len;
362                        }
363                       
364                        /// <summary>
365                        /// Scan a literal or distance tree to determine the frequencies of the codes
366                        /// in the bit length tree.
367                        /// </summary>
368                        public void CalcBLFreq(Tree blTree)
369                        {
370                                int max_count;               /* max repeat count */
371                                int min_count;               /* min repeat count */
372                                int count;                   /* repeat count of the current code */
373                                int curlen = -1;             /* length of current code */
374                               
375                                int i = 0;
376                                while (i < numCodes) {
377                                        count = 1;
378                                        int nextlen = length[i];
379                                        if (nextlen == 0) {
380                                                max_count = 138;
381                                                min_count = 3;
382                                        } else {
383                                                max_count = 6;
384                                                min_count = 3;
385                                                if (curlen != nextlen) {
386                                                        blTree.freqs[nextlen]++;
387                                                        count = 0;
388                                                }
389                                        }
390                                        curlen = nextlen;
391                                        i++;
392                                       
393                                        while (i < numCodes && curlen == length[i]) {
394                                                i++;
395                                                if (++count >= max_count) {
396                                                        break;
397                                                }
398                                        }
399                                       
400                                        if (count < min_count) {
401                                                blTree.freqs[curlen] += (short)count;
402                                        } else if (curlen != 0) {
403                                                blTree.freqs[REP_3_6]++;
404                                        } else if (count <= 10) {
405                                                blTree.freqs[REP_3_10]++;
406                                        } else {
407                                                blTree.freqs[REP_11_138]++;
408                                        }
409                                }
410                        }
411               
412                        /// <summary>
413                        /// Write tree values
414                        /// </summary>
415                        /// <param name="blTree">Tree to write</param>
416                        public void WriteTree(Tree blTree)
417                        {
418                                int max_count;               // max repeat count
419                                int min_count;               // min repeat count
420                                int count;                   // repeat count of the current code
421                                int curlen = -1;             // length of current code
422                               
423                                int i = 0;
424                                while (i < numCodes) {
425                                        count = 1;
426                                        int nextlen = length[i];
427                                        if (nextlen == 0) {
428                                                max_count = 138;
429                                                min_count = 3;
430                                        } else {
431                                                max_count = 6;
432                                                min_count = 3;
433                                                if (curlen != nextlen) {
434                                                        blTree.WriteSymbol(nextlen);
435                                                        count = 0;
436                                                }
437                                        }
438                                        curlen = nextlen;
439                                        i++;
440                                       
441                                        while (i < numCodes && curlen == length[i]) {
442                                                i++;
443                                                if (++count >= max_count) {
444                                                        break;
445                                                }
446                                        }
447                                       
448                                        if (count < min_count) {
449                                                while (count-- > 0) {
450                                                        blTree.WriteSymbol(curlen);
451                                                }
452                                        } else if (curlen != 0) {
453                                                blTree.WriteSymbol(REP_3_6);
454                                                dh.pending.WriteBits(count - 3, 2);
455                                        } else if (count <= 10) {
456                                                blTree.WriteSymbol(REP_3_10);
457                                                dh.pending.WriteBits(count - 3, 3);
458                                        } else {
459                                                blTree.WriteSymbol(REP_11_138);
460                                                dh.pending.WriteBits(count - 11, 7);
461                                        }
462                                }
463                        }
464
465                        void BuildLength(int[] childs)
466                        {
467                                this.length = new byte [freqs.Length];
468                                int numNodes = childs.Length / 2;
469                                int numLeafs = (numNodes + 1) / 2;
470                                int overflow = 0;
471                               
472                                for (int i = 0; i < maxLength; i++) {
473                                        bl_counts[i] = 0;
474                                }
475                               
476                                // First calculate optimal bit lengths
477                                int[] lengths = new int[numNodes];
478                                lengths[numNodes-1] = 0;
479                               
480                                for (int i = numNodes - 1; i >= 0; i--) {
481                                        if (childs[2 * i + 1] != -1) {
482                                                int bitLength = lengths[i] + 1;
483                                                if (bitLength > maxLength) {
484                                                        bitLength = maxLength;
485                                                        overflow++;
486                                                }
487                                                lengths[childs[2 * i]] = lengths[childs[2 * i + 1]] = bitLength;
488                                        } else {
489                                                // A leaf node
490                                                int bitLength = lengths[i];
491                                                bl_counts[bitLength - 1]++;
492                                                this.length[childs[2*i]] = (byte) lengths[i];
493                                        }
494                                }
495                               
496                                //                              if (DeflaterConstants.DEBUGGING) {
497                                //                                      //Console.WriteLine("Tree "+freqs.Length+" lengths:");
498                                //                                      for (int i=0; i < numLeafs; i++) {
499                                //                                              //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
500                                //                                                                + " len: "+length[childs[2*i]]);
501                                //                                      }
502                                //                              }
503                               
504                                if (overflow == 0) {
505                                        return;
506                                }
507                               
508                                int incrBitLen = maxLength - 1;
509                                do {
510                                        // Find the first bit length which could increase:
511                                        while (bl_counts[--incrBitLen] == 0)
512                                                ;
513                                       
514                                        // Move this node one down and remove a corresponding
515                                        // number of overflow nodes.
516                                        do {
517                                                bl_counts[incrBitLen]--;
518                                                bl_counts[++incrBitLen]++;
519                                                overflow -= 1 << (maxLength - 1 - incrBitLen);
520                                        } while (overflow > 0 && incrBitLen < maxLength - 1);
521                                } while (overflow > 0);
522                               
523                                /* We may have overshot above.  Move some nodes from maxLength to
524                                * maxLength-1 in that case.
525                                */
526                                bl_counts[maxLength-1] += overflow;
527                                bl_counts[maxLength-2] -= overflow;
528                               
529                                /* Now recompute all bit lengths, scanning in increasing
530                                * frequency.  It is simpler to reconstruct all lengths instead of
531                                * fixing only the wrong ones. This idea is taken from 'ar'
532                                * written by Haruhiko Okumura.
533                                *
534                                * The nodes were inserted with decreasing frequency into the childs
535                                * array.
536                                */
537                                int nodePtr = 2 * numLeafs;
538                                for (int bits = maxLength; bits != 0; bits--) {
539                                        int n = bl_counts[bits-1];
540                                        while (n > 0) {
541                                                int childPtr = 2*childs[nodePtr++];
542                                                if (childs[childPtr + 1] == -1) {
543                                                        // We found another leaf
544                                                        length[childs[childPtr]] = (byte) bits;
545                                                        n--;
546                                                }
547                                        }
548                                }
549                                //                              if (DeflaterConstants.DEBUGGING) {
550                                //                                      //Console.WriteLine("*** After overflow elimination. ***");
551                                //                                      for (int i=0; i < numLeafs; i++) {
552                                //                                              //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
553                                //                                                                + " len: "+length[childs[2*i]]);
554                                //                                      }
555                                //                              }
556                        }
557                       
558                }
559
560                #region Instance Fields
561                /// <summary>
562                /// Pending buffer to use
563                /// </summary>
564                public DeflaterPending pending;
565               
566                Tree literalTree;
567                Tree distTree;
568                Tree blTree;
569               
570                // Buffer for distances
571                short[] d_buf;
572                byte[]  l_buf;
573                int last_lit;
574                int extra_bits;
575                #endregion
576
577                static DeflaterHuffman()
578                {
579                        // See RFC 1951 3.2.6
580                        // Literal codes
581                        staticLCodes = new short[LITERAL_NUM];
582                        staticLLength = new byte[LITERAL_NUM];
583
584                        int i = 0;
585                        while (i < 144) {
586                                staticLCodes[i] = BitReverse((0x030 + i) << 8);
587                                staticLLength[i++] = 8;
588                        }
589
590                        while (i < 256) {
591                                staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
592                                staticLLength[i++] = 9;
593                        }
594
595                        while (i < 280) {
596                                staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
597                                staticLLength[i++] = 7;
598                        }
599
600                        while (i < LITERAL_NUM) {
601                                staticLCodes[i] = BitReverse((0x0c0 - 280 + i)  << 8);
602                                staticLLength[i++] = 8;
603                        }
604                       
605                        // Distance codes
606                        staticDCodes = new short[DIST_NUM];
607                        staticDLength = new byte[DIST_NUM];
608                        for (i = 0; i < DIST_NUM; i++) {
609                                staticDCodes[i] = BitReverse(i << 11);
610                                staticDLength[i] = 5;
611                        }
612                }
613               
614                /// <summary>
615                /// Construct instance with pending buffer
616                /// </summary>
617                /// <param name="pending">Pending buffer to use</param>
618                public DeflaterHuffman(DeflaterPending pending)
619                {
620                        this.pending = pending;
621                       
622                        literalTree = new Tree(this, LITERAL_NUM, 257, 15);
623                        distTree    = new Tree(this, DIST_NUM, 1, 15);
624                        blTree      = new Tree(this, BITLEN_NUM, 4, 7);
625                       
626                        d_buf = new short[BUFSIZE];
627                        l_buf = new byte [BUFSIZE];
628                }
629
630                /// <summary>
631                /// Reset internal state
632                /// </summary>         
633                public void Reset()
634                {
635                        last_lit = 0;
636                        extra_bits = 0;
637                        literalTree.Reset();
638                        distTree.Reset();
639                        blTree.Reset();
640                }
641               
642                /// <summary>
643                /// Write all trees to pending buffer
644                /// </summary>
645                /// <param name="blTreeCodes">The number/rank of treecodes to send.</param>
646                public void SendAllTrees(int blTreeCodes)
647                {
648                        blTree.BuildCodes();
649                        literalTree.BuildCodes();
650                        distTree.BuildCodes();
651                        pending.WriteBits(literalTree.numCodes - 257, 5);
652                        pending.WriteBits(distTree.numCodes - 1, 5);
653                        pending.WriteBits(blTreeCodes - 4, 4);
654                        for (int rank = 0; rank < blTreeCodes; rank++) {
655                                pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
656                        }
657                        literalTree.WriteTree(blTree);
658                        distTree.WriteTree(blTree);
659
660#if DebugDeflation
661                        if (DeflaterConstants.DEBUGGING) {
662                                blTree.CheckEmpty();
663                        }
664#endif
665                }
666
667                /// <summary>
668                /// Compress current buffer writing data to pending buffer
669                /// </summary>
670                public void CompressBlock()
671                {
672                        for (int i = 0; i < last_lit; i++) {
673                                int litlen = l_buf[i] & 0xff;
674                                int dist = d_buf[i];
675                                if (dist-- != 0) {
676                                        //                                      if (DeflaterConstants.DEBUGGING) {
677                                        //                                              Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
678                                        //                                      }
679                                       
680                                        int lc = Lcode(litlen);
681                                        literalTree.WriteSymbol(lc);
682                                       
683                                        int bits = (lc - 261) / 4;
684                                        if (bits > 0 && bits <= 5) {
685                                                pending.WriteBits(litlen & ((1 << bits) - 1), bits);
686                                        }
687                                       
688                                        int dc = Dcode(dist);
689                                        distTree.WriteSymbol(dc);
690                                       
691                                        bits = dc / 2 - 1;
692                                        if (bits > 0) {
693                                                pending.WriteBits(dist & ((1 << bits) - 1), bits);
694                                        }
695                                } else {
696                                        //                                      if (DeflaterConstants.DEBUGGING) {
697                                        //                                              if (litlen > 32 && litlen < 127) {
698                                        //                                                      Console.Write("("+(char)litlen+"): ");
699                                        //                                              } else {
700                                        //                                                      Console.Write("{"+litlen+"}: ");
701                                        //                                              }
702                                        //                                      }
703                                        literalTree.WriteSymbol(litlen);
704                                }
705                        }
706
707#if DebugDeflation
708                        if (DeflaterConstants.DEBUGGING) {
709                                Console.Write("EOF: ");
710                        }
711#endif
712                        literalTree.WriteSymbol(EOF_SYMBOL);
713
714#if DebugDeflation
715                        if (DeflaterConstants.DEBUGGING) {
716                                literalTree.CheckEmpty();
717                                distTree.CheckEmpty();
718                        }
719#endif
720                }
721               
722                /// <summary>
723                /// Flush block to output with no compression
724                /// </summary>
725                /// <param name="stored">Data to write</param>
726                /// <param name="storedOffset">Index of first byte to write</param>
727                /// <param name="storedLength">Count of bytes to write</param>
728                /// <param name="lastBlock">True if this is the last block</param>
729                public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
730                {
731#if DebugDeflation
732                        //                      if (DeflaterConstants.DEBUGGING) {
733                        //                              //Console.WriteLine("Flushing stored block "+ storedLength);
734                        //                      }
735#endif
736                        pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
737                        pending.AlignToByte();
738                        pending.WriteShort(storedLength);
739                        pending.WriteShort(~storedLength);
740                        pending.WriteBlock(stored, storedOffset, storedLength);
741                        Reset();
742                }
743
744                /// <summary>
745                /// Flush block to output with compression
746                /// </summary>         
747                /// <param name="stored">Data to flush</param>
748                /// <param name="storedOffset">Index of first byte to flush</param>
749                /// <param name="storedLength">Count of bytes to flush</param>
750                /// <param name="lastBlock">True if this is the last block</param>
751                public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
752                {
753                        literalTree.freqs[EOF_SYMBOL]++;
754                       
755                        // Build trees
756                        literalTree.BuildTree();
757                        distTree.BuildTree();
758                       
759                        // Calculate bitlen frequency
760                        literalTree.CalcBLFreq(blTree);
761                        distTree.CalcBLFreq(blTree);
762                       
763                        // Build bitlen tree
764                        blTree.BuildTree();
765                       
766                        int blTreeCodes = 4;
767                        for (int i = 18; i > blTreeCodes; i--) {
768                                if (blTree.length[BL_ORDER[i]] > 0) {
769                                        blTreeCodes = i+1;
770                                }
771                        }
772                        int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
773                                literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
774                                extra_bits;
775                       
776                        int static_len = extra_bits;
777                        for (int i = 0; i < LITERAL_NUM; i++) {
778                                static_len += literalTree.freqs[i] * staticLLength[i];
779                        }
780                        for (int i = 0; i < DIST_NUM; i++) {
781                                static_len += distTree.freqs[i] * staticDLength[i];
782                        }
783                        if (opt_len >= static_len) {
784                                // Force static trees
785                                opt_len = static_len;
786                        }
787                       
788                        if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3) {
789                                // Store Block
790
791                                //                              if (DeflaterConstants.DEBUGGING) {
792                                //                                      //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
793                                //                                                        + " <= " + static_len);
794                                //                              }
795                                FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
796                        } else if (opt_len == static_len) {
797                                // Encode with static tree
798                                pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
799                                literalTree.SetStaticCodes(staticLCodes, staticLLength);
800                                distTree.SetStaticCodes(staticDCodes, staticDLength);
801                                CompressBlock();
802                                Reset();
803                        } else {
804                                // Encode with dynamic tree
805                                pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
806                                SendAllTrees(blTreeCodes);
807                                CompressBlock();
808                                Reset();
809                        }
810                }
811               
812                /// <summary>
813                /// Get value indicating if internal buffer is full
814                /// </summary>
815                /// <returns>true if buffer is full</returns>
816                public bool IsFull()
817                {
818                        return last_lit >= BUFSIZE;
819                }
820               
821                /// <summary>
822                /// Add literal to buffer
823                /// </summary>
824                /// <param name="literal">Literal value to add to buffer.</param>
825                /// <returns>Value indicating internal buffer is full</returns>
826                public bool TallyLit(int literal)
827                {
828                        //                      if (DeflaterConstants.DEBUGGING) {
829                        //                              if (lit > 32 && lit < 127) {
830                        //                                      //Console.WriteLine("("+(char)lit+")");
831                        //                              } else {
832                        //                                      //Console.WriteLine("{"+lit+"}");
833                        //                              }
834                        //                      }
835                        d_buf[last_lit] = 0;
836                        l_buf[last_lit++] = (byte)literal;
837                        literalTree.freqs[literal]++;
838                        return IsFull();
839                }
840               
841                /// <summary>
842                /// Add distance code and length to literal and distance trees
843                /// </summary>
844                /// <param name="distance">Distance code</param>
845                /// <param name="length">Length</param>
846                /// <returns>Value indicating if internal buffer is full</returns>
847                public bool TallyDist(int distance, int length)
848                {
849                        //                      if (DeflaterConstants.DEBUGGING) {
850                        //                              //Console.WriteLine("[" + distance + "," + length + "]");
851                        //                      }
852                       
853                        d_buf[last_lit]   = (short)distance;
854                        l_buf[last_lit++] = (byte)(length - 3);
855                       
856                        int lc = Lcode(length - 3);
857                        literalTree.freqs[lc]++;
858                        if (lc >= 265 && lc < 285) {
859                                extra_bits += (lc - 261) / 4;
860                        }
861                       
862                        int dc = Dcode(distance - 1);
863                        distTree.freqs[dc]++;
864                        if (dc >= 4) {
865                                extra_bits += dc / 2 - 1;
866                        }
867                        return IsFull();
868                }
869
870               
871                /// <summary>
872                /// Reverse the bits of a 16 bit value.
873                /// </summary>
874                /// <param name="toReverse">Value to reverse bits</param>
875                /// <returns>Value with bits reversed</returns>
876                public static short BitReverse(int toReverse)
877                {
878                        return (short) (bit4Reverse[toReverse & 0xF] << 12 |
879                                        bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
880                                        bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
881                                        bit4Reverse[toReverse >> 12]);
882                }
883               
884                static int Lcode(int length)
885                {
886                        if (length == 255) {
887                                return 285;
888                        }
889                       
890                        int code = 257;
891                        while (length >= 8) {
892                                code += 4;
893                                length >>= 1;
894                        }
895                        return code + length;
896                }
897               
898                static int Dcode(int distance)
899                {
900                        int code = 0;
901                        while (distance >= 4) {
902                                code += 2;
903                                distance >>= 1;
904                        }
905                        return code + distance;
906                }
907        }
908}
Notatka: Zobacz TracBrowser aby uzyskać więcej informacji.