1
2
3
4
5
6
7 package org.htmlunit.util.brotli;
8
9 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR;
10 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_CORRUPTED_PADDING_BITS;
11 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_READ_AFTER_END;
12 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_TRUNCATED_INPUT;
13 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_UNUSED_BYTES_AFTER_END;
14 import static org.htmlunit.util.brotli.BrotliError.BROTLI_OK;
15 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_UNALIGNED_COPY_BYTES;
16
17
18
19
20 final class BitReader {
21
22
23
24 private static final int LOG_BITNESS = Utils.getLogBintness();
25
26
27
28 private static final int BIT_READER_DEBUG = Utils.isDebugMode();
29
30 static final int BITNESS = 1 << LOG_BITNESS;
31
32 private static final int BYTENESS = BITNESS / 8;
33 private static final int CAPACITY = 4096;
34
35 private static final int SLACK = 64;
36 private static final int BUFFER_SIZE = CAPACITY + SLACK;
37
38 private static final int SAFEGUARD = 36;
39 private static final int WATERLINE = CAPACITY - SAFEGUARD;
40
41
42
43 private static final int HALF_BITNESS = BITNESS / 2;
44 private static final int HALF_SIZE = BYTENESS / 2;
45 private static final int HALVES_CAPACITY = CAPACITY / HALF_SIZE;
46 private static final int HALF_BUFFER_SIZE = BUFFER_SIZE / HALF_SIZE;
47
48 private static final int LOG_HALF_SIZE = LOG_BITNESS - 4;
49
50 static final int HALF_WATERLINE = WATERLINE / HALF_SIZE;
51
52
53
54
55
56
57
58
59
60 static int readMoreInput(State s) {
61 if (s.endOfStreamReached != 0) {
62 if (halfAvailable(s) >= -2) {
63 return BROTLI_OK;
64 }
65 return Utils.makeError(s, BROTLI_ERROR_TRUNCATED_INPUT);
66 }
67 final int readOffset = s.halfOffset << LOG_HALF_SIZE;
68 int bytesInBuffer = CAPACITY - readOffset;
69
70 Utils.copyBytesWithin(s.byteBuffer, 0, readOffset, CAPACITY);
71 s.halfOffset = 0;
72 while (bytesInBuffer < CAPACITY) {
73 final int spaceLeft = CAPACITY - bytesInBuffer;
74 final int len = Utils.readInput(s, s.byteBuffer, bytesInBuffer, spaceLeft);
75
76 if (len < BROTLI_ERROR) {
77 return len;
78 }
79 if (len <= 0) {
80 s.endOfStreamReached = 1;
81 s.tailBytes = bytesInBuffer;
82 bytesInBuffer += HALF_SIZE - 1;
83 break;
84 }
85 bytesInBuffer += len;
86 }
87 bytesToNibbles(s, bytesInBuffer);
88 return BROTLI_OK;
89 }
90
91 static int checkHealth(State s, int endOfStream) {
92 if (s.endOfStreamReached == 0) {
93 return BROTLI_OK;
94 }
95 final int byteOffset = (s.halfOffset << LOG_HALF_SIZE) + ((s.bitOffset + 7) >> 3) - BYTENESS;
96 if (byteOffset > s.tailBytes) {
97 return Utils.makeError(s, BROTLI_ERROR_READ_AFTER_END);
98 }
99 if ((endOfStream != 0) && (byteOffset != s.tailBytes)) {
100 return Utils.makeError(s, BROTLI_ERROR_UNUSED_BYTES_AFTER_END);
101 }
102 return BROTLI_OK;
103 }
104
105 static void assertAccumulatorHealthy(State s) {
106 if (s.bitOffset > BITNESS) {
107 throw new IllegalStateException("Accumulator underloaded: " + s.bitOffset);
108 }
109 }
110
111 static void fillBitWindow(State s) {
112 if (BIT_READER_DEBUG != 0) {
113 assertAccumulatorHealthy(s);
114 }
115 if (s.bitOffset >= HALF_BITNESS) {
116
117 if (BITNESS == 64) {
118 s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS)
119 | Utils.shr64(s.accumulator64, HALF_BITNESS);
120 } else {
121 s.accumulator32 = (s.shortBuffer[s.halfOffset++] << HALF_BITNESS)
122 | Utils.shr32(s.accumulator32, HALF_BITNESS);
123 }
124 s.bitOffset -= HALF_BITNESS;
125 }
126 }
127
128 static void doFillBitWindow(State s) {
129 if (BIT_READER_DEBUG != 0) {
130 assertAccumulatorHealthy(s);
131 }
132 if (BITNESS == 64) {
133 s.accumulator64 = ((long) s.intBuffer[s.halfOffset++] << HALF_BITNESS)
134 | Utils.shr64(s.accumulator64, HALF_BITNESS);
135 } else {
136 s.accumulator32 = (s.shortBuffer[s.halfOffset++] << HALF_BITNESS)
137 | Utils.shr32(s.accumulator32, HALF_BITNESS);
138 }
139 s.bitOffset -= HALF_BITNESS;
140 }
141
142 static int peekBits(State s) {
143 if (BITNESS == 64) {
144 return (int) Utils.shr64(s.accumulator64, s.bitOffset);
145 }
146 return Utils.shr32(s.accumulator32, s.bitOffset);
147 }
148
149
150
151
152
153
154
155 static int readFewBits(State s, int n) {
156 final int v = peekBits(s) & ((1 << n) - 1);
157 s.bitOffset += n;
158 return v;
159 }
160
161 static int readBits(State s, int n) {
162 if (HALF_BITNESS >= 24) {
163 return readFewBits(s, n);
164 }
165 return (n <= 16) ? readFewBits(s, n) : readManyBits(s, n);
166 }
167
168 private static int readManyBits(State s, int n) {
169 final int low = readFewBits(s, 16);
170 doFillBitWindow(s);
171 return low | (readFewBits(s, n - 16) << 16);
172 }
173
174 static int initBitReader(State s) {
175 s.byteBuffer = new byte[BUFFER_SIZE];
176 if (BITNESS == 64) {
177 s.accumulator64 = 0;
178 s.intBuffer = new int[HALF_BUFFER_SIZE];
179 } else {
180 s.accumulator32 = 0;
181 s.shortBuffer = new short[HALF_BUFFER_SIZE];
182 }
183 s.bitOffset = BITNESS;
184 s.halfOffset = HALVES_CAPACITY;
185 s.endOfStreamReached = 0;
186 return prepare(s);
187 }
188
189 private static int prepare(State s) {
190 if (s.halfOffset > BitReader.HALF_WATERLINE) {
191 final int result = readMoreInput(s);
192 if (result != BROTLI_OK) {
193 return result;
194 }
195 }
196 int health = checkHealth(s, 0);
197 if (health != BROTLI_OK) {
198 return health;
199 }
200 doFillBitWindow(s);
201 doFillBitWindow(s);
202 return BROTLI_OK;
203 }
204
205 static int reload(State s) {
206 if (s.bitOffset == BITNESS) {
207 return prepare(s);
208 }
209 return BROTLI_OK;
210 }
211
212 static int jumpToByteBoundary(State s) {
213 final int padding = (BITNESS - s.bitOffset) & 7;
214 if (padding != 0) {
215 final int paddingBits = readFewBits(s, padding);
216 if (paddingBits != 0) {
217 return Utils.makeError(s, BROTLI_ERROR_CORRUPTED_PADDING_BITS);
218 }
219 }
220 return BROTLI_OK;
221 }
222
223 static int halfAvailable(State s) {
224 int limit = HALVES_CAPACITY;
225 if (s.endOfStreamReached != 0) {
226 limit = (s.tailBytes + (HALF_SIZE - 1)) >> LOG_HALF_SIZE;
227 }
228 return limit - s.halfOffset;
229 }
230
231 static int copyRawBytes(State s, byte[] data, int offset, int length) {
232 int pos = offset;
233 int len = length;
234 if ((s.bitOffset & 7) != 0) {
235 return Utils.makeError(s, BROTLI_PANIC_UNALIGNED_COPY_BYTES);
236 }
237
238
239 while ((s.bitOffset != BITNESS) && (len != 0)) {
240 data[pos++] = (byte) peekBits(s);
241 s.bitOffset += 8;
242 len--;
243 }
244 if (len == 0) {
245 return BROTLI_OK;
246 }
247
248
249 final int copyNibbles = Utils.min(halfAvailable(s), len >> LOG_HALF_SIZE);
250 if (copyNibbles > 0) {
251 final int readOffset = s.halfOffset << LOG_HALF_SIZE;
252 final int delta = copyNibbles << LOG_HALF_SIZE;
253 Utils.copyBytes(data, pos, s.byteBuffer, readOffset, readOffset + delta);
254 pos += delta;
255 len -= delta;
256 s.halfOffset += copyNibbles;
257 }
258 if (len == 0) {
259 return BROTLI_OK;
260 }
261
262
263 if (halfAvailable(s) > 0) {
264
265 fillBitWindow(s);
266 while (len != 0) {
267 data[pos++] = (byte) peekBits(s);
268 s.bitOffset += 8;
269 len--;
270 }
271 return checkHealth(s, 0);
272 }
273
274
275 while (len > 0) {
276 final int chunkLen = Utils.readInput(s, data, pos, len);
277
278 if (len < BROTLI_ERROR) {
279 return len;
280 }
281 if (chunkLen <= 0) {
282 return Utils.makeError(s, BROTLI_ERROR_TRUNCATED_INPUT);
283 }
284 pos += chunkLen;
285 len -= chunkLen;
286 }
287 return BROTLI_OK;
288 }
289
290
291
292
293 static void bytesToNibbles(State s, int byteLen) {
294 final byte[] byteBuffer = s.byteBuffer;
295 final int halfLen = byteLen >> LOG_HALF_SIZE;
296 if (BITNESS == 64) {
297 final int[] intBuffer = s.intBuffer;
298 for (int i = 0; i < halfLen; ++i) {
299 intBuffer[i] = (byteBuffer[i * 4] & 0xFF)
300 | ((byteBuffer[(i * 4) + 1] & 0xFF) << 8)
301 | ((byteBuffer[(i * 4) + 2] & 0xFF) << 16)
302 | ((byteBuffer[(i * 4) + 3] & 0xFF) << 24);
303 }
304 } else {
305 final short[] shortBuffer = s.shortBuffer;
306 for (int i = 0; i < halfLen; ++i) {
307 shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF)
308 | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));
309 }
310 }
311 }
312 }