Libraryless. Click here for Pure Java version (13725L/78K).
1 | sclass HuffmanTree is BitIO {
|
2 | settable Node root; |
3 | Leaf[] characterMap = new[256]; |
4 | |
5 | settable bool debug; |
6 | replace print with if (debug) print. |
7 | |
8 | /* |
9 | algebraic type Node {
|
10 | constructor Branch(Node zero, Node one) {}
|
11 | constructor Leaf(byte literal) {}
|
12 | } |
13 | */ |
14 | |
15 | abstract class Node is BitIO {
|
16 | settable Branch parent; |
17 | |
18 | void buildSymbol(BitBuffer head, Node child) {
|
19 | parent?.buildSymbol(head, this); |
20 | } |
21 | |
22 | abstract Leaf readSymbol(BitHead head); |
23 | } |
24 | |
25 | class Branch > Node {
|
26 | gettable Node zero; |
27 | gettable Node one; |
28 | |
29 | meta-for zero also as one {
|
30 | selfType zero(Node zero) {
|
31 | this.zero = zero; |
32 | zero.parent = this; |
33 | this; |
34 | } |
35 | } |
36 | |
37 | public void readWrite(BitHead head) {
|
38 | head.exchangeBit(1); |
39 | head.exchange(zero, -> zero(readNode(head))); |
40 | head.exchange(one, -> one(readNode(head))); |
41 | } |
42 | |
43 | void buildSymbol(BitBuffer head, Node child) {
|
44 | head.add(child == one); |
45 | super.buildSymbol(head, child); |
46 | } |
47 | |
48 | Leaf readSymbol(BitHead head) {
|
49 | bool bit = head.readBit(); |
50 | print("Read bit " + bit);
|
51 | ret (bit ? one : zero).readSymbol(head); |
52 | } |
53 | } |
54 | |
55 | class Leaf > Node {
|
56 | gettable byte literal; |
57 | |
58 | *() {}
|
59 | *(int literal) { literal((byte) literal); }
|
60 | |
61 | byte get() { ret literal; }
|
62 | |
63 | selfType literal(byte b) {
|
64 | literal = b; |
65 | fillCharacterMap(); |
66 | this; |
67 | } |
68 | |
69 | public void readWrite(BitHead head) {
|
70 | head.exchangeBit(0); |
71 | head.exchangeByte(literal, l1 literal); |
72 | print(this); |
73 | } |
74 | |
75 | void fillCharacterMap {
|
76 | characterMap[ubyteToInt(literal)] = this; |
77 | } |
78 | |
79 | Leaf readSymbol(BitHead head) {
|
80 | print("Reached symbol " + this);
|
81 | this; |
82 | } |
83 | |
84 | toString {
|
85 | ret "Literal " + byteToHex(literal); |
86 | } |
87 | } |
88 | |
89 | void makeRootIfEmpty {
|
90 | root ifNull = new Leaf(0); |
91 | } |
92 | |
93 | Node readNode(BitHead head) {
|
94 | bool type = head.peekBit(); |
95 | Node node = type ? new Branch : new Leaf; |
96 | print(type ? "Branch" : "Leaf"); |
97 | node.readWrite(head); |
98 | ret node; |
99 | } |
100 | |
101 | public void readWrite(BitHead head) {
|
102 | if (head.writeMode()) {
|
103 | makeRootIfEmpty(); |
104 | root.readWrite(head); |
105 | } |
106 | |
107 | if (head.readMode()) |
108 | root = readNode(head); |
109 | } |
110 | |
111 | toString {
|
112 | makeRootIfEmpty(); |
113 | new LS out; |
114 | new StringBuilder symbol; |
115 | |
116 | embedded void toString_collect(Node node) {
|
117 | if (node cast Leaf) {
|
118 | out.add(symbol + ": " + /*ubyteToHex*/quote(codePoint(ubyteToInt(node!)))); |
119 | } else {
|
120 | cast node to Branch; |
121 | symbol.append("0");
|
122 | toString_collect(node.zero()); |
123 | removeLast(symbol); |
124 | symbol.append("1");
|
125 | toString_collect(node.one()); |
126 | removeLast(symbol); |
127 | } |
128 | } |
129 | |
130 | toString_collect(root); |
131 | ret lines(out); |
132 | } |
133 | |
134 | void writeCharacter aka writeSymbol(int sym, BitHead head) {
|
135 | sym &= 0xFF; |
136 | Leaf node = characterMap[sym]; |
137 | if (node == null) |
138 | fail("Symbol cannot be encoded: " + sym);
|
139 | new BitBuffer buffer; |
140 | node.buildSymbol(buffer, null); |
141 | |
142 | // when there is only one symbol |
143 | if (buffer.isEmpty()) |
144 | buffer.add(0); |
145 | |
146 | for (int i = l(buffer)-1; i >= 0; i--) |
147 | head.writeBit(buffer.get(i)); |
148 | } |
149 | |
150 | int readSymbol(BitHead head) {
|
151 | if (head.isEOF()) ret -1; |
152 | |
153 | if (root instanceof Leaf) |
154 | head.advanceBit(); // don't even care |
155 | |
156 | ret ubyteToInt(root.readSymbol(head)!); |
157 | } |
158 | } |
download show line numbers debug dex old transpilations
Travelled to 2 computer(s): elmgxqgtpvxh, mqqgnosmbjvj
No comments. add comment
| Snippet ID: | #1035665 |
| Snippet name: | HuffmanTree |
| Eternal ID of this version: | #1035665/41 |
| Text MD5: | 7958e64a838760d732647aa3e60ed5b3 |
| Transpilation MD5: | a32895591c00765eddc0fc320d79e588 |
| Author: | stefan |
| Category: | javax / compression |
| Type: | JavaX fragment (include) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2022-07-15 20:57:14 |
| Source code size: | 3647 bytes / 158 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 646 / 975 |
| Version history: | 40 change(s) |
| Referenced in: | [show references] |