1
2
3
4
5
6
7 package org.htmlunit.util.brotli;
8
9 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_CORRUPTED_CODE_LENGTH_TABLE;
10 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_CORRUPTED_CONTEXT_MAP;
11 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_CORRUPTED_HUFFMAN_CODE_HISTOGRAM;
12 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_CORRUPTED_RESERVED_BIT;
13 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_DUPLICATE_SIMPLE_HUFFMAN_SYMBOL;
14 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_EXUBERANT_NIBBLE;
15 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_INVALID_BACKWARD_REFERENCE;
16 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_INVALID_METABLOCK_LENGTH;
17 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_INVALID_WINDOW_BITS;
18 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_NEGATIVE_DISTANCE;
19 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_SYMBOL_OUT_OF_RANGE;
20 import static org.htmlunit.util.brotli.BrotliError.BROTLI_ERROR_UNUSED_HUFFMAN_SPACE;
21 import static org.htmlunit.util.brotli.BrotliError.BROTLI_OK;
22 import static org.htmlunit.util.brotli.BrotliError.BROTLI_OK_DONE;
23 import static org.htmlunit.util.brotli.BrotliError.BROTLI_OK_NEED_MORE_OUTPUT;
24 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_ALREADY_CLOSED;
25 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_MAX_DISTANCE_TOO_SMALL;
26 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_STATE_NOT_FRESH;
27 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_STATE_NOT_INITIALIZED;
28 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_STATE_NOT_UNINITIALIZED;
29 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_TOO_MANY_DICTIONARY_CHUNKS;
30 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_UNEXPECTED_STATE;
31 import static org.htmlunit.util.brotli.BrotliError.BROTLI_PANIC_UNREACHABLE;
32
33 import java.nio.ByteBuffer;
34
35
36
37
38 final class Decode {
39
40 static final int MIN_LARGE_WINDOW_BITS = 10;
41
42
43 static final int MAX_LARGE_WINDOW_BITS = 30;
44
45
46
47
48
49 private static final int UNINITIALIZED = 0;
50 private static final int INITIALIZED = 1;
51 private static final int BLOCK_START = 2;
52 private static final int COMPRESSED_BLOCK_START = 3;
53 private static final int MAIN_LOOP = 4;
54 private static final int READ_METADATA = 5;
55 private static final int COPY_UNCOMPRESSED = 6;
56 private static final int INSERT_LOOP = 7;
57 private static final int COPY_LOOP = 8;
58 private static final int USE_DICTIONARY = 9;
59 private static final int FINISHED = 10;
60 private static final int CLOSED = 11;
61 private static final int INIT_WRITE = 12;
62 private static final int WRITE = 13;
63 private static final int COPY_FROM_COMPOUND_DICTIONARY = 14;
64
65 private static final int DEFAULT_CODE_LENGTH = 8;
66 private static final int CODE_LENGTH_REPEAT_CODE = 16;
67 private static final int NUM_LITERAL_CODES = 256;
68 private static final int NUM_COMMAND_CODES = 704;
69 private static final int NUM_BLOCK_LENGTH_CODES = 26;
70 private static final int LITERAL_CONTEXT_BITS = 6;
71 private static final int DISTANCE_CONTEXT_BITS = 2;
72
73 private static final int CD_BLOCK_MAP_BITS = 8;
74 private static final int HUFFMAN_TABLE_BITS = 8;
75 private static final int HUFFMAN_TABLE_MASK = 0xFF;
76
77
78
79
80
81
82
83
84 static final int[] MAX_HUFFMAN_TABLE_SIZE = {
85 256, 402, 436, 468, 500, 534, 566, 598, 630, 662, 694, 726, 758, 790, 822,
86 854, 886, 920, 952, 984, 1016, 1048, 1080
87 };
88
89 private static final int HUFFMAN_TABLE_SIZE_26 = 396;
90 private static final int HUFFMAN_TABLE_SIZE_258 = 632;
91
92 private static final int CODE_LENGTH_CODES = 18;
93 private static final int[] CODE_LENGTH_CODE_ORDER = {
94 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
95 };
96
97 private static final int NUM_DISTANCE_SHORT_CODES = 16;
98 private static final int[] DISTANCE_SHORT_CODE_INDEX_OFFSET = {
99 0, 3, 2, 1, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3
100 };
101
102 private static final int[] DISTANCE_SHORT_CODE_VALUE_OFFSET = {
103 0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3
104 };
105
106
107
108
109 private static final int[] FIXED_TABLE = {
110 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040001,
111 0x020000, 0x020004, 0x020003, 0x030002, 0x020000, 0x020004, 0x020003, 0x040005
112 };
113
114
115 static final int MAX_TRANSFORMED_WORD_LENGTH = 5 + 24 + 8;
116
117 private static final int MAX_DISTANCE_BITS = 24;
118 private static final int MAX_LARGE_WINDOW_DISTANCE_BITS = 62;
119
120
121
122
123
124
125
126 private static final int MAX_ALLOWED_DISTANCE = 0x7FFFFFFC;
127
128
129
130
131 static final int[] BLOCK_LENGTH_OFFSET = {
132 1, 5, 9, 13, 17, 25, 33, 41, 49, 65, 81, 97, 113, 145, 177, 209, 241, 305, 369, 497,
133 753, 1265, 2289, 4337, 8433, 16625
134 };
135
136 static final int[] BLOCK_LENGTH_N_BITS = {
137 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 24
138 };
139
140 static final short[] INSERT_LENGTH_N_BITS = {
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03,
142 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0E, 0x18
143 };
144
145 static final short[] COPY_LENGTH_N_BITS = {
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
147 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x18
148 };
149
150
151
152
153
154
155 static final short[] CMD_LOOKUP = new short[NUM_COMMAND_CODES * 4];
156
157 static {
158 unpackCommandLookupTable(CMD_LOOKUP);
159 }
160
161 private static int log2floor(int i) {
162
163 int result = -1;
164 int step = 16;
165 int v = i;
166 while (step > 0) {
167 int next = v >> step;
168 if (next != 0) {
169 result += step;
170 v = next;
171 }
172 step = step >> 1;
173 }
174 return result + v;
175 }
176
177 private static int calculateDistanceAlphabetSize(int npostfix, int ndirect, int maxndistbits) {
178 return NUM_DISTANCE_SHORT_CODES + ndirect + 2 * (maxndistbits << npostfix);
179 }
180
181
182
183 private static int calculateDistanceAlphabetLimit(State s, int maxDistance, int npostfix, int ndirect) {
184 if (maxDistance < ndirect + (2 << npostfix)) {
185 return Utils.makeError(s, BROTLI_PANIC_MAX_DISTANCE_TOO_SMALL);
186 }
187 final int offset = ((maxDistance - ndirect) >> npostfix) + 4;
188 final int ndistbits = log2floor(offset) - 1;
189 final int group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1);
190 return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + NUM_DISTANCE_SHORT_CODES;
191 }
192
193 private static void unpackCommandLookupTable(short[] cmdLookup) {
194 final int[] insertLengthOffsets = new int[24];
195 final int[] copyLengthOffsets = new int[24];
196 copyLengthOffsets[0] = 2;
197 for (int i = 0; i < 23; ++i) {
198 insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);
199 copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);
200 }
201
202 for (int cmdCode = 0; cmdCode < NUM_COMMAND_CODES; ++cmdCode) {
203 int rangeIdx = cmdCode >> 6;
204
205 int distanceContextOffset = -4;
206 if (rangeIdx >= 2) {
207 rangeIdx -= 2;
208 distanceContextOffset = 0;
209 }
210 final int insertCode = (((0x29850 >> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >> 3) & 7);
211 final int copyCode = (((0x26244 >> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
212 final int copyLengthOffset = copyLengthOffsets[copyCode];
213 final int distanceContext = distanceContextOffset + Utils.min(copyLengthOffset, 5) - 2;
214 final int index = cmdCode * 4;
215 cmdLookup[index + 0] =
216 (short)
217 (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
218 cmdLookup[index + 1] = (short) insertLengthOffsets[insertCode];
219 cmdLookup[index + 2] = (short) copyLengthOffsets[copyCode];
220 cmdLookup[index + 3] = (short) distanceContext;
221 }
222 }
223
224
225
226
227
228
229
230 private static int decodeWindowBits(State s) {
231
232
233
234
235 final int largeWindowEnabled = s.isLargeWindow;
236 s.isLargeWindow = 0;
237
238 BitReader.fillBitWindow(s);
239 if (BitReader.readFewBits(s, 1) == 0) {
240 return 16;
241 }
242 int n = BitReader.readFewBits(s, 3);
243 if (n != 0) {
244 return 17 + n;
245 }
246 n = BitReader.readFewBits(s, 3);
247 if (n != 0) {
248 if (n == 1) {
249 if (largeWindowEnabled == 0) {
250
251 return -1;
252 }
253 s.isLargeWindow = 1;
254
255 if (BitReader.readFewBits(s, 1) == 1) {
256 return -1;
257 }
258 n = BitReader.readFewBits(s, 6);
259 if (n < MIN_LARGE_WINDOW_BITS || n > MAX_LARGE_WINDOW_BITS) {
260
261 return -1;
262 }
263 return n;
264 }
265 return 8 + n;
266 }
267 return 17;
268 }
269
270
271
272
273
274
275
276
277 static int enableEagerOutput(State s) {
278 if (s.runningState != INITIALIZED) {
279 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_FRESH);
280 }
281 s.isEager = 1;
282 return BROTLI_OK;
283 }
284
285 static int enableLargeWindow(State s) {
286 if (s.runningState != INITIALIZED) {
287 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_FRESH);
288 }
289 s.isLargeWindow = 1;
290 return BROTLI_OK;
291 }
292
293
294 static int attachDictionaryChunk(State s, byte[] data) {
295 if (s.runningState != INITIALIZED) {
296 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_FRESH);
297 }
298 if (s.cdNumChunks == 0) {
299 s.cdChunks = new byte[16][];
300 s.cdChunkOffsets = new int[16];
301 s.cdBlockBits = -1;
302 }
303 if (s.cdNumChunks == 15) {
304 return Utils.makeError(s, BROTLI_PANIC_TOO_MANY_DICTIONARY_CHUNKS);
305 }
306 s.cdChunks[s.cdNumChunks] = data;
307 s.cdNumChunks++;
308 s.cdTotalSize += data.length;
309 s.cdChunkOffsets[s.cdNumChunks] = s.cdTotalSize;
310 return BROTLI_OK;
311 }
312
313
314
315
316
317
318 static int initState(State s) {
319 if (s.runningState != UNINITIALIZED) {
320 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_UNINITIALIZED);
321 }
322
323 s.blockTrees = new int[7 + 3 * (HUFFMAN_TABLE_SIZE_258 + HUFFMAN_TABLE_SIZE_26)];
324 s.blockTrees[0] = 7;
325 s.distRbIdx = 3;
326 int result = calculateDistanceAlphabetLimit(s, MAX_ALLOWED_DISTANCE, 3, 15 << 3);
327 if (result < BROTLI_OK) {
328 return result;
329 }
330 final int maxDistanceAlphabetLimit = result;
331 s.distExtraBits = new byte[maxDistanceAlphabetLimit];
332 s.distOffset = new int[maxDistanceAlphabetLimit];
333 result = BitReader.initBitReader(s);
334 if (result < BROTLI_OK) {
335 return result;
336 }
337 s.runningState = INITIALIZED;
338 return BROTLI_OK;
339 }
340
341 static int close(State s) {
342 if (s.runningState == UNINITIALIZED) {
343 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_INITIALIZED);
344 }
345 if (s.runningState > 0) {
346 s.runningState = CLOSED;
347 }
348 return BROTLI_OK;
349 }
350
351
352
353
354 private static int decodeVarLenUnsignedByte(State s) {
355 BitReader.fillBitWindow(s);
356 if (BitReader.readFewBits(s, 1) != 0) {
357 final int n = BitReader.readFewBits(s, 3);
358 if (n == 0) {
359 return 1;
360 }
361 return BitReader.readFewBits(s, n) + (1 << n);
362 }
363 return 0;
364 }
365
366 private static int decodeMetaBlockLength(State s) {
367 BitReader.fillBitWindow(s);
368 s.inputEnd = BitReader.readFewBits(s, 1);
369 s.metaBlockLength = 0;
370 s.isUncompressed = 0;
371 s.isMetadata = 0;
372 if ((s.inputEnd != 0) && BitReader.readFewBits(s, 1) != 0) {
373 return BROTLI_OK;
374 }
375 final int sizeNibbles = BitReader.readFewBits(s, 2) + 4;
376 if (sizeNibbles == 7) {
377 s.isMetadata = 1;
378 if (BitReader.readFewBits(s, 1) != 0) {
379 return Utils.makeError(s, BROTLI_ERROR_CORRUPTED_RESERVED_BIT);
380 }
381 final int sizeBytes = BitReader.readFewBits(s, 2);
382 if (sizeBytes == 0) {
383 return BROTLI_OK;
384 }
385 for (int i = 0; i < sizeBytes; ++i) {
386 BitReader.fillBitWindow(s);
387 final int bits = BitReader.readFewBits(s, 8);
388 if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
389 return Utils.makeError(s, BROTLI_ERROR_EXUBERANT_NIBBLE);
390 }
391 s.metaBlockLength += bits << (i * 8);
392 }
393 } else {
394 for (int i = 0; i < sizeNibbles; ++i) {
395 BitReader.fillBitWindow(s);
396 final int bits = BitReader.readFewBits(s, 4);
397 if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
398 return Utils.makeError(s, BROTLI_ERROR_EXUBERANT_NIBBLE);
399 }
400 s.metaBlockLength += bits << (i * 4);
401 }
402 }
403 s.metaBlockLength++;
404 if (s.inputEnd == 0) {
405 s.isUncompressed = BitReader.readFewBits(s, 1);
406 }
407 return BROTLI_OK;
408 }
409
410
411
412
413 private static int readSymbol(int[] tableGroup, int tableIdx, State s) {
414 int offset = tableGroup[tableIdx];
415 final int v = BitReader.peekBits(s);
416 offset += v & HUFFMAN_TABLE_MASK;
417 final int bits = tableGroup[offset] >> 16;
418 final int sym = tableGroup[offset] & 0xFFFF;
419 if (bits <= HUFFMAN_TABLE_BITS) {
420 s.bitOffset += bits;
421 return sym;
422 }
423 offset += sym;
424 final int mask = (1 << bits) - 1;
425 offset += Utils.shr32(v & mask, HUFFMAN_TABLE_BITS);
426 s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS);
427 return tableGroup[offset] & 0xFFFF;
428 }
429
430 private static int readBlockLength(int[] tableGroup, int tableIdx, State s) {
431 BitReader.fillBitWindow(s);
432 final int code = readSymbol(tableGroup, tableIdx, s);
433 final int n = BLOCK_LENGTH_N_BITS[code];
434 BitReader.fillBitWindow(s);
435 return BLOCK_LENGTH_OFFSET[code] + BitReader.readBits(s, n);
436 }
437
438 private static void moveToFront(int[] v, int index) {
439 int i = index;
440 final int value = v[i];
441 while (i > 0) {
442 v[i] = v[i - 1];
443 i--;
444 }
445 v[0] = value;
446 }
447
448 private static void inverseMoveToFrontTransform(byte[] v, int vLen) {
449 final int[] mtf = new int[256];
450 for (int i = 0; i < 256; ++i) {
451 mtf[i] = i;
452 }
453 for (int i = 0; i < vLen; ++i) {
454 final int index = v[i] & 0xFF;
455 v[i] = (byte) mtf[index];
456 if (index != 0) {
457 moveToFront(mtf, index);
458 }
459 }
460 }
461
462 private static int readHuffmanCodeLengths(
463 int[] codeLengthCodeLengths, int numSymbols, int[] codeLengths, State s) {
464 int symbol = 0;
465 int prevCodeLen = DEFAULT_CODE_LENGTH;
466 int repeat = 0;
467 int repeatCodeLen = 0;
468 int space = 32768;
469 final int[] table = new int[32 + 1];
470 final int tableIdx = table.length - 1;
471 Huffman.buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, CODE_LENGTH_CODES);
472
473 while (symbol < numSymbols && space > 0) {
474 if (s.halfOffset > BitReader.HALF_WATERLINE) {
475 final int result = BitReader.readMoreInput(s);
476 if (result < BROTLI_OK) {
477 return result;
478 }
479 }
480 BitReader.fillBitWindow(s);
481 final int p = BitReader.peekBits(s) & 31;
482 s.bitOffset += table[p] >> 16;
483 final int codeLen = table[p] & 0xFFFF;
484 if (codeLen < CODE_LENGTH_REPEAT_CODE) {
485 repeat = 0;
486 codeLengths[symbol++] = codeLen;
487 if (codeLen != 0) {
488 prevCodeLen = codeLen;
489 space -= 32768 >> codeLen;
490 }
491 } else {
492 final int extraBits = codeLen - 14;
493 int newLen = 0;
494 if (codeLen == CODE_LENGTH_REPEAT_CODE) {
495 newLen = prevCodeLen;
496 }
497 if (repeatCodeLen != newLen) {
498 repeat = 0;
499 repeatCodeLen = newLen;
500 }
501 final int oldRepeat = repeat;
502 if (repeat > 0) {
503 repeat -= 2;
504 repeat = repeat << extraBits;
505 }
506 BitReader.fillBitWindow(s);
507 repeat += BitReader.readFewBits(s, extraBits) + 3;
508 final int repeatDelta = repeat - oldRepeat;
509 if (symbol + repeatDelta > numSymbols) {
510 return Utils.makeError(s, BROTLI_ERROR_CORRUPTED_CODE_LENGTH_TABLE);
511 }
512 for (int i = 0; i < repeatDelta; ++i) {
513 codeLengths[symbol++] = repeatCodeLen;
514 }
515 if (repeatCodeLen != 0) {
516 space -= repeatDelta << (15 - repeatCodeLen);
517 }
518 }
519 }
520 if (space != 0) {
521 return Utils.makeError(s, BROTLI_ERROR_UNUSED_HUFFMAN_SPACE);
522 }
523
524 Utils.fillIntsWithZeroes(codeLengths, symbol, numSymbols);
525 return BROTLI_OK;
526 }
527
528 private static int checkDupes(State s, int[] symbols, int length) {
529 for (int i = 0; i < length - 1; ++i) {
530 for (int j = i + 1; j < length; ++j) {
531 if (symbols[i] == symbols[j]) {
532 return Utils.makeError(s, BROTLI_ERROR_DUPLICATE_SIMPLE_HUFFMAN_SYMBOL);
533 }
534 }
535 }
536 return BROTLI_OK;
537 }
538
539
540
541
542 private static int readSimpleHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
543 int[] tableGroup, int tableIdx, State s) {
544
545 final int[] codeLengths = new int[alphabetSizeLimit];
546 final int[] symbols = new int[4];
547
548 final int maxBits = 1 + log2floor(alphabetSizeMax - 1);
549
550 final int numSymbols = BitReader.readFewBits(s, 2) + 1;
551 for (int i = 0; i < numSymbols; ++i) {
552 BitReader.fillBitWindow(s);
553 final int symbol = BitReader.readFewBits(s, maxBits);
554 if (symbol >= alphabetSizeLimit) {
555 return Utils.makeError(s, BROTLI_ERROR_SYMBOL_OUT_OF_RANGE);
556 }
557 symbols[i] = symbol;
558 }
559 final int result = checkDupes(s, symbols, numSymbols);
560 if (result < BROTLI_OK) {
561 return result;
562 }
563
564 int histogramId = numSymbols;
565 if (numSymbols == 4) {
566 histogramId += BitReader.readFewBits(s, 1);
567 }
568
569 switch (histogramId) {
570 case 1:
571 codeLengths[symbols[0]] = 1;
572 break;
573
574 case 2:
575 codeLengths[symbols[0]] = 1;
576 codeLengths[symbols[1]] = 1;
577 break;
578
579 case 3:
580 codeLengths[symbols[0]] = 1;
581 codeLengths[symbols[1]] = 2;
582 codeLengths[symbols[2]] = 2;
583 break;
584
585 case 4:
586 codeLengths[symbols[0]] = 2;
587 codeLengths[symbols[1]] = 2;
588 codeLengths[symbols[2]] = 2;
589 codeLengths[symbols[3]] = 2;
590 break;
591
592 case 5:
593 codeLengths[symbols[0]] = 1;
594 codeLengths[symbols[1]] = 2;
595 codeLengths[symbols[2]] = 3;
596 codeLengths[symbols[3]] = 3;
597 break;
598
599 default:
600 break;
601 }
602
603
604 return Huffman.buildHuffmanTable(
605 tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
606 }
607
608
609 private static int readComplexHuffmanCode(int alphabetSizeLimit, int skip,
610 int[] tableGroup, int tableIdx, State s) {
611
612 final int[] codeLengths = new int[alphabetSizeLimit];
613 final int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES];
614 int space = 32;
615 int numCodes = 0;
616 for (int i = skip; i < CODE_LENGTH_CODES; ++i) {
617 final int codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
618 BitReader.fillBitWindow(s);
619 final int p = BitReader.peekBits(s) & 15;
620
621 s.bitOffset += FIXED_TABLE[p] >> 16;
622 final int v = FIXED_TABLE[p] & 0xFFFF;
623 codeLengthCodeLengths[codeLenIdx] = v;
624 if (v != 0) {
625 space -= (32 >> v);
626 numCodes++;
627 if (space <= 0) {
628 break;
629 }
630 }
631 }
632 if (space != 0 && numCodes != 1) {
633 return Utils.makeError(s, BROTLI_ERROR_CORRUPTED_HUFFMAN_CODE_HISTOGRAM);
634 }
635
636 final int result = readHuffmanCodeLengths(codeLengthCodeLengths, alphabetSizeLimit, codeLengths, s);
637 if (result < BROTLI_OK) {
638 return result;
639 }
640
641 return Huffman.buildHuffmanTable(
642 tableGroup, tableIdx, HUFFMAN_TABLE_BITS, codeLengths, alphabetSizeLimit);
643 }
644
645
646
647
648
649
650 private static int readHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
651 int[] tableGroup, int tableIdx, State s) {
652 if (s.halfOffset > BitReader.HALF_WATERLINE) {
653 final int result = BitReader.readMoreInput(s);
654 if (result < BROTLI_OK) {
655 return result;
656 }
657 }
658 BitReader.fillBitWindow(s);
659 final int simpleCodeOrSkip = BitReader.readFewBits(s, 2);
660 if (simpleCodeOrSkip == 1) {
661 return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
662 }
663 return readComplexHuffmanCode(alphabetSizeLimit, simpleCodeOrSkip, tableGroup, tableIdx, s);
664 }
665
666 private static int decodeContextMap(int contextMapSize, byte[] contextMap, State s) {
667 int result;
668 if (s.halfOffset > BitReader.HALF_WATERLINE) {
669 result = BitReader.readMoreInput(s);
670 if (result < BROTLI_OK) {
671 return result;
672 }
673 }
674 final int numTrees = decodeVarLenUnsignedByte(s) + 1;
675
676 if (numTrees == 1) {
677 Utils.fillBytesWithZeroes(contextMap, 0, contextMapSize);
678 return numTrees;
679 }
680
681 BitReader.fillBitWindow(s);
682 final int useRleForZeros = BitReader.readFewBits(s, 1);
683 int maxRunLengthPrefix = 0;
684 if (useRleForZeros != 0) {
685 maxRunLengthPrefix = BitReader.readFewBits(s, 4) + 1;
686 }
687 final int alphabetSize = numTrees + maxRunLengthPrefix;
688 final int tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5];
689
690 final int[] table = new int[tableSize + 1];
691 final int tableIdx = table.length - 1;
692 result = readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
693 if (result < BROTLI_OK) {
694 return result;
695 }
696 int i = 0;
697 while (i < contextMapSize) {
698 if (s.halfOffset > BitReader.HALF_WATERLINE) {
699 result = BitReader.readMoreInput(s);
700 if (result < BROTLI_OK) {
701 return result;
702 }
703 }
704 BitReader.fillBitWindow(s);
705 final int code = readSymbol(table, tableIdx, s);
706 if (code == 0) {
707 contextMap[i] = 0;
708 i++;
709 } else if (code <= maxRunLengthPrefix) {
710 BitReader.fillBitWindow(s);
711 int reps = (1 << code) + BitReader.readFewBits(s, code);
712 while (reps != 0) {
713 if (i >= contextMapSize) {
714 return Utils.makeError(s, BROTLI_ERROR_CORRUPTED_CONTEXT_MAP);
715 }
716 contextMap[i] = 0;
717 i++;
718 reps--;
719 }
720 } else {
721 contextMap[i] = (byte) (code - maxRunLengthPrefix);
722 i++;
723 }
724 }
725 BitReader.fillBitWindow(s);
726 if (BitReader.readFewBits(s, 1) == 1) {
727 inverseMoveToFrontTransform(contextMap, contextMapSize);
728 }
729 return numTrees;
730 }
731
732 private static int decodeBlockTypeAndLength(State s, int treeType, int numBlockTypes) {
733 final int[] ringBuffers = s.rings;
734 final int offset = 4 + treeType * 2;
735 BitReader.fillBitWindow(s);
736 int blockType = readSymbol(s.blockTrees, 2 * treeType, s);
737 final int result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
738
739 if (blockType == 1) {
740 blockType = ringBuffers[offset + 1] + 1;
741 } else if (blockType == 0) {
742 blockType = ringBuffers[offset];
743 } else {
744 blockType -= 2;
745 }
746 if (blockType >= numBlockTypes) {
747 blockType -= numBlockTypes;
748 }
749 ringBuffers[offset] = ringBuffers[offset + 1];
750 ringBuffers[offset + 1] = blockType;
751 return result;
752 }
753
754 private static void decodeLiteralBlockSwitch(State s) {
755 s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
756 final int literalBlockType = s.rings[5];
757 s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS;
758 s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF;
759 final int contextMode = s.contextModes[literalBlockType];
760 s.contextLookupOffset1 = contextMode << 9;
761 s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
762 }
763
764 private static void decodeCommandBlockSwitch(State s) {
765 s.commandBlockLength = decodeBlockTypeAndLength(s, 1, s.numCommandBlockTypes);
766 s.commandTreeIdx = s.rings[7];
767 }
768
769 private static void decodeDistanceBlockSwitch(State s) {
770 s.distanceBlockLength = decodeBlockTypeAndLength(s, 2, s.numDistanceBlockTypes);
771 s.distContextMapSlice = s.rings[9] << DISTANCE_CONTEXT_BITS;
772 }
773
774 private static void maybeReallocateRingBuffer(State s) {
775 int newSize = s.maxRingBufferSize;
776 if (newSize > s.expectedTotalSize) {
777
778 final int minimalNewSize = s.expectedTotalSize;
779 while ((newSize >> 1) > minimalNewSize) {
780 newSize = newSize >> 1;
781 }
782 if ((s.inputEnd == 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
783 newSize = 16384;
784 }
785 }
786 if (newSize <= s.ringBufferSize) {
787 return;
788 }
789 final int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH;
790 final byte[] newBuffer = new byte[ringBufferSizeWithSlack];
791 final byte[] oldBuffer = s.ringBuffer;
792 if (oldBuffer.length != 0) {
793 Utils.copyBytes(newBuffer, 0, oldBuffer, 0, s.ringBufferSize);
794 }
795 s.ringBuffer = newBuffer;
796 s.ringBufferSize = newSize;
797 }
798
799 private static int readNextMetablockHeader(State s) {
800 if (s.inputEnd != 0) {
801 s.nextRunningState = FINISHED;
802 s.runningState = INIT_WRITE;
803 return BROTLI_OK;
804 }
805
806 s.literalTreeGroup = new int[0];
807 s.commandTreeGroup = new int[0];
808 s.distanceTreeGroup = new int[0];
809
810 int result;
811 if (s.halfOffset > BitReader.HALF_WATERLINE) {
812 result = BitReader.readMoreInput(s);
813 if (result < BROTLI_OK) {
814 return result;
815 }
816 }
817 result = decodeMetaBlockLength(s);
818 if (result < BROTLI_OK) {
819 return result;
820 }
821 if ((s.metaBlockLength == 0) && (s.isMetadata == 0)) {
822 return BROTLI_OK;
823 }
824 if ((s.isUncompressed != 0) || (s.isMetadata != 0)) {
825 result = BitReader.jumpToByteBoundary(s);
826 if (result < BROTLI_OK) {
827 return result;
828 }
829 if (s.isMetadata == 0) {
830 s.runningState = COPY_UNCOMPRESSED;
831 } else {
832 s.runningState = READ_METADATA;
833 }
834 } else {
835 s.runningState = COMPRESSED_BLOCK_START;
836 }
837
838 if (s.isMetadata != 0) {
839 return BROTLI_OK;
840 }
841 s.expectedTotalSize += s.metaBlockLength;
842 if (s.expectedTotalSize > 1 << 30) {
843 s.expectedTotalSize = 1 << 30;
844 }
845 if (s.ringBufferSize < s.maxRingBufferSize) {
846 maybeReallocateRingBuffer(s);
847 }
848 return BROTLI_OK;
849 }
850
851 private static int readMetablockPartition(State s, int treeType, int numBlockTypes) {
852 int offset = s.blockTrees[2 * treeType];
853 if (numBlockTypes <= 1) {
854 s.blockTrees[2 * treeType + 1] = offset;
855 s.blockTrees[2 * treeType + 2] = offset;
856 return 1 << 28;
857 }
858
859 final int blockTypeAlphabetSize = numBlockTypes + 2;
860 int result = readHuffmanCode(
861 blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
862 if (result < BROTLI_OK) {
863 return result;
864 }
865 offset += result;
866 s.blockTrees[2 * treeType + 1] = offset;
867
868 final int blockLengthAlphabetSize = NUM_BLOCK_LENGTH_CODES;
869 result = readHuffmanCode(
870 blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
871 if (result < BROTLI_OK) {
872 return result;
873 }
874 offset += result;
875 s.blockTrees[2 * treeType + 2] = offset;
876
877 return readBlockLength(s.blockTrees, 2 * treeType + 1, s);
878 }
879
880 private static void calculateDistanceLut(State s, int alphabetSizeLimit) {
881 final byte[] distExtraBits = s.distExtraBits;
882 final int[] distOffset = s.distOffset;
883 final int npostfix = s.distancePostfixBits;
884 final int ndirect = s.numDirectDistanceCodes;
885 final int postfix = 1 << npostfix;
886 int bits = 1;
887 int half = 0;
888
889
890 int i = NUM_DISTANCE_SHORT_CODES;
891
892
893 for (int j = 0; j < ndirect; ++j) {
894 distExtraBits[i] = 0;
895 distOffset[i] = j + 1;
896 ++i;
897 }
898
899
900 while (i < alphabetSizeLimit) {
901 final int base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
902
903 for (int j = 0; j < postfix; ++j) {
904 distExtraBits[i] = (byte) bits;
905 distOffset[i] = base + j;
906 ++i;
907 }
908 bits = bits + half;
909 half = half ^ 1;
910 }
911 }
912
913 private static int readMetablockHuffmanCodesAndContextMaps(State s) {
914 s.numLiteralBlockTypes = decodeVarLenUnsignedByte(s) + 1;
915 int result = readMetablockPartition(s, 0, s.numLiteralBlockTypes);
916 if (result < BROTLI_OK) {
917 return result;
918 }
919 s.literalBlockLength = result;
920 s.numCommandBlockTypes = decodeVarLenUnsignedByte(s) + 1;
921 result = readMetablockPartition(s, 1, s.numCommandBlockTypes);
922 if (result < BROTLI_OK) {
923 return result;
924 }
925 s.commandBlockLength = result;
926 s.numDistanceBlockTypes = decodeVarLenUnsignedByte(s) + 1;
927 result = readMetablockPartition(s, 2, s.numDistanceBlockTypes);
928 if (result < BROTLI_OK) {
929 return result;
930 }
931 s.distanceBlockLength = result;
932
933 if (s.halfOffset > BitReader.HALF_WATERLINE) {
934 result = BitReader.readMoreInput(s);
935 if (result < BROTLI_OK) {
936 return result;
937 }
938 }
939 BitReader.fillBitWindow(s);
940 s.distancePostfixBits = BitReader.readFewBits(s, 2);
941 s.numDirectDistanceCodes = BitReader.readFewBits(s, 4) << s.distancePostfixBits;
942
943 s.contextModes = new byte[s.numLiteralBlockTypes];
944 int i = 0;
945 while (i < s.numLiteralBlockTypes) {
946
947 final int limit = Utils.min(i + 96, s.numLiteralBlockTypes);
948 while (i < limit) {
949 BitReader.fillBitWindow(s);
950 s.contextModes[i] = (byte) BitReader.readFewBits(s, 2);
951 i++;
952 }
953 if (s.halfOffset > BitReader.HALF_WATERLINE) {
954 result = BitReader.readMoreInput(s);
955 if (result < BROTLI_OK) {
956 return result;
957 }
958 }
959 }
960
961
962 final int contextMapLength = s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS;
963 s.contextMap = new byte[contextMapLength];
964 result = decodeContextMap(contextMapLength, s.contextMap, s);
965 if (result < BROTLI_OK) {
966 return result;
967 }
968 final int numLiteralTrees = result;
969 s.trivialLiteralContext = 1;
970 for (int j = 0; j < contextMapLength; ++j) {
971 if (s.contextMap[j] != j >> LITERAL_CONTEXT_BITS) {
972 s.trivialLiteralContext = 0;
973 break;
974 }
975 }
976
977
978 s.distContextMap = new byte[s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS];
979 result = decodeContextMap(s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS,
980 s.distContextMap, s);
981 if (result < BROTLI_OK) {
982 return result;
983 }
984 final int numDistTrees = result;
985
986 s.literalTreeGroup = new int[huffmanTreeGroupAllocSize(NUM_LITERAL_CODES, numLiteralTrees)];
987 result = decodeHuffmanTreeGroup(
988 NUM_LITERAL_CODES, NUM_LITERAL_CODES, numLiteralTrees, s, s.literalTreeGroup);
989 if (result < BROTLI_OK) {
990 return result;
991 }
992 s.commandTreeGroup =
993 new int[huffmanTreeGroupAllocSize(NUM_COMMAND_CODES, s.numCommandBlockTypes)];
994 result = decodeHuffmanTreeGroup(
995 NUM_COMMAND_CODES, NUM_COMMAND_CODES, s.numCommandBlockTypes, s, s.commandTreeGroup);
996 if (result < BROTLI_OK) {
997 return result;
998 }
999 int distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
1000 s.distancePostfixBits, s.numDirectDistanceCodes, MAX_DISTANCE_BITS);
1001 int distanceAlphabetSizeLimit = distanceAlphabetSizeMax;
1002 if (s.isLargeWindow == 1) {
1003 distanceAlphabetSizeMax = calculateDistanceAlphabetSize(
1004 s.distancePostfixBits, s.numDirectDistanceCodes, MAX_LARGE_WINDOW_DISTANCE_BITS);
1005 result = calculateDistanceAlphabetLimit(
1006 s, MAX_ALLOWED_DISTANCE, s.distancePostfixBits, s.numDirectDistanceCodes);
1007 if (result < BROTLI_OK) {
1008 return result;
1009 }
1010 distanceAlphabetSizeLimit = result;
1011 }
1012 s.distanceTreeGroup =
1013 new int[huffmanTreeGroupAllocSize(distanceAlphabetSizeLimit, numDistTrees)];
1014 result = decodeHuffmanTreeGroup(
1015 distanceAlphabetSizeMax, distanceAlphabetSizeLimit, numDistTrees, s, s.distanceTreeGroup);
1016 if (result < BROTLI_OK) {
1017 return result;
1018 }
1019 calculateDistanceLut(s, distanceAlphabetSizeLimit);
1020
1021 s.contextMapSlice = 0;
1022 s.distContextMapSlice = 0;
1023 s.contextLookupOffset1 = s.contextModes[0] * 512;
1024 s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
1025 s.literalTreeIdx = 0;
1026 s.commandTreeIdx = 0;
1027
1028 s.rings[4] = 1;
1029 s.rings[5] = 0;
1030 s.rings[6] = 1;
1031 s.rings[7] = 0;
1032 s.rings[8] = 1;
1033 s.rings[9] = 0;
1034 return BROTLI_OK;
1035 }
1036
1037 private static int copyUncompressedData(State s) {
1038 final byte[] ringBuffer = s.ringBuffer;
1039 int result;
1040
1041
1042 if (s.metaBlockLength <= 0) {
1043 result = BitReader.reload(s);
1044 if (result < BROTLI_OK) {
1045 return result;
1046 }
1047 s.runningState = BLOCK_START;
1048 return BROTLI_OK;
1049 }
1050
1051 final int chunkLength = Utils.min(s.ringBufferSize - s.pos, s.metaBlockLength);
1052 result = BitReader.copyRawBytes(s, ringBuffer, s.pos, chunkLength);
1053 if (result < BROTLI_OK) {
1054 return result;
1055 }
1056 s.metaBlockLength -= chunkLength;
1057 s.pos += chunkLength;
1058 if (s.pos == s.ringBufferSize) {
1059 s.nextRunningState = COPY_UNCOMPRESSED;
1060 s.runningState = INIT_WRITE;
1061 return BROTLI_OK;
1062 }
1063
1064 result = BitReader.reload(s);
1065 if (result < BROTLI_OK) {
1066 return result;
1067 }
1068 s.runningState = BLOCK_START;
1069 return BROTLI_OK;
1070 }
1071
1072 private static int writeRingBuffer(State s) {
1073 final int toWrite = Utils.min(s.outputLength - s.outputUsed,
1074 s.ringBufferBytesReady - s.ringBufferBytesWritten);
1075
1076 if (toWrite != 0) {
1077 Utils.copyBytes(s.output, s.outputOffset + s.outputUsed, s.ringBuffer,
1078 s.ringBufferBytesWritten, s.ringBufferBytesWritten + toWrite);
1079 s.outputUsed += toWrite;
1080 s.ringBufferBytesWritten += toWrite;
1081 }
1082
1083 if (s.outputUsed < s.outputLength) {
1084 return BROTLI_OK;
1085 }
1086 return BROTLI_OK_NEED_MORE_OUTPUT;
1087 }
1088
1089 private static int huffmanTreeGroupAllocSize(int alphabetSizeLimit, int n) {
1090 final int maxTableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSizeLimit + 31) >> 5];
1091 return n + n * maxTableSize;
1092 }
1093
1094 private static int decodeHuffmanTreeGroup(int alphabetSizeMax, int alphabetSizeLimit,
1095 int n, State s, int[] group) {
1096 int next = n;
1097 for (int i = 0; i < n; ++i) {
1098 group[i] = next;
1099 final int result = readHuffmanCode(alphabetSizeMax, alphabetSizeLimit, group, i, s);
1100 if (result < BROTLI_OK) {
1101 return result;
1102 }
1103 next += result;
1104 }
1105 return BROTLI_OK;
1106 }
1107
1108
1109 private static int calculateFence(State s) {
1110 int result = s.ringBufferSize;
1111 if (s.isEager != 0) {
1112 result = Utils.min(result, s.ringBufferBytesWritten + s.outputLength - s.outputUsed);
1113 }
1114 return result;
1115 }
1116
1117 private static int doUseDictionary(State s, int fence) {
1118 if (s.distance > MAX_ALLOWED_DISTANCE) {
1119 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1120 }
1121 final int address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
1122 if (address < 0) {
1123 final int result = initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
1124 if (result < BROTLI_OK) {
1125 return result;
1126 }
1127 s.runningState = COPY_FROM_COMPOUND_DICTIONARY;
1128 } else {
1129
1130 final ByteBuffer dictionaryData = Dictionary.getData();
1131 final int wordLength = s.copyLength;
1132 if (wordLength > Dictionary.MAX_DICTIONARY_WORD_LENGTH) {
1133 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1134 }
1135 final int shift = Dictionary.sizeBits[wordLength];
1136 if (shift == 0) {
1137 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1138 }
1139 int offset = Dictionary.offsets[wordLength];
1140 final int mask = (1 << shift) - 1;
1141 final int wordIdx = address & mask;
1142 final int transformIdx = address >> shift;
1143 offset += wordIdx * wordLength;
1144 final Transform.Transforms transforms = Transform.RFC_TRANSFORMS;
1145 if (transformIdx >= transforms.numTransforms) {
1146 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1147 }
1148 final int len = Transform.transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData,
1149 offset, wordLength, transforms, transformIdx);
1150 s.pos += len;
1151 s.metaBlockLength -= len;
1152 if (s.pos >= fence) {
1153 s.nextRunningState = MAIN_LOOP;
1154 s.runningState = INIT_WRITE;
1155 return BROTLI_OK;
1156 }
1157 s.runningState = MAIN_LOOP;
1158 }
1159 return BROTLI_OK;
1160 }
1161
1162 private static void initializeCompoundDictionary(State s) {
1163 s.cdBlockMap = new byte[1 << CD_BLOCK_MAP_BITS];
1164 int blockBits = CD_BLOCK_MAP_BITS;
1165
1166 while (((s.cdTotalSize - 1) >> blockBits) != 0) {
1167 blockBits++;
1168 }
1169 blockBits -= CD_BLOCK_MAP_BITS;
1170 s.cdBlockBits = blockBits;
1171 int cursor = 0;
1172 int index = 0;
1173 while (cursor < s.cdTotalSize) {
1174 while (s.cdChunkOffsets[index + 1] < cursor) {
1175 index++;
1176 }
1177 s.cdBlockMap[cursor >> blockBits] = (byte) index;
1178 cursor += 1 << blockBits;
1179 }
1180 }
1181
1182 private static int initializeCompoundDictionaryCopy(State s, int address, int length) {
1183 if (s.cdBlockBits == -1) {
1184 initializeCompoundDictionary(s);
1185 }
1186 int index = s.cdBlockMap[address >> s.cdBlockBits];
1187 while (address >= s.cdChunkOffsets[index + 1]) {
1188 index++;
1189 }
1190 if (s.cdTotalSize > address + length) {
1191 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1192 }
1193
1194 s.distRbIdx = (s.distRbIdx + 1) & 0x3;
1195 s.rings[s.distRbIdx] = s.distance;
1196 s.metaBlockLength -= length;
1197 s.cdBrIndex = index;
1198 s.cdBrOffset = address - s.cdChunkOffsets[index];
1199 s.cdBrLength = length;
1200 s.cdBrCopied = 0;
1201 return BROTLI_OK;
1202 }
1203
1204 private static int copyFromCompoundDictionary(State s, int fence) {
1205 int pos = s.pos;
1206 final int origPos = pos;
1207 while (s.cdBrLength != s.cdBrCopied) {
1208 final int space = fence - pos;
1209 final int chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex];
1210 final int remChunkLength = chunkLength - s.cdBrOffset;
1211 int length = s.cdBrLength - s.cdBrCopied;
1212 if (length > remChunkLength) {
1213 length = remChunkLength;
1214 }
1215 if (length > space) {
1216 length = space;
1217 }
1218 Utils.copyBytes(
1219 s.ringBuffer, pos, s.cdChunks[s.cdBrIndex], s.cdBrOffset, s.cdBrOffset + length);
1220 pos += length;
1221 s.cdBrOffset += length;
1222 s.cdBrCopied += length;
1223 if (length == remChunkLength) {
1224 s.cdBrIndex++;
1225 s.cdBrOffset = 0;
1226 }
1227 if (pos >= fence) {
1228 break;
1229 }
1230 }
1231 return pos - origPos;
1232 }
1233
1234
1235
1236
1237 static int decompress(State s) {
1238 int result;
1239 if (s.runningState == UNINITIALIZED) {
1240 return Utils.makeError(s, BROTLI_PANIC_STATE_NOT_INITIALIZED);
1241 }
1242 if (s.runningState < 0) {
1243 return Utils.makeError(s, BROTLI_PANIC_UNEXPECTED_STATE);
1244 }
1245 if (s.runningState == CLOSED) {
1246 return Utils.makeError(s, BROTLI_PANIC_ALREADY_CLOSED);
1247 }
1248 if (s.runningState == INITIALIZED) {
1249 final int windowBits = decodeWindowBits(s);
1250 if (windowBits == -1) {
1251 return Utils.makeError(s, BROTLI_ERROR_INVALID_WINDOW_BITS);
1252 }
1253 s.maxRingBufferSize = 1 << windowBits;
1254 s.maxBackwardDistance = s.maxRingBufferSize - 16;
1255 s.runningState = BLOCK_START;
1256 }
1257
1258 int fence = calculateFence(s);
1259 int ringBufferMask = s.ringBufferSize - 1;
1260 byte[] ringBuffer = s.ringBuffer;
1261
1262 while (s.runningState != FINISHED) {
1263
1264 switch (s.runningState) {
1265 case BLOCK_START:
1266 if (s.metaBlockLength < 0) {
1267 return Utils.makeError(s, BROTLI_ERROR_INVALID_METABLOCK_LENGTH);
1268 }
1269 result = readNextMetablockHeader(s);
1270 if (result < BROTLI_OK) {
1271 return result;
1272 }
1273
1274 fence = calculateFence(s);
1275 ringBufferMask = s.ringBufferSize - 1;
1276 ringBuffer = s.ringBuffer;
1277 continue;
1278
1279 case COMPRESSED_BLOCK_START: {
1280 result = readMetablockHuffmanCodesAndContextMaps(s);
1281 if (result < BROTLI_OK) {
1282 return result;
1283 }
1284 s.runningState = MAIN_LOOP;
1285 continue;
1286 }
1287
1288 case MAIN_LOOP:
1289 if (s.metaBlockLength <= 0) {
1290 s.runningState = BLOCK_START;
1291 continue;
1292 }
1293 if (s.halfOffset > BitReader.HALF_WATERLINE) {
1294 result = BitReader.readMoreInput(s);
1295 if (result < BROTLI_OK) {
1296 return result;
1297 }
1298 }
1299 if (s.commandBlockLength == 0) {
1300 decodeCommandBlockSwitch(s);
1301 }
1302 s.commandBlockLength--;
1303 BitReader.fillBitWindow(s);
1304 final int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
1305 final int insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
1306 final int insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
1307 final int copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
1308 s.distanceCode = CMD_LOOKUP[cmdCode + 3];
1309 BitReader.fillBitWindow(s);
1310 {
1311 final int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF;
1312 s.insertLength = insertLengthOffset + BitReader.readBits(s, insertLengthExtraBits);
1313 }
1314 BitReader.fillBitWindow(s);
1315 {
1316 final int copyLengthExtraBits = insertAndCopyExtraBits >> 8;
1317 s.copyLength = copyLengthOffset + BitReader.readBits(s, copyLengthExtraBits);
1318 }
1319
1320 s.j = 0;
1321 s.runningState = INSERT_LOOP;
1322 continue;
1323
1324 case INSERT_LOOP:
1325 if (s.trivialLiteralContext != 0) {
1326 while (s.j < s.insertLength) {
1327 if (s.halfOffset > BitReader.HALF_WATERLINE) {
1328 result = BitReader.readMoreInput(s);
1329 if (result < BROTLI_OK) {
1330 return result;
1331 }
1332 }
1333 if (s.literalBlockLength == 0) {
1334 decodeLiteralBlockSwitch(s);
1335 }
1336 s.literalBlockLength--;
1337 BitReader.fillBitWindow(s);
1338 ringBuffer[s.pos] = (byte) readSymbol(s.literalTreeGroup, s.literalTreeIdx, s);
1339 s.pos++;
1340 s.j++;
1341 if (s.pos >= fence) {
1342 s.nextRunningState = INSERT_LOOP;
1343 s.runningState = INIT_WRITE;
1344 break;
1345 }
1346 }
1347 } else {
1348 int prevByte1 = ringBuffer[(s.pos - 1) & ringBufferMask] & 0xFF;
1349 int prevByte2 = ringBuffer[(s.pos - 2) & ringBufferMask] & 0xFF;
1350 while (s.j < s.insertLength) {
1351 if (s.halfOffset > BitReader.HALF_WATERLINE) {
1352 result = BitReader.readMoreInput(s);
1353 if (result < BROTLI_OK) {
1354 return result;
1355 }
1356 }
1357 if (s.literalBlockLength == 0) {
1358 decodeLiteralBlockSwitch(s);
1359 }
1360 final int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1]
1361 | Context.LOOKUP[s.contextLookupOffset2 + prevByte2];
1362 final int literalTreeIdx =
1363 s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
1364 s.literalBlockLength--;
1365 prevByte2 = prevByte1;
1366 BitReader.fillBitWindow(s);
1367 prevByte1 = readSymbol(s.literalTreeGroup, literalTreeIdx, s);
1368 ringBuffer[s.pos] = (byte) prevByte1;
1369 s.pos++;
1370 s.j++;
1371 if (s.pos >= fence) {
1372 s.nextRunningState = INSERT_LOOP;
1373 s.runningState = INIT_WRITE;
1374 break;
1375 }
1376 }
1377 }
1378 if (s.runningState != INSERT_LOOP) {
1379 continue;
1380 }
1381 s.metaBlockLength -= s.insertLength;
1382 if (s.metaBlockLength <= 0) {
1383 s.runningState = MAIN_LOOP;
1384 continue;
1385 }
1386 int distanceCode = s.distanceCode;
1387 if (distanceCode < 0) {
1388
1389 s.distance = s.rings[s.distRbIdx];
1390 } else {
1391 if (s.halfOffset > BitReader.HALF_WATERLINE) {
1392 result = BitReader.readMoreInput(s);
1393 if (result < BROTLI_OK) {
1394 return result;
1395 }
1396 }
1397 if (s.distanceBlockLength == 0) {
1398 decodeDistanceBlockSwitch(s);
1399 }
1400 s.distanceBlockLength--;
1401 BitReader.fillBitWindow(s);
1402 final int distTreeIdx =
1403 s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
1404 distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
1405 if (distanceCode < NUM_DISTANCE_SHORT_CODES) {
1406 final int index =
1407 (s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode]) & 0x3;
1408 s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
1409 if (s.distance < 0) {
1410 return Utils.makeError(s, BROTLI_ERROR_NEGATIVE_DISTANCE);
1411 }
1412 } else {
1413 final int extraBits = s.distExtraBits[distanceCode];
1414 int bits;
1415 if (s.bitOffset + extraBits <= BitReader.BITNESS) {
1416 bits = BitReader.readFewBits(s, extraBits);
1417 } else {
1418 BitReader.fillBitWindow(s);
1419 bits = BitReader.readBits(s, extraBits);
1420 }
1421 s.distance = s.distOffset[distanceCode] + (bits << s.distancePostfixBits);
1422 }
1423 }
1424
1425 if (s.maxDistance != s.maxBackwardDistance
1426 && s.pos < s.maxBackwardDistance) {
1427 s.maxDistance = s.pos;
1428 } else {
1429 s.maxDistance = s.maxBackwardDistance;
1430 }
1431
1432 if (s.distance > s.maxDistance) {
1433 s.runningState = USE_DICTIONARY;
1434 continue;
1435 }
1436
1437 if (distanceCode > 0) {
1438 s.distRbIdx = (s.distRbIdx + 1) & 0x3;
1439 s.rings[s.distRbIdx] = s.distance;
1440 }
1441
1442 if (s.copyLength > s.metaBlockLength) {
1443 return Utils.makeError(s, BROTLI_ERROR_INVALID_BACKWARD_REFERENCE);
1444 }
1445 s.j = 0;
1446 s.runningState = COPY_LOOP;
1447 continue;
1448
1449 case COPY_LOOP:
1450 int src = (s.pos - s.distance) & ringBufferMask;
1451 int dst = s.pos;
1452 final int copyLength = s.copyLength - s.j;
1453 final int srcEnd = src + copyLength;
1454 final int dstEnd = dst + copyLength;
1455 if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
1456 if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
1457 final int numQuads = (copyLength + 3) >> 2;
1458 for (int k = 0; k < numQuads; ++k) {
1459 ringBuffer[dst++] = ringBuffer[src++];
1460 ringBuffer[dst++] = ringBuffer[src++];
1461 ringBuffer[dst++] = ringBuffer[src++];
1462 ringBuffer[dst++] = ringBuffer[src++];
1463 }
1464 } else {
1465 Utils.copyBytesWithin(ringBuffer, dst, src, srcEnd);
1466 }
1467 s.j += copyLength;
1468 s.metaBlockLength -= copyLength;
1469 s.pos += copyLength;
1470 } else {
1471 while (s.j < s.copyLength) {
1472 ringBuffer[s.pos] =
1473 ringBuffer[(s.pos - s.distance) & ringBufferMask];
1474 s.metaBlockLength--;
1475 s.pos++;
1476 s.j++;
1477 if (s.pos >= fence) {
1478 s.nextRunningState = COPY_LOOP;
1479 s.runningState = INIT_WRITE;
1480 break;
1481 }
1482 }
1483 }
1484 if (s.runningState == COPY_LOOP) {
1485 s.runningState = MAIN_LOOP;
1486 }
1487 continue;
1488
1489 case USE_DICTIONARY:
1490 result = doUseDictionary(s, fence);
1491 if (result < BROTLI_OK) {
1492 return result;
1493 }
1494 continue;
1495
1496 case COPY_FROM_COMPOUND_DICTIONARY:
1497 s.pos += copyFromCompoundDictionary(s, fence);
1498 if (s.pos >= fence) {
1499 s.nextRunningState = COPY_FROM_COMPOUND_DICTIONARY;
1500 s.runningState = INIT_WRITE;
1501 return BROTLI_OK_NEED_MORE_OUTPUT;
1502 }
1503 s.runningState = MAIN_LOOP;
1504 continue;
1505
1506 case READ_METADATA:
1507 while (s.metaBlockLength > 0) {
1508 if (s.halfOffset > BitReader.HALF_WATERLINE) {
1509 result = BitReader.readMoreInput(s);
1510 if (result < BROTLI_OK) {
1511 return result;
1512 }
1513 }
1514
1515 BitReader.fillBitWindow(s);
1516 BitReader.readFewBits(s, 8);
1517 s.metaBlockLength--;
1518 }
1519 s.runningState = BLOCK_START;
1520 continue;
1521
1522 case COPY_UNCOMPRESSED:
1523 result = copyUncompressedData(s);
1524 if (result < BROTLI_OK) {
1525 return result;
1526 }
1527 continue;
1528
1529 case INIT_WRITE:
1530 s.ringBufferBytesReady = Utils.min(s.pos, s.ringBufferSize);
1531 s.runningState = WRITE;
1532 continue;
1533
1534 case WRITE:
1535 result = writeRingBuffer(s);
1536 if (result != BROTLI_OK) {
1537
1538 return result;
1539 }
1540 if (s.pos >= s.maxBackwardDistance) {
1541 s.maxDistance = s.maxBackwardDistance;
1542 }
1543
1544 if (s.pos >= s.ringBufferSize) {
1545 if (s.pos > s.ringBufferSize) {
1546 Utils.copyBytesWithin(ringBuffer, 0, s.ringBufferSize, s.pos);
1547 }
1548 s.pos = s.pos & ringBufferMask;
1549 s.ringBufferBytesWritten = 0;
1550 }
1551 s.runningState = s.nextRunningState;
1552 continue;
1553
1554 default:
1555 return Utils.makeError(s, BROTLI_PANIC_UNEXPECTED_STATE);
1556 }
1557 }
1558 if (s.runningState != FINISHED) {
1559 return Utils.makeError(s, BROTLI_PANIC_UNREACHABLE);
1560 }
1561 if (s.metaBlockLength < 0) {
1562 return Utils.makeError(s, BROTLI_ERROR_INVALID_METABLOCK_LENGTH);
1563 }
1564 result = BitReader.jumpToByteBoundary(s);
1565 if (result != BROTLI_OK) {
1566 return result;
1567 }
1568 result = BitReader.checkHealth(s, 1);
1569 if (result != BROTLI_OK) {
1570 return result;
1571 }
1572 return BROTLI_OK_DONE;
1573 }
1574 }