- Change dispatcher lock release to be more like documented in Windows Internals...
[reactos.git] / irc / TechBot / Compression / DeflaterHuffman.cs
1 // DeflaterHuffman.cs
2 // Copyright (C) 2001 Mike Krueger
3 //
4 // This file was translated from java, it was part of the GNU Classpath
5 // Copyright (C) 2001 Free Software Foundation, Inc.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 2
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 //
21 // Linking this library statically or dynamically with other modules is
22 // making a combined work based on this library. Thus, the terms and
23 // conditions of the GNU General Public License cover the whole
24 // combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent
29 // modules, and to copy and distribute the resulting executable under
30 // terms of your choice, provided that you also meet, for each linked
31 // independent module, the terms and conditions of the license of that
32 // module. An independent module is a module which is not derived from
33 // or based on this library. If you modify this library, you may extend
34 // this exception to your version of the library, but you are not
35 // obligated to do so. If you do not wish to do so, delete this
36 // exception statement from your version.
37
38 using System;
39
40 namespace ICSharpCode.SharpZipLib.Zip.Compression
41 {
42
43 /// <summary>
44 /// This is the DeflaterHuffman class.
45 ///
46 /// This class is <i>not</i> thread safe. This is inherent in the API, due
47 /// to the split of deflate and setInput.
48 ///
49 /// author of the original java version : Jochen Hoenicke
50 /// </summary>
51 public class DeflaterHuffman
52 {
53 private static int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
54 private static int LITERAL_NUM = 286;
55 private static int DIST_NUM = 30;
56 private static int BITLEN_NUM = 19;
57 private static int REP_3_6 = 16;
58 private static int REP_3_10 = 17;
59 private static int REP_11_138 = 18;
60 private static int EOF_SYMBOL = 256;
61 private static int[] BL_ORDER = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
62
63 private static byte[] bit4Reverse = {
64 0,
65 8,
66 4,
67 12,
68 2,
69 10,
70 6,
71 14,
72 1,
73 9,
74 5,
75 13,
76 3,
77 11,
78 7,
79 15
80 };
81
82 public class Tree
83 {
84 public short[] freqs;
85 public byte[] length;
86 public int minNumCodes, numCodes;
87
88 short[] codes;
89 int[] bl_counts;
90 int maxLength;
91 DeflaterHuffman dh;
92
93 public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
94 {
95 this.dh = dh;
96 this.minNumCodes = minCodes;
97 this.maxLength = maxLength;
98 freqs = new short[elems];
99 bl_counts = new int[maxLength];
100 }
101
102 public void Reset()
103 {
104 for (int i = 0; i < freqs.Length; i++) {
105 freqs[i] = 0;
106 }
107 codes = null;
108 length = null;
109 }
110
111 public void WriteSymbol(int code)
112 {
113 // if (DeflaterConstants.DEBUGGING) {
114 // freqs[code]--;
115 // // Console.Write("writeSymbol("+freqs.length+","+code+"): ");
116 // }
117 dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
118 }
119
120 public void CheckEmpty()
121 {
122 bool empty = true;
123 for (int i = 0; i < freqs.Length; i++) {
124 if (freqs[i] != 0) {
125 //Console.WriteLine("freqs["+i+"] == "+freqs[i]);
126 empty = false;
127 }
128 }
129 if (!empty) {
130 throw new Exception();
131 }
132 //Console.WriteLine("checkEmpty suceeded!");
133 }
134
135 public void SetStaticCodes(short[] stCodes, byte[] stLength)
136 {
137 codes = stCodes;
138 length = stLength;
139 }
140
141 public void BuildCodes()
142 {
143 int numSymbols = freqs.Length;
144 int[] nextCode = new int[maxLength];
145 int code = 0;
146 codes = new short[freqs.Length];
147
148 // if (DeflaterConstants.DEBUGGING) {
149 // //Console.WriteLine("buildCodes: "+freqs.Length);
150 // }
151
152 for (int bits = 0; bits < maxLength; bits++) {
153 nextCode[bits] = code;
154 code += bl_counts[bits] << (15 - bits);
155 // if (DeflaterConstants.DEBUGGING) {
156 // //Console.WriteLine("bits: "+(bits+1)+" count: "+bl_counts[bits]
157 // +" nextCode: "+code); // HACK : Integer.toHexString(
158 // }
159 }
160 if (DeflaterConstants.DEBUGGING && code != 65536) {
161 throw new Exception("Inconsistent bl_counts!");
162 }
163
164 for (int i=0; i < numCodes; i++) {
165 int bits = length[i];
166 if (bits > 0) {
167 // if (DeflaterConstants.DEBUGGING) {
168 // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+")," // HACK : Integer.toHexString(
169 // +bits);
170 // }
171 codes[i] = BitReverse(nextCode[bits-1]);
172 nextCode[bits-1] += 1 << (16 - bits);
173 }
174 }
175 }
176
177 void BuildLength(int[] childs)
178 {
179 this.length = new byte [freqs.Length];
180 int numNodes = childs.Length / 2;
181 int numLeafs = (numNodes + 1) / 2;
182 int overflow = 0;
183
184 for (int i = 0; i < maxLength; i++) {
185 bl_counts[i] = 0;
186 }
187
188 /* First calculate optimal bit lengths */
189 int[] lengths = new int[numNodes];
190 lengths[numNodes-1] = 0;
191
192 for (int i = numNodes - 1; i >= 0; i--) {
193 if (childs[2*i+1] != -1) {
194 int bitLength = lengths[i] + 1;
195 if (bitLength > maxLength) {
196 bitLength = maxLength;
197 overflow++;
198 }
199 lengths[childs[2*i]] = lengths[childs[2*i+1]] = bitLength;
200 } else {
201 /* A leaf node */
202 int bitLength = lengths[i];
203 bl_counts[bitLength - 1]++;
204 this.length[childs[2*i]] = (byte) lengths[i];
205 }
206 }
207
208 // if (DeflaterConstants.DEBUGGING) {
209 // //Console.WriteLine("Tree "+freqs.Length+" lengths:");
210 // for (int i=0; i < numLeafs; i++) {
211 // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
212 // + " len: "+length[childs[2*i]]);
213 // }
214 // }
215
216 if (overflow == 0) {
217 return;
218 }
219
220 int incrBitLen = maxLength - 1;
221 do {
222 /* Find the first bit length which could increase: */
223 while (bl_counts[--incrBitLen] == 0)
224 ;
225
226 /* Move this node one down and remove a corresponding
227 * amount of overflow nodes.
228 */
229 do {
230 bl_counts[incrBitLen]--;
231 bl_counts[++incrBitLen]++;
232 overflow -= 1 << (maxLength - 1 - incrBitLen);
233 } while (overflow > 0 && incrBitLen < maxLength - 1);
234 } while (overflow > 0);
235
236 /* We may have overshot above. Move some nodes from maxLength to
237 * maxLength-1 in that case.
238 */
239 bl_counts[maxLength-1] += overflow;
240 bl_counts[maxLength-2] -= overflow;
241
242 /* Now recompute all bit lengths, scanning in increasing
243 * frequency. It is simpler to reconstruct all lengths instead of
244 * fixing only the wrong ones. This idea is taken from 'ar'
245 * written by Haruhiko Okumura.
246 *
247 * The nodes were inserted with decreasing frequency into the childs
248 * array.
249 */
250 int nodePtr = 2 * numLeafs;
251 for (int bits = maxLength; bits != 0; bits--) {
252 int n = bl_counts[bits-1];
253 while (n > 0) {
254 int childPtr = 2*childs[nodePtr++];
255 if (childs[childPtr + 1] == -1) {
256 /* We found another leaf */
257 length[childs[childPtr]] = (byte) bits;
258 n--;
259 }
260 }
261 }
262 // if (DeflaterConstants.DEBUGGING) {
263 // //Console.WriteLine("*** After overflow elimination. ***");
264 // for (int i=0; i < numLeafs; i++) {
265 // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
266 // + " len: "+length[childs[2*i]]);
267 // }
268 // }
269 }
270
271 public void BuildTree()
272 {
273 int numSymbols = freqs.Length;
274
275 /* heap is a priority queue, sorted by frequency, least frequent
276 * nodes first. The heap is a binary tree, with the property, that
277 * the parent node is smaller than both child nodes. This assures
278 * that the smallest node is the first parent.
279 *
280 * The binary tree is encoded in an array: 0 is root node and
281 * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
282 */
283 int[] heap = new int[numSymbols];
284 int heapLen = 0;
285 int maxCode = 0;
286 for (int n = 0; n < numSymbols; n++) {
287 int freq = freqs[n];
288 if (freq != 0) {
289 /* Insert n into heap */
290 int pos = heapLen++;
291 int ppos;
292 while (pos > 0 && freqs[heap[ppos = (pos - 1) / 2]] > freq) {
293 heap[pos] = heap[ppos];
294 pos = ppos;
295 }
296 heap[pos] = n;
297
298 maxCode = n;
299 }
300 }
301
302 /* We could encode a single literal with 0 bits but then we
303 * don't see the literals. Therefore we force at least two
304 * literals to avoid this case. We don't care about order in
305 * this case, both literals get a 1 bit code.
306 */
307 while (heapLen < 2) {
308 int node = maxCode < 2 ? ++maxCode : 0;
309 heap[heapLen++] = node;
310 }
311
312 numCodes = Math.Max(maxCode + 1, minNumCodes);
313
314 int numLeafs = heapLen;
315 int[] childs = new int[4*heapLen - 2];
316 int[] values = new int[2*heapLen - 1];
317 int numNodes = numLeafs;
318 for (int i = 0; i < heapLen; i++) {
319 int node = heap[i];
320 childs[2*i] = node;
321 childs[2*i+1] = -1;
322 values[i] = freqs[node] << 8;
323 heap[i] = i;
324 }
325
326 /* Construct the Huffman tree by repeatedly combining the least two
327 * frequent nodes.
328 */
329 do {
330 int first = heap[0];
331 int last = heap[--heapLen];
332
333 /* Propagate the hole to the leafs of the heap */
334 int ppos = 0;
335 int path = 1;
336
337 while (path < heapLen) {
338 if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
339 path++;
340 }
341
342 heap[ppos] = heap[path];
343 ppos = path;
344 path = path * 2 + 1;
345 }
346
347 /* Now propagate the last element down along path. Normally
348 * it shouldn't go too deep.
349 */
350 int lastVal = values[last];
351 while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
352 heap[path] = heap[ppos];
353 }
354 heap[path] = last;
355
356
357 int second = heap[0];
358
359 /* Create a new node father of first and second */
360 last = numNodes++;
361 childs[2*last] = first;
362 childs[2*last+1] = second;
363 int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
364 values[last] = lastVal = values[first] + values[second] - mindepth + 1;
365
366 /* Again, propagate the hole to the leafs */
367 ppos = 0;
368 path = 1;
369
370 while (path < heapLen) {
371 if (path + 1 < heapLen && values[heap[path]] > values[heap[path+1]]) {
372 path++;
373 }
374
375 heap[ppos] = heap[path];
376 ppos = path;
377 path = ppos * 2 + 1;
378 }
379
380 /* Now propagate the new element down along path */
381 while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal) {
382 heap[path] = heap[ppos];
383 }
384 heap[path] = last;
385 } while (heapLen > 1);
386
387 if (heap[0] != childs.Length / 2 - 1) {
388 throw new Exception("Weird!");
389 }
390 BuildLength(childs);
391 }
392
393 public int GetEncodedLength()
394 {
395 int len = 0;
396 for (int i = 0; i < freqs.Length; i++) {
397 len += freqs[i] * length[i];
398 }
399 return len;
400 }
401
402 public void CalcBLFreq(Tree blTree)
403 {
404 int max_count; /* max repeat count */
405 int min_count; /* min repeat count */
406 int count; /* repeat count of the current code */
407 int curlen = -1; /* length of current code */
408
409 int i = 0;
410 while (i < numCodes) {
411 count = 1;
412 int nextlen = length[i];
413 if (nextlen == 0) {
414 max_count = 138;
415 min_count = 3;
416 } else {
417 max_count = 6;
418 min_count = 3;
419 if (curlen != nextlen) {
420 blTree.freqs[nextlen]++;
421 count = 0;
422 }
423 }
424 curlen = nextlen;
425 i++;
426
427 while (i < numCodes && curlen == length[i]) {
428 i++;
429 if (++count >= max_count) {
430 break;
431 }
432 }
433
434 if (count < min_count) {
435 blTree.freqs[curlen] += (short)count;
436 } else if (curlen != 0) {
437 blTree.freqs[REP_3_6]++;
438 } else if (count <= 10) {
439 blTree.freqs[REP_3_10]++;
440 } else {
441 blTree.freqs[REP_11_138]++;
442 }
443 }
444 }
445
446 public void WriteTree(Tree blTree)
447 {
448 int max_count; /* max repeat count */
449 int min_count; /* min repeat count */
450 int count; /* repeat count of the current code */
451 int curlen = -1; /* length of current code */
452
453 int i = 0;
454 while (i < numCodes) {
455 count = 1;
456 int nextlen = length[i];
457 if (nextlen == 0) {
458 max_count = 138;
459 min_count = 3;
460 } else {
461 max_count = 6;
462 min_count = 3;
463 if (curlen != nextlen) {
464 blTree.WriteSymbol(nextlen);
465 count = 0;
466 }
467 }
468 curlen = nextlen;
469 i++;
470
471 while (i < numCodes && curlen == length[i]) {
472 i++;
473 if (++count >= max_count) {
474 break;
475 }
476 }
477
478 if (count < min_count) {
479 while (count-- > 0) {
480 blTree.WriteSymbol(curlen);
481 }
482 } else if (curlen != 0) {
483 blTree.WriteSymbol(REP_3_6);
484 dh.pending.WriteBits(count - 3, 2);
485 } else if (count <= 10) {
486 blTree.WriteSymbol(REP_3_10);
487 dh.pending.WriteBits(count - 3, 3);
488 } else {
489 blTree.WriteSymbol(REP_11_138);
490 dh.pending.WriteBits(count - 11, 7);
491 }
492 }
493 }
494 }
495
496 public DeflaterPending pending;
497 private Tree literalTree, distTree, blTree;
498
499 private short[] d_buf;
500 private byte[] l_buf;
501 private int last_lit;
502 private int extra_bits;
503
504 private static short[] staticLCodes;
505 private static byte[] staticLLength;
506 private static short[] staticDCodes;
507 private static byte[] staticDLength;
508
509 /// <summary>
510 /// Reverse the bits of a 16 bit value.
511 /// </summary>
512 public static short BitReverse(int value)
513 {
514 return (short) (bit4Reverse[value & 0xF] << 12 |
515 bit4Reverse[(value >> 4) & 0xF] << 8 |
516 bit4Reverse[(value >> 8) & 0xF] << 4 |
517 bit4Reverse[value >> 12]);
518 }
519
520
521 static DeflaterHuffman()
522 {
523 /* See RFC 1951 3.2.6 */
524 /* Literal codes */
525 staticLCodes = new short[LITERAL_NUM];
526 staticLLength = new byte[LITERAL_NUM];
527 int i = 0;
528 while (i < 144) {
529 staticLCodes[i] = BitReverse((0x030 + i) << 8);
530 staticLLength[i++] = 8;
531 }
532 while (i < 256) {
533 staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
534 staticLLength[i++] = 9;
535 }
536 while (i < 280) {
537 staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
538 staticLLength[i++] = 7;
539 }
540 while (i < LITERAL_NUM) {
541 staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
542 staticLLength[i++] = 8;
543 }
544
545 /* Distant codes */
546 staticDCodes = new short[DIST_NUM];
547 staticDLength = new byte[DIST_NUM];
548 for (i = 0; i < DIST_NUM; i++) {
549 staticDCodes[i] = BitReverse(i << 11);
550 staticDLength[i] = 5;
551 }
552 }
553
554 public DeflaterHuffman(DeflaterPending pending)
555 {
556 this.pending = pending;
557
558 literalTree = new Tree(this, LITERAL_NUM, 257, 15);
559 distTree = new Tree(this, DIST_NUM, 1, 15);
560 blTree = new Tree(this, BITLEN_NUM, 4, 7);
561
562 d_buf = new short[BUFSIZE];
563 l_buf = new byte [BUFSIZE];
564 }
565
566 public void Reset()
567 {
568 last_lit = 0;
569 extra_bits = 0;
570 literalTree.Reset();
571 distTree.Reset();
572 blTree.Reset();
573 }
574
575 int Lcode(int len)
576 {
577 if (len == 255) {
578 return 285;
579 }
580
581 int code = 257;
582 while (len >= 8) {
583 code += 4;
584 len >>= 1;
585 }
586 return code + len;
587 }
588
589 int Dcode(int distance)
590 {
591 int code = 0;
592 while (distance >= 4) {
593 code += 2;
594 distance >>= 1;
595 }
596 return code + distance;
597 }
598
599 public void SendAllTrees(int blTreeCodes)
600 {
601 blTree.BuildCodes();
602 literalTree.BuildCodes();
603 distTree.BuildCodes();
604 pending.WriteBits(literalTree.numCodes - 257, 5);
605 pending.WriteBits(distTree.numCodes - 1, 5);
606 pending.WriteBits(blTreeCodes - 4, 4);
607 for (int rank = 0; rank < blTreeCodes; rank++) {
608 pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
609 }
610 literalTree.WriteTree(blTree);
611 distTree.WriteTree(blTree);
612 // if (DeflaterConstants.DEBUGGING) {
613 // blTree.CheckEmpty();
614 // }
615 }
616
617 public void CompressBlock()
618 {
619 for (int i = 0; i < last_lit; i++) {
620 int litlen = l_buf[i] & 0xff;
621 int dist = d_buf[i];
622 if (dist-- != 0) {
623 // if (DeflaterConstants.DEBUGGING) {
624 // Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
625 // }
626
627 int lc = Lcode(litlen);
628 literalTree.WriteSymbol(lc);
629
630 int bits = (lc - 261) / 4;
631 if (bits > 0 && bits <= 5) {
632 pending.WriteBits(litlen & ((1 << bits) - 1), bits);
633 }
634
635 int dc = Dcode(dist);
636 distTree.WriteSymbol(dc);
637
638 bits = dc / 2 - 1;
639 if (bits > 0) {
640 pending.WriteBits(dist & ((1 << bits) - 1), bits);
641 }
642 } else {
643 // if (DeflaterConstants.DEBUGGING) {
644 // if (litlen > 32 && litlen < 127) {
645 // Console.Write("("+(char)litlen+"): ");
646 // } else {
647 // Console.Write("{"+litlen+"}: ");
648 // }
649 // }
650 literalTree.WriteSymbol(litlen);
651 }
652 }
653 // if (DeflaterConstants.DEBUGGING) {
654 // Console.Write("EOF: ");
655 // }
656 literalTree.WriteSymbol(EOF_SYMBOL);
657 // if (DeflaterConstants.DEBUGGING) {
658 // literalTree.CheckEmpty();
659 // distTree.CheckEmpty();
660 // }
661 }
662
663 public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
664 {
665 // if (DeflaterConstants.DEBUGGING) {
666 // //Console.WriteLine("Flushing stored block "+ storedLength);
667 // }
668 pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
669 pending.AlignToByte();
670 pending.WriteShort(storedLength);
671 pending.WriteShort(~storedLength);
672 pending.WriteBlock(stored, storedOffset, storedLength);
673 Reset();
674 }
675
676 public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
677 {
678 literalTree.freqs[EOF_SYMBOL]++;
679
680 /* Build trees */
681 literalTree.BuildTree();
682 distTree.BuildTree();
683
684 /* Calculate bitlen frequency */
685 literalTree.CalcBLFreq(blTree);
686 distTree.CalcBLFreq(blTree);
687
688 /* Build bitlen tree */
689 blTree.BuildTree();
690
691 int blTreeCodes = 4;
692 for (int i = 18; i > blTreeCodes; i--) {
693 if (blTree.length[BL_ORDER[i]] > 0) {
694 blTreeCodes = i+1;
695 }
696 }
697 int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
698 literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
699 extra_bits;
700
701 int static_len = extra_bits;
702 for (int i = 0; i < LITERAL_NUM; i++) {
703 static_len += literalTree.freqs[i] * staticLLength[i];
704 }
705 for (int i = 0; i < DIST_NUM; i++) {
706 static_len += distTree.freqs[i] * staticDLength[i];
707 }
708 if (opt_len >= static_len) {
709 /* Force static trees */
710 opt_len = static_len;
711 }
712
713 if (storedOffset >= 0 && storedLength+4 < opt_len >> 3) {
714 /* Store Block */
715 // if (DeflaterConstants.DEBUGGING) {
716 // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
717 // + " <= " + static_len);
718 // }
719 FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
720 } else if (opt_len == static_len) {
721 /* Encode with static tree */
722 pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
723 literalTree.SetStaticCodes(staticLCodes, staticLLength);
724 distTree.SetStaticCodes(staticDCodes, staticDLength);
725 CompressBlock();
726 Reset();
727 } else {
728 /* Encode with dynamic tree */
729 pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
730 SendAllTrees(blTreeCodes);
731 CompressBlock();
732 Reset();
733 }
734 }
735
736 public bool IsFull()
737 {
738 // return last_lit + 16 >= BUFSIZE; // HACK: This was == 'last_lit == BUFSIZE', but errors occured with DeflateFast
739 return last_lit >= BUFSIZE; // -jr- This is the correct form!
740 }
741
742 public bool TallyLit(int lit)
743 {
744 // if (DeflaterConstants.DEBUGGING) {
745 // if (lit > 32 && lit < 127) {
746 // //Console.WriteLine("("+(char)lit+")");
747 // } else {
748 // //Console.WriteLine("{"+lit+"}");
749 // }
750 // }
751 d_buf[last_lit] = 0;
752 l_buf[last_lit++] = (byte)lit;
753 literalTree.freqs[lit]++;
754 return IsFull();
755 }
756
757 public bool TallyDist(int dist, int len)
758 {
759 // if (DeflaterConstants.DEBUGGING) {
760 // //Console.WriteLine("["+dist+","+len+"]");
761 // }
762
763 d_buf[last_lit] = (short)dist;
764 l_buf[last_lit++] = (byte)(len - 3);
765
766 int lc = Lcode(len - 3);
767 literalTree.freqs[lc]++;
768 if (lc >= 265 && lc < 285) {
769 extra_bits += (lc - 261) / 4;
770 }
771
772 int dc = Dcode(dist - 1);
773 distTree.freqs[dc]++;
774 if (dc >= 4) {
775 extra_bits += dc / 2 - 1;
776 }
777 return IsFull();
778 }
779 }
780 }