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 System.arraycopy(newSizeBits, 0, dictionarySizeBits, 0, newSizeBits.length);
64 int pos = 0;
65 for (int i = 0; i < newSizeBits.length; ++i) {
66 dictionaryOffsets[i] = pos;
67 final int bits = dictionarySizeBits[i];
68 if (bits != 0) {
69 pos += i << (bits & 31);
70 if (DICTIONARY_DEBUG != 0) {
71 if (bits >= 31) {
72 throw new BrotliRuntimeException("newSizeBits values must be less than 31");
73 }
74 if (pos <= 0 || pos > newData.capacity()) {
75 throw new BrotliRuntimeException("newSizeBits is inconsistent: overflow");
76 }
77 }
78 }
79 }
80 for (int i = newSizeBits.length; i < 32; ++i) {
81 dictionaryOffsets[i] = pos;
82 }
83 if (DICTIONARY_DEBUG != 0) {
84 if (pos != newData.capacity()) {
85 throw new BrotliRuntimeException("newSizeBits is inconsistent: underflow");
86 }
87 }
88 Dictionary.data = newData;
89 }
90
91 public static ByteBuffer getData() {
92 if (data.capacity() != 0) {
93 return data;
94 }
95 if (!DataLoader.OK) {
96 throw new BrotliRuntimeException("brotli dictionary is not set");
97 }
98
99 return data;
100 }
101 }