package net.mcforkage.ant.diff2; import java.io.IOException; import java.io.PrintWriter; import net.mcforkage.ant.compression.BitInputStream; import net.mcforkage.ant.compression.HuffmanNode; import net.mcforkage.ant.compression.HuffmanTable; public class UncompressDiff2 { public static void uncompress(BitInputStream in, PrintWriter out) throws IOException { final int LITERAL_INDEX = -1; final int EOF_INDEX = -2; HuffmanTable<Character> charTable = HuffmanTable.readTable(in, Character.class); HuffmanTable<String> literalTable = new HuffmanTable<>(readStringHuffmanTable(in, charTable)); HuffmanTable<Integer> indexTable = readDiffedHuffmanTable(in, 1); HuffmanTable<Integer> lengthTable = HuffmanTable.readTable(in, Integer.class); while(true) { int index = indexTable.read(in); if(index == EOF_INDEX) break; if(index == LITERAL_INDEX) { String s = literalTable.read(in); out.print("write "); out.println(s); } else { int length = lengthTable.read(in); out.print("copy "); out.print(index); out.print(" ");; out.println(length); } } } private static HuffmanNode<String> readStringHuffmanTable(BitInputStream in, HuffmanTable<Character> charTable) throws IOException { if(in.readBit()) return new HuffmanNode.Node<String>(readStringHuffmanTable(in, charTable), readStringHuffmanTable(in, charTable)); StringBuilder val = new StringBuilder(); while(true) { char ch = charTable.read(in); if(ch == '\uFFFE') break; val.append(ch); } return new HuffmanNode.Leaf<String>(val.toString(), 0); } private static HuffmanNode<Integer> readDiffedHuffmanNode(BitInputStream in, HuffmanTable<Integer> diffTable, int[] lastValue) throws IOException { if(in.readBit()) return new HuffmanNode.Node<Integer>(readDiffedHuffmanNode(in, diffTable, lastValue), readDiffedHuffmanNode(in, diffTable, lastValue)); lastValue[0] += diffTable.read(in); return new HuffmanNode.Leaf<Integer>(lastValue[0], 0); } private static HuffmanTable<Integer> readDiffedHuffmanTable(final BitInputStream in, int levels) throws IOException { if(levels == 0) return HuffmanTable.readTable(in, Integer.class); HuffmanTable<Integer> diffTable = readDiffedHuffmanTable(in, levels - 1); return new HuffmanTable<>(readDiffedHuffmanNode(in, diffTable, new int[] {-2})); } }