1
2
3
4
5
6
7 package org.htmlunit.util.brotli;
8
9
10
11
12 final class Huffman {
13
14 private static final int MAX_LENGTH = 15;
15
16
17
18
19
20
21 private static int getNextKey(int key, int len) {
22 int step = 1 << (len - 1);
23 while ((key & step) != 0) {
24 step = step >> 1;
25 }
26 return (key & (step - 1)) + step;
27 }
28
29
30
31
32
33
34 private static void replicateValue(int[] table, int offset, int step, int end, int item) {
35 int pos = end;
36 while (pos > 0) {
37 pos -= step;
38 table[offset + pos] = item;
39 }
40 }
41
42
43
44
45
46
47 private static int nextTableBitSize(int[] count, int len, int rootBits) {
48 int bits = len;
49 int left = 1 << (bits - rootBits);
50 while (bits < MAX_LENGTH) {
51 left -= count[bits];
52 if (left <= 0) {
53 break;
54 }
55 bits++;
56 left = left << 1;
57 }
58 return bits - rootBits;
59 }
60
61
62
63
64
65
66 static int buildHuffmanTable(int[] tableGroup, int tableIdx, int rootBits, int[] codeLengths,
67 int codeLengthsSize) {
68 final int tableOffset = tableGroup[tableIdx];
69 final int[] sorted = new int[codeLengthsSize];
70
71 final int[] count = new int[MAX_LENGTH + 1];
72 final int[] offset = new int[MAX_LENGTH + 1];
73
74
75 for (int sym = 0; sym < codeLengthsSize; ++sym) {
76 count[codeLengths[sym]]++;
77 }
78
79
80 offset[1] = 0;
81 for (int len = 1; len < MAX_LENGTH; ++len) {
82 offset[len + 1] = offset[len] + count[len];
83 }
84
85
86 for (int sym = 0; sym < codeLengthsSize; ++sym) {
87 if (codeLengths[sym] != 0) {
88 sorted[offset[codeLengths[sym]]++] = sym;
89 }
90 }
91
92 int tableBits = rootBits;
93 int tableSize = 1 << tableBits;
94 int totalSize = tableSize;
95
96
97 if (offset[MAX_LENGTH] == 1) {
98 for (int k = 0; k < totalSize; ++k) {
99 tableGroup[tableOffset + k] = sorted[0];
100 }
101 return totalSize;
102 }
103
104
105 int key = 0;
106 int symbol = 0;
107 int step = 1;
108 for (int len = 1; len <= rootBits; ++len) {
109 step = step << 1;
110 while (count[len] > 0) {
111 replicateValue(tableGroup, tableOffset + key, step, tableSize,
112 len << 16 | sorted[symbol++]);
113 key = getNextKey(key, len);
114 count[len]--;
115 }
116 }
117
118
119 final int mask = totalSize - 1;
120 int low = -1;
121 int currentOffset = tableOffset;
122 step = 1;
123 for (int len = rootBits + 1; len <= MAX_LENGTH; ++len) {
124 step = step << 1;
125 while (count[len] > 0) {
126 if ((key & mask) != low) {
127 currentOffset += tableSize;
128 tableBits = nextTableBitSize(count, len, rootBits);
129 tableSize = 1 << tableBits;
130 totalSize += tableSize;
131 low = key & mask;
132 tableGroup[tableOffset + low] =
133 (tableBits + rootBits) << 16 | (currentOffset - tableOffset - low);
134 }
135 replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize,
136 (len - rootBits) << 16 | sorted[symbol++]);
137 key = getNextKey(key, len);
138 count[len]--;
139 }
140 }
141 return totalSize;
142 }
143 }