in src/core/flate_stream.js [307:474]
readBlock() {
let buffer, hdr, len;
const str = this.str;
// read block header
try {
hdr = this.getBits(3);
} catch (ex) {
this.#endsStreamOnError(ex.message);
return;
}
if (hdr & 1) {
this.eof = true;
}
hdr >>= 1;
if (hdr === 0) {
// uncompressed block
let b;
if ((b = str.getByte()) === -1) {
this.#endsStreamOnError("Bad block header in flate stream");
return;
}
let blockLen = b;
if ((b = str.getByte()) === -1) {
this.#endsStreamOnError("Bad block header in flate stream");
return;
}
blockLen |= b << 8;
if ((b = str.getByte()) === -1) {
this.#endsStreamOnError("Bad block header in flate stream");
return;
}
let check = b;
if ((b = str.getByte()) === -1) {
this.#endsStreamOnError("Bad block header in flate stream");
return;
}
check |= b << 8;
if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
// Ignoring error for bad "empty" block (see issue 1277)
throw new FormatError("Bad uncompressed block length in flate stream");
}
this.codeBuf = 0;
this.codeSize = 0;
const bufferLength = this.bufferLength,
end = bufferLength + blockLen;
buffer = this.ensureBuffer(end);
this.bufferLength = end;
if (blockLen === 0) {
if (str.peekByte() === -1) {
this.eof = true;
}
} else {
const block = str.getBytes(blockLen);
buffer.set(block, bufferLength);
if (block.length < blockLen) {
this.eof = true;
}
}
return;
}
let litCodeTable;
let distCodeTable;
if (hdr === 1) {
// compressed block, fixed codes
litCodeTable = fixedLitCodeTab;
distCodeTable = fixedDistCodeTab;
} else if (hdr === 2) {
// compressed block, dynamic codes
const numLitCodes = this.getBits(5) + 257;
const numDistCodes = this.getBits(5) + 1;
const numCodeLenCodes = this.getBits(4) + 4;
// build the code lengths code table
const codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
let i;
for (i = 0; i < numCodeLenCodes; ++i) {
codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
}
const codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
// build the literal and distance code tables
len = 0;
i = 0;
const codes = numLitCodes + numDistCodes;
const codeLengths = new Uint8Array(codes);
let bitsLength, bitsOffset, what;
while (i < codes) {
const code = this.getCode(codeLenCodeTab);
if (code === 16) {
bitsLength = 2;
bitsOffset = 3;
what = len;
} else if (code === 17) {
bitsLength = 3;
bitsOffset = 3;
what = len = 0;
} else if (code === 18) {
bitsLength = 7;
bitsOffset = 11;
what = len = 0;
} else {
codeLengths[i++] = len = code;
continue;
}
let repeatLength = this.getBits(bitsLength) + bitsOffset;
while (repeatLength-- > 0) {
codeLengths[i++] = what;
}
}
litCodeTable = this.generateHuffmanTable(
codeLengths.subarray(0, numLitCodes)
);
distCodeTable = this.generateHuffmanTable(
codeLengths.subarray(numLitCodes, codes)
);
} else {
throw new FormatError("Unknown block type in flate stream");
}
buffer = this.buffer;
let limit = buffer ? buffer.length : 0;
let pos = this.bufferLength;
while (true) {
let code1 = this.getCode(litCodeTable);
if (code1 < 256) {
if (pos + 1 >= limit) {
buffer = this.ensureBuffer(pos + 1);
limit = buffer.length;
}
buffer[pos++] = code1;
continue;
}
if (code1 === 256) {
this.bufferLength = pos;
return;
}
code1 -= 257;
code1 = lengthDecode[code1];
let code2 = code1 >> 16;
if (code2 > 0) {
code2 = this.getBits(code2);
}
len = (code1 & 0xffff) + code2;
code1 = this.getCode(distCodeTable);
code1 = distDecode[code1];
code2 = code1 >> 16;
if (code2 > 0) {
code2 = this.getBits(code2);
}
const dist = (code1 & 0xffff) + code2;
if (pos + len >= limit) {
buffer = this.ensureBuffer(pos + len);
limit = buffer.length;
}
for (let k = 0; k < len; ++k, ++pos) {
buffer[pos] = buffer[pos - dist];
}
}
}