JS: stronger typing

PiperOrigin-RevId: 526909255
This commit is contained in:
Evgenii Kliuchnikov 2023-04-25 09:58:13 +00:00 committed by Evgenii Kliuchnikov
parent e1f5788fb0
commit ffbe112328
9 changed files with 398 additions and 386 deletions

View File

@ -61,14 +61,14 @@ final class BitReader {
} }
throw new BrotliRuntimeException("No more input"); throw new BrotliRuntimeException("No more input");
} }
int readOffset = s.halfOffset << LOG_HALF_SIZE; final int readOffset = s.halfOffset << LOG_HALF_SIZE;
int bytesInBuffer = CAPACITY - readOffset; int bytesInBuffer = CAPACITY - readOffset;
// Move unused bytes to the head of the buffer. // Move unused bytes to the head of the buffer.
Utils.copyBytesWithin(s.byteBuffer, 0, readOffset, CAPACITY); Utils.copyBytesWithin(s.byteBuffer, 0, readOffset, CAPACITY);
s.halfOffset = 0; s.halfOffset = 0;
while (bytesInBuffer < CAPACITY) { while (bytesInBuffer < CAPACITY) {
int spaceLeft = CAPACITY - bytesInBuffer; final int spaceLeft = CAPACITY - bytesInBuffer;
int len = Utils.readInput(s.input, s.byteBuffer, bytesInBuffer, spaceLeft); final int len = Utils.readInput(s.input, s.byteBuffer, bytesInBuffer, spaceLeft);
// EOF is -1 in Java, but 0 in C#. // EOF is -1 in Java, but 0 in C#.
if (len <= 0) { if (len <= 0) {
s.endOfStreamReached = 1; s.endOfStreamReached = 1;
@ -85,7 +85,7 @@ final class BitReader {
if (s.endOfStreamReached == 0) { if (s.endOfStreamReached == 0) {
return; return;
} }
int byteOffset = (s.halfOffset << LOG_HALF_SIZE) + ((s.bitOffset + 7) >> 3) - BYTENESS; final int byteOffset = (s.halfOffset << LOG_HALF_SIZE) + ((s.bitOffset + 7) >> 3) - BYTENESS;
if (byteOffset > s.tailBytes) { if (byteOffset > s.tailBytes) {
throw new BrotliRuntimeException("Read after end"); throw new BrotliRuntimeException("Read after end");
} }
@ -146,7 +146,7 @@ final class BitReader {
* otherwise BitReader will become broken. * otherwise BitReader will become broken.
*/ */
static int readFewBits(State s, int n) { static int readFewBits(State s, int n) {
int val = peekBits(s) & ((1 << n) - 1); final int val = peekBits(s) & ((1 << n) - 1);
s.bitOffset += n; s.bitOffset += n;
return val; return val;
} }
@ -160,7 +160,7 @@ final class BitReader {
} }
private static int readManyBits(State s, int n) { private static int readManyBits(State s, int n) {
int low = readFewBits(s, 16); final int low = readFewBits(s, 16);
doFillBitWindow(s); doFillBitWindow(s);
return low | (readFewBits(s, n - 16) << 16); return low | (readFewBits(s, n - 16) << 16);
} }
@ -194,9 +194,9 @@ final class BitReader {
} }
static void jumpToByteBoundary(State s) { static void jumpToByteBoundary(State s) {
int padding = (BITNESS - s.bitOffset) & 7; final int padding = (BITNESS - s.bitOffset) & 7;
if (padding != 0) { if (padding != 0) {
int paddingBits = readFewBits(s, padding); final int paddingBits = readFewBits(s, padding);
if (paddingBits != 0) { if (paddingBits != 0) {
throw new BrotliRuntimeException("Corrupted padding bits"); throw new BrotliRuntimeException("Corrupted padding bits");
} }
@ -227,10 +227,10 @@ final class BitReader {
} }
// Get data from shadow buffer with "sizeof(int)" granularity. // Get data from shadow buffer with "sizeof(int)" granularity.
int copyNibbles = Math.min(halfAvailable(s), length >> LOG_HALF_SIZE); final int copyNibbles = Math.min(halfAvailable(s), length >> LOG_HALF_SIZE);
if (copyNibbles > 0) { if (copyNibbles > 0) {
int readOffset = s.halfOffset << LOG_HALF_SIZE; final int readOffset = s.halfOffset << LOG_HALF_SIZE;
int delta = copyNibbles << LOG_HALF_SIZE; final int delta = copyNibbles << LOG_HALF_SIZE;
System.arraycopy(s.byteBuffer, readOffset, data, offset, delta); System.arraycopy(s.byteBuffer, readOffset, data, offset, delta);
offset += delta; offset += delta;
length -= delta; length -= delta;
@ -255,7 +255,7 @@ final class BitReader {
// Now it is possible to copy bytes directly. // Now it is possible to copy bytes directly.
while (length > 0) { while (length > 0) {
int len = Utils.readInput(s.input, data, offset, length); final int len = Utils.readInput(s.input, data, offset, length);
if (len == -1) { if (len == -1) {
throw new BrotliRuntimeException("Unexpected end of input"); throw new BrotliRuntimeException("Unexpected end of input");
} }
@ -268,10 +268,10 @@ final class BitReader {
* Translates bytes to halves (int/short). * Translates bytes to halves (int/short).
*/ */
static void bytesToNibbles(State s, int byteLen) { static void bytesToNibbles(State s, int byteLen) {
byte[] byteBuffer = s.byteBuffer; final byte[] byteBuffer = s.byteBuffer;
int halfLen = byteLen >> LOG_HALF_SIZE; final int halfLen = byteLen >> LOG_HALF_SIZE;
if (BITNESS == 64) { if (BITNESS == 64) {
int[] intBuffer = s.intBuffer; final int[] intBuffer = s.intBuffer;
for (int i = 0; i < halfLen; ++i) { for (int i = 0; i < halfLen; ++i) {
intBuffer[i] = ((byteBuffer[i * 4] & 0xFF)) intBuffer[i] = ((byteBuffer[i * 4] & 0xFF))
| ((byteBuffer[(i * 4) + 1] & 0xFF) << 8) | ((byteBuffer[(i * 4) + 1] & 0xFF) << 8)
@ -279,7 +279,7 @@ final class BitReader {
| ((byteBuffer[(i * 4) + 3] & 0xFF) << 24); | ((byteBuffer[(i * 4) + 3] & 0xFF) << 24);
} }
} else { } else {
short[] shortBuffer = s.shortBuffer; final short[] shortBuffer = s.shortBuffer;
for (int i = 0; i < halfLen; ++i) { for (int i = 0; i < halfLen; ++i) {
shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF) shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF)
| ((byteBuffer[(i * 2) + 1] & 0xFF) << 8)); | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));

View File

@ -34,8 +34,8 @@ final class Context {
} }
int offset = 1280; int offset = 1280;
for (int k = 0; k < 19; ++k) { for (int k = 0; k < 19; ++k) {
int value = k & 3; final int value = k & 3;
int rep = rle.charAt(k) - 32; final int rep = rle.charAt(k) - 32;
for (int i = 0; i < rep; ++i) { for (int i = 0; i < rep; ++i) {
lookup[offset++] = value; lookup[offset++] = value;
} }

View File

@ -158,15 +158,15 @@ final class Decode {
if (maxDistance < ndirect + (2 << npostfix)) { if (maxDistance < ndirect + (2 << npostfix)) {
throw new IllegalArgumentException("maxDistance is too small"); throw new IllegalArgumentException("maxDistance is too small");
} }
int offset = ((maxDistance - ndirect) >> npostfix) + 4; final int offset = ((maxDistance - ndirect) >> npostfix) + 4;
int ndistbits = log2floor(offset) - 1; final int ndistbits = log2floor(offset) - 1;
int group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1); final int group = ((ndistbits - 1) << 1) | ((offset >> ndistbits) & 1);
return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + NUM_DISTANCE_SHORT_CODES; return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + NUM_DISTANCE_SHORT_CODES;
} }
private static void unpackCommandLookupTable(short[] cmdLookup) { private static void unpackCommandLookupTable(short[] cmdLookup) {
short[] insertLengthOffsets = new short[24]; final short[] insertLengthOffsets = new short[24];
short[] copyLengthOffsets = new short[24]; final short[] copyLengthOffsets = new short[24];
copyLengthOffsets[0] = 2; copyLengthOffsets[0] = 2;
for (int i = 0; i < 23; ++i) { for (int i = 0; i < 23; ++i) {
insertLengthOffsets[i + 1] = insertLengthOffsets[i + 1] =
@ -183,12 +183,12 @@ final class Decode {
rangeIdx -= 2; rangeIdx -= 2;
distanceContextOffset = 0; distanceContextOffset = 0;
} }
int insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7); final int insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
int copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7); final int copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
short copyLengthOffset = copyLengthOffsets[copyCode]; final short copyLengthOffset = copyLengthOffsets[copyCode];
int distanceContext = final int distanceContext =
distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2); distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
int index = cmdCode * 4; final int index = cmdCode * 4;
cmdLookup[index + 0] = cmdLookup[index + 0] =
(short) (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8)); (short) (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
cmdLookup[index + 1] = insertLengthOffsets[insertCode]; cmdLookup[index + 1] = insertLengthOffsets[insertCode];
@ -208,7 +208,7 @@ final class Decode {
* "large-window" brotli stream. After this step it means that "large-window" feature * "large-window" brotli stream. After this step it means that "large-window" feature
* is actually detected. Despite the window size could be same as before (lgwin = 10..24), * is actually detected. Despite the window size could be same as before (lgwin = 10..24),
* encoded distances are allowed to be much greater, thus bigger dictinary could be used. */ * encoded distances are allowed to be much greater, thus bigger dictinary could be used. */
int largeWindowEnabled = s.isLargeWindow; final int largeWindowEnabled = s.isLargeWindow;
s.isLargeWindow = 0; s.isLargeWindow = 0;
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
@ -298,7 +298,8 @@ final class Decode {
s.blockTrees = new int[7 + 3 * (HUFFMAN_TABLE_SIZE_258 + HUFFMAN_TABLE_SIZE_26)]; s.blockTrees = new int[7 + 3 * (HUFFMAN_TABLE_SIZE_258 + HUFFMAN_TABLE_SIZE_26)];
s.blockTrees[0] = 7; s.blockTrees[0] = 7;
s.distRbIdx = 3; s.distRbIdx = 3;
int maxDistanceAlphabetLimit = calculateDistanceAlphabetLimit(MAX_ALLOWED_DISTANCE, 3, 15 << 3); final int maxDistanceAlphabetLimit =
calculateDistanceAlphabetLimit(MAX_ALLOWED_DISTANCE, 3, 15 << 3);
s.distExtraBits = new byte[maxDistanceAlphabetLimit]; s.distExtraBits = new byte[maxDistanceAlphabetLimit];
s.distOffset = new int[maxDistanceAlphabetLimit]; s.distOffset = new int[maxDistanceAlphabetLimit];
s.input = input; s.input = input;
@ -326,7 +327,7 @@ final class Decode {
private static int decodeVarLenUnsignedByte(State s) { private static int decodeVarLenUnsignedByte(State s) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
if (BitReader.readFewBits(s, 1) != 0) { if (BitReader.readFewBits(s, 1) != 0) {
int n = BitReader.readFewBits(s, 3); final int n = BitReader.readFewBits(s, 3);
if (n == 0) { if (n == 0) {
return 1; return 1;
} else { } else {
@ -345,19 +346,19 @@ final class Decode {
if ((s.inputEnd != 0) && BitReader.readFewBits(s, 1) != 0) { if ((s.inputEnd != 0) && BitReader.readFewBits(s, 1) != 0) {
return; return;
} }
int sizeNibbles = BitReader.readFewBits(s, 2) + 4; final int sizeNibbles = BitReader.readFewBits(s, 2) + 4;
if (sizeNibbles == 7) { if (sizeNibbles == 7) {
s.isMetadata = 1; s.isMetadata = 1;
if (BitReader.readFewBits(s, 1) != 0) { if (BitReader.readFewBits(s, 1) != 0) {
throw new BrotliRuntimeException("Corrupted reserved bit"); throw new BrotliRuntimeException("Corrupted reserved bit");
} }
int sizeBytes = BitReader.readFewBits(s, 2); final int sizeBytes = BitReader.readFewBits(s, 2);
if (sizeBytes == 0) { if (sizeBytes == 0) {
return; return;
} }
for (int i = 0; i < sizeBytes; i++) { for (int i = 0; i < sizeBytes; i++) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int bits = BitReader.readFewBits(s, 8); final int bits = BitReader.readFewBits(s, 8);
if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) { if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
throw new BrotliRuntimeException("Exuberant nibble"); throw new BrotliRuntimeException("Exuberant nibble");
} }
@ -366,7 +367,7 @@ final class Decode {
} else { } else {
for (int i = 0; i < sizeNibbles; i++) { for (int i = 0; i < sizeNibbles; i++) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int bits = BitReader.readFewBits(s, 4); final int bits = BitReader.readFewBits(s, 4);
if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) { if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
throw new BrotliRuntimeException("Exuberant nibble"); throw new BrotliRuntimeException("Exuberant nibble");
} }
@ -384,16 +385,16 @@ final class Decode {
*/ */
private static int readSymbol(int[] tableGroup, int tableIdx, State s) { private static int readSymbol(int[] tableGroup, int tableIdx, State s) {
int offset = tableGroup[tableIdx]; int offset = tableGroup[tableIdx];
int val = BitReader.peekBits(s); final int val = BitReader.peekBits(s);
offset += val & HUFFMAN_TABLE_MASK; offset += val & HUFFMAN_TABLE_MASK;
int bits = tableGroup[offset] >> 16; final int bits = tableGroup[offset] >> 16;
int sym = tableGroup[offset] & 0xFFFF; final int sym = tableGroup[offset] & 0xFFFF;
if (bits <= HUFFMAN_TABLE_BITS) { if (bits <= HUFFMAN_TABLE_BITS) {
s.bitOffset += bits; s.bitOffset += bits;
return sym; return sym;
} }
offset += sym; offset += sym;
int mask = (1 << bits) - 1; final int mask = (1 << bits) - 1;
offset += (val & mask) >>> HUFFMAN_TABLE_BITS; offset += (val & mask) >>> HUFFMAN_TABLE_BITS;
s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS); s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS);
return tableGroup[offset] & 0xFFFF; return tableGroup[offset] & 0xFFFF;
@ -401,14 +402,14 @@ final class Decode {
private static int readBlockLength(int[] tableGroup, int tableIdx, State s) { private static int readBlockLength(int[] tableGroup, int tableIdx, State s) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int code = readSymbol(tableGroup, tableIdx, s); final int code = readSymbol(tableGroup, tableIdx, s);
int n = BLOCK_LENGTH_N_BITS[code]; final int n = BLOCK_LENGTH_N_BITS[code];
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
return BLOCK_LENGTH_OFFSET[code] + BitReader.readBits(s, n); return BLOCK_LENGTH_OFFSET[code] + BitReader.readBits(s, n);
} }
private static void moveToFront(int[] v, int index) { private static void moveToFront(int[] v, int index) {
int value = v[index]; final int value = v[index];
for (; index > 0; index--) { for (; index > 0; index--) {
v[index] = v[index - 1]; v[index] = v[index - 1];
} }
@ -416,12 +417,12 @@ final class Decode {
} }
private static void inverseMoveToFrontTransform(byte[] v, int vLen) { private static void inverseMoveToFrontTransform(byte[] v, int vLen) {
int[] mtf = new int[256]; final int[] mtf = new int[256];
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
mtf[i] = i; mtf[i] = i;
} }
for (int i = 0; i < vLen; i++) { for (int i = 0; i < vLen; i++) {
int index = v[i] & 0xFF; final int index = v[i] & 0xFF;
v[i] = (byte) mtf[index]; v[i] = (byte) mtf[index];
if (index != 0) { if (index != 0) {
moveToFront(mtf, index); moveToFront(mtf, index);
@ -436,16 +437,16 @@ final class Decode {
int repeat = 0; int repeat = 0;
int repeatCodeLen = 0; int repeatCodeLen = 0;
int space = 32768; int space = 32768;
int[] table = new int[32 + 1]; /* Speculative single entry table group. */ final int[] table = new int[32 + 1]; /* Speculative single entry table group. */
int tableIdx = table.length - 1; final int tableIdx = table.length - 1;
Huffman.buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, CODE_LENGTH_CODES); Huffman.buildHuffmanTable(table, tableIdx, 5, codeLengthCodeLengths, CODE_LENGTH_CODES);
while (symbol < numSymbols && space > 0) { while (symbol < numSymbols && space > 0) {
BitReader.readMoreInput(s); BitReader.readMoreInput(s);
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int p = BitReader.peekBits(s) & 31; final int p = BitReader.peekBits(s) & 31;
s.bitOffset += table[p] >> 16; s.bitOffset += table[p] >> 16;
int codeLen = table[p] & 0xFFFF; final int codeLen = table[p] & 0xFFFF;
if (codeLen < CODE_LENGTH_REPEAT_CODE) { if (codeLen < CODE_LENGTH_REPEAT_CODE) {
repeat = 0; repeat = 0;
codeLengths[symbol++] = codeLen; codeLengths[symbol++] = codeLen;
@ -454,7 +455,7 @@ final class Decode {
space -= 32768 >> codeLen; space -= 32768 >> codeLen;
} }
} else { } else {
int extraBits = codeLen - 14; final int extraBits = codeLen - 14;
int newLen = 0; int newLen = 0;
if (codeLen == CODE_LENGTH_REPEAT_CODE) { if (codeLen == CODE_LENGTH_REPEAT_CODE) {
newLen = prevCodeLen; newLen = prevCodeLen;
@ -463,14 +464,14 @@ final class Decode {
repeat = 0; repeat = 0;
repeatCodeLen = newLen; repeatCodeLen = newLen;
} }
int oldRepeat = repeat; final int oldRepeat = repeat;
if (repeat > 0) { if (repeat > 0) {
repeat -= 2; repeat -= 2;
repeat <<= extraBits; repeat <<= extraBits;
} }
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
repeat += BitReader.readFewBits(s, extraBits) + 3; repeat += BitReader.readFewBits(s, extraBits) + 3;
int repeatDelta = repeat - oldRepeat; final int repeatDelta = repeat - oldRepeat;
if (symbol + repeatDelta > numSymbols) { if (symbol + repeatDelta > numSymbols) {
throw new BrotliRuntimeException("symbol + repeatDelta > numSymbols"); // COV_NF_LINE throw new BrotliRuntimeException("symbol + repeatDelta > numSymbols"); // COV_NF_LINE
} }
@ -505,15 +506,15 @@ final class Decode {
private static int readSimpleHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit, private static int readSimpleHuffmanCode(int alphabetSizeMax, int alphabetSizeLimit,
int[] tableGroup, int tableIdx, State s) { int[] tableGroup, int tableIdx, State s) {
// TODO(eustas): Avoid allocation? // TODO(eustas): Avoid allocation?
int[] codeLengths = new int[alphabetSizeLimit]; final int[] codeLengths = new int[alphabetSizeLimit];
int[] symbols = new int[4]; final int[] symbols = new int[4];
int maxBits = 1 + log2floor(alphabetSizeMax - 1); final int maxBits = 1 + log2floor(alphabetSizeMax - 1);
int numSymbols = BitReader.readFewBits(s, 2) + 1; final int numSymbols = BitReader.readFewBits(s, 2) + 1;
for (int i = 0; i < numSymbols; i++) { for (int i = 0; i < numSymbols; i++) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int symbol = BitReader.readFewBits(s, maxBits); final int symbol = BitReader.readFewBits(s, maxBits);
if (symbol >= alphabetSizeLimit) { if (symbol >= alphabetSizeLimit) {
throw new BrotliRuntimeException("Can't readHuffmanCode"); // COV_NF_LINE throw new BrotliRuntimeException("Can't readHuffmanCode"); // COV_NF_LINE
} }
@ -569,17 +570,17 @@ final class Decode {
private static int readComplexHuffmanCode(int alphabetSizeLimit, int skip, private static int readComplexHuffmanCode(int alphabetSizeLimit, int skip,
int[] tableGroup, int tableIdx, State s) { int[] tableGroup, int tableIdx, State s) {
// TODO(eustas): Avoid allocation? // TODO(eustas): Avoid allocation?
int[] codeLengths = new int[alphabetSizeLimit]; final int[] codeLengths = new int[alphabetSizeLimit];
int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES]; final int[] codeLengthCodeLengths = new int[CODE_LENGTH_CODES];
int space = 32; int space = 32;
int numCodes = 0; int numCodes = 0;
for (int i = skip; i < CODE_LENGTH_CODES && space > 0; i++) { for (int i = skip; i < CODE_LENGTH_CODES && space > 0; i++) {
int codeLenIdx = CODE_LENGTH_CODE_ORDER[i]; final int codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int p = BitReader.peekBits(s) & 15; final int p = BitReader.peekBits(s) & 15;
// TODO(eustas): Demultiplex FIXED_TABLE. // TODO(eustas): Demultiplex FIXED_TABLE.
s.bitOffset += FIXED_TABLE[p] >> 16; s.bitOffset += FIXED_TABLE[p] >> 16;
int v = FIXED_TABLE[p] & 0xFFFF; final int v = FIXED_TABLE[p] & 0xFFFF;
codeLengthCodeLengths[codeLenIdx] = v; codeLengthCodeLengths[codeLenIdx] = v;
if (v != 0) { if (v != 0) {
space -= (32 >> v); space -= (32 >> v);
@ -605,7 +606,7 @@ final class Decode {
int[] tableGroup, int tableIdx, State s) { int[] tableGroup, int tableIdx, State s) {
BitReader.readMoreInput(s); BitReader.readMoreInput(s);
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int simpleCodeOrSkip = BitReader.readFewBits(s, 2); final int simpleCodeOrSkip = BitReader.readFewBits(s, 2);
if (simpleCodeOrSkip == 1) { if (simpleCodeOrSkip == 1) {
return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s); return readSimpleHuffmanCode(alphabetSizeMax, alphabetSizeLimit, tableGroup, tableIdx, s);
} else { } else {
@ -615,7 +616,7 @@ final class Decode {
private static int decodeContextMap(int contextMapSize, byte[] contextMap, State s) { private static int decodeContextMap(int contextMapSize, byte[] contextMap, State s) {
BitReader.readMoreInput(s); BitReader.readMoreInput(s);
int numTrees = decodeVarLenUnsignedByte(s) + 1; final int numTrees = decodeVarLenUnsignedByte(s) + 1;
if (numTrees == 1) { if (numTrees == 1) {
Utils.fillBytesWithZeroes(contextMap, 0, contextMapSize); Utils.fillBytesWithZeroes(contextMap, 0, contextMapSize);
@ -623,21 +624,21 @@ final class Decode {
} }
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int useRleForZeros = BitReader.readFewBits(s, 1); final int useRleForZeros = BitReader.readFewBits(s, 1);
int maxRunLengthPrefix = 0; int maxRunLengthPrefix = 0;
if (useRleForZeros != 0) { if (useRleForZeros != 0) {
maxRunLengthPrefix = BitReader.readFewBits(s, 4) + 1; maxRunLengthPrefix = BitReader.readFewBits(s, 4) + 1;
} }
int alphabetSize = numTrees + maxRunLengthPrefix; final int alphabetSize = numTrees + maxRunLengthPrefix;
int tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5]; final int tableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSize + 31) >> 5];
/* Speculative single entry table group. */ /* Speculative single entry table group. */
int[] table = new int[tableSize + 1]; final int[] table = new int[tableSize + 1];
int tableIdx = table.length - 1; final int tableIdx = table.length - 1;
readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s); readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
for (int i = 0; i < contextMapSize; ) { for (int i = 0; i < contextMapSize; ) {
BitReader.readMoreInput(s); BitReader.readMoreInput(s);
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int code = readSymbol(table, tableIdx, s); final int code = readSymbol(table, tableIdx, s);
if (code == 0) { if (code == 0) {
contextMap[i] = 0; contextMap[i] = 0;
i++; i++;
@ -669,7 +670,7 @@ final class Decode {
final int offset = 4 + treeType * 2; final int offset = 4 + treeType * 2;
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int blockType = readSymbol(s.blockTrees, 2 * treeType, s); int blockType = readSymbol(s.blockTrees, 2 * treeType, s);
int result = readBlockLength(s.blockTrees, 2 * treeType + 1, s); final int result = readBlockLength(s.blockTrees, 2 * treeType + 1, s);
if (blockType == 1) { if (blockType == 1) {
blockType = ringBuffers[offset + 1] + 1; blockType = ringBuffers[offset + 1] + 1;
@ -688,10 +689,10 @@ final class Decode {
private static void decodeLiteralBlockSwitch(State s) { private static void decodeLiteralBlockSwitch(State s) {
s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes); s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
int literalBlockType = s.rings[5]; final int literalBlockType = s.rings[5];
s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS; s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS;
s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF; s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF;
int contextMode = s.contextModes[literalBlockType]; final int contextMode = s.contextModes[literalBlockType];
s.contextLookupOffset1 = contextMode << 9; s.contextLookupOffset1 = contextMode << 9;
s.contextLookupOffset2 = s.contextLookupOffset1 + 256; s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
} }
@ -710,7 +711,7 @@ final class Decode {
int newSize = s.maxRingBufferSize; int newSize = s.maxRingBufferSize;
if (newSize > s.expectedTotalSize) { if (newSize > s.expectedTotalSize) {
/* TODO(eustas): Handle 2GB+ cases more gracefully. */ /* TODO(eustas): Handle 2GB+ cases more gracefully. */
int minimalNewSize = s.expectedTotalSize; final int minimalNewSize = s.expectedTotalSize;
while ((newSize >> 1) > minimalNewSize) { while ((newSize >> 1) > minimalNewSize) {
newSize >>= 1; newSize >>= 1;
} }
@ -721,8 +722,8 @@ final class Decode {
if (newSize <= s.ringBufferSize) { if (newSize <= s.ringBufferSize) {
return; return;
} }
int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH; final int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH;
byte[] newBuffer = new byte[ringBufferSizeWithSlack]; final byte[] newBuffer = new byte[ringBufferSizeWithSlack];
if (s.ringBuffer.length != 0) { if (s.ringBuffer.length != 0) {
System.arraycopy(s.ringBuffer, 0, newBuffer, 0, s.ringBufferSize); System.arraycopy(s.ringBuffer, 0, newBuffer, 0, s.ringBufferSize);
} }
@ -773,12 +774,12 @@ final class Decode {
return 1 << 28; return 1 << 28;
} }
int blockTypeAlphabetSize = numBlockTypes + 2; final int blockTypeAlphabetSize = numBlockTypes + 2;
offset += readHuffmanCode( offset += readHuffmanCode(
blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s); blockTypeAlphabetSize, blockTypeAlphabetSize, s.blockTrees, 2 * treeType, s);
s.blockTrees[2 * treeType + 1] = offset; s.blockTrees[2 * treeType + 1] = offset;
int blockLengthAlphabetSize = NUM_BLOCK_LENGTH_CODES; final int blockLengthAlphabetSize = NUM_BLOCK_LENGTH_CODES;
offset += readHuffmanCode( offset += readHuffmanCode(
blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s); blockLengthAlphabetSize, blockLengthAlphabetSize, s.blockTrees, 2 * treeType + 1, s);
s.blockTrees[2 * treeType + 2] = offset; s.blockTrees[2 * treeType + 2] = offset;
@ -787,11 +788,11 @@ final class Decode {
} }
private static void calculateDistanceLut(State s, int alphabetSizeLimit) { private static void calculateDistanceLut(State s, int alphabetSizeLimit) {
byte[] distExtraBits = s.distExtraBits; final byte[] distExtraBits = s.distExtraBits;
int[] distOffset = s.distOffset; final int[] distOffset = s.distOffset;
int npostfix = s.distancePostfixBits; final int npostfix = s.distancePostfixBits;
int ndirect = s.numDirectDistanceCodes; final int ndirect = s.numDirectDistanceCodes;
int postfix = 1 << npostfix; final int postfix = 1 << npostfix;
int bits = 1; int bits = 1;
int half = 0; int half = 0;
@ -807,7 +808,7 @@ final class Decode {
/* Fill regular distance codes. */ /* Fill regular distance codes. */
while (i < alphabetSizeLimit) { while (i < alphabetSizeLimit) {
int base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1; final int base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
/* Always fill the complete group. */ /* Always fill the complete group. */
for (int j = 0; j < postfix; ++j) { for (int j = 0; j < postfix; ++j) {
distExtraBits[i] = (byte) bits; distExtraBits[i] = (byte) bits;
@ -835,7 +836,7 @@ final class Decode {
s.contextModes = new byte[s.numLiteralBlockTypes]; s.contextModes = new byte[s.numLiteralBlockTypes];
for (int i = 0; i < s.numLiteralBlockTypes;) { for (int i = 0; i < s.numLiteralBlockTypes;) {
/* Ensure that less than 256 bits read between readMoreInput. */ /* Ensure that less than 256 bits read between readMoreInput. */
int limit = Math.min(i + 96, s.numLiteralBlockTypes); final int limit = Math.min(i + 96, s.numLiteralBlockTypes);
for (; i < limit; ++i) { for (; i < limit; ++i) {
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
s.contextModes[i] = (byte) BitReader.readFewBits(s, 2); s.contextModes[i] = (byte) BitReader.readFewBits(s, 2);
@ -845,7 +846,7 @@ final class Decode {
// TODO(eustas): Reuse? // TODO(eustas): Reuse?
s.contextMap = new byte[s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS]; s.contextMap = new byte[s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS];
int numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS, final int numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS,
s.contextMap, s); s.contextMap, s);
s.trivialLiteralContext = 1; s.trivialLiteralContext = 1;
for (int j = 0; j < s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS; j++) { for (int j = 0; j < s.numLiteralBlockTypes << LITERAL_CONTEXT_BITS; j++) {
@ -857,7 +858,7 @@ final class Decode {
// TODO(eustas): Reuse? // TODO(eustas): Reuse?
s.distContextMap = new byte[s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS]; s.distContextMap = new byte[s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS];
int numDistTrees = decodeContextMap(s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS, final int numDistTrees = decodeContextMap(s.numDistanceBlockTypes << DISTANCE_CONTEXT_BITS,
s.distContextMap, s); s.distContextMap, s);
s.literalTreeGroup = decodeHuffmanTreeGroup(NUM_LITERAL_CODES, NUM_LITERAL_CODES, s.literalTreeGroup = decodeHuffmanTreeGroup(NUM_LITERAL_CODES, NUM_LITERAL_CODES,
@ -902,7 +903,7 @@ final class Decode {
return; return;
} }
int chunkLength = Math.min(s.ringBufferSize - s.pos, s.metaBlockLength); final int chunkLength = Math.min(s.ringBufferSize - s.pos, s.metaBlockLength);
BitReader.copyRawBytes(s, ringBuffer, s.pos, chunkLength); BitReader.copyRawBytes(s, ringBuffer, s.pos, chunkLength);
s.metaBlockLength -= chunkLength; s.metaBlockLength -= chunkLength;
s.pos += chunkLength; s.pos += chunkLength;
@ -917,7 +918,7 @@ final class Decode {
} }
private static int writeRingBuffer(State s) { private static int writeRingBuffer(State s) {
int toWrite = Math.min(s.outputLength - s.outputUsed, final int toWrite = Math.min(s.outputLength - s.outputUsed,
s.ringBufferBytesReady - s.ringBufferBytesWritten); s.ringBufferBytesReady - s.ringBufferBytesWritten);
// TODO(eustas): DCHECK(toWrite >= 0) // TODO(eustas): DCHECK(toWrite >= 0)
if (toWrite != 0) { if (toWrite != 0) {
@ -936,8 +937,8 @@ final class Decode {
private static int[] decodeHuffmanTreeGroup(int alphabetSizeMax, int alphabetSizeLimit, private static int[] decodeHuffmanTreeGroup(int alphabetSizeMax, int alphabetSizeLimit,
int n, State s) { int n, State s) {
int maxTableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSizeLimit + 31) >> 5]; final int maxTableSize = MAX_HUFFMAN_TABLE_SIZE[(alphabetSizeLimit + 31) >> 5];
int[] group = new int[n + n * maxTableSize]; final int[] group = new int[n + n * maxTableSize];
int next = n; int next = n;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
group[i] = next; group[i] = next;
@ -959,31 +960,31 @@ final class Decode {
if (s.distance > MAX_ALLOWED_DISTANCE) { if (s.distance > MAX_ALLOWED_DISTANCE) {
throw new BrotliRuntimeException("Invalid backward reference"); throw new BrotliRuntimeException("Invalid backward reference");
} }
int address = s.distance - s.maxDistance - 1 - s.cdTotalSize; final int address = s.distance - s.maxDistance - 1 - s.cdTotalSize;
if (address < 0) { if (address < 0) {
initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength); initializeCompoundDictionaryCopy(s, -address - 1, s.copyLength);
s.runningState = COPY_FROM_COMPOUND_DICTIONARY; s.runningState = COPY_FROM_COMPOUND_DICTIONARY;
} else { } else {
// Force lazy dictionary initialization. // Force lazy dictionary initialization.
ByteBuffer dictionaryData = Dictionary.getData(); final ByteBuffer dictionaryData = Dictionary.getData();
int wordLength = s.copyLength; final int wordLength = s.copyLength;
if (wordLength > Dictionary.MAX_DICTIONARY_WORD_LENGTH) { if (wordLength > Dictionary.MAX_DICTIONARY_WORD_LENGTH) {
throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
} }
int shift = Dictionary.sizeBits[wordLength]; final int shift = Dictionary.sizeBits[wordLength];
if (shift == 0) { if (shift == 0) {
throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
} }
int offset = Dictionary.offsets[wordLength]; int offset = Dictionary.offsets[wordLength];
int mask = (1 << shift) - 1; final int mask = (1 << shift) - 1;
int wordIdx = address & mask; final int wordIdx = address & mask;
int transformIdx = address >>> shift; final int transformIdx = address >>> shift;
offset += wordIdx * wordLength; offset += wordIdx * wordLength;
Transform.Transforms transforms = Transform.RFC_TRANSFORMS; final Transform.Transforms transforms = Transform.RFC_TRANSFORMS;
if (transformIdx >= transforms.numTransforms) { if (transformIdx >= transforms.numTransforms) {
throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE throw new BrotliRuntimeException("Invalid backward reference"); // COV_NF_LINE
} }
int len = Transform.transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData, final int len = Transform.transformDictionaryWord(s.ringBuffer, s.pos, dictionaryData,
offset, wordLength, transforms, transformIdx); offset, wordLength, transforms, transformIdx);
s.pos += len; s.pos += len;
s.metaBlockLength -= len; s.metaBlockLength -= len;
@ -1039,11 +1040,11 @@ final class Decode {
private static int copyFromCompoundDictionary(State s, int fence) { private static int copyFromCompoundDictionary(State s, int fence) {
int pos = s.pos; int pos = s.pos;
int origPos = pos; final int origPos = pos;
while (s.cdBrLength != s.cdBrCopied) { while (s.cdBrLength != s.cdBrCopied) {
int space = fence - pos; final int space = fence - pos;
int chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex]; final int chunkLength = s.cdChunkOffsets[s.cdBrIndex + 1] - s.cdChunkOffsets[s.cdBrIndex];
int remChunkLength = chunkLength - s.cdBrOffset; final int remChunkLength = chunkLength - s.cdBrOffset;
int length = s.cdBrLength - s.cdBrCopied; int length = s.cdBrLength - s.cdBrCopied;
if (length > remChunkLength) { if (length > remChunkLength) {
length = remChunkLength; length = remChunkLength;
@ -1078,7 +1079,7 @@ final class Decode {
throw new IllegalStateException("Can't decompress after close"); throw new IllegalStateException("Can't decompress after close");
} }
if (s.runningState == INITIALIZED) { if (s.runningState == INITIALIZED) {
int windowBits = decodeWindowBits(s); final int windowBits = decodeWindowBits(s);
if (windowBits == -1) { /* Reserved case for future expansion. */ if (windowBits == -1) { /* Reserved case for future expansion. */
throw new BrotliRuntimeException("Invalid 'windowBits' code"); throw new BrotliRuntimeException("Invalid 'windowBits' code");
} }
@ -1121,19 +1122,19 @@ final class Decode {
} }
s.commandBlockLength--; s.commandBlockLength--;
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2; final int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
short insertAndCopyExtraBits = CMD_LOOKUP[cmdCode]; final short insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
int insertLengthOffset = CMD_LOOKUP[cmdCode + 1]; final int insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
int copyLengthOffset = CMD_LOOKUP[cmdCode + 2]; final int copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
s.distanceCode = CMD_LOOKUP[cmdCode + 3]; s.distanceCode = CMD_LOOKUP[cmdCode + 3];
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
{ {
int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF; final int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF;
s.insertLength = insertLengthOffset + BitReader.readBits(s, insertLengthExtraBits); s.insertLength = insertLengthOffset + BitReader.readBits(s, insertLengthExtraBits);
} }
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
{ {
int copyLengthExtraBits = insertAndCopyExtraBits >> 8; final int copyLengthExtraBits = insertAndCopyExtraBits >> 8;
s.copyLength = copyLengthOffset + BitReader.readBits(s, copyLengthExtraBits); s.copyLength = copyLengthOffset + BitReader.readBits(s, copyLengthExtraBits);
} }
@ -1167,9 +1168,9 @@ final class Decode {
if (s.literalBlockLength == 0) { if (s.literalBlockLength == 0) {
decodeLiteralBlockSwitch(s); decodeLiteralBlockSwitch(s);
} }
int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1] final int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1]
| Context.LOOKUP[s.contextLookupOffset2 + prevByte2]; | Context.LOOKUP[s.contextLookupOffset2 + prevByte2];
int literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 0xFF; final int literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
s.literalBlockLength--; s.literalBlockLength--;
prevByte2 = prevByte1; prevByte2 = prevByte1;
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
@ -1203,16 +1204,17 @@ final class Decode {
} }
s.distanceBlockLength--; s.distanceBlockLength--;
BitReader.fillBitWindow(s); BitReader.fillBitWindow(s);
int distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF; final int distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s); distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
if (distanceCode < NUM_DISTANCE_SHORT_CODES) { if (distanceCode < NUM_DISTANCE_SHORT_CODES) {
int index = (s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode]) & 0x3; final int index =
(s.distRbIdx + DISTANCE_SHORT_CODE_INDEX_OFFSET[distanceCode]) & 0x3;
s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode]; s.distance = s.rings[index] + DISTANCE_SHORT_CODE_VALUE_OFFSET[distanceCode];
if (s.distance < 0) { if (s.distance < 0) {
throw new BrotliRuntimeException("Negative distance"); // COV_NF_LINE throw new BrotliRuntimeException("Negative distance"); // COV_NF_LINE
} }
} else { } else {
int extraBits = s.distExtraBits[distanceCode]; final int extraBits = s.distExtraBits[distanceCode];
int bits; int bits;
if (s.bitOffset + extraBits <= BitReader.BITNESS) { if (s.bitOffset + extraBits <= BitReader.BITNESS) {
bits = BitReader.readFewBits(s, extraBits); bits = BitReader.readFewBits(s, extraBits);
@ -1250,9 +1252,9 @@ final class Decode {
case COPY_LOOP: case COPY_LOOP:
int src = (s.pos - s.distance) & ringBufferMask; int src = (s.pos - s.distance) & ringBufferMask;
int dst = s.pos; int dst = s.pos;
int copyLength = s.copyLength - s.j; final int copyLength = s.copyLength - s.j;
int srcEnd = src + copyLength; final int srcEnd = src + copyLength;
int dstEnd = dst + copyLength; final int dstEnd = dst + copyLength;
if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) { if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) { if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
for (int k = 0; k < copyLength; k += 4) { for (int k = 0; k < copyLength; k += 4) {
@ -1339,7 +1341,7 @@ final class Decode {
continue; continue;
default: default:
throw new BrotliRuntimeException("Unexpected state " + s.runningState); throw new BrotliRuntimeException("Unexpected state " + String.valueOf(s.runningState));
} }
} }
if (s.runningState == FINISHED) { if (s.runningState == FINISHED) {

View File

@ -21,7 +21,7 @@ public final class Dictionary {
static final int MIN_DICTIONARY_WORD_LENGTH = 4; static final int MIN_DICTIONARY_WORD_LENGTH = 4;
static final int MAX_DICTIONARY_WORD_LENGTH = 31; static final int MAX_DICTIONARY_WORD_LENGTH = 31;
private static ByteBuffer data = null; private static ByteBuffer data = ByteBuffer.allocateDirect(0);
static final int[] offsets = new int[32]; static final int[] offsets = new int[32];
static final int[] sizeBits = new int[32]; static final int[] sizeBits = new int[32];
@ -46,21 +46,22 @@ public final class Dictionary {
// TODO: is that so? // TODO: is that so?
if (newSizeBits.length > MAX_DICTIONARY_WORD_LENGTH) { if (newSizeBits.length > MAX_DICTIONARY_WORD_LENGTH) {
throw new BrotliRuntimeException( throw new BrotliRuntimeException(
"sizeBits length must be at most " + MAX_DICTIONARY_WORD_LENGTH); "sizeBits length must be at most " + String.valueOf(MAX_DICTIONARY_WORD_LENGTH));
} }
for (int i = 0; i < MIN_DICTIONARY_WORD_LENGTH; ++i) { for (int i = 0; i < MIN_DICTIONARY_WORD_LENGTH; ++i) {
if (newSizeBits[i] != 0) { if (newSizeBits[i] != 0) {
throw new BrotliRuntimeException("first " + MIN_DICTIONARY_WORD_LENGTH + " must be 0"); throw new BrotliRuntimeException(
"first " + String.valueOf(MIN_DICTIONARY_WORD_LENGTH) + " must be 0");
} }
} }
int[] dictionaryOffsets = Dictionary.offsets; final int[] dictionaryOffsets = Dictionary.offsets;
int[] dictionarySizeBits = Dictionary.sizeBits; final int[] dictionarySizeBits = Dictionary.sizeBits;
System.arraycopy(newSizeBits, 0, dictionarySizeBits, 0, newSizeBits.length); System.arraycopy(newSizeBits, 0, dictionarySizeBits, 0, newSizeBits.length);
int pos = 0; int pos = 0;
int limit = newData.capacity(); final int limit = newData.capacity();
for (int i = 0; i < newSizeBits.length; ++i) { for (int i = 0; i < newSizeBits.length; ++i) {
dictionaryOffsets[i] = pos; dictionaryOffsets[i] = pos;
int bits = dictionarySizeBits[i]; final int bits = dictionarySizeBits[i];
if (bits != 0) { if (bits != 0) {
if (bits >= 31) { if (bits >= 31) {
throw new BrotliRuntimeException("newSizeBits values must be less than 31"); throw new BrotliRuntimeException("newSizeBits values must be less than 31");
@ -81,7 +82,7 @@ public final class Dictionary {
} }
public static ByteBuffer getData() { public static ByteBuffer getData() {
if (data != null) { if (data.capacity() != 0) {
return data; return data;
} }
if (!DataLoader.OK) { if (!DataLoader.OK) {

View File

@ -36,17 +36,17 @@ final class DictionaryData {
private static void unpackDictionaryData(ByteBuffer dictionary, String data0, String data1, private static void unpackDictionaryData(ByteBuffer dictionary, String data0, String data1,
String skipFlip, int[] sizeBits, String sizeBitsData) { String skipFlip, int[] sizeBits, String sizeBitsData) {
// Initialize lower 7 bits of every byte in the dictionary. // Initialize lower 7 bits of every byte in the dictionary.
byte[] dict = Utils.toUsAsciiBytes(data0 + data1); final byte[] dict = Utils.toUsAsciiBytes(data0 + data1);
if (dict.length != dictionary.capacity()) { if (dict.length != dictionary.capacity()) {
throw new RuntimeException("Corrupted brotli dictionary"); throw new RuntimeException("Corrupted brotli dictionary");
} }
// Toggle high bit using run-length delta encoded "skipFlip". // Toggle high bit using run-length delta encoded "skipFlip".
int offset = 0; int offset = 0;
int n = skipFlip.length(); final int n = skipFlip.length();
for (int i = 0; i < n; i += 2) { for (int i = 0; i < n; i += 2) {
int skip = skipFlip.charAt(i) - 36; final int skip = skipFlip.charAt(i) - 36;
int flip = skipFlip.charAt(i + 1) - 36; final int flip = skipFlip.charAt(i + 1) - 36;
for (int j = 0; j < skip; ++j) { for (int j = 0; j < skip; ++j) {
dict[offset] ^= 3; dict[offset] ^= 3;
offset++; offset++;
@ -65,8 +65,8 @@ final class DictionaryData {
} }
static { static {
ByteBuffer dictionaryData = ByteBuffer.allocateDirect(122784); final ByteBuffer dictionaryData = ByteBuffer.allocateDirect(122784);
int[] dictionarySizeBits = new int[25]; final int[] dictionarySizeBits = new int[25];
unpackDictionaryData( unpackDictionaryData(
dictionaryData, DATA0, DATA1, SKIP_FLIP, dictionarySizeBits, SIZE_BITS_DATA); dictionaryData, DATA0, DATA1, SKIP_FLIP, dictionarySizeBits, SIZE_BITS_DATA);
Utils.flipBuffer(dictionaryData); Utils.flipBuffer(dictionaryData);

View File

@ -63,12 +63,12 @@ final class Huffman {
*/ */
static int buildHuffmanTable(int[] tableGroup, int tableIdx, int rootBits, int[] codeLengths, static int buildHuffmanTable(int[] tableGroup, int tableIdx, int rootBits, int[] codeLengths,
int codeLengthsSize) { int codeLengthsSize) {
int tableOffset = tableGroup[tableIdx]; final int tableOffset = tableGroup[tableIdx];
int key; // Reversed prefix code. int key; // Reversed prefix code.
int[] sorted = new int[codeLengthsSize]; // Symbols sorted by code length. final int[] sorted = new int[codeLengthsSize]; // Symbols sorted by code length.
// TODO(eustas): fill with zeroes? // TODO(eustas): fill with zeroes?
int[] count = new int[MAX_LENGTH + 1]; // Number of codes of each length. final int[] count = new int[MAX_LENGTH + 1]; // Number of codes of each length.
int[] offset = new int[MAX_LENGTH + 1]; // Offsets in sorted table for each length. final int[] offset = new int[MAX_LENGTH + 1]; // Offsets in sorted table for each length.
int symbol; int symbol;
// Build histogram of code lengths. // Build histogram of code lengths.
@ -113,7 +113,7 @@ final class Huffman {
} }
// Fill in 2nd level tables and add pointers to root table. // Fill in 2nd level tables and add pointers to root table.
int mask = totalSize - 1; final int mask = totalSize - 1;
int low = -1; int low = -1;
int currentOffset = tableOffset; int currentOffset = tableOffset;
for (int len = rootBits + 1, step = 2; len <= MAX_LENGTH; len++, step <<= 1) { for (int len = rootBits + 1, step = 2; len <= MAX_LENGTH; len++, step <<= 1) {

View File

@ -76,11 +76,11 @@ final class Transform {
private static void unpackTransforms(byte[] prefixSuffix, private static void unpackTransforms(byte[] prefixSuffix,
int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) { int[] prefixSuffixHeads, int[] transforms, String prefixSuffixSrc, String transformsSrc) {
int n = prefixSuffixSrc.length(); final int n = prefixSuffixSrc.length();
int index = 1; int index = 1;
int j = 0; int j = 0;
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) {
char c = prefixSuffixSrc.charAt(i); final char c = prefixSuffixSrc.charAt(i);
if (c == 35) { // == # if (c == 35) { // == #
prefixSuffixHeads[index++] = j; prefixSuffixHeads[index++] = j;
} else { } else {
@ -101,17 +101,17 @@ final class Transform {
static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset, static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset,
int len, Transforms transforms, int transformIndex) { int len, Transforms transforms, int transformIndex) {
int offset = dstOffset; int offset = dstOffset;
int[] triplets = transforms.triplets; final int[] triplets = transforms.triplets;
byte[] prefixSuffixStorage = transforms.prefixSuffixStorage; final byte[] prefixSuffixStorage = transforms.prefixSuffixStorage;
int[] prefixSuffixHeads = transforms.prefixSuffixHeads; final int[] prefixSuffixHeads = transforms.prefixSuffixHeads;
int transformOffset = 3 * transformIndex; final int transformOffset = 3 * transformIndex;
int prefixIdx = triplets[transformOffset]; final int prefixIdx = triplets[transformOffset];
int transformType = triplets[transformOffset + 1]; final int transformType = triplets[transformOffset + 1];
int suffixIdx = triplets[transformOffset + 2]; final int suffixIdx = triplets[transformOffset + 2];
int prefix = prefixSuffixHeads[prefixIdx]; int prefix = prefixSuffixHeads[prefixIdx];
int prefixEnd = prefixSuffixHeads[prefixIdx + 1]; final int prefixEnd = prefixSuffixHeads[prefixIdx + 1];
int suffix = prefixSuffixHeads[suffixIdx]; int suffix = prefixSuffixHeads[suffixIdx];
int suffixEnd = prefixSuffixHeads[suffixIdx + 1]; final int suffixEnd = prefixSuffixHeads[suffixIdx + 1];
int omitFirst = transformType - OMIT_FIRST_BASE; int omitFirst = transformType - OMIT_FIRST_BASE;
int omitLast = transformType - OMIT_LAST_BASE; int omitLast = transformType - OMIT_LAST_BASE;
@ -147,7 +147,7 @@ final class Transform {
len = 1; len = 1;
} }
while (len > 0) { while (len > 0) {
int c0 = dst[uppercaseOffset] & 0xFF; final int c0 = dst[uppercaseOffset] & 0xFF;
if (c0 < 0xC0) { if (c0 < 0xC0) {
if (c0 >= 97 && c0 <= 122) { // in [a..z] range if (c0 >= 97 && c0 <= 122) { // in [a..z] range
dst[uppercaseOffset] ^= (byte) 32; dst[uppercaseOffset] ^= (byte) 32;
@ -166,12 +166,12 @@ final class Transform {
} }
} else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) { } else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) {
int shiftOffset = offset - len; int shiftOffset = offset - len;
short param = transforms.params[transformIndex]; final short param = transforms.params[transformIndex];
/* Limited sign extension: scalar < (1 << 24). */ /* Limited sign extension: scalar < (1 << 24). */
int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000)); int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000));
while (len > 0) { while (len > 0) {
int step = 1; int step = 1;
int c0 = dst[shiftOffset] & 0xFF; final int c0 = dst[shiftOffset] & 0xFF;
if (c0 < 0x80) { if (c0 < 0x80) {
/* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */ /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
scalar += c0; scalar += c0;
@ -181,7 +181,7 @@ final class Transform {
} else if (c0 < 0xE0) { } else if (c0 < 0xE0) {
/* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */ /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
if (len >= 2) { if (len >= 2) {
byte c1 = dst[shiftOffset + 1]; final byte c1 = dst[shiftOffset + 1];
scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6); scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
dst[shiftOffset] = (byte) (0xC0 | ((scalar >> 6) & 0x1F)); dst[shiftOffset] = (byte) (0xC0 | ((scalar >> 6) & 0x1F));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | (scalar & 0x3F)); dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | (scalar & 0x3F));
@ -192,8 +192,8 @@ final class Transform {
} else if (c0 < 0xF0) { } else if (c0 < 0xF0) {
/* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */ /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
if (len >= 3) { if (len >= 3) {
byte c1 = dst[shiftOffset + 1]; final byte c1 = dst[shiftOffset + 1];
byte c2 = dst[shiftOffset + 2]; final byte c2 = dst[shiftOffset + 2];
scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12); scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
dst[shiftOffset] = (byte) (0xE0 | ((scalar >> 12) & 0x0F)); dst[shiftOffset] = (byte) (0xE0 | ((scalar >> 12) & 0x0F));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 6) & 0x3F)); dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
@ -205,9 +205,9 @@ final class Transform {
} else if (c0 < 0xF8) { } else if (c0 < 0xF8) {
/* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */ /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
if (len >= 4) { if (len >= 4) {
byte c1 = dst[shiftOffset + 1]; final byte c1 = dst[shiftOffset + 1];
byte c2 = dst[shiftOffset + 2]; final byte c2 = dst[shiftOffset + 2];
byte c3 = dst[shiftOffset + 3]; final byte c3 = dst[shiftOffset + 3];
scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18); scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
dst[shiftOffset] = (byte) (0xF0 | ((scalar >> 18) & 0x07)); dst[shiftOffset] = (byte) (0xF0 | ((scalar >> 18) & 0x07));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 12) & 0x3F)); dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));

File diff suppressed because one or more lines are too long

2
js/decode.min.js vendored

File diff suppressed because one or more lines are too long