UNPKG

@matschik/lz-string

Version:
430 lines (428 loc) 12.9 kB
var __defProp = Object.defineProperty; var __markAsModule = (target) => __defProp(target, "__esModule", {value: true}); var __export = (target, all) => { __markAsModule(target); for (var name in all) __defProp(target, name, {get: all[name], enumerable: true}); }; // src/index.ts __export(exports, { compress: () => compress, compressToBase64: () => compressToBase64, compressToURL: () => compressToURL, decompress: () => decompress, decompressFromBase64: () => decompressFromBase64, decompressFromURL: () => decompressFromURL }); var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$"; var baseReverseDic = {}; function getBaseValue(alphabet, character) { if (!baseReverseDic[alphabet]) { baseReverseDic[alphabet] = {}; for (let i = 0; i < alphabet.length; i++) { baseReverseDic[alphabet][alphabet.charAt(i)] = i; } } return baseReverseDic[alphabet][character]; } function compressToBase64(input) { if (input == null) return ""; const res = _compress(input, 6, (a) => keyStrBase64.charAt(a)); switch (res.length % 4) { default: case 0: return res; case 1: return res + "==="; case 2: return res + "=="; case 3: return res + "="; } } function decompressFromBase64(input) { if (input == null) return ""; if (input == "") return null; return _decompress(input.length, 32, (index) => getBaseValue(keyStrBase64, input.charAt(index))); } function compressToURL(input) { if (input == null) return ""; return _compress(input, 6, (a) => keyStrUriSafe.charAt(a)); } function decompressFromURL(input) { if (input == null) return ""; if (input == "") return null; input = input.replaceAll(" ", "+"); return _decompress(input.length, 32, (index) => getBaseValue(keyStrUriSafe, input.charAt(index))); } function compress(uncompressed) { return _compress(uncompressed, 16, String.fromCharCode); } function decompress(compressed) { if (compressed == null) return ""; if (compressed == "") return null; return _decompress(compressed.length, 32768, (index) => compressed.charCodeAt(index)); } function _compress(uncompressed, bitsPerChar, getCharFromInt) { if (uncompressed == null) return ""; const contextData = []; const contextDictionary = {}; const contextDictionaryToCreate = {}; let i; let j; let value; let contextC = ""; let contextW = ""; let contextWc = ""; let contextEnlargeIn = 2; let contextDictSize = 3; let contextNumBits = 2; let contextDataVal = 0; let contextDataPosition = 0; for (j = 0; j < uncompressed.length; j += 1) { contextC = uncompressed.charAt(j); if (!Object.prototype.hasOwnProperty.call(contextDictionary, contextC)) { contextDictionary[contextC] = contextDictSize++; contextDictionaryToCreate[contextC] = true; } contextWc = contextW + contextC; if (Object.prototype.hasOwnProperty.call(contextDictionary, contextWc)) { contextW = contextWc; } else { if (Object.prototype.hasOwnProperty.call(contextDictionaryToCreate, contextW)) { if (contextW.charCodeAt(0) < 256) { for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } } value = contextW.charCodeAt(0); for (i = 0; i < 8; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } else { value = 1; for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1 | value; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = 0; } value = contextW.charCodeAt(0); for (i = 0; i < 16; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } contextEnlargeIn--; if (contextEnlargeIn == 0) { contextEnlargeIn = Math.pow(2, contextNumBits); contextNumBits++; } delete contextDictionaryToCreate[contextW]; } else { value = contextDictionary[contextW]; for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } contextEnlargeIn--; if (contextEnlargeIn == 0) { contextEnlargeIn = Math.pow(2, contextNumBits); contextNumBits++; } contextDictionary[contextWc] = contextDictSize++; contextW = String(contextC); } } if (contextW !== "") { if (Object.prototype.hasOwnProperty.call(contextDictionaryToCreate, contextW)) { if (contextW.charCodeAt(0) < 256) { for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } } value = contextW.charCodeAt(0); for (i = 0; i < 8; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } else { value = 1; for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1 | value; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = 0; } value = contextW.charCodeAt(0); for (i = 0; i < 16; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } contextEnlargeIn--; if (contextEnlargeIn == 0) { contextEnlargeIn = Math.pow(2, contextNumBits); contextNumBits++; } delete contextDictionaryToCreate[contextW]; } else { value = contextDictionary[contextW]; for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else { contextDataPosition++; } value = value >> 1; } } contextEnlargeIn--; if (contextEnlargeIn == 0) { contextEnlargeIn = Math.pow(2, contextNumBits); contextNumBits++; } } value = 2; for (i = 0; i < contextNumBits; i++) { contextDataVal = contextDataVal << 1 | value & 1; if (contextDataPosition == bitsPerChar - 1) { contextDataPosition = 0; contextData.push(getCharFromInt(contextDataVal)); contextDataVal = 0; } else contextDataPosition++; value = value >> 1; } while (true) { contextDataVal = contextDataVal << 1; if (contextDataPosition == bitsPerChar - 1) { contextData.push(getCharFromInt(contextDataVal)); break; } else contextDataPosition++; } return contextData.join(""); } function _decompress(length, resetValue, getNextValue) { let dictionary = []; let next; let enlargeIn = 4; let dictSize = 4; let numBits = 3; let entry = ""; let result = []; let i; let w; let bits; let resb; let maxpower; let power; let c; let data = {val: getNextValue(0), position: resetValue, index: 1}; for (i = 0; i < 3; i += 1) dictionary[i] = i; bits = 0; maxpower = Math.pow(2, 2); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } switch (next = bits) { case 0: bits = 0; maxpower = Math.pow(2, 8); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } c = String.fromCharCode(bits); break; case 1: bits = 0; maxpower = Math.pow(2, 16); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } c = String.fromCharCode(bits); break; case 2: return ""; } dictionary[3] = c; w = c; result.push(c); while (true) { if (data.index > length) { return ""; } bits = 0; maxpower = Math.pow(2, numBits); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } switch (c = bits) { case 0: bits = 0; maxpower = Math.pow(2, 8); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } dictionary[dictSize++] = String.fromCharCode(bits); c = dictSize - 1; enlargeIn--; break; case 1: bits = 0; maxpower = Math.pow(2, 16); power = 1; while (power != maxpower) { resb = data.val & data.position; data.position >>= 1; if (data.position == 0) { data.position = resetValue; data.val = getNextValue(data.index++); } bits |= (resb > 0 ? 1 : 0) * power; power <<= 1; } dictionary[dictSize++] = String.fromCharCode(bits); c = dictSize - 1; enlargeIn--; break; case 2: return result.join(""); } if (enlargeIn == 0) { enlargeIn = Math.pow(2, numBits); numBits++; } if (dictionary[c]) { entry = dictionary[c]; } else { if (c === dictSize && typeof w === "string") { entry = w + w.charAt(0); } else { return null; } } result.push(entry); dictionary[dictSize++] = w + entry.charAt(0); enlargeIn--; w = entry; if (enlargeIn == 0) { enlargeIn = Math.pow(2, numBits); numBits++; } } }