@matschik/lz-string
Version:
Modern port of LZ-String
430 lines (428 loc) • 12.9 kB
JavaScript
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++;
}
}
}