Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

158
LINES

< > BotCompany Repo | #1035665 // HuffmanTree

JavaX fragment (include) [tags: use-pretranspiled]

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: 151 / 414
Version history: 40 change(s)
Referenced in: [show references]