aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java/util/zip/DeflaterHuffman.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/util/zip/DeflaterHuffman.java')
-rw-r--r--libjava/classpath/java/util/zip/DeflaterHuffman.java776
1 files changed, 0 insertions, 776 deletions
diff --git a/libjava/classpath/java/util/zip/DeflaterHuffman.java b/libjava/classpath/java/util/zip/DeflaterHuffman.java
deleted file mode 100644
index 8da987e0..0000000
--- a/libjava/classpath/java/util/zip/DeflaterHuffman.java
+++ /dev/null
@@ -1,776 +0,0 @@
-/* DeflaterHuffman.java --
- Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java.util.zip;
-
-/**
- * This is the DeflaterHuffman class.
- *
- * This class is <i>not</i> thread safe. This is inherent in the API, due
- * to the split of deflate and setInput.
- *
- * @author Jochen Hoenicke
- * @date Jan 6, 2000
- */
-class DeflaterHuffman
-{
- private static final int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
- private static final int LITERAL_NUM = 286;
- private static final int DIST_NUM = 30;
- private static final int BITLEN_NUM = 19;
- private static final int REP_3_6 = 16;
- private static final int REP_3_10 = 17;
- private static final int REP_11_138 = 18;
- private static final int EOF_SYMBOL = 256;
- private static final int[] BL_ORDER =
- { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
-
- private static final String bit4Reverse =
- "\000\010\004\014\002\012\006\016\001\011\005\015\003\013\007\017";
-
- class Tree {
- short[] freqs;
- short[] codes;
- byte[] length;
- int[] bl_counts;
- int minNumCodes, numCodes;
- int maxLength;
-
- Tree(int elems, int minCodes, int maxLength) {
- this.minNumCodes = minCodes;
- this.maxLength = maxLength;
- freqs = new short[elems];
- bl_counts = new int[maxLength];
- }
-
- void reset() {
- for (int i = 0; i < freqs.length; i++)
- freqs[i] = 0;
- codes = null;
- length = null;
- }
-
- final void writeSymbol(int code)
- {
- if (DeflaterConstants.DEBUGGING)
- {
- freqs[code]--;
-// System.err.print("writeSymbol("+freqs.length+","+code+"): ");
- }
- pending.writeBits(codes[code] & 0xffff, length[code]);
- }
-
- final void checkEmpty()
- {
- boolean empty = true;
- for (int i = 0; i < freqs.length; i++)
- if (freqs[i] != 0)
- {
- System.err.println("freqs["+i+"] == "+freqs[i]);
- empty = false;
- }
- if (!empty)
- throw new InternalError();
- System.err.println("checkEmpty suceeded!");
- }
-
- void setStaticCodes(short[] stCodes, byte[] stLength)
- {
- codes = stCodes;
- length = stLength;
- }
-
- public void buildCodes() {
- int[] nextCode = new int[maxLength];
- int code = 0;
- codes = new short[freqs.length];
-
- if (DeflaterConstants.DEBUGGING)
- System.err.println("buildCodes: "+freqs.length);
- for (int bits = 0; bits < maxLength; bits++)
- {
- nextCode[bits] = code;
- code += bl_counts[bits] << (15 - bits);
- if (DeflaterConstants.DEBUGGING)
- System.err.println("bits: "+(bits+1)+" count: "+bl_counts[bits]
- +" nextCode: "+Integer.toHexString(code));
- }
- if (DeflaterConstants.DEBUGGING && code != 65536)
- throw new RuntimeException("Inconsistent bl_counts!");
-
- for (int i=0; i < numCodes; i++)
- {
- int bits = length[i];
- if (bits > 0)
- {
- if (DeflaterConstants.DEBUGGING)
- System.err.println("codes["+i+"] = rev("
- +Integer.toHexString(nextCode[bits-1])+"),"
- +bits);
- codes[i] = bitReverse(nextCode[bits-1]);
- nextCode[bits-1] += 1 << (16 - bits);
- }
- }
- }
-
- private void buildLength(int childs[])
- {
- this.length = new byte [freqs.length];
- int numNodes = childs.length / 2;
- int numLeafs = (numNodes + 1) / 2;
- int overflow = 0;
-
- for (int i = 0; i < maxLength; i++)
- bl_counts[i] = 0;
-
- /* First calculate optimal bit lengths */
- int lengths[] = new int[numNodes];
- lengths[numNodes-1] = 0;
- for (int i = numNodes - 1; i >= 0; i--)
- {
- if (childs[2*i+1] != -1)
- {
- int bitLength = lengths[i] + 1;
- if (bitLength > maxLength)
- {
- bitLength = maxLength;
- overflow++;
- }
- lengths[childs[2*i]] = lengths[childs[2*i+1]] = bitLength;
- }
- else
- {
- /* A leaf node */
- int bitLength = lengths[i];
- bl_counts[bitLength - 1]++;
- this.length[childs[2*i]] = (byte) lengths[i];
- }
- }
-
- if (DeflaterConstants.DEBUGGING)
- {
- System.err.println("Tree "+freqs.length+" lengths:");
- for (int i=0; i < numLeafs; i++)
- System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
- + " len: "+length[childs[2*i]]);
- }
-
- if (overflow == 0)
- return;
-
- int incrBitLen = maxLength - 1;
- do
- {
- /* Find the first bit length which could increase: */
- while (bl_counts[--incrBitLen] == 0)
- ;
-
- /* Move this node one down and remove a corresponding
- * amount of overflow nodes.
- */
- do
- {
- bl_counts[incrBitLen]--;
- bl_counts[++incrBitLen]++;
- overflow -= 1 << (maxLength - 1 - incrBitLen);
- }
- while (overflow > 0 && incrBitLen < maxLength - 1);
- }
- while (overflow > 0);
-
- /* We may have overshot above. Move some nodes from maxLength to
- * maxLength-1 in that case.
- */
- bl_counts[maxLength-1] += overflow;
- bl_counts[maxLength-2] -= overflow;
-
- /* Now recompute all bit lengths, scanning in increasing
- * frequency. It is simpler to reconstruct all lengths instead of
- * fixing only the wrong ones. This idea is taken from 'ar'
- * written by Haruhiko Okumura.
- *
- * The nodes were inserted with decreasing frequency into the childs
- * array.
- */
- int nodePtr = 2 * numLeafs;
- for (int bits = maxLength; bits != 0; bits--)
- {
- int n = bl_counts[bits-1];
- while (n > 0)
- {
- int childPtr = 2*childs[nodePtr++];
- if (childs[childPtr + 1] == -1)
- {
- /* We found another leaf */
- length[childs[childPtr]] = (byte) bits;
- n--;
- }
- }
- }
- if (DeflaterConstants.DEBUGGING)
- {
- System.err.println("*** After overflow elimination. ***");
- for (int i=0; i < numLeafs; i++)
- System.err.println("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
- + " len: "+length[childs[2*i]]);
- }
- }
-
- void buildTree()
- {
- int numSymbols = freqs.length;
-
- /* heap is a priority queue, sorted by frequency, least frequent
- * nodes first. The heap is a binary tree, with the property, that
- * the parent node is smaller than both child nodes. This assures
- * that the smallest node is the first parent.
- *
- * The binary tree is encoded in an array: 0 is root node and
- * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
- */
- int[] heap = new int[numSymbols];
- int heapLen = 0;
- int maxCode = 0;
- for (int n = 0; n < numSymbols; n++)
- {
- int freq = freqs[n];
- if (freq != 0)
- {
- /* Insert n into heap */
- int pos = heapLen++;
- int ppos;
- while (pos > 0 &&
- freqs[heap[ppos = (pos - 1) / 2]] > freq) {
- heap[pos] = heap[ppos];
- pos = ppos;
- }
- heap[pos] = n;
- maxCode = n;
- }
- }
-
- /* We could encode a single literal with 0 bits but then we
- * don't see the literals. Therefore we force at least two
- * literals to avoid this case. We don't care about order in
- * this case, both literals get a 1 bit code.
- */
- while (heapLen < 2)
- {
- int node = maxCode < 2 ? ++maxCode : 0;
- heap[heapLen++] = node;
- }
-
- numCodes = Math.max(maxCode + 1, minNumCodes);
-
- int numLeafs = heapLen;
- int[] childs = new int[4*heapLen - 2];
- int[] values = new int[2*heapLen - 1];
- int numNodes = numLeafs;
- for (int i = 0; i < heapLen; i++)
- {
- int node = heap[i];
- childs[2*i] = node;
- childs[2*i+1] = -1;
- values[i] = freqs[node] << 8;
- heap[i] = i;
- }
-
- /* Construct the Huffman tree by repeatedly combining the least two
- * frequent nodes.
- */
- do
- {
- int first = heap[0];
- int last = heap[--heapLen];
-
- /* Propagate the hole to the leafs of the heap */
- int ppos = 0;
- int path = 1;
- while (path < heapLen)
- {
- if (path + 1 < heapLen
- && values[heap[path]] > values[heap[path+1]])
- path++;
-
- heap[ppos] = heap[path];
- ppos = path;
- path = path * 2 + 1;
- }
-
- /* Now propagate the last element down along path. Normally
- * it shouldn't go too deep.
- */
- int lastVal = values[last];
- while ((path = ppos) > 0
- && values[heap[ppos = (path - 1)/2]] > lastVal)
- heap[path] = heap[ppos];
- heap[path] = last;
-
-
- int second = heap[0];
-
- /* Create a new node father of first and second */
- last = numNodes++;
- childs[2*last] = first;
- childs[2*last+1] = second;
- int mindepth = Math.min(values[first] & 0xff, values[second] & 0xff);
- values[last] = lastVal = values[first] + values[second] - mindepth + 1;
-
- /* Again, propagate the hole to the leafs */
- ppos = 0;
- path = 1;
- while (path < heapLen)
- {
- if (path + 1 < heapLen
- && values[heap[path]] > values[heap[path+1]])
- path++;
-
- heap[ppos] = heap[path];
- ppos = path;
- path = ppos * 2 + 1;
- }
-
- /* Now propagate the new element down along path */
- while ((path = ppos) > 0
- && values[heap[ppos = (path - 1)/2]] > lastVal)
- heap[path] = heap[ppos];
- heap[path] = last;
- }
- while (heapLen > 1);
-
- if (heap[0] != childs.length / 2 - 1)
- throw new RuntimeException("Weird!");
-
- buildLength(childs);
- }
-
- int getEncodedLength()
- {
- int len = 0;
- for (int i = 0; i < freqs.length; i++)
- len += freqs[i] * length[i];
- return len;
- }
-
- void calcBLFreq(Tree blTree) {
- int max_count; /* max repeat count */
- int min_count; /* min repeat count */
- int count; /* repeat count of the current code */
- int curlen = -1; /* length of current code */
-
- int i = 0;
- while (i < numCodes)
- {
- count = 1;
- int nextlen = length[i];
- if (nextlen == 0)
- {
- max_count = 138;
- min_count = 3;
- }
- else
- {
- max_count = 6;
- min_count = 3;
- if (curlen != nextlen)
- {
- blTree.freqs[nextlen]++;
- count = 0;
- }
- }
- curlen = nextlen;
- i++;
-
- while (i < numCodes && curlen == length[i])
- {
- i++;
- if (++count >= max_count)
- break;
- }
-
- if (count < min_count)
- blTree.freqs[curlen] += count;
- else if (curlen != 0)
- blTree.freqs[REP_3_6]++;
- else if (count <= 10)
- blTree.freqs[REP_3_10]++;
- else
- blTree.freqs[REP_11_138]++;
- }
- }
-
- void writeTree(Tree blTree)
- {
- int max_count; /* max repeat count */
- int min_count; /* min repeat count */
- int count; /* repeat count of the current code */
- int curlen = -1; /* length of current code */
-
- int i = 0;
- while (i < numCodes)
- {
- count = 1;
- int nextlen = length[i];
- if (nextlen == 0)
- {
- max_count = 138;
- min_count = 3;
- }
- else
- {
- max_count = 6;
- min_count = 3;
- if (curlen != nextlen)
- {
- blTree.writeSymbol(nextlen);
- count = 0;
- }
- }
- curlen = nextlen;
- i++;
-
- while (i < numCodes && curlen == length[i])
- {
- i++;
- if (++count >= max_count)
- break;
- }
-
- if (count < min_count)
- {
- while (count-- > 0)
- blTree.writeSymbol(curlen);
- }
- else if (curlen != 0)
- {
- blTree.writeSymbol(REP_3_6);
- pending.writeBits(count - 3, 2);
- }
- else if (count <= 10)
- {
- blTree.writeSymbol(REP_3_10);
- pending.writeBits(count - 3, 3);
- }
- else
- {
- blTree.writeSymbol(REP_11_138);
- pending.writeBits(count - 11, 7);
- }
- }
- }
- }
-
-
-
- DeflaterPending pending;
- private Tree literalTree, distTree, blTree;
-
- private short d_buf[];
- private byte l_buf[];
- private int last_lit;
- private int extra_bits;
-
- private static short staticLCodes[];
- private static byte staticLLength[];
- private static short staticDCodes[];
- private static byte staticDLength[];
-
- /**
- * Reverse the bits of a 16 bit value.
- */
- static short bitReverse(int value) {
- return (short) (bit4Reverse.charAt(value & 0xf) << 12
- | bit4Reverse.charAt((value >> 4) & 0xf) << 8
- | bit4Reverse.charAt((value >> 8) & 0xf) << 4
- | bit4Reverse.charAt(value >> 12));
- }
-
- static {
- /* See RFC 1951 3.2.6 */
- /* Literal codes */
- staticLCodes = new short[LITERAL_NUM];
- staticLLength = new byte[LITERAL_NUM];
- int i = 0;
- while (i < 144) {
- staticLCodes[i] = bitReverse((0x030 + i) << 8);
- staticLLength[i++] = 8;
- }
- while (i < 256) {
- staticLCodes[i] = bitReverse((0x190 - 144 + i) << 7);
- staticLLength[i++] = 9;
- }
- while (i < 280) {
- staticLCodes[i] = bitReverse((0x000 - 256 + i) << 9);
- staticLLength[i++] = 7;
- }
- while (i < LITERAL_NUM) {
- staticLCodes[i] = bitReverse((0x0c0 - 280 + i) << 8);
- staticLLength[i++] = 8;
- }
-
- /* Distant codes */
- staticDCodes = new short[DIST_NUM];
- staticDLength = new byte[DIST_NUM];
- for (i = 0; i < DIST_NUM; i++) {
- staticDCodes[i] = bitReverse(i << 11);
- staticDLength[i] = 5;
- }
- }
-
- public DeflaterHuffman(DeflaterPending pending)
- {
- this.pending = pending;
-
- literalTree = new Tree(LITERAL_NUM, 257, 15);
- distTree = new Tree(DIST_NUM, 1, 15);
- blTree = new Tree(BITLEN_NUM, 4, 7);
-
- d_buf = new short[BUFSIZE];
- l_buf = new byte [BUFSIZE];
- }
-
- public final void reset() {
- last_lit = 0;
- extra_bits = 0;
- literalTree.reset();
- distTree.reset();
- blTree.reset();
- }
-
- private int l_code(int len) {
- if (len == 255)
- return 285;
-
- int code = 257;
- while (len >= 8)
- {
- code += 4;
- len >>= 1;
- }
- return code + len;
- }
-
- private int d_code(int distance) {
- int code = 0;
- while (distance >= 4)
- {
- code += 2;
- distance >>= 1;
- }
- return code + distance;
- }
-
- public void sendAllTrees(int blTreeCodes) {
- blTree.buildCodes();
- literalTree.buildCodes();
- distTree.buildCodes();
- pending.writeBits(literalTree.numCodes - 257, 5);
- pending.writeBits(distTree.numCodes - 1, 5);
- pending.writeBits(blTreeCodes - 4, 4);
- for (int rank = 0; rank < blTreeCodes; rank++)
- pending.writeBits(blTree.length[BL_ORDER[rank]], 3);
- literalTree.writeTree(blTree);
- distTree.writeTree(blTree);
- if (DeflaterConstants.DEBUGGING)
- blTree.checkEmpty();
- }
-
- public void compressBlock() {
- for (int i = 0; i < last_lit; i++)
- {
- int litlen = l_buf[i] & 0xff;
- int dist = d_buf[i];
- if (dist-- != 0)
- {
- if (DeflaterConstants.DEBUGGING)
- System.err.print("["+(dist+1)+","+(litlen+3)+"]: ");
-
- int lc = l_code(litlen);
- literalTree.writeSymbol(lc);
-
- int bits = (lc - 261) / 4;
- if (bits > 0 && bits <= 5)
- pending.writeBits(litlen & ((1 << bits) - 1), bits);
-
- int dc = d_code(dist);
- distTree.writeSymbol(dc);
-
- bits = dc / 2 - 1;
- if (bits > 0)
- pending.writeBits(dist & ((1 << bits) - 1), bits);
- }
- else
- {
- if (DeflaterConstants.DEBUGGING)
- {
- if (litlen > 32 && litlen < 127)
- System.err.print("("+(char)litlen+"): ");
- else
- System.err.print("{"+litlen+"}: ");
- }
- literalTree.writeSymbol(litlen);
- }
- }
- if (DeflaterConstants.DEBUGGING)
- System.err.print("EOF: ");
- literalTree.writeSymbol(EOF_SYMBOL);
- if (DeflaterConstants.DEBUGGING)
- {
- literalTree.checkEmpty();
- distTree.checkEmpty();
- }
- }
-
- public void flushStoredBlock(byte[] stored,
- int stored_offset, int stored_len,
- boolean lastBlock) {
- if (DeflaterConstants.DEBUGGING)
- System.err.println("Flushing stored block "+ stored_len);
- pending.writeBits((DeflaterConstants.STORED_BLOCK << 1)
- + (lastBlock ? 1 : 0), 3);
- pending.alignToByte();
- pending.writeShort(stored_len);
- pending.writeShort(~stored_len);
- pending.writeBlock(stored, stored_offset, stored_len);
- reset();
- }
-
- public void flushBlock(byte[] stored, int stored_offset, int stored_len,
- boolean lastBlock) {
- literalTree.freqs[EOF_SYMBOL]++;
-
- /* Build trees */
- literalTree.buildTree();
- distTree.buildTree();
-
- /* Calculate bitlen frequency */
- literalTree.calcBLFreq(blTree);
- distTree.calcBLFreq(blTree);
-
- /* Build bitlen tree */
- blTree.buildTree();
-
- int blTreeCodes = 4;
- for (int i = 18; i > blTreeCodes; i--)
- {
- if (blTree.length[BL_ORDER[i]] > 0)
- blTreeCodes = i+1;
- }
- int opt_len = 14 + blTreeCodes * 3 + blTree.getEncodedLength()
- + literalTree.getEncodedLength() + distTree.getEncodedLength()
- + extra_bits;
-
- int static_len = extra_bits;
- for (int i = 0; i < LITERAL_NUM; i++)
- static_len += literalTree.freqs[i] * staticLLength[i];
- for (int i = 0; i < DIST_NUM; i++)
- static_len += distTree.freqs[i] * staticDLength[i];
- if (opt_len >= static_len)
- {
- /* Force static trees */
- opt_len = static_len;
- }
-
- if (stored_offset >= 0 && stored_len+4 < opt_len >> 3)
- {
- /* Store Block */
- if (DeflaterConstants.DEBUGGING)
- System.err.println("Storing, since " + stored_len + " < " + opt_len
- + " <= " + static_len);
- flushStoredBlock(stored, stored_offset, stored_len, lastBlock);
- }
- else if (opt_len == static_len)
- {
- /* Encode with static tree */
- pending.writeBits((DeflaterConstants.STATIC_TREES << 1)
- + (lastBlock ? 1 : 0), 3);
- literalTree.setStaticCodes(staticLCodes, staticLLength);
- distTree.setStaticCodes(staticDCodes, staticDLength);
- compressBlock();
- reset();
- }
- else
- {
- /* Encode with dynamic tree */
- pending.writeBits((DeflaterConstants.DYN_TREES << 1)
- + (lastBlock ? 1 : 0), 3);
- sendAllTrees(blTreeCodes);
- compressBlock();
- reset();
- }
- }
-
- public final boolean isFull()
- {
- return last_lit == BUFSIZE;
- }
-
- public final boolean tallyLit(int lit)
- {
- if (DeflaterConstants.DEBUGGING)
- {
- if (lit > 32 && lit < 127)
- System.err.println("("+(char)lit+")");
- else
- System.err.println("{"+lit+"}");
- }
- d_buf[last_lit] = 0;
- l_buf[last_lit++] = (byte) lit;
- literalTree.freqs[lit]++;
- return last_lit == BUFSIZE;
- }
-
- public final boolean tallyDist(int dist, int len)
- {
- if (DeflaterConstants.DEBUGGING)
- System.err.println("["+dist+","+len+"]");
-
- d_buf[last_lit] = (short) dist;
- l_buf[last_lit++] = (byte) (len - 3);
-
- int lc = l_code(len-3);
- literalTree.freqs[lc]++;
- if (lc >= 265 && lc < 285)
- extra_bits += (lc - 261) / 4;
-
- int dc = d_code(dist-1);
- distTree.freqs[dc]++;
- if (dc >= 4)
- extra_bits += dc / 2 - 1;
- return last_lit == BUFSIZE;
- }
-}