mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-13 18:21:51 +00:00
Many configuration files in this repository were created a long time ago, then were modified as problems occurred. Now that there is TypeScript support, it makes sense to clean up this mess, at least by making small steps. This configuration is based on strict settings, but most of these are currently disabled - otherwise it would be too hard to work with existing JavaScript code. The downside of this change is pollution of files with warnings and errors, even though they are valid. - ESLint/TypeScript upgraded - TS configuration is now shared between arbitrary Node scripts, Gulp files and the Electron wrapper - A few eslint-disable comments are removed
492 lines
17 KiB
JavaScript
492 lines
17 KiB
JavaScript
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
|
|
// This work is free. You can redistribute it and/or modify it
|
|
// under the terms of the WTFPL, Version 2
|
|
// For more information see LICENSE.txt or http://www.wtfpl.net/
|
|
//
|
|
// For more information, the home page:
|
|
// http://pieroxy.net/blog/pages/lz-string/testing.html
|
|
//
|
|
// LZ-based compression algorithm, version 1.4.4
|
|
|
|
const fromCharCode = String.fromCharCode;
|
|
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
|
|
const keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
|
|
const 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];
|
|
}
|
|
|
|
//compress into uint8array (UCS-2 big endian format)
|
|
export function compressU8(uncompressed) {
|
|
let compressed = compress(uncompressed);
|
|
let buf = new Uint8Array(compressed.length * 2); // 2 bytes per character
|
|
|
|
for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
|
|
let current_value = compressed.charCodeAt(i);
|
|
buf[i * 2] = current_value >>> 8;
|
|
buf[i * 2 + 1] = current_value % 256;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
// Compreses with header
|
|
/**
|
|
* @param {string} uncompressed
|
|
* @param {number} header
|
|
*/
|
|
export function compressU8WHeader(uncompressed, header) {
|
|
let compressed = compress(uncompressed);
|
|
let buf = new Uint8Array(2 + compressed.length * 2); // 2 bytes per character
|
|
|
|
buf[0] = header >>> 8;
|
|
buf[1] = header % 256;
|
|
for (let i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
|
|
let current_value = compressed.charCodeAt(i);
|
|
buf[2 + i * 2] = current_value >>> 8;
|
|
buf[2 + i * 2 + 1] = current_value % 256;
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
//decompress from uint8array (UCS-2 big endian format)
|
|
/**
|
|
*
|
|
* @param {Uint8Array} compressed
|
|
*/
|
|
export function decompressU8WHeader(compressed) {
|
|
// let buf = new Array(compressed.length / 2); // 2 bytes per character
|
|
// for (let i = 0, TotalLen = buf.length; i < TotalLen; i++) {
|
|
// buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1];
|
|
// }
|
|
|
|
// let result = [];
|
|
// buf.forEach(function (c) {
|
|
// result.push(fromCharCode(c));
|
|
// });
|
|
let result = [];
|
|
for (let i = 2, n = compressed.length; i < n; i += 2) {
|
|
const code = compressed[i] * 256 + compressed[i + 1];
|
|
result.push(fromCharCode(code));
|
|
}
|
|
return decompress(result.join(""));
|
|
}
|
|
|
|
//compress into a string that is already URI encoded
|
|
export function compressX64(input) {
|
|
if (input == null) return "";
|
|
return _compress(input, 6, function (a) {
|
|
return keyStrUriSafe.charAt(a);
|
|
});
|
|
}
|
|
|
|
//decompress from an output of compressToEncodedURIComponent
|
|
export function decompressX64(input) {
|
|
if (input == null) return "";
|
|
if (input == "") return null;
|
|
input = input.replace(/ /g, "+");
|
|
return _decompress(input.length, 32, function (index) {
|
|
return getBaseValue(keyStrUriSafe, input.charAt(index));
|
|
});
|
|
}
|
|
|
|
function compress(uncompressed) {
|
|
return _compress(uncompressed, 16, function (a) {
|
|
return fromCharCode(a);
|
|
});
|
|
}
|
|
|
|
function _compress(uncompressed, bitsPerChar, getCharFromInt) {
|
|
if (uncompressed == null) return "";
|
|
let i,
|
|
value,
|
|
context_dictionary = {},
|
|
context_dictionaryToCreate = {},
|
|
context_c = "",
|
|
context_wc = "",
|
|
context_w = "",
|
|
context_enlargeIn = 2, // Compensate for the first entry which should not count
|
|
context_dictSize = 3,
|
|
context_numBits = 2,
|
|
context_data = [],
|
|
context_data_val = 0,
|
|
context_data_position = 0,
|
|
ii;
|
|
|
|
for (ii = 0; ii < uncompressed.length; ii += 1) {
|
|
context_c = uncompressed.charAt(ii);
|
|
if (!hasOwnProperty.call(context_dictionary, context_c)) {
|
|
context_dictionary[context_c] = context_dictSize++;
|
|
context_dictionaryToCreate[context_c] = true;
|
|
}
|
|
|
|
context_wc = context_w + context_c;
|
|
if (hasOwnProperty.call(context_dictionary, context_wc)) {
|
|
context_w = context_wc;
|
|
} else {
|
|
if (hasOwnProperty.call(context_dictionaryToCreate, context_w)) {
|
|
if (context_w.charCodeAt(0) < 256) {
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = context_data_val << 1;
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
}
|
|
value = context_w.charCodeAt(0);
|
|
for (i = 0; i < 8; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
} else {
|
|
value = 1;
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = (context_data_val << 1) | value;
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = 0;
|
|
}
|
|
value = context_w.charCodeAt(0);
|
|
for (i = 0; i < 16; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
}
|
|
context_enlargeIn--;
|
|
if (context_enlargeIn == 0) {
|
|
context_enlargeIn = Math.pow(2, context_numBits);
|
|
context_numBits++;
|
|
}
|
|
delete context_dictionaryToCreate[context_w];
|
|
} else {
|
|
value = context_dictionary[context_w];
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
}
|
|
context_enlargeIn--;
|
|
if (context_enlargeIn == 0) {
|
|
context_enlargeIn = Math.pow(2, context_numBits);
|
|
context_numBits++;
|
|
}
|
|
// Add wc to the dictionary.
|
|
context_dictionary[context_wc] = context_dictSize++;
|
|
context_w = String(context_c);
|
|
}
|
|
}
|
|
|
|
// Output the code for w.
|
|
if (context_w !== "") {
|
|
if (hasOwnProperty.call(context_dictionaryToCreate, context_w)) {
|
|
if (context_w.charCodeAt(0) < 256) {
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = context_data_val << 1;
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
}
|
|
value = context_w.charCodeAt(0);
|
|
for (i = 0; i < 8; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
} else {
|
|
value = 1;
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = (context_data_val << 1) | value;
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = 0;
|
|
}
|
|
value = context_w.charCodeAt(0);
|
|
for (i = 0; i < 16; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
}
|
|
context_enlargeIn--;
|
|
if (context_enlargeIn == 0) {
|
|
context_enlargeIn = Math.pow(2, context_numBits);
|
|
context_numBits++;
|
|
}
|
|
delete context_dictionaryToCreate[context_w];
|
|
} else {
|
|
value = context_dictionary[context_w];
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
}
|
|
context_enlargeIn--;
|
|
if (context_enlargeIn == 0) {
|
|
context_enlargeIn = Math.pow(2, context_numBits);
|
|
context_numBits++;
|
|
}
|
|
}
|
|
|
|
// Mark the end of the stream
|
|
value = 2;
|
|
for (i = 0; i < context_numBits; i++) {
|
|
context_data_val = (context_data_val << 1) | (value & 1);
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data_position = 0;
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
context_data_val = 0;
|
|
} else {
|
|
context_data_position++;
|
|
}
|
|
value = value >> 1;
|
|
}
|
|
|
|
// Flush the last char
|
|
while (true) {
|
|
context_data_val = context_data_val << 1;
|
|
if (context_data_position == bitsPerChar - 1) {
|
|
context_data.push(getCharFromInt(context_data_val));
|
|
break;
|
|
} else context_data_position++;
|
|
}
|
|
return context_data.join("");
|
|
}
|
|
|
|
function decompress(compressed) {
|
|
if (compressed == null) return "";
|
|
if (compressed == "") return null;
|
|
return _decompress(compressed.length, 32768, function (index) {
|
|
return compressed.charCodeAt(index);
|
|
});
|
|
}
|
|
|
|
function _decompress(length, resetValue, getNextValue) {
|
|
let dictionary = [],
|
|
next,
|
|
enlargeIn = 4,
|
|
dictSize = 4,
|
|
numBits = 3,
|
|
entry = "",
|
|
result = [],
|
|
i,
|
|
w,
|
|
bits,
|
|
resb,
|
|
maxpower,
|
|
power,
|
|
c,
|
|
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 = 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 = 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++] = 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++] = fromCharCode(bits);
|
|
c = dictSize - 1;
|
|
enlargeIn--;
|
|
break;
|
|
case 2:
|
|
return result.join("");
|
|
}
|
|
|
|
if (enlargeIn == 0) {
|
|
enlargeIn = Math.pow(2, numBits);
|
|
numBits++;
|
|
}
|
|
|
|
if (dictionary[c]) {
|
|
// @ts-ignore
|
|
entry = dictionary[c];
|
|
} else {
|
|
if (c === dictSize) {
|
|
entry = w + w.charAt(0);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
result.push(entry);
|
|
|
|
// Add w+entry[0] to the dictionary.
|
|
dictionary[dictSize++] = w + entry.charAt(0);
|
|
enlargeIn--;
|
|
|
|
w = entry;
|
|
|
|
if (enlargeIn == 0) {
|
|
enlargeIn = Math.pow(2, numBits);
|
|
numBits++;
|
|
}
|
|
}
|
|
}
|