mirror of
https://github.com/codedread/bitjs
synced 2025-10-03 17:49:16 +02:00
Updates to jsdoc for better IDE analysis. A couple other minor tweaks.
This commit is contained in:
parent
843caf4e61
commit
2a90e32c89
7 changed files with 69 additions and 18 deletions
|
@ -72,7 +72,6 @@ const BIT = [0x01, 0x02, 0x04, 0x08,
|
||||||
0x100, 0x200, 0x400, 0x800,
|
0x100, 0x200, 0x400, 0x800,
|
||||||
0x1000, 0x2000, 0x4000, 0x8000];
|
0x1000, 0x2000, 0x4000, 0x8000];
|
||||||
|
|
||||||
|
|
||||||
class ZipLocalFile {
|
class ZipLocalFile {
|
||||||
// takes a ByteStream and parses out the local file information
|
// takes a ByteStream and parses out the local file information
|
||||||
constructor(bstream) {
|
constructor(bstream) {
|
||||||
|
@ -209,9 +208,18 @@ class ZipLocalFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a table of Huffman codes
|
/**
|
||||||
// each entry's index is its code and its value is a JavaScript object
|
* @typedef SymbolLengthPair
|
||||||
// containing {length: 6, symbol: X}
|
* @property {number} length
|
||||||
|
* @property {number} symbol
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a table of Huffman codes. Each entry's key is its code and its value is a JavaScript
|
||||||
|
* object containing {length: 6, symbol: X}.
|
||||||
|
* @param {number[]} bitLengths
|
||||||
|
* @returns {Map<number, SymbolLengthPair>}
|
||||||
|
*/
|
||||||
function getHuffmanCodes(bitLengths) {
|
function getHuffmanCodes(bitLengths) {
|
||||||
// ensure bitLengths is an array containing at least one element
|
// ensure bitLengths is an array containing at least one element
|
||||||
if (typeof bitLengths != typeof [] || bitLengths.length < 1) {
|
if (typeof bitLengths != typeof [] || bitLengths.length < 1) {
|
||||||
|
@ -251,6 +259,7 @@ function getHuffmanCodes(bitLengths) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Assign numerical values to all codes
|
// Step 3: Assign numerical values to all codes
|
||||||
|
/** @type Map<number, SymbolLengthPair> */
|
||||||
const table = new Map();
|
const table = new Map();
|
||||||
for (let n = 0; n < numLengths; ++n) {
|
for (let n = 0; n < numLengths; ++n) {
|
||||||
const len = bitLengths[n];
|
const len = bitLengths[n];
|
||||||
|
@ -282,6 +291,7 @@ function getHuffmanCodes(bitLengths) {
|
||||||
// fixed Huffman codes go from 7-9 bits, so we need an array whose index can hold up to 9 bits
|
// fixed Huffman codes go from 7-9 bits, so we need an array whose index can hold up to 9 bits
|
||||||
let fixedHCtoLiteral = null;
|
let fixedHCtoLiteral = null;
|
||||||
let fixedHCtoDistance = null;
|
let fixedHCtoDistance = null;
|
||||||
|
/** @returns {Map<number, SymbolLengthPair>} */
|
||||||
function getFixedLiteralTable() {
|
function getFixedLiteralTable() {
|
||||||
// create once
|
// create once
|
||||||
if (!fixedHCtoLiteral) {
|
if (!fixedHCtoLiteral) {
|
||||||
|
@ -297,6 +307,7 @@ function getFixedLiteralTable() {
|
||||||
return fixedHCtoLiteral;
|
return fixedHCtoLiteral;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @returns {Map<number, SymbolLengthPair>} */
|
||||||
function getFixedDistanceTable() {
|
function getFixedDistanceTable() {
|
||||||
// create once
|
// create once
|
||||||
if (!fixedHCtoDistance) {
|
if (!fixedHCtoDistance) {
|
||||||
|
@ -309,8 +320,13 @@ function getFixedDistanceTable() {
|
||||||
return fixedHCtoDistance;
|
return fixedHCtoDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract one bit at a time until we find a matching Huffman Code
|
/**
|
||||||
// then return that symbol
|
* Extract one bit at a time until we find a matching Huffman Code
|
||||||
|
* then return that symbol.
|
||||||
|
* @param {bitjs.io.BitStream} bstream
|
||||||
|
* @param {Map<number, SymbolLengthPair>} hcTable
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
function decodeSymbol(bstream, hcTable) {
|
function decodeSymbol(bstream, hcTable) {
|
||||||
let code = 0;
|
let code = 0;
|
||||||
let len = 0;
|
let len = 0;
|
||||||
|
@ -326,7 +342,7 @@ function decodeSymbol(bstream, hcTable) {
|
||||||
if (hcTable.has(code) && hcTable.get(code).length == len) {
|
if (hcTable.has(code) && hcTable.get(code).length == len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (len > hcTable.maxLength) {
|
if (len > hcTable.length) {
|
||||||
err(`Bit stream out of sync, didn't find a Huffman Code, length was ${len} ` +
|
err(`Bit stream out of sync, didn't find a Huffman Code, length was ${len} ` +
|
||||||
`and table only max code length of ${hcTable.length}`);
|
`and table only max code length of ${hcTable.length}`);
|
||||||
break;
|
break;
|
||||||
|
@ -396,6 +412,13 @@ const DistLookupTable = [
|
||||||
[13, 16385], [13, 24577]
|
[13, 16385], [13, 24577]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {bitjs.io.BitStream} bstream
|
||||||
|
* @param {Map<number, SymbolLengthPair>} hcLiteralTable
|
||||||
|
* @param {Map<number, SymbolLengthPair>} hcDistanceTable
|
||||||
|
* @param {bitjs.io.ByteBuffer} buffer
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
||||||
/*
|
/*
|
||||||
loop (until end of block code recognized)
|
loop (until end of block code recognized)
|
||||||
|
@ -412,11 +435,9 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
||||||
stream, and copy length bytes from this
|
stream, and copy length bytes from this
|
||||||
position to the output stream.
|
position to the output stream.
|
||||||
*/
|
*/
|
||||||
let numSymbols = 0;
|
|
||||||
let blockSize = 0;
|
let blockSize = 0;
|
||||||
for (; ;) {
|
for (; ;) {
|
||||||
const symbol = decodeSymbol(bstream, hcLiteralTable);
|
const symbol = decodeSymbol(bstream, hcLiteralTable);
|
||||||
++numSymbols;
|
|
||||||
if (symbol < 256) {
|
if (symbol < 256) {
|
||||||
// copy literal byte to output
|
// copy literal byte to output
|
||||||
buffer.insertByte(symbol);
|
buffer.insertByte(symbol);
|
||||||
|
@ -458,15 +479,20 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
||||||
return blockSize;
|
return blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// {Uint8Array} compressedData A Uint8Array of the compressed file data.
|
/**
|
||||||
// compression method 8
|
* Compression method 8. Deflate: http://tools.ietf.org/html/rfc1951
|
||||||
// deflate: http://tools.ietf.org/html/rfc1951
|
* @param {Uint8Array} compressedData A Uint8Array of the compressed file data.
|
||||||
|
* @param {number} numDecompressedBytes
|
||||||
|
* @returns {Uint8Array} The decompressed array.
|
||||||
|
*/
|
||||||
function inflate(compressedData, numDecompressedBytes) {
|
function inflate(compressedData, numDecompressedBytes) {
|
||||||
// Bit stream representing the compressed data.
|
// Bit stream representing the compressed data.
|
||||||
|
/** @type {bitjs.io.BitStream} */
|
||||||
const bstream = new bitjs.io.BitStream(compressedData.buffer,
|
const bstream = new bitjs.io.BitStream(compressedData.buffer,
|
||||||
false /* rtl */,
|
false /* rtl */,
|
||||||
compressedData.byteOffset,
|
compressedData.byteOffset,
|
||||||
compressedData.byteLength);
|
compressedData.byteLength);
|
||||||
|
/** @type {bitjs.io.ByteBuffer} */
|
||||||
const buffer = new bitjs.io.ByteBuffer(numDecompressedBytes);
|
const buffer = new bitjs.io.ByteBuffer(numDecompressedBytes);
|
||||||
let blockSize = 0;
|
let blockSize = 0;
|
||||||
|
|
||||||
|
@ -523,17 +549,18 @@ function inflate(compressedData, numDecompressedBytes) {
|
||||||
// and distance tables together
|
// and distance tables together
|
||||||
const literalCodeLengths = [];
|
const literalCodeLengths = [];
|
||||||
let prevCodeLength = 0;
|
let prevCodeLength = 0;
|
||||||
while (literalCodeLengths.length < numLiteralLengthCodes + numDistanceCodes) {
|
const maxCodeLengths = numLiteralLengthCodes + numDistanceCodes;
|
||||||
|
while (literalCodeLengths.length < maxCodeLengths) {
|
||||||
const symbol = decodeSymbol(bstream, codeLengthsCodes);
|
const symbol = decodeSymbol(bstream, codeLengthsCodes);
|
||||||
if (symbol <= 15) {
|
if (symbol <= 15) {
|
||||||
literalCodeLengths.push(symbol);
|
literalCodeLengths.push(symbol);
|
||||||
prevCodeLength = symbol;
|
prevCodeLength = symbol;
|
||||||
} else if (symbol == 16) {
|
} else if (symbol === 16) {
|
||||||
let repeat = bstream.readBits(2) + 3;
|
let repeat = bstream.readBits(2) + 3;
|
||||||
while (repeat--) {
|
while (repeat--) {
|
||||||
literalCodeLengths.push(prevCodeLength);
|
literalCodeLengths.push(prevCodeLength);
|
||||||
}
|
}
|
||||||
} else if (symbol == 17) {
|
} else if (symbol === 17) {
|
||||||
let repeat = bstream.readBits(3) + 3;
|
let repeat = bstream.readBits(3) + 3;
|
||||||
while (repeat--) {
|
while (repeat--) {
|
||||||
literalCodeLengths.push(0);
|
literalCodeLengths.push(0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
OUT_PATH=/out/io
|
OUT_PATH=../../io
|
||||||
|
|
||||||
BITSTREAM_MODULE=${OUT_PATH}/bitstream.js
|
BITSTREAM_MODULE=${OUT_PATH}/bitstream.js
|
||||||
BITSTREAM_WORKER=${OUT_PATH}/bitstream-worker.js
|
BITSTREAM_WORKER=${OUT_PATH}/bitstream-worker.js
|
||||||
|
|
|
@ -21,7 +21,15 @@
|
||||||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @type {Uint8Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.data = new Uint8Array(numBytes);
|
this.data = new Uint8Array(numBytes);
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.ptr = 0;
|
this.ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,15 @@ bitjs.io.ByteBuffer =
|
||||||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @type {Uint8Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.data = new Uint8Array(numBytes);
|
this.data = new Uint8Array(numBytes);
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.ptr = 0;
|
this.ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,15 @@ export const ByteBuffer =
|
||||||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @type {Uint8Array}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.data = new Uint8Array(numBytes);
|
this.data = new Uint8Array(numBytes);
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
this.ptr = 0;
|
this.ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue