UNPKG

tsmaz

Version:

TypeScript port of the smaz string compression library

152 lines 4.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const trie_1 = require("./trie"); const EMPTY_STRING = ''; const EMPTY_UINT8_ARRAY = new Uint8Array(0); class Smaz { constructor(codebook) { this.buffer = new Uint8Array(30000); this.verbatim = new Uint8Array(255); this.codebook = codebook; this.trie = trie_1.default(codebook); } compress(str) { const compressedSize = this.inplaceCompress(str); if (compressedSize === 0) { return EMPTY_UINT8_ARRAY; } return this.buffer.slice(0, compressedSize); } UNSAFE_compress(str) { const compressedSize = this.inplaceCompress(str); if (compressedSize === 0) { return EMPTY_UINT8_ARRAY; } return this.buffer.subarray(0, compressedSize); } decompress(arr) { if (arr.byteLength === 0) { return EMPTY_STRING; } let output = EMPTY_STRING; let i = 0; while (i < arr.byteLength) { if (arr[i] === 254) { output += String.fromCharCode(arr[i + 1]); i += 2; } else if (arr[i] === 255) { output += String.fromCharCode.apply(null, // @ts-ignore arr.subarray(i + 2, i + arr[i + 1] + 2)); i += arr[i + 1] + 2; } else { output += this.codebook[arr[i]]; i += 1; } } return output; } getCompressedSize(str) { if (str.length === 0) { return 0; } let bufferIndex = 0; let verbatimIndex = 0; let inputIndex = 0; while (inputIndex < str.length) { let indexAfterMatch = -1; let code = -1; let root = this.trie; for (let j = inputIndex; j < str.length; j += 1) { root = root.chars[str[j]]; if (root === undefined) { break; } if (root.code !== undefined) { code = root.code; indexAfterMatch = j + 1; } } if (code === -1) { verbatimIndex++; inputIndex++; if (verbatimIndex === 255) { bufferIndex += 2 + verbatimIndex; verbatimIndex = 0; } } else { if (verbatimIndex !== 0) { bufferIndex += 2 + (verbatimIndex === 1 ? 0 : verbatimIndex); verbatimIndex = 0; } bufferIndex++; inputIndex = indexAfterMatch; } } if (verbatimIndex !== 0) { bufferIndex += 2 + (verbatimIndex === 1 ? 0 : verbatimIndex); } return bufferIndex; } inplaceCompress(str) { if (str.length === 0) { return 0; } let bufferIndex = 0; let verbatimIndex = 0; let inputIndex = 0; while (inputIndex < str.length) { let indexAfterMatch = -1; let code = -1; let root = this.trie; for (let j = inputIndex; j < str.length; j += 1) { root = root.chars[str[j]]; if (root === undefined) { break; } if (root.code !== undefined) { code = root.code; indexAfterMatch = j + 1; } } if (code === -1) { this.verbatim[verbatimIndex++] = str.charCodeAt(inputIndex++); if (verbatimIndex === 255) { bufferIndex = this.flushVerbatim(verbatimIndex, bufferIndex); verbatimIndex = 0; } } else { if (verbatimIndex !== 0) { bufferIndex = this.flushVerbatim(verbatimIndex, bufferIndex); verbatimIndex = 0; } this.buffer[bufferIndex++] = code; inputIndex = indexAfterMatch; } } if (verbatimIndex !== 0) { bufferIndex = this.flushVerbatim(verbatimIndex, bufferIndex); } return bufferIndex; } flushVerbatim(verbatimIndex, bufferIndex) { if (verbatimIndex === 1) { this.buffer[bufferIndex++] = 254; this.buffer[bufferIndex++] = this.verbatim[0]; } else { this.buffer[bufferIndex++] = 255; this.buffer[bufferIndex++] = verbatimIndex; for (let k = 0; k < verbatimIndex; k += 1) { this.buffer[bufferIndex++] = this.verbatim[k]; } } return bufferIndex; } } exports.default = Smaz; //# sourceMappingURL=factory.js.map