1
2
3
4
5
6
7 package org.htmlunit.util.brotli;
8
9 import java.nio.ByteBuffer;
10
11
12
13
14
15
16
17
18
19
20 public final class Dictionary {
21 static final int MIN_DICTIONARY_WORD_LENGTH = 4;
22 static final int MAX_DICTIONARY_WORD_LENGTH = 31;
23
24 private static ByteBuffer data = ByteBuffer.allocateDirect(0);
25 static final int[] offsets = new int[32];
26 static final int[] sizeBits = new int[32];
27
28 private static class DataLoader {
29 static final boolean OK;
30
31 static {
32 boolean ok = true;
33 try {
34 Class.forName(Dictionary.class.getPackage().getName() + ".DictionaryData");
35 } catch (Throwable ex) {
36 ok = false;
37 }
38 OK = ok;
39 }
40 }
41
42 private static final int DICTIONARY_DEBUG = Utils.isDebugMode();
43
44 public static void setData(ByteBuffer newData, int[] newSizeBits) {
45 if (DICTIONARY_DEBUG != 0) {
46 if ((Utils.isDirect(newData) == 0) || (Utils.isReadOnly(newData) == 0)) {
47 throw new BrotliRuntimeException("newData must be a direct read-only byte buffer");
48 }
49
50 if (newSizeBits.length > MAX_DICTIONARY_WORD_LENGTH) {
51 throw new BrotliRuntimeException(
52 "sizeBits length must be at most " + String.valueOf(MAX_DICTIONARY_WORD_LENGTH));
53 }
54 for (int i = 0; i < MIN_DICTIONARY_WORD_LENGTH; ++i) {
55 if (newSizeBits[i] != 0) {
56 throw new BrotliRuntimeException(
57 "first " + String.valueOf(MIN_DICTIONARY_WORD_LENGTH) + " must be 0");
58 }
59 }
60 }
61 final int[] dictionaryOffsets = Dictionary.offsets;
62 final int[] dictionarySizeBits = Dictionary.sizeBits;
63 for (int i = 0; i < newSizeBits.length; ++i) {
64 dictionarySizeBits[i] = newSizeBits[i];
65 }
66 int pos = 0;
67 for (int i = 0; i < newSizeBits.length; ++i) {
68 dictionaryOffsets[i] = pos;
69 final int bits = dictionarySizeBits[i];
70 if (bits != 0) {
71 pos += i << (bits & 31);
72 if (DICTIONARY_DEBUG != 0) {
73 if (bits >= 31) {
74 throw new BrotliRuntimeException("newSizeBits values must be less than 31");
75 }
76 if (pos <= 0 || pos > newData.capacity()) {
77 throw new BrotliRuntimeException("newSizeBits is inconsistent: overflow");
78 }
79 }
80 }
81 }
82 for (int i = newSizeBits.length; i < 32; ++i) {
83 dictionaryOffsets[i] = pos;
84 }
85 if (DICTIONARY_DEBUG != 0) {
86 if (pos != newData.capacity()) {
87 throw new BrotliRuntimeException("newSizeBits is inconsistent: underflow");
88 }
89 }
90 Dictionary.data = newData;
91 }
92
93 public static ByteBuffer getData() {
94 if (data.capacity() != 0) {
95 return data;
96 }
97 if (!DataLoader.OK) {
98 throw new BrotliRuntimeException("brotli dictionary is not set");
99 }
100
101 return data;
102 }
103 }