mirror of
https://github.com/google/brotli.git
synced 2024-11-21 19:20:09 +00:00
JS: stronger typing
PiperOrigin-RevId: 526909255
This commit is contained in:
parent
e1f5788fb0
commit
ffbe112328
@ -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));
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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));
|
||||||
|
463
js/decode.js
463
js/decode.js
File diff suppressed because one or more lines are too long
2
js/decode.min.js
vendored
2
js/decode.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user