PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/SourceBackup/zip/Zip/Compression/DeflaterHuffman.cs

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