further preparations for Kotlin transpilation

PiperOrigin-RevId: 603638823
This commit is contained in:
Evgenii Kliuchnikov 2024-02-02 03:26:05 -08:00 committed by Copybara-Service
parent 200f37984a
commit c1362a7903
11 changed files with 391 additions and 335 deletions

View File

@ -146,9 +146,9 @@ final class BitReader {
* otherwise BitReader will become broken.
*/
static int readFewBits(State s, int n) {
final int val = peekBits(s) & ((1 << n) - 1);
final int v = peekBits(s) & ((1 << n) - 1);
s.bitOffset += n;
return val;
return v;
}
static int readBits(State s, int n) {
@ -212,31 +212,33 @@ final class BitReader {
}
static void copyRawBytes(State s, byte[] data, int offset, int length) {
int pos = offset;
int len = length;
if ((s.bitOffset & 7) != 0) {
throw new BrotliRuntimeException("Unaligned copyBytes");
}
// Drain accumulator.
while ((s.bitOffset != BITNESS) && (length != 0)) {
data[offset++] = (byte) peekBits(s);
while ((s.bitOffset != BITNESS) && (len != 0)) {
data[pos++] = (byte) peekBits(s);
s.bitOffset += 8;
length--;
len--;
}
if (length == 0) {
if (len == 0) {
return;
}
// Get data from shadow buffer with "sizeof(int)" granularity.
final int copyNibbles = Math.min(halfAvailable(s), length >> LOG_HALF_SIZE);
final int copyNibbles = Math.min(halfAvailable(s), len >> LOG_HALF_SIZE);
if (copyNibbles > 0) {
final int readOffset = s.halfOffset << LOG_HALF_SIZE;
final int delta = copyNibbles << LOG_HALF_SIZE;
System.arraycopy(s.byteBuffer, readOffset, data, offset, delta);
offset += delta;
length -= delta;
System.arraycopy(s.byteBuffer, readOffset, data, pos, delta);
pos += delta;
len -= delta;
s.halfOffset += copyNibbles;
}
if (length == 0) {
if (len == 0) {
return;
}
@ -244,23 +246,23 @@ final class BitReader {
if (halfAvailable(s) > 0) {
// length = 1..3
fillBitWindow(s);
while (length != 0) {
data[offset++] = (byte) peekBits(s);
while (len != 0) {
data[pos++] = (byte) peekBits(s);
s.bitOffset += 8;
length--;
len--;
}
checkHealth(s, 0);
return;
}
// Now it is possible to copy bytes directly.
while (length > 0) {
final int len = Utils.readInput(s, data, offset, length);
if (len == -1) {
while (len > 0) {
final int chunkLen = Utils.readInput(s, data, pos, len);
if (chunkLen == -1) {
throw new BrotliRuntimeException("Unexpected end of input");
}
offset += len;
length -= len;
pos += chunkLen;
len -= chunkLen;
}
}
@ -273,16 +275,16 @@ final class BitReader {
if (BITNESS == 64) {
final int[] intBuffer = s.intBuffer;
for (int i = 0; i < halfLen; ++i) {
intBuffer[i] = ((byteBuffer[i * 4] & 0xFF))
| ((byteBuffer[(i * 4) + 1] & 0xFF) << 8)
| ((byteBuffer[(i * 4) + 2] & 0xFF) << 16)
| ((byteBuffer[(i * 4) + 3] & 0xFF) << 24);
intBuffer[i] = ((int) byteBuffer[i * 4] & 0xFF)
| (((int) byteBuffer[(i * 4) + 1] & 0xFF) << 8)
| (((int) byteBuffer[(i * 4) + 2] & 0xFF) << 16)
| (((int) byteBuffer[(i * 4) + 3] & 0xFF) << 24);
}
} else {
final short[] shortBuffer = s.shortBuffer;
for (int i = 0; i < halfLen; ++i) {
shortBuffer[i] = (short) ((byteBuffer[i * 2] & 0xFF)
| ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));
shortBuffer[i] = (short) (((int) byteBuffer[i * 2] & 0xFF)
| (((int) byteBuffer[(i * 2) + 1] & 0xFF) << 8));
}
}
}

View File

@ -26,7 +26,7 @@ final class Context {
}
// UTF8
for (int i = 0; i < 128; ++i) {
lookup[1024 + i] = 4 * (map.charAt(i) - 32);
lookup[1024 + i] = 4 * ((int) map.charAt(i) - 32);
}
for (int i = 0; i < 64; ++i) {
lookup[1152 + i] = i & 1;
@ -35,7 +35,7 @@ final class Context {
int offset = 1280;
for (int k = 0; k < 19; ++k) {
final int value = k & 3;
final int rep = rle.charAt(k) - 32;
final int rep = (int) rle.charAt(k) - 32;
for (int i = 0; i < rep; ++i) {
lookup[offset++] = value;
}

View File

@ -137,14 +137,16 @@ final class Decode {
private static int log2floor(int i) {
int result = -1;
int step = 16;
int v = i;
while (step > 0) {
if ((i >>> step) != 0) {
int next = v >>> step;
if (next != 0) {
result += step;
i = i >>> step;
v = next;
}
step = step >> 1;
}
return result + i;
return result + v;
}
private static int calculateDistanceAlphabetSize(int npostfix, int ndirect, int maxndistbits) {
@ -164,14 +166,12 @@ final class Decode {
}
private static void unpackCommandLookupTable(short[] cmdLookup) {
final short[] insertLengthOffsets = new short[24];
final short[] copyLengthOffsets = new short[24];
final int[] insertLengthOffsets = new int[24];
final int[] copyLengthOffsets = new int[24];
copyLengthOffsets[0] = 2;
for (int i = 0; i < 23; ++i) {
insertLengthOffsets[i + 1] =
(short) (insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]));
copyLengthOffsets[i + 1] =
(short) (copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]));
insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << (int) INSERT_LENGTH_N_BITS[i]);
copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << (int) COPY_LENGTH_N_BITS[i]);
}
for (int cmdCode = 0; cmdCode < NUM_COMMAND_CODES; ++cmdCode) {
@ -184,14 +184,15 @@ final class Decode {
}
final int insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
final int copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
final short copyLengthOffset = copyLengthOffsets[copyCode];
final int copyLengthOffset = copyLengthOffsets[copyCode];
final int distanceContext =
distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
distanceContextOffset + (copyLengthOffset > 4 ? 3 : (copyLengthOffset - 2));
final int index = cmdCode * 4;
cmdLookup[index + 0] =
(short) (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
cmdLookup[index + 1] = insertLengthOffsets[insertCode];
cmdLookup[index + 2] = copyLengthOffsets[copyCode];
(short)
((int) INSERT_LENGTH_N_BITS[insertCode] | ((int) COPY_LENGTH_N_BITS[copyCode] << 8));
cmdLookup[index + 1] = (short) insertLengthOffsets[insertCode];
cmdLookup[index + 2] = (short) copyLengthOffsets[copyCode];
cmdLookup[index + 3] = (short) distanceContext;
}
}
@ -357,7 +358,7 @@ final class Decode {
if (bits == 0 && i + 1 == sizeBytes && sizeBytes > 1) {
throw new BrotliRuntimeException("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 8);
s.metaBlockLength += bits << (i * 8);
}
} else {
for (int i = 0; i < sizeNibbles; ++i) {
@ -366,7 +367,7 @@ final class Decode {
if (bits == 0 && i + 1 == sizeNibbles && sizeNibbles > 4) {
throw new BrotliRuntimeException("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 4);
s.metaBlockLength += bits << (i * 4);
}
}
s.metaBlockLength++;
@ -380,8 +381,8 @@ final class Decode {
*/
private static int readSymbol(int[] tableGroup, int tableIdx, State s) {
int offset = tableGroup[tableIdx];
final int val = BitReader.peekBits(s);
offset += val & HUFFMAN_TABLE_MASK;
final int v = BitReader.peekBits(s);
offset += v & HUFFMAN_TABLE_MASK;
final int bits = tableGroup[offset] >> 16;
final int sym = tableGroup[offset] & 0xFFFF;
if (bits <= HUFFMAN_TABLE_BITS) {
@ -390,7 +391,7 @@ final class Decode {
}
offset += sym;
final int mask = (1 << bits) - 1;
offset += (val & mask) >>> HUFFMAN_TABLE_BITS;
offset += (v & mask) >>> HUFFMAN_TABLE_BITS;
s.bitOffset += ((tableGroup[offset] >> 16) + HUFFMAN_TABLE_BITS);
return tableGroup[offset] & 0xFFFF;
}
@ -404,10 +405,11 @@ final class Decode {
}
private static void moveToFront(int[] v, int index) {
final int value = v[index];
while (index > 0) {
v[index] = v[index - 1];
index--;
int i = index;
final int value = v[i];
while (i > 0) {
v[i] = v[i - 1];
i--;
}
v[0] = value;
}
@ -418,7 +420,7 @@ final class Decode {
mtf[i] = i;
}
for (int i = 0; i < vLen; ++i) {
final int index = v[i] & 0xFF;
final int index = (int) v[i] & 0xFF;
v[i] = (byte) mtf[index];
if (index != 0) {
moveToFront(mtf, index);
@ -463,7 +465,7 @@ final class Decode {
final int oldRepeat = repeat;
if (repeat > 0) {
repeat -= 2;
repeat <<= extraBits;
repeat = repeat << extraBits;
}
BitReader.fillBitWindow(s);
repeat += BitReader.readFewBits(s, extraBits) + 3;
@ -689,8 +691,8 @@ final class Decode {
s.literalBlockLength = decodeBlockTypeAndLength(s, 0, s.numLiteralBlockTypes);
final int literalBlockType = s.rings[5];
s.contextMapSlice = literalBlockType << LITERAL_CONTEXT_BITS;
s.literalTreeIdx = s.contextMap[s.contextMapSlice] & 0xFF;
final int contextMode = s.contextModes[literalBlockType];
s.literalTreeIdx = (int) s.contextMap[s.contextMapSlice] & 0xFF;
final int contextMode = (int) s.contextModes[literalBlockType];
s.contextLookupOffset1 = contextMode << 9;
s.contextLookupOffset2 = s.contextLookupOffset1 + 256;
}
@ -711,7 +713,7 @@ final class Decode {
/* TODO(eustas): Handle 2GB+ cases more gracefully. */
final int minimalNewSize = s.expectedTotalSize;
while ((newSize >> 1) > minimalNewSize) {
newSize >>= 1;
newSize = newSize >> 1;
}
if ((s.inputEnd == 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
newSize = 16384;
@ -722,8 +724,9 @@ final class Decode {
}
final int ringBufferSizeWithSlack = newSize + MAX_TRANSFORMED_WORD_LENGTH;
final byte[] newBuffer = new byte[ringBufferSizeWithSlack];
if (s.ringBuffer.length != 0) {
System.arraycopy(s.ringBuffer, 0, newBuffer, 0, s.ringBufferSize);
final byte[] oldBuffer = s.ringBuffer;
if (oldBuffer.length != 0) {
System.arraycopy(oldBuffer, 0, newBuffer, 0, s.ringBufferSize);
}
s.ringBuffer = newBuffer;
s.ringBufferSize = newSize;
@ -850,7 +853,7 @@ final class Decode {
final int numLiteralTrees = decodeContextMap(contextMapLength, s.contextMap, s);
s.trivialLiteralContext = 1;
for (int j = 0; j < contextMapLength; ++j) {
if (s.contextMap[j] != j >> LITERAL_CONTEXT_BITS) {
if ((int) s.contextMap[j] != j >> LITERAL_CONTEXT_BITS) {
s.trivialLiteralContext = 0;
break;
}
@ -1021,7 +1024,7 @@ final class Decode {
if (s.cdBlockBits == -1) {
initializeCompoundDictionary(s);
}
int index = s.cdBlockMap[address >>> s.cdBlockBits];
int index = (int) s.cdBlockMap[address >>> s.cdBlockBits];
while (address >= s.cdChunkOffsets[index + 1]) {
index++;
}
@ -1123,10 +1126,10 @@ final class Decode {
s.commandBlockLength--;
BitReader.fillBitWindow(s);
final int cmdCode = readSymbol(s.commandTreeGroup, s.commandTreeIdx, s) << 2;
final short insertAndCopyExtraBits = CMD_LOOKUP[cmdCode];
final int insertLengthOffset = CMD_LOOKUP[cmdCode + 1];
final int copyLengthOffset = CMD_LOOKUP[cmdCode + 2];
s.distanceCode = CMD_LOOKUP[cmdCode + 3];
final int insertAndCopyExtraBits = (int) CMD_LOOKUP[cmdCode];
final int insertLengthOffset = (int) CMD_LOOKUP[cmdCode + 1];
final int copyLengthOffset = (int) CMD_LOOKUP[cmdCode + 2];
s.distanceCode = (int) CMD_LOOKUP[cmdCode + 3];
BitReader.fillBitWindow(s);
{
final int insertLengthExtraBits = insertAndCopyExtraBits & 0xFF;
@ -1161,8 +1164,8 @@ final class Decode {
}
}
} else {
int prevByte1 = ringBuffer[(s.pos - 1) & ringBufferMask] & 0xFF;
int prevByte2 = ringBuffer[(s.pos - 2) & ringBufferMask] & 0xFF;
int prevByte1 = (int) ringBuffer[(s.pos - 1) & ringBufferMask] & 0xFF;
int prevByte2 = (int) ringBuffer[(s.pos - 2) & ringBufferMask] & 0xFF;
while (s.j < s.insertLength) {
BitReader.readMoreInput(s);
if (s.literalBlockLength == 0) {
@ -1170,7 +1173,8 @@ final class Decode {
}
final int literalContext = Context.LOOKUP[s.contextLookupOffset1 + prevByte1]
| Context.LOOKUP[s.contextLookupOffset2 + prevByte2];
final int literalTreeIdx = s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
final int literalTreeIdx =
(int) s.contextMap[s.contextMapSlice + literalContext] & 0xFF;
s.literalBlockLength--;
prevByte2 = prevByte1;
BitReader.fillBitWindow(s);
@ -1204,7 +1208,8 @@ final class Decode {
}
s.distanceBlockLength--;
BitReader.fillBitWindow(s);
final int distTreeIdx = s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
final int distTreeIdx =
(int) s.distContextMap[s.distContextMapSlice + distanceCode] & 0xFF;
distanceCode = readSymbol(s.distanceTreeGroup, distTreeIdx, s);
if (distanceCode < NUM_DISTANCE_SHORT_CODES) {
final int index =
@ -1214,7 +1219,7 @@ final class Decode {
throw new BrotliRuntimeException("Negative distance"); // COV_NF_LINE
}
} else {
final int extraBits = s.distExtraBits[distanceCode];
final int extraBits = (int) s.distExtraBits[distanceCode];
int bits;
if (s.bitOffset + extraBits <= BitReader.BITNESS) {
bits = BitReader.readFewBits(s, extraBits);
@ -1337,7 +1342,7 @@ final class Decode {
if (s.pos > s.ringBufferSize) {
Utils.copyBytesWithin(ringBuffer, 0, s.ringBufferSize, s.pos);
}
s.pos &= ringBufferMask;
s.pos = s.pos & ringBufferMask;
s.ringBufferBytesWritten = 0;
}
s.runningState = s.nextRunningState;

View File

@ -45,20 +45,20 @@ final class DictionaryData {
int offset = 0;
final int n = skipFlip.length() >> 1;
for (int i = 0; i < n; ++i) {
final int skip = skipFlip.charAt(2 * i) - 36;
final int flip = skipFlip.charAt(2 * i + 1) - 36;
final int skip = (int) skipFlip.charAt(2 * i) - 36;
final int flip = (int) skipFlip.charAt(2 * i + 1) - 36;
for (int j = 0; j < skip; ++j) {
dict[offset] ^= 3;
dict[offset] = (byte) ((int) dict[offset] ^ 3);
offset++;
}
for (int j = 0; j < flip; ++j) {
dict[offset] ^= 236;
dict[offset] = (byte) ((int) dict[offset] ^ 236);
offset++;
}
}
for (int i = 0; i < sizeBitsData.length(); ++i) {
sizeBits[i] = sizeBitsData.charAt(i) - 65;
sizeBits[i] = (int) sizeBitsData.charAt(i) - 65;
}
dictionary.put(dict);

View File

@ -21,7 +21,7 @@ final class Huffman {
private static int getNextKey(int key, int len) {
int step = 1 << (len - 1);
while ((key & step) != 0) {
step >>= 1;
step = step >> 1;
}
return (key & (step - 1)) + step;
}
@ -32,10 +32,11 @@ final class Huffman {
* <p> Assumes that end is an integer multiple of step.
*/
private static void replicateValue(int[] table, int offset, int step, int end, int item) {
int pos = end;
do {
end -= step;
table[offset + end] = item;
} while (end > 0);
pos -= step;
table[offset + pos] = item;
} while (pos > 0);
}
/**
@ -44,16 +45,17 @@ final class Huffman {
* @return table width of the next 2nd level table.
*/
private static int nextTableBitSize(int[] count, int len, int rootBits) {
int left = 1 << (len - rootBits);
while (len < MAX_LENGTH) {
left -= count[len];
int bits = len;
int left = 1 << (bits - rootBits);
while (bits < MAX_LENGTH) {
left -= count[bits];
if (left <= 0) {
break;
}
len++;
left <<= 1;
bits++;
left = left << 1;
}
return len - rootBits;
return bits - rootBits;
}
/**
@ -104,7 +106,7 @@ final class Huffman {
int symbol = 0;
int step = 1;
for (int len = 1; len <= rootBits; ++len) {
step <<= 1;
step = step << 1;
while (count[len] > 0) {
replicateValue(tableGroup, tableOffset + key, step, tableSize,
len << 16 | sorted[symbol++]);
@ -119,7 +121,7 @@ final class Huffman {
int currentOffset = tableOffset;
step = 1;
for (int len = rootBits + 1; len <= MAX_LENGTH; ++len) {
step <<= 1;
step = step << 1;
while (count[len] > 0) {
if ((key & mask) != low) {
currentOffset += tableSize;

View File

@ -87,7 +87,7 @@ final class State {
int cdBlockBits;
byte[] cdBlockMap;
InputStream /* @Nullable */ input; // BitReader
InputStream input = Utils.makeEmptyInput(); // BitReader
State() {
this.ringBuffer = new byte[0];

View File

@ -80,7 +80,7 @@ final class Transform {
int index = 1;
int j = 0;
for (int i = 0; i < n; ++i) {
final char c = prefixSuffixSrc.charAt(i);
final int c = (int) prefixSuffixSrc.charAt(i);
if (c == 35) { // == #
prefixSuffixHeads[index++] = j;
} else {
@ -89,7 +89,7 @@ final class Transform {
}
for (int i = 0; i < NUM_RFC_TRANSFORMS * 3; ++i) {
transforms[i] = transformsSrc.charAt(i) - 32;
transforms[i] = (int) transformsSrc.charAt(i) - 32;
}
}
@ -99,7 +99,7 @@ final class Transform {
}
static int transformDictionaryWord(byte[] dst, int dstOffset, ByteBuffer src, int srcOffset,
int len, Transforms transforms, int transformIndex) {
int wordLen, Transforms transforms, int transformIndex) {
int offset = dstOffset;
final int[] triplets = transforms.triplets;
final byte[] prefixSuffixStorage = transforms.prefixSuffixStorage;
@ -127,16 +127,17 @@ final class Transform {
dst[offset++] = prefixSuffixStorage[prefix++];
}
int len = wordLen;
// Copy trimmed word.
if (omitFirst > len) {
omitFirst = len;
}
srcOffset += omitFirst;
int dictOffset = srcOffset + omitFirst;
len -= omitFirst;
len -= omitLast;
int i = len;
while (i > 0) {
dst[offset++] = src.get(srcOffset++);
dst[offset++] = src.get(dictOffset++);
i--;
}
@ -147,31 +148,31 @@ final class Transform {
len = 1;
}
while (len > 0) {
final int c0 = dst[uppercaseOffset] & 0xFF;
final int c0 = (int) dst[uppercaseOffset] & 0xFF;
if (c0 < 0xC0) {
if (c0 >= 97 && c0 <= 122) { // in [a..z] range
dst[uppercaseOffset] ^= (byte) 32;
dst[uppercaseOffset] = (byte) ((int) dst[uppercaseOffset] ^ 32);
}
uppercaseOffset += 1;
len -= 1;
} else if (c0 < 0xE0) {
dst[uppercaseOffset + 1] ^= (byte) 32;
dst[uppercaseOffset + 1] = (byte) ((int) dst[uppercaseOffset + 1] ^ 32);
uppercaseOffset += 2;
len -= 2;
} else {
dst[uppercaseOffset + 2] ^= (byte) 5;
dst[uppercaseOffset + 2] = (byte) ((int) dst[uppercaseOffset + 2] ^ 5);
uppercaseOffset += 3;
len -= 3;
}
}
} else if (transformType == SHIFT_FIRST || transformType == SHIFT_ALL) {
int shiftOffset = offset - len;
final short param = transforms.params[transformIndex];
final int param = (int) transforms.params[transformIndex];
/* Limited sign extension: scalar < (1 << 24). */
int scalar = (param & 0x7FFF) + (0x1000000 - (param & 0x8000));
while (len > 0) {
int step = 1;
final int c0 = dst[shiftOffset] & 0xFF;
final int c0 = (int) dst[shiftOffset] & 0xFF;
if (c0 < 0x80) {
/* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
scalar += c0;
@ -181,7 +182,7 @@ final class Transform {
} else if (c0 < 0xE0) {
/* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
if (len >= 2) {
final byte c1 = dst[shiftOffset + 1];
final int c1 = (int) dst[shiftOffset + 1];
scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
dst[shiftOffset] = (byte) (0xC0 | ((scalar >> 6) & 0x1F));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | (scalar & 0x3F));
@ -192,8 +193,8 @@ final class Transform {
} else if (c0 < 0xF0) {
/* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
if (len >= 3) {
final byte c1 = dst[shiftOffset + 1];
final byte c2 = dst[shiftOffset + 2];
final int c1 = (int) dst[shiftOffset + 1];
final int c2 = (int) dst[shiftOffset + 2];
scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
dst[shiftOffset] = (byte) (0xE0 | ((scalar >> 12) & 0x0F));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
@ -205,9 +206,9 @@ final class Transform {
} else if (c0 < 0xF8) {
/* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
if (len >= 4) {
final byte c1 = dst[shiftOffset + 1];
final byte c2 = dst[shiftOffset + 2];
final byte c3 = dst[shiftOffset + 3];
final int c1 = (int) dst[shiftOffset + 1];
final int c2 = (int) dst[shiftOffset + 2];
final int c3 = (int) dst[shiftOffset + 3];
scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
dst[shiftOffset] = (byte) (0xF0 | ((scalar >> 18) & 0x07));
dst[shiftOffset + 1] = (byte) ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));

View File

@ -6,7 +6,9 @@
package org.brotli.dec;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
@ -74,11 +76,13 @@ final class Utils {
}
}
static InputStream makeEmptyInput() {
return new ByteArrayInputStream(new byte[0]);
}
static void closeInput(State s) throws IOException {
if (s.input != null) {
s.input.close();
s.input = null;
}
s.input.close();
s.input = makeEmptyInput();
}
static byte[] toUsAsciiBytes(String src) {

View File

@ -47,14 +47,16 @@ let makeBrotliDecode = () => {
function log2floor(i) {
let /** @type {number} */ result = -1;
let /** @type {number} */ step = 16;
let /** @type {number} */ v = i;
while (step > 0) {
if ((i >>> step) !== 0) {
let /** @type {number} */ next = v >>> step;
if (next !== 0) {
result += step;
i = i >>> step;
v = next;
}
step = step >> 1;
}
return result + i;
return result + v;
}
/**
* @param {number} npostfix
@ -85,12 +87,12 @@ let makeBrotliDecode = () => {
* @return {void}
*/
function unpackCommandLookupTable(cmdLookup) {
const /** @type {!Int16Array} */ insertLengthOffsets = new Int16Array(24);
const /** @type {!Int16Array} */ copyLengthOffsets = new Int16Array(24);
const /** @type {!Int32Array} */ insertLengthOffsets = new Int32Array(24);
const /** @type {!Int32Array} */ copyLengthOffsets = new Int32Array(24);
copyLengthOffsets[0] = 2;
for (let /** @type {number} */ i = 0; i < 23; ++i) {
insertLengthOffsets[i + 1] = (insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]));
copyLengthOffsets[i + 1] = (copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]));
insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);
copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);
}
for (let /** @type {number} */ cmdCode = 0; cmdCode < 704; ++cmdCode) {
let /** @type {number} */ rangeIdx = cmdCode >>> 6;
@ -102,9 +104,9 @@ let makeBrotliDecode = () => {
const /** @type {number} */ insertCode = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
const /** @type {number} */ copyCode = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
const /** @type {number} */ copyLengthOffset = copyLengthOffsets[copyCode];
const /** @type {number} */ distanceContext = distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
const /** @type {number} */ distanceContext = distanceContextOffset + (copyLengthOffset > 4 ? 3 : (copyLengthOffset - 2));
const /** @type {number} */ index = cmdCode * 4;
cmdLookup[index] = (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
cmdLookup[index] = INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8);
cmdLookup[index + 1] = insertLengthOffsets[insertCode];
cmdLookup[index + 2] = copyLengthOffsets[copyCode];
cmdLookup[index + 3] = distanceContext;
@ -220,7 +222,7 @@ let makeBrotliDecode = () => {
return;
}
s.runningState = 11;
s.input = null;
s.input = new InputStream(new Int8Array(0));
}
/**
* @param {!State} s
@ -267,7 +269,7 @@ let makeBrotliDecode = () => {
if (sizeBytes === 0) {
return;
}
for (let /** @type {number} */ i = 0; i < sizeBytes; i++) {
for (let /** @type {number} */ i = 0; i < sizeBytes; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -276,10 +278,10 @@ let makeBrotliDecode = () => {
if (bits === 0 && i + 1 === sizeBytes && sizeBytes > 1) {
throw new Error("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 8);
s.metaBlockLength += bits << (i * 8);
}
} else {
for (let /** @type {number} */ i = 0; i < sizeNibbles; i++) {
for (let /** @type {number} */ i = 0; i < sizeNibbles; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -288,7 +290,7 @@ let makeBrotliDecode = () => {
if (bits === 0 && i + 1 === sizeNibbles && sizeNibbles > 4) {
throw new Error("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 4);
s.metaBlockLength += bits << (i * 4);
}
}
s.metaBlockLength++;
@ -304,8 +306,8 @@ let makeBrotliDecode = () => {
*/
function readSymbol(tableGroup, tableIdx, s) {
let /** @type {number} */ offset = tableGroup[tableIdx];
const /** @type {number} */ val = (s.accumulator32 >>> s.bitOffset);
offset += val & 0xFF;
const /** @type {number} */ v = s.accumulator32 >>> s.bitOffset;
offset += v & 0xFF;
const /** @type {number} */ bits = tableGroup[offset] >> 16;
const /** @type {number} */ sym = tableGroup[offset] & 0xFFFF;
if (bits <= 8) {
@ -314,8 +316,8 @@ let makeBrotliDecode = () => {
}
offset += sym;
const /** @type {number} */ mask = (1 << bits) - 1;
offset += (val & mask) >>> 8;
s.bitOffset += ((tableGroup[offset] >> 16) + 8);
offset += (v & mask) >>> 8;
s.bitOffset += (tableGroup[offset] >> 16) + 8;
return tableGroup[offset] & 0xFFFF;
}
/**
@ -343,9 +345,11 @@ let makeBrotliDecode = () => {
* @return {void}
*/
function moveToFront(v, index) {
const /** @type {number} */ value = v[index];
for (; index > 0; index--) {
v[index] = v[index - 1];
let /** @type {number} */ i = index;
const /** @type {number} */ value = v[i];
while (i > 0) {
v[i] = v[i - 1];
i--;
}
v[0] = value;
}
@ -356,10 +360,10 @@ let makeBrotliDecode = () => {
*/
function inverseMoveToFrontTransform(v, vLen) {
const /** @type {!Int32Array} */ mtf = new Int32Array(256);
for (let /** @type {number} */ i = 0; i < 256; i++) {
for (let /** @type {number} */ i = 0; i < 256; ++i) {
mtf[i] = i;
}
for (let /** @type {number} */ i = 0; i < vLen; i++) {
for (let /** @type {number} */ i = 0; i < vLen; ++i) {
const /** @type {number} */ index = v[i] & 0xFF;
v[i] = mtf[index];
if (index !== 0) {
@ -414,7 +418,7 @@ let makeBrotliDecode = () => {
const /** @type {number} */ oldRepeat = repeat;
if (repeat > 0) {
repeat -= 2;
repeat <<= extraBits;
repeat = repeat << extraBits;
}
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
@ -425,7 +429,7 @@ let makeBrotliDecode = () => {
if (symbol + repeatDelta > numSymbols) {
throw new Error("symbol + repeatDelta > numSymbols");
}
for (let /** @type {number} */ i = 0; i < repeatDelta; i++) {
for (let /** @type {number} */ i = 0; i < repeatDelta; ++i) {
codeLengths[symbol++] = repeatCodeLen;
}
if (repeatCodeLen !== 0) {
@ -465,7 +469,7 @@ let makeBrotliDecode = () => {
const /** @type {!Int32Array} */ symbols = new Int32Array(4);
const /** @type {number} */ maxBits = 1 + log2floor(alphabetSizeMax - 1);
const /** @type {number} */ numSymbols = readFewBits(s, 2) + 1;
for (let /** @type {number} */ i = 0; i < numSymbols; i++) {
for (let /** @type {number} */ i = 0; i < numSymbols; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -524,7 +528,7 @@ let makeBrotliDecode = () => {
const /** @type {!Int32Array} */ codeLengthCodeLengths = new Int32Array(18);
let /** @type {number} */ space = 32;
let /** @type {number} */ numCodes = 0;
for (let /** @type {number} */ i = skip; i < 18 && space > 0; i++) {
for (let /** @type {number} */ i = skip; i < 18; ++i) {
const /** @type {number} */ codeLenIdx = CODE_LENGTH_CODE_ORDER[i];
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
@ -535,8 +539,10 @@ let makeBrotliDecode = () => {
const /** @type {number} */ v = FIXED_TABLE[p] & 0xFFFF;
codeLengthCodeLengths[codeLenIdx] = v;
if (v !== 0) {
space -= (32 >> v);
space -= 32 >> v;
numCodes++;
if (space <= 0)
break;
}
}
if (space !== 0 && numCodes !== 1) {
@ -597,7 +603,8 @@ let makeBrotliDecode = () => {
const /** @type {!Int32Array} */ table = new Int32Array(tableSize + 1);
const /** @type {number} */ tableIdx = table.length - 1;
readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
for (let /** @type {number} */ i = 0; i < contextMapSize; ) {
let /** @type {number} */ i = 0;
while (i < contextMapSize) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
@ -624,7 +631,7 @@ let makeBrotliDecode = () => {
reps--;
}
} else {
contextMap[i] = (code - maxRunLengthPrefix);
contextMap[i] = code - maxRunLengthPrefix;
i++;
}
}
@ -704,7 +711,7 @@ let makeBrotliDecode = () => {
if (newSize > s.expectedTotalSize) {
const /** @type {number} */ minimalNewSize = s.expectedTotalSize;
while ((newSize >> 1) > minimalNewSize) {
newSize >>= 1;
newSize = newSize >> 1;
}
if ((s.inputEnd === 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
newSize = 16384;
@ -715,8 +722,9 @@ let makeBrotliDecode = () => {
}
const /** @type {number} */ ringBufferSizeWithSlack = newSize + 37;
const /** @type {!Int8Array} */ newBuffer = new Int8Array(ringBufferSizeWithSlack);
if (s.ringBuffer.length !== 0) {
newBuffer.set(s.ringBuffer.subarray(0, s.ringBufferSize), 0);
const /** @type {!Int8Array} */ oldBuffer = s.ringBuffer;
if (oldBuffer.length !== 0) {
newBuffer.set(oldBuffer.subarray(0, s.ringBufferSize), 0);
}
s.ringBuffer = newBuffer;
s.ringBufferSize = newSize;
@ -830,23 +838,26 @@ let makeBrotliDecode = () => {
s.distancePostfixBits = readFewBits(s, 2);
s.numDirectDistanceCodes = readFewBits(s, 4) << s.distancePostfixBits;
s.contextModes = new Int8Array(s.numLiteralBlockTypes);
for (let /** @type {number} */ i = 0; i < s.numLiteralBlockTypes; ) {
let /** @type {number} */ i = 0;
while (i < s.numLiteralBlockTypes) {
const /** @type {number} */ limit = Math.min(i + 96, s.numLiteralBlockTypes);
for (; i < limit; ++i) {
while (i < limit) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
}
s.contextModes[i] = readFewBits(s, 2);
i++;
}
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
}
s.contextMap = new Int8Array(s.numLiteralBlockTypes << 6);
const /** @type {number} */ numLiteralTrees = decodeContextMap(s.numLiteralBlockTypes << 6, s.contextMap, s);
const /** @type {number} */ contextMapLength = s.numLiteralBlockTypes << 6;
s.contextMap = new Int8Array(contextMapLength);
const /** @type {number} */ numLiteralTrees = decodeContextMap(contextMapLength, s.contextMap, s);
s.trivialLiteralContext = 1;
for (let /** @type {number} */ j = 0; j < s.numLiteralBlockTypes << 6; j++) {
for (let /** @type {number} */ j = 0; j < contextMapLength; ++j) {
if (s.contextMap[j] !== j >> 6) {
s.trivialLiteralContext = 0;
break;
@ -1264,7 +1275,8 @@ let makeBrotliDecode = () => {
const /** @type {number} */ dstEnd = dst + copyLength;
if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
for (let /** @type {number} */ k = 0; k < copyLength; k += 4) {
const /** @type {number} */ numQuads = (copyLength + 3) >> 2;
for (let /** @type {number} */ k = 0; k < numQuads; ++k) {
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
@ -1277,7 +1289,7 @@ let makeBrotliDecode = () => {
s.metaBlockLength -= copyLength;
s.pos += copyLength;
} else {
for (; s.j < s.copyLength; ) {
while (s.j < s.copyLength) {
ringBuffer[s.pos] = ringBuffer[(s.pos - s.distance) & ringBufferMask];
s.metaBlockLength--;
s.pos++;
@ -1336,7 +1348,7 @@ let makeBrotliDecode = () => {
if (s.pos > s.ringBufferSize) {
ringBuffer.copyWithin(0, s.ringBufferSize, s.pos);
}
s.pos &= ringBufferMask;
s.pos = s.pos & ringBufferMask;
s.ringBufferBytesWritten = 0;
}
s.runningState = s.nextRunningState;
@ -1413,12 +1425,12 @@ let makeBrotliDecode = () => {
* @param {number} dstOffset
* @param {!Int8Array} src
* @param {number} srcOffset
* @param {number} len
* @param {number} wordLen
* @param {!Transforms} transforms
* @param {number} transformIndex
* @return {number}
*/
function transformDictionaryWord(dst, dstOffset, src, srcOffset, len, transforms, transformIndex) {
function transformDictionaryWord(dst, dstOffset, src, srcOffset, wordLen, transforms, transformIndex) {
let /** @type {number} */ offset = dstOffset;
const /** @type {!Int32Array} */ triplets = transforms.triplets;
const /** @type {!Int8Array} */ prefixSuffixStorage = transforms.prefixSuffixStorage;
@ -1442,15 +1454,16 @@ let makeBrotliDecode = () => {
while (prefix !== prefixEnd) {
dst[offset++] = prefixSuffixStorage[prefix++];
}
let /** @type {number} */ len = wordLen;
if (omitFirst > len) {
omitFirst = len;
}
srcOffset += omitFirst;
let /** @type {number} */ dictOffset = srcOffset + omitFirst;
len -= omitFirst;
len -= omitLast;
let /** @type {number} */ i = len;
while (i > 0) {
dst[offset++] = src[srcOffset++];
dst[offset++] = src[dictOffset++];
i--;
}
if (transformType === 10 || transformType === 11) {
@ -1462,16 +1475,16 @@ let makeBrotliDecode = () => {
const /** @type {number} */ c0 = dst[uppercaseOffset] & 0xFF;
if (c0 < 0xC0) {
if (c0 >= 97 && c0 <= 122) {
dst[uppercaseOffset] ^= 32;
dst[uppercaseOffset] = dst[uppercaseOffset] ^ 32;
}
uppercaseOffset += 1;
len -= 1;
} else if (c0 < 0xE0) {
dst[uppercaseOffset + 1] ^= 32;
dst[uppercaseOffset + 1] = dst[uppercaseOffset + 1] ^ 32;
uppercaseOffset += 2;
len -= 2;
} else {
dst[uppercaseOffset + 2] ^= 5;
dst[uppercaseOffset + 2] = dst[uppercaseOffset + 2] ^ 5;
uppercaseOffset += 3;
len -= 3;
}
@ -1485,14 +1498,14 @@ let makeBrotliDecode = () => {
const /** @type {number} */ c0 = dst[shiftOffset] & 0xFF;
if (c0 < 0x80) {
scalar += c0;
dst[shiftOffset] = (scalar & 0x7F);
dst[shiftOffset] = scalar & 0x7F;
} else if (c0 < 0xC0) {
} else if (c0 < 0xE0) {
if (len >= 2) {
const /** @type {number} */ c1 = dst[shiftOffset + 1];
scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
dst[shiftOffset] = (0xC0 | ((scalar >> 6) & 0x1F));
dst[shiftOffset + 1] = ((c1 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xC0 | ((scalar >> 6) & 0x1F);
dst[shiftOffset + 1] = (c1 & 0xC0) | (scalar & 0x3F);
step = 2;
} else {
step = len;
@ -1502,9 +1515,9 @@ let makeBrotliDecode = () => {
const /** @type {number} */ c1 = dst[shiftOffset + 1];
const /** @type {number} */ c2 = dst[shiftOffset + 2];
scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
dst[shiftOffset] = (0xE0 | ((scalar >> 12) & 0x0F));
dst[shiftOffset + 1] = ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
dst[shiftOffset + 2] = ((c2 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xE0 | ((scalar >> 12) & 0x0F);
dst[shiftOffset + 1] = (c1 & 0xC0) | ((scalar >> 6) & 0x3F);
dst[shiftOffset + 2] = (c2 & 0xC0) | (scalar & 0x3F);
step = 3;
} else {
step = len;
@ -1515,10 +1528,10 @@ let makeBrotliDecode = () => {
const /** @type {number} */ c2 = dst[shiftOffset + 2];
const /** @type {number} */ c3 = dst[shiftOffset + 3];
scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
dst[shiftOffset] = (0xF0 | ((scalar >> 18) & 0x07));
dst[shiftOffset + 1] = ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));
dst[shiftOffset + 2] = ((c2 & 0xC0) | ((scalar >> 6) & 0x3F));
dst[shiftOffset + 3] = ((c3 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xF0 | ((scalar >> 18) & 0x07);
dst[shiftOffset + 1] = (c1 & 0xC0) | ((scalar >> 12) & 0x3F);
dst[shiftOffset + 2] = (c2 & 0xC0) | ((scalar >> 6) & 0x3F);
dst[shiftOffset + 3] = (c3 & 0xC0) | (scalar & 0x3F);
step = 4;
} else {
step = len;
@ -1545,7 +1558,7 @@ let makeBrotliDecode = () => {
function getNextKey(key, len) {
let /** @type {number} */ step = 1 << (len - 1);
while ((key & step) !== 0) {
step >>= 1;
step = step >> 1;
}
return (key & (step - 1)) + step;
}
@ -1558,10 +1571,11 @@ let makeBrotliDecode = () => {
* @return {void}
*/
function replicateValue(table, offset, step, end, item) {
let /** @type {number} */ pos = end;
do {
end -= step;
table[offset + end] = item;
} while (end > 0);
pos -= step;
table[offset + pos] = item;
} while (pos > 0);
}
/**
* @param {!Int32Array} count
@ -1570,16 +1584,17 @@ let makeBrotliDecode = () => {
* @return {number}
*/
function nextTableBitSize(count, len, rootBits) {
let /** @type {number} */ left = 1 << (len - rootBits);
while (len < 15) {
left -= count[len];
let /** @type {number} */ bits = len;
let /** @type {number} */ left = 1 << (bits - rootBits);
while (bits < 15) {
left -= count[bits];
if (left <= 0) {
break;
}
len++;
left <<= 1;
bits++;
left = left << 1;
}
return len - rootBits;
return bits - rootBits;
}
/**
* @param {!Int32Array} tableGroup
@ -1591,45 +1606,48 @@ let makeBrotliDecode = () => {
*/
function buildHuffmanTable(tableGroup, tableIdx, rootBits, codeLengths, codeLengthsSize) {
const /** @type {number} */ tableOffset = tableGroup[tableIdx];
let /** @type {number} */ key;
const /** @type {!Int32Array} */ sorted = new Int32Array(codeLengthsSize);
const /** @type {!Int32Array} */ count = new Int32Array(16);
const /** @type {!Int32Array} */ offset = new Int32Array(16);
let /** @type {number} */ symbol;
for (symbol = 0; symbol < codeLengthsSize; symbol++) {
count[codeLengths[symbol]]++;
for (let /** @type {number} */ sym = 0; sym < codeLengthsSize; ++sym) {
count[codeLengths[sym]]++;
}
offset[1] = 0;
for (let /** @type {number} */ len = 1; len < 15; len++) {
for (let /** @type {number} */ len = 1; len < 15; ++len) {
offset[len + 1] = offset[len] + count[len];
}
for (symbol = 0; symbol < codeLengthsSize; symbol++) {
if (codeLengths[symbol] !== 0) {
sorted[offset[codeLengths[symbol]]++] = symbol;
for (let /** @type {number} */ sym = 0; sym < codeLengthsSize; ++sym) {
if (codeLengths[sym] !== 0) {
sorted[offset[codeLengths[sym]]++] = sym;
}
}
let /** @type {number} */ tableBits = rootBits;
let /** @type {number} */ tableSize = 1 << tableBits;
let /** @type {number} */ totalSize = tableSize;
if (offset[15] === 1) {
for (key = 0; key < totalSize; key++) {
tableGroup[tableOffset + key] = sorted[0];
for (let /** @type {number} */ k = 0; k < totalSize; ++k) {
tableGroup[tableOffset + k] = sorted[0];
}
return totalSize;
}
key = 0;
symbol = 0;
for (let /** @type {number} */ len = 1, /** @type {number} */ step = 2; len <= rootBits; len++, step <<= 1) {
for (; count[len] > 0; count[len]--) {
let /** @type {number} */ key = 0;
let /** @type {number} */ symbol = 0;
let /** @type {number} */ step = 1;
for (let /** @type {number} */ len = 1; len <= rootBits; ++len) {
step = step << 1;
while (count[len] > 0) {
replicateValue(tableGroup, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);
key = getNextKey(key, len);
count[len]--;
}
}
const /** @type {number} */ mask = totalSize - 1;
let /** @type {number} */ low = -1;
let /** @type {number} */ currentOffset = tableOffset;
for (let /** @type {number} */ len = rootBits + 1, /** @type {number} */ step = 2; len <= 15; len++, step <<= 1) {
for (; count[len] > 0; count[len]--) {
step = 1;
for (let /** @type {number} */ len = rootBits + 1; len <= 15; ++len) {
step = step << 1;
while (count[len] > 0) {
if ((key & mask) !== low) {
currentOffset += tableSize;
tableBits = nextTableBitSize(count, len, rootBits);
@ -1640,6 +1658,7 @@ let makeBrotliDecode = () => {
}
replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize, (len - rootBits) << 16 | sorted[symbol++]);
key = getNextKey(key, len);
count[len]--;
}
}
return totalSize;
@ -1696,9 +1715,9 @@ let makeBrotliDecode = () => {
* @return {number}
*/
function readFewBits(s, n) {
const /** @type {number} */ val = (s.accumulator32 >>> s.bitOffset) & ((1 << n) - 1);
const /** @type {number} */ v = (s.accumulator32 >>> s.bitOffset) & ((1 << n) - 1);
s.bitOffset += n;
return val;
return v;
}
/**
* @param {!State} s
@ -1779,27 +1798,29 @@ let makeBrotliDecode = () => {
* @return {void}
*/
function copyRawBytes(s, data, offset, length) {
let /** @type {number} */ pos = offset;
let /** @type {number} */ len = length;
if ((s.bitOffset & 7) !== 0) {
throw new Error("Unaligned copyBytes");
}
while ((s.bitOffset !== 32) && (length !== 0)) {
data[offset++] = (s.accumulator32 >>> s.bitOffset);
while ((s.bitOffset !== 32) && (len !== 0)) {
data[pos++] = s.accumulator32 >>> s.bitOffset;
s.bitOffset += 8;
length--;
len--;
}
if (length === 0) {
if (len === 0) {
return;
}
const /** @type {number} */ copyNibbles = Math.min(halfAvailable(s), length >> 1);
const /** @type {number} */ copyNibbles = Math.min(halfAvailable(s), len >> 1);
if (copyNibbles > 0) {
const /** @type {number} */ readOffset = s.halfOffset << 1;
const /** @type {number} */ delta = copyNibbles << 1;
data.set(s.byteBuffer.subarray(readOffset, readOffset + delta), offset);
offset += delta;
length -= delta;
data.set(s.byteBuffer.subarray(readOffset, readOffset + delta), pos);
pos += delta;
len -= delta;
s.halfOffset += copyNibbles;
}
if (length === 0) {
if (len === 0) {
return;
}
if (halfAvailable(s) > 0) {
@ -1807,21 +1828,21 @@ let makeBrotliDecode = () => {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
}
while (length !== 0) {
data[offset++] = (s.accumulator32 >>> s.bitOffset);
while (len !== 0) {
data[pos++] = s.accumulator32 >>> s.bitOffset;
s.bitOffset += 8;
length--;
len--;
}
checkHealth(s, 0);
return;
}
while (length > 0) {
const /** @type {number} */ len = readInput(s, data, offset, length);
if (len === -1) {
while (len > 0) {
const /** @type {number} */ chunkLen = readInput(s, data, pos, len);
if (chunkLen === -1) {
throw new Error("Unexpected end of input");
}
offset += len;
length -= len;
pos += chunkLen;
len -= chunkLen;
}
}
/**
@ -1834,7 +1855,7 @@ let makeBrotliDecode = () => {
const /** @type {number} */ halfLen = byteLen >> 1;
const /** @type {!Int16Array} */ shortBuffer = s.shortBuffer;
for (let /** @type {number} */ i = 0; i < halfLen; ++i) {
shortBuffer[i] = ((byteBuffer[i * 2] & 0xFF) | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));
shortBuffer[i] = (byteBuffer[i * 2] & 0xFF) | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8);
}
}
@ -2028,8 +2049,8 @@ let makeBrotliDecode = () => {
this.cdBlockBits = 0;
/** @type {!Int8Array} */
this.cdBlockMap = new Int8Array(0);
/** @type {!InputStream|null} */
this.input = null;
/** @type {!InputStream} */
this.input = new InputStream(new Int8Array(0));
this.ringBuffer = new Int8Array(0);
this.rings = new Int32Array(10);
this.rings[0] = 16;
@ -2100,16 +2121,16 @@ let makeBrotliDecode = () => {
throw new Error("Corrupted brotli dictionary");
}
let /** @type {number} */ offset = 0;
const /** @type {number} */ n = skipFlip.length;
for (let /** @type {number} */ i = 0; i < n; i += 2) {
const /** @type {number} */ skip = skipFlip.charCodeAt(i) - 36;
const /** @type {number} */ flip = skipFlip.charCodeAt(i + 1) - 36;
const /** @type {number} */ n = skipFlip.length >> 1;
for (let /** @type {number} */ i = 0; i < n; ++i) {
const /** @type {number} */ skip = skipFlip.charCodeAt(2 * i) - 36;
const /** @type {number} */ flip = skipFlip.charCodeAt(2 * i + 1) - 36;
for (let /** @type {number} */ j = 0; j < skip; ++j) {
dict[offset] ^= 3;
dict[offset] = dict[offset] ^ 3;
offset++;
}
for (let /** @type {number} */ j = 0; j < flip; ++j) {
dict[offset] ^= 236;
dict[offset] = dict[offset] ^ 236;
offset++;
}
}
@ -2158,8 +2179,8 @@ let makeBrotliDecode = () => {
return -1;
}
const /** @type {!InputStream} */ src = s.input;
let /** @type {number} */ end = Math.min(src.offset + length, src.data.length);
let /** @type {number} */ bytesRead = end - src.offset;
const /** @type {number} */ end = Math.min(src.offset + length, src.data.length);
const /** @type {number} */ bytesRead = end - src.offset;
dst.set(src.data.subarray(src.offset, end), offset);
src.offset += bytesRead;
return bytesRead;
@ -2169,8 +2190,8 @@ let makeBrotliDecode = () => {
* @return {!Int8Array}
*/
function toUsAsciiBytes(src) {
let /** @type {number} */ n = src.length;
let /** @type {!Int8Array} */ result = new Int8Array(n);
const /** @type {number} */ n = src.length;
const /** @type {!Int8Array} */ result = new Int8Array(n);
for (let /** @type {number} */ i = 0; i < n; ++i) {
result[i] = src.charCodeAt(i);
}

2
js/decode.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -25,14 +25,16 @@ const CMD_LOOKUP = new Int16Array(2816);
function log2floor(i: number): number {
let result: number = -1;
let step = 16;
let v: number = i;
while (step > 0) {
if ((i >>> step) !== 0) {
let next: number = v >>> step;
if (next !== 0) {
result += step;
i = i >>> step;
v = next;
}
step = step >> 1;
}
return result + i;
return result + v;
}
function calculateDistanceAlphabetSize(npostfix: number, ndirect: number, maxndistbits: number): number {
return 16 + ndirect + 2 * (maxndistbits << npostfix);
@ -47,12 +49,12 @@ function calculateDistanceAlphabetLimit(maxDistance: number, npostfix: number, n
return ((group - 1) << npostfix) + (1 << npostfix) + ndirect + 16;
}
function unpackCommandLookupTable(cmdLookup: Int16Array): void {
const insertLengthOffsets = new Int16Array(24);
const copyLengthOffsets = new Int16Array(24);
const insertLengthOffsets = new Int32Array(24);
const copyLengthOffsets = new Int32Array(24);
copyLengthOffsets[0] = 2;
for (let i = 0; i < 23; ++i) {
insertLengthOffsets[i + 1] = (insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]));
copyLengthOffsets[i + 1] = (copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]));
insertLengthOffsets[i + 1] = insertLengthOffsets[i] + (1 << INSERT_LENGTH_N_BITS[i]);
copyLengthOffsets[i + 1] = copyLengthOffsets[i] + (1 << COPY_LENGTH_N_BITS[i]);
}
for (let cmdCode = 0; cmdCode < 704; ++cmdCode) {
let rangeIdx: number = cmdCode >>> 6;
@ -64,9 +66,9 @@ function unpackCommandLookupTable(cmdLookup: Int16Array): void {
const insertCode: number = (((0x29850 >>> (rangeIdx * 2)) & 0x3) << 3) | ((cmdCode >>> 3) & 7);
const copyCode: number = (((0x26244 >>> (rangeIdx * 2)) & 0x3) << 3) | (cmdCode & 7);
const copyLengthOffset: number = copyLengthOffsets[copyCode];
const distanceContext: number = distanceContextOffset + (copyLengthOffset > 4 ? 3 : copyLengthOffset - 2);
const distanceContext: number = distanceContextOffset + (copyLengthOffset > 4 ? 3 : (copyLengthOffset - 2));
const index: number = cmdCode * 4;
cmdLookup[index] = (INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8));
cmdLookup[index] = INSERT_LENGTH_N_BITS[insertCode] | (COPY_LENGTH_N_BITS[copyCode] << 8);
cmdLookup[index + 1] = insertLengthOffsets[insertCode];
cmdLookup[index + 2] = copyLengthOffsets[copyCode];
cmdLookup[index + 3] = distanceContext;
@ -157,7 +159,7 @@ function close(s: State): void {
return;
}
s.runningState = 11;
s.input = null;
s.input = new InputStream(new Int8Array(0));
}
function decodeVarLenUnsignedByte(s: State): number {
if (s.bitOffset >= 16) {
@ -196,7 +198,7 @@ function decodeMetaBlockLength(s: State): void {
if (sizeBytes === 0) {
return;
}
for (let i = 0; i < sizeBytes; i++) {
for (let i = 0; i < sizeBytes; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -205,10 +207,10 @@ function decodeMetaBlockLength(s: State): void {
if (bits === 0 && i + 1 === sizeBytes && sizeBytes > 1) {
throw new Error("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 8);
s.metaBlockLength += bits << (i * 8);
}
} else {
for (let i = 0; i < sizeNibbles; i++) {
for (let i = 0; i < sizeNibbles; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -217,7 +219,7 @@ function decodeMetaBlockLength(s: State): void {
if (bits === 0 && i + 1 === sizeNibbles && sizeNibbles > 4) {
throw new Error("Exuberant nibble");
}
s.metaBlockLength |= bits << (i * 4);
s.metaBlockLength += bits << (i * 4);
}
}
s.metaBlockLength++;
@ -227,8 +229,8 @@ function decodeMetaBlockLength(s: State): void {
}
function readSymbol(tableGroup: Int32Array, tableIdx: number, s: State): number {
let offset: number = tableGroup[tableIdx];
const val: number = (s.accumulator32 >>> s.bitOffset);
offset += val & 0xFF;
const v: number = s.accumulator32 >>> s.bitOffset;
offset += v & 0xFF;
const bits: number = tableGroup[offset] >> 16;
const sym: number = tableGroup[offset] & 0xFFFF;
if (bits <= 8) {
@ -237,8 +239,8 @@ function readSymbol(tableGroup: Int32Array, tableIdx: number, s: State): number
}
offset += sym;
const mask: number = (1 << bits) - 1;
offset += (val & mask) >>> 8;
s.bitOffset += ((tableGroup[offset] >> 16) + 8);
offset += (v & mask) >>> 8;
s.bitOffset += (tableGroup[offset] >> 16) + 8;
return tableGroup[offset] & 0xFFFF;
}
function readBlockLength(tableGroup: Int32Array, tableIdx: number, s: State): number {
@ -255,18 +257,20 @@ function readBlockLength(tableGroup: Int32Array, tableIdx: number, s: State): nu
return BLOCK_LENGTH_OFFSET[code] + ((n <= 16) ? readFewBits(s, n) : readManyBits(s, n));
}
function moveToFront(v: Int32Array, index: number): void {
const value: number = v[index];
for (; index > 0; index--) {
v[index] = v[index - 1];
let i: number = index;
const value: number = v[i];
while (i > 0) {
v[i] = v[i - 1];
i--;
}
v[0] = value;
}
function inverseMoveToFrontTransform(v: Int8Array, vLen: number): void {
const mtf = new Int32Array(256);
for (let i = 0; i < 256; i++) {
for (let i = 0; i < 256; ++i) {
mtf[i] = i;
}
for (let i = 0; i < vLen; i++) {
for (let i = 0; i < vLen; ++i) {
const index: number = v[i] & 0xFF;
v[i] = mtf[index];
if (index !== 0) {
@ -314,7 +318,7 @@ function readHuffmanCodeLengths(codeLengthCodeLengths: Int32Array, numSymbols: n
const oldRepeat: number = repeat;
if (repeat > 0) {
repeat -= 2;
repeat <<= extraBits;
repeat = repeat << extraBits;
}
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
@ -325,7 +329,7 @@ function readHuffmanCodeLengths(codeLengthCodeLengths: Int32Array, numSymbols: n
if (symbol + repeatDelta > numSymbols) {
throw new Error("symbol + repeatDelta > numSymbols");
}
for (let i = 0; i < repeatDelta; i++) {
for (let i = 0; i < repeatDelta; ++i) {
codeLengths[symbol++] = repeatCodeLen;
}
if (repeatCodeLen !== 0) {
@ -352,7 +356,7 @@ function readSimpleHuffmanCode(alphabetSizeMax: number, alphabetSizeLimit: numbe
const symbols = new Int32Array(4);
const maxBits: number = 1 + log2floor(alphabetSizeMax - 1);
const numSymbols: number = readFewBits(s, 2) + 1;
for (let i = 0; i < numSymbols; i++) {
for (let i = 0; i < numSymbols; ++i) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
@ -403,7 +407,7 @@ function readComplexHuffmanCode(alphabetSizeLimit: number, skip: number, tableGr
const codeLengthCodeLengths = new Int32Array(18);
let space = 32;
let numCodes = 0;
for (let i: number = skip; i < 18 && space > 0; i++) {
for (let i: number = skip; i < 18; ++i) {
const codeLenIdx: number = CODE_LENGTH_CODE_ORDER[i];
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
@ -414,8 +418,10 @@ function readComplexHuffmanCode(alphabetSizeLimit: number, skip: number, tableGr
const v: number = FIXED_TABLE[p] & 0xFFFF;
codeLengthCodeLengths[codeLenIdx] = v;
if (v !== 0) {
space -= (32 >> v);
space -= 32 >> v;
numCodes++;
if (space <= 0)
break;
}
}
if (space !== 0 && numCodes !== 1) {
@ -462,7 +468,8 @@ function decodeContextMap(contextMapSize: number, contextMap: Int8Array, s: Stat
const table = new Int32Array(tableSize + 1);
const tableIdx: number = table.length - 1;
readHuffmanCode(alphabetSize, alphabetSize, table, tableIdx, s);
for (let i = 0; i < contextMapSize; ) {
let i = 0;
while (i < contextMapSize) {
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
@ -489,7 +496,7 @@ function decodeContextMap(contextMapSize: number, contextMap: Int8Array, s: Stat
reps--;
}
} else {
contextMap[i] = (code - maxRunLengthPrefix);
contextMap[i] = code - maxRunLengthPrefix;
i++;
}
}
@ -547,7 +554,7 @@ function maybeReallocateRingBuffer(s: State): void {
if (newSize > s.expectedTotalSize) {
const minimalNewSize: number = s.expectedTotalSize;
while ((newSize >> 1) > minimalNewSize) {
newSize >>= 1;
newSize = newSize >> 1;
}
if ((s.inputEnd === 0) && newSize < 16384 && s.maxRingBufferSize >= 16384) {
newSize = 16384;
@ -558,8 +565,9 @@ function maybeReallocateRingBuffer(s: State): void {
}
const ringBufferSizeWithSlack: number = newSize + 37;
const newBuffer = new Int8Array(ringBufferSizeWithSlack);
if (s.ringBuffer.length !== 0) {
newBuffer.set(s.ringBuffer.subarray(0, s.ringBufferSize), 0);
const oldBuffer: Int8Array = s.ringBuffer;
if (oldBuffer.length !== 0) {
newBuffer.set(oldBuffer.subarray(0, s.ringBufferSize), 0);
}
s.ringBuffer = newBuffer;
s.ringBufferSize = newSize;
@ -654,23 +662,26 @@ function readMetablockHuffmanCodesAndContextMaps(s: State): void {
s.distancePostfixBits = readFewBits(s, 2);
s.numDirectDistanceCodes = readFewBits(s, 4) << s.distancePostfixBits;
s.contextModes = new Int8Array(s.numLiteralBlockTypes);
for (let i = 0; i < s.numLiteralBlockTypes; ) {
let i = 0;
while (i < s.numLiteralBlockTypes) {
const limit: number = Math.min(i + 96, s.numLiteralBlockTypes);
for (; i < limit; ++i) {
while (i < limit) {
if (s.bitOffset >= 16) {
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
}
s.contextModes[i] = readFewBits(s, 2);
i++;
}
if (s.halfOffset > 2030) {
doReadMoreInput(s);
}
}
s.contextMap = new Int8Array(s.numLiteralBlockTypes << 6);
const numLiteralTrees: number = decodeContextMap(s.numLiteralBlockTypes << 6, s.contextMap, s);
const contextMapLength: number = s.numLiteralBlockTypes << 6;
s.contextMap = new Int8Array(contextMapLength);
const numLiteralTrees: number = decodeContextMap(contextMapLength, s.contextMap, s);
s.trivialLiteralContext = 1;
for (let j = 0; j < s.numLiteralBlockTypes << 6; j++) {
for (let j = 0; j < contextMapLength; ++j) {
if (s.contextMap[j] !== j >> 6) {
s.trivialLiteralContext = 0;
break;
@ -1054,7 +1065,8 @@ function decompress(s: State): void {
const dstEnd: number = dst + copyLength;
if ((srcEnd < ringBufferMask) && (dstEnd < ringBufferMask)) {
if (copyLength < 12 || (srcEnd > dst && dstEnd > src)) {
for (let k = 0; k < copyLength; k += 4) {
const numQuads: number = (copyLength + 3) >> 2;
for (let k = 0; k < numQuads; ++k) {
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
ringBuffer[dst++] = ringBuffer[src++];
@ -1067,7 +1079,7 @@ function decompress(s: State): void {
s.metaBlockLength -= copyLength;
s.pos += copyLength;
} else {
for (; s.j < s.copyLength; ) {
while (s.j < s.copyLength) {
ringBuffer[s.pos] = ringBuffer[(s.pos - s.distance) & ringBufferMask];
s.metaBlockLength--;
s.pos++;
@ -1129,7 +1141,7 @@ function decompress(s: State): void {
if (s.pos > s.ringBufferSize) {
ringBuffer.copyWithin(0, s.ringBufferSize, s.pos);
}
s.pos &= ringBufferMask;
s.pos = s.pos & ringBufferMask;
s.ringBufferBytesWritten = 0;
}
s.runningState = s.nextRunningState;
@ -1182,7 +1194,7 @@ function unpackTransforms(prefixSuffix: Int8Array, prefixSuffixHeads: Int32Array
{
unpackTransforms(RFC_TRANSFORMS.prefixSuffixStorage, RFC_TRANSFORMS.prefixSuffixHeads, RFC_TRANSFORMS.triplets, "# #s #, #e #.# the #.com/#\xC2\xA0# of # and # in # to #\"#\">#\n#]# for # a # that #. # with #'# from # by #. The # on # as # is #ing #\n\t#:#ed #(# at #ly #=\"# of the #. This #,# not #er #al #='#ful #ive #less #est #ize #ous #", " !! ! , *! &! \" ! ) * * - ! # ! #!*! + ,$ ! - % . / # 0 1 . \" 2 3!* 4% ! # / 5 6 7 8 0 1 & $ 9 + : ; < ' != > ?! 4 @ 4 2 & A *# ( B C& ) % ) !*# *-% A +! *. D! %' & E *6 F G% ! *A *% H! D I!+! J!+ K +- *4! A L!*4 M N +6 O!*% +.! K *G P +%( ! G *D +D Q +# *K!*G!+D!+# +G +A +4!+% +K!+4!*D!+K!*K");
}
function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuffer, srcOffset: number, len: number, transforms: Transforms, transformIndex: number): number {
function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuffer, srcOffset: number, wordLen: number, transforms: Transforms, transformIndex: number): number {
let offset: number = dstOffset;
const triplets: Int32Array = transforms.triplets;
const prefixSuffixStorage: Int8Array = transforms.prefixSuffixStorage;
@ -1206,15 +1218,16 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
while (prefix !== prefixEnd) {
dst[offset++] = prefixSuffixStorage[prefix++];
}
let len: number = wordLen;
if (omitFirst > len) {
omitFirst = len;
}
srcOffset += omitFirst;
let dictOffset: number = srcOffset + omitFirst;
len -= omitFirst;
len -= omitLast;
let i: number = len;
while (i > 0) {
dst[offset++] = src[srcOffset++];
dst[offset++] = src[dictOffset++];
i--;
}
if (transformType === 10 || transformType === 11) {
@ -1226,16 +1239,16 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
const c0: number = dst[uppercaseOffset] & 0xFF;
if (c0 < 0xC0) {
if (c0 >= 97 && c0 <= 122) {
dst[uppercaseOffset] ^= 32;
dst[uppercaseOffset] = dst[uppercaseOffset] ^ 32;
}
uppercaseOffset += 1;
len -= 1;
} else if (c0 < 0xE0) {
dst[uppercaseOffset + 1] ^= 32;
dst[uppercaseOffset + 1] = dst[uppercaseOffset + 1] ^ 32;
uppercaseOffset += 2;
len -= 2;
} else {
dst[uppercaseOffset + 2] ^= 5;
dst[uppercaseOffset + 2] = dst[uppercaseOffset + 2] ^ 5;
uppercaseOffset += 3;
len -= 3;
}
@ -1249,14 +1262,14 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
const c0: number = dst[shiftOffset] & 0xFF;
if (c0 < 0x80) {
scalar += c0;
dst[shiftOffset] = (scalar & 0x7F);
dst[shiftOffset] = scalar & 0x7F;
} else if (c0 < 0xC0) {
} else if (c0 < 0xE0) {
if (len >= 2) {
const c1: number = dst[shiftOffset + 1];
scalar += (c1 & 0x3F) | ((c0 & 0x1F) << 6);
dst[shiftOffset] = (0xC0 | ((scalar >> 6) & 0x1F));
dst[shiftOffset + 1] = ((c1 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xC0 | ((scalar >> 6) & 0x1F);
dst[shiftOffset + 1] = (c1 & 0xC0) | (scalar & 0x3F);
step = 2;
} else {
step = len;
@ -1266,9 +1279,9 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
const c1: number = dst[shiftOffset + 1];
const c2: number = dst[shiftOffset + 2];
scalar += (c2 & 0x3F) | ((c1 & 0x3F) << 6) | ((c0 & 0x0F) << 12);
dst[shiftOffset] = (0xE0 | ((scalar >> 12) & 0x0F));
dst[shiftOffset + 1] = ((c1 & 0xC0) | ((scalar >> 6) & 0x3F));
dst[shiftOffset + 2] = ((c2 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xE0 | ((scalar >> 12) & 0x0F);
dst[shiftOffset + 1] = (c1 & 0xC0) | ((scalar >> 6) & 0x3F);
dst[shiftOffset + 2] = (c2 & 0xC0) | (scalar & 0x3F);
step = 3;
} else {
step = len;
@ -1279,10 +1292,10 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
const c2: number = dst[shiftOffset + 2];
const c3: number = dst[shiftOffset + 3];
scalar += (c3 & 0x3F) | ((c2 & 0x3F) << 6) | ((c1 & 0x3F) << 12) | ((c0 & 0x07) << 18);
dst[shiftOffset] = (0xF0 | ((scalar >> 18) & 0x07));
dst[shiftOffset + 1] = ((c1 & 0xC0) | ((scalar >> 12) & 0x3F));
dst[shiftOffset + 2] = ((c2 & 0xC0) | ((scalar >> 6) & 0x3F));
dst[shiftOffset + 3] = ((c3 & 0xC0) | (scalar & 0x3F));
dst[shiftOffset] = 0xF0 | ((scalar >> 18) & 0x07);
dst[shiftOffset + 1] = (c1 & 0xC0) | ((scalar >> 12) & 0x3F);
dst[shiftOffset + 2] = (c2 & 0xC0) | ((scalar >> 6) & 0x3F);
dst[shiftOffset + 3] = (c3 & 0xC0) | (scalar & 0x3F);
step = 4;
} else {
step = len;
@ -1304,69 +1317,74 @@ function transformDictionaryWord(dst: Int8Array, dstOffset: number, src: ByteBuf
function getNextKey(key: number, len: number): number {
let step: number = 1 << (len - 1);
while ((key & step) !== 0) {
step >>= 1;
step = step >> 1;
}
return (key & (step - 1)) + step;
}
function replicateValue(table: Int32Array, offset: number, step: number, end: number, item: number): void {
let pos: number = end;
do {
end -= step;
table[offset + end] = item;
} while (end > 0);
pos -= step;
table[offset + pos] = item;
} while (pos > 0);
}
function nextTableBitSize(count: Int32Array, len: number, rootBits: number): number {
let left: number = 1 << (len - rootBits);
while (len < 15) {
left -= count[len];
let bits: number = len;
let left: number = 1 << (bits - rootBits);
while (bits < 15) {
left -= count[bits];
if (left <= 0) {
break;
}
len++;
left <<= 1;
bits++;
left = left << 1;
}
return len - rootBits;
return bits - rootBits;
}
function buildHuffmanTable(tableGroup: Int32Array, tableIdx: number, rootBits: number, codeLengths: Int32Array, codeLengthsSize: number): number {
const tableOffset: number = tableGroup[tableIdx];
let key: number;
const sorted = new Int32Array(codeLengthsSize);
const count = new Int32Array(16);
const offset = new Int32Array(16);
let symbol: number;
for (symbol = 0; symbol < codeLengthsSize; symbol++) {
count[codeLengths[symbol]]++;
for (let sym = 0; sym < codeLengthsSize; ++sym) {
count[codeLengths[sym]]++;
}
offset[1] = 0;
for (let len = 1; len < 15; len++) {
for (let len = 1; len < 15; ++len) {
offset[len + 1] = offset[len] + count[len];
}
for (symbol = 0; symbol < codeLengthsSize; symbol++) {
if (codeLengths[symbol] !== 0) {
sorted[offset[codeLengths[symbol]]++] = symbol;
for (let sym = 0; sym < codeLengthsSize; ++sym) {
if (codeLengths[sym] !== 0) {
sorted[offset[codeLengths[sym]]++] = sym;
}
}
let tableBits: number = rootBits;
let tableSize: number = 1 << tableBits;
let totalSize: number = tableSize;
if (offset[15] === 1) {
for (key = 0; key < totalSize; key++) {
tableGroup[tableOffset + key] = sorted[0];
for (let k = 0; k < totalSize; ++k) {
tableGroup[tableOffset + k] = sorted[0];
}
return totalSize;
}
key = 0;
symbol = 0;
for (let len = 1, step = 2; len <= rootBits; len++, step <<= 1) {
for (; count[len] > 0; count[len]--) {
let key = 0;
let symbol = 0;
let step = 1;
for (let len = 1; len <= rootBits; ++len) {
step = step << 1;
while (count[len] > 0) {
replicateValue(tableGroup, tableOffset + key, step, tableSize, len << 16 | sorted[symbol++]);
key = getNextKey(key, len);
count[len]--;
}
}
const mask: number = totalSize - 1;
let low: number = -1;
let currentOffset: number = tableOffset;
for (let len: number = rootBits + 1, step = 2; len <= 15; len++, step <<= 1) {
for (; count[len] > 0; count[len]--) {
step = 1;
for (let len: number = rootBits + 1; len <= 15; ++len) {
step = step << 1;
while (count[len] > 0) {
if ((key & mask) !== low) {
currentOffset += tableSize;
tableBits = nextTableBitSize(count, len, rootBits);
@ -1377,6 +1395,7 @@ function buildHuffmanTable(tableGroup: Int32Array, tableIdx: number, rootBits: n
}
replicateValue(tableGroup, currentOffset + (key >> rootBits), step, tableSize, (len - rootBits) << 16 | sorted[symbol++]);
key = getNextKey(key, len);
count[len]--;
}
}
return totalSize;
@ -1419,9 +1438,9 @@ function checkHealth(s: State, endOfStream: number): void {
}
}
function readFewBits(s: State, n: number): number {
const val: number = (s.accumulator32 >>> s.bitOffset) & ((1 << n) - 1);
const v: number = (s.accumulator32 >>> s.bitOffset) & ((1 << n) - 1);
s.bitOffset += n;
return val;
return v;
}
function readManyBits(s: State, n: number): number {
const low: number = readFewBits(s, 16);
@ -1470,27 +1489,29 @@ function halfAvailable(s: State): number {
return limit - s.halfOffset;
}
function copyRawBytes(s: State, data: Int8Array, offset: number, length: number): void {
let pos: number = offset;
let len: number = length;
if ((s.bitOffset & 7) !== 0) {
throw new Error("Unaligned copyBytes");
}
while ((s.bitOffset !== 32) && (length !== 0)) {
data[offset++] = (s.accumulator32 >>> s.bitOffset);
while ((s.bitOffset !== 32) && (len !== 0)) {
data[pos++] = s.accumulator32 >>> s.bitOffset;
s.bitOffset += 8;
length--;
len--;
}
if (length === 0) {
if (len === 0) {
return;
}
const copyNibbles: number = Math.min(halfAvailable(s), length >> 1);
const copyNibbles: number = Math.min(halfAvailable(s), len >> 1);
if (copyNibbles > 0) {
const readOffset: number = s.halfOffset << 1;
const delta: number = copyNibbles << 1;
data.set(s.byteBuffer.subarray(readOffset, readOffset + delta), offset);
offset += delta;
length -= delta;
data.set(s.byteBuffer.subarray(readOffset, readOffset + delta), pos);
pos += delta;
len -= delta;
s.halfOffset += copyNibbles;
}
if (length === 0) {
if (len === 0) {
return;
}
if (halfAvailable(s) > 0) {
@ -1498,21 +1519,21 @@ function copyRawBytes(s: State, data: Int8Array, offset: number, length: number)
s.accumulator32 = (s.shortBuffer[s.halfOffset++] << 16) | (s.accumulator32 >>> 16);
s.bitOffset -= 16;
}
while (length !== 0) {
data[offset++] = (s.accumulator32 >>> s.bitOffset);
while (len !== 0) {
data[pos++] = s.accumulator32 >>> s.bitOffset;
s.bitOffset += 8;
length--;
len--;
}
checkHealth(s, 0);
return;
}
while (length > 0) {
const len: number = readInput(s, data, offset, length);
if (len === -1) {
while (len > 0) {
const chunkLen: number = readInput(s, data, pos, len);
if (chunkLen === -1) {
throw new Error("Unexpected end of input");
}
offset += len;
length -= len;
pos += chunkLen;
len -= chunkLen;
}
}
function bytesToNibbles(s: State, byteLen: number): void {
@ -1520,7 +1541,7 @@ function bytesToNibbles(s: State, byteLen: number): void {
const halfLen: number = byteLen >> 1;
const shortBuffer: Int16Array = s.shortBuffer;
for (let i = 0; i < halfLen; ++i) {
shortBuffer[i] = ((byteBuffer[i * 2] & 0xFF) | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8));
shortBuffer[i] = (byteBuffer[i * 2] & 0xFF) | ((byteBuffer[(i * 2) + 1] & 0xFF) << 8);
}
}
@ -1632,7 +1653,7 @@ class State {
cdChunkOffsets = new Int32Array(0);
cdBlockBits = 0;
cdBlockMap = new Int8Array(0);
input: InputStream|null = null;
input = new InputStream(new Int8Array(0));
constructor () {
this.ringBuffer = new Int8Array(0);
this.rings = new Int32Array(10);
@ -1688,16 +1709,16 @@ function unpackDictionaryData(dictionary: ByteBuffer, data0: string, data1: stri
throw new Error("Corrupted brotli dictionary");
}
let offset = 0;
const n: number = skipFlip.length;
for (let i = 0; i < n; i += 2) {
const skip: number = skipFlip.charCodeAt(i) - 36;
const flip: number = skipFlip.charCodeAt(i + 1) - 36;
const n: number = skipFlip.length >> 1;
for (let i = 0; i < n; ++i) {
const skip: number = skipFlip.charCodeAt(2 * i) - 36;
const flip: number = skipFlip.charCodeAt(2 * i + 1) - 36;
for (let j = 0; j < skip; ++j) {
dict[offset] ^= 3;
dict[offset] = dict[offset] ^ 3;
offset++;
}
for (let j = 0; j < flip; ++j) {
dict[offset] ^= 236;
dict[offset] = dict[offset] ^ 236;
offset++;
}
}