package net.mcforkage.ant.compression; import java.io.IOException; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; public class HuffmanTable<T> { public HuffmanNode<T> root; public Map<T, HuffmanNode<T>> valueToNode = new HashMap<>(); public HuffmanTable(HuffmanNode<T> root) { this.root = root; root.initCodes(null, false, this); } public static <T extends Comparable<? super T>> HuffmanTable<T> build(final FrequencyTable<T> freqs) { PriorityQueue<HuffmanNode<T>> pq = new PriorityQueue<HuffmanNode<T>>(freqs.counts.size(), new Comparator<HuffmanNode<T>>() { @Override public int compare(HuffmanNode<T> o1, HuffmanNode<T> o2) { int c = Integer.compare(o1.freq, o2.freq); if(c != 0) return c; return o1.getRepresentativeValue().compareTo(o2.getRepresentativeValue()); } }); for(Map.Entry<T, Integer> entry : freqs.counts.entrySet()) pq.add(new HuffmanNode.Leaf<>(entry.getKey(), entry.getValue())); while(pq.size() > 1) { pq.add(new HuffmanNode.Node<>(pq.poll(), pq.poll())); } return new HuffmanTable<T>(pq.poll()); } public void write(T value, BitOutputStream out) throws IOException { out.write(valueToNode.get(value).code); } public void writeTable(BitOutputStream out) throws IOException { root.writeTree(out); } public static <T> HuffmanTable<T> readTable(BitInputStream in, Class<T> valueType) throws IOException { return new HuffmanTable<T>(HuffmanNode.readTree(in, valueType)); } public T read(BitInputStream in) throws IOException { return root.read(in); } }