mirror of
https://github.com/codedread/bitjs
synced 2025-10-03 09:39: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,
|
||||
0x1000, 0x2000, 0x4000, 0x8000];
|
||||
|
||||
|
||||
class ZipLocalFile {
|
||||
// takes a ByteStream and parses out the local file information
|
||||
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
|
||||
// containing {length: 6, symbol: X}
|
||||
/**
|
||||
* @typedef SymbolLengthPair
|
||||
* @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) {
|
||||
// ensure bitLengths is an array containing at least one element
|
||||
if (typeof bitLengths != typeof [] || bitLengths.length < 1) {
|
||||
|
@ -251,6 +259,7 @@ function getHuffmanCodes(bitLengths) {
|
|||
}
|
||||
|
||||
// Step 3: Assign numerical values to all codes
|
||||
/** @type Map<number, SymbolLengthPair> */
|
||||
const table = new Map();
|
||||
for (let n = 0; n < numLengths; ++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
|
||||
let fixedHCtoLiteral = null;
|
||||
let fixedHCtoDistance = null;
|
||||
/** @returns {Map<number, SymbolLengthPair>} */
|
||||
function getFixedLiteralTable() {
|
||||
// create once
|
||||
if (!fixedHCtoLiteral) {
|
||||
|
@ -297,6 +307,7 @@ function getFixedLiteralTable() {
|
|||
return fixedHCtoLiteral;
|
||||
}
|
||||
|
||||
/** @returns {Map<number, SymbolLengthPair>} */
|
||||
function getFixedDistanceTable() {
|
||||
// create once
|
||||
if (!fixedHCtoDistance) {
|
||||
|
@ -309,8 +320,13 @@ function getFixedDistanceTable() {
|
|||
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) {
|
||||
let code = 0;
|
||||
let len = 0;
|
||||
|
@ -326,7 +342,7 @@ function decodeSymbol(bstream, hcTable) {
|
|||
if (hcTable.has(code) && hcTable.get(code).length == len) {
|
||||
break;
|
||||
}
|
||||
if (len > hcTable.maxLength) {
|
||||
if (len > hcTable.length) {
|
||||
err(`Bit stream out of sync, didn't find a Huffman Code, length was ${len} ` +
|
||||
`and table only max code length of ${hcTable.length}`);
|
||||
break;
|
||||
|
@ -396,6 +412,13 @@ const DistLookupTable = [
|
|||
[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) {
|
||||
/*
|
||||
loop (until end of block code recognized)
|
||||
|
@ -412,11 +435,9 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
|||
stream, and copy length bytes from this
|
||||
position to the output stream.
|
||||
*/
|
||||
let numSymbols = 0;
|
||||
let blockSize = 0;
|
||||
for (; ;) {
|
||||
const symbol = decodeSymbol(bstream, hcLiteralTable);
|
||||
++numSymbols;
|
||||
if (symbol < 256) {
|
||||
// copy literal byte to output
|
||||
buffer.insertByte(symbol);
|
||||
|
@ -458,15 +479,20 @@ function inflateBlockData(bstream, hcLiteralTable, hcDistanceTable, buffer) {
|
|||
return blockSize;
|
||||
}
|
||||
|
||||
// {Uint8Array} compressedData A Uint8Array of the compressed file data.
|
||||
// compression method 8
|
||||
// deflate: http://tools.ietf.org/html/rfc1951
|
||||
/**
|
||||
* Compression method 8. 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) {
|
||||
// Bit stream representing the compressed data.
|
||||
/** @type {bitjs.io.BitStream} */
|
||||
const bstream = new bitjs.io.BitStream(compressedData.buffer,
|
||||
false /* rtl */,
|
||||
compressedData.byteOffset,
|
||||
compressedData.byteLength);
|
||||
/** @type {bitjs.io.ByteBuffer} */
|
||||
const buffer = new bitjs.io.ByteBuffer(numDecompressedBytes);
|
||||
let blockSize = 0;
|
||||
|
||||
|
@ -523,17 +549,18 @@ function inflate(compressedData, numDecompressedBytes) {
|
|||
// and distance tables together
|
||||
const literalCodeLengths = [];
|
||||
let prevCodeLength = 0;
|
||||
while (literalCodeLengths.length < numLiteralLengthCodes + numDistanceCodes) {
|
||||
const maxCodeLengths = numLiteralLengthCodes + numDistanceCodes;
|
||||
while (literalCodeLengths.length < maxCodeLengths) {
|
||||
const symbol = decodeSymbol(bstream, codeLengthsCodes);
|
||||
if (symbol <= 15) {
|
||||
literalCodeLengths.push(symbol);
|
||||
prevCodeLength = symbol;
|
||||
} else if (symbol == 16) {
|
||||
} else if (symbol === 16) {
|
||||
let repeat = bstream.readBits(2) + 3;
|
||||
while (repeat--) {
|
||||
literalCodeLengths.push(prevCodeLength);
|
||||
}
|
||||
} else if (symbol == 17) {
|
||||
} else if (symbol === 17) {
|
||||
let repeat = bstream.readBits(3) + 3;
|
||||
while (repeat--) {
|
||||
literalCodeLengths.push(0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
OUT_PATH=/out/io
|
||||
OUT_PATH=../../io
|
||||
|
||||
BITSTREAM_MODULE=${OUT_PATH}/bitstream.js
|
||||
BITSTREAM_WORKER=${OUT_PATH}/bitstream-worker.js
|
||||
|
|
|
@ -21,7 +21,15 @@
|
|||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||
}
|
||||
/**
|
||||
* @type {Uint8Array}
|
||||
* @public
|
||||
*/
|
||||
this.data = new Uint8Array(numBytes);
|
||||
/**
|
||||
* @type {number}
|
||||
* @public
|
||||
*/
|
||||
this.ptr = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,15 @@ bitjs.io.ByteBuffer =
|
|||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||
}
|
||||
/**
|
||||
* @type {Uint8Array}
|
||||
* @public
|
||||
*/
|
||||
this.data = new Uint8Array(numBytes);
|
||||
/**
|
||||
* @type {number}
|
||||
* @public
|
||||
*/
|
||||
this.ptr = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,15 @@ export const ByteBuffer =
|
|||
if (typeof numBytes != typeof 1 || numBytes <= 0) {
|
||||
throw "Error! ByteBuffer initialized with '" + numBytes + "'";
|
||||
}
|
||||
/**
|
||||
* @type {Uint8Array}
|
||||
* @public
|
||||
*/
|
||||
this.data = new Uint8Array(numBytes);
|
||||
/**
|
||||
* @type {number}
|
||||
* @public
|
||||
*/
|
||||
this.ptr = 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue