diff --git a/src/js/core/read_write_proxy.js b/src/js/core/read_write_proxy.js index 2bc31396..949eb802 100644 --- a/src/js/core/read_write_proxy.js +++ b/src/js/core/read_write_proxy.js @@ -3,7 +3,6 @@ import { Application } from "../application"; /* typehints:end */ import { FsError } from "@/platform/fs_error"; -import { compressObject, decompressObject } from "../savegame/savegame_compressor"; import { asyncCompressor, compressionPrefix } from "./async_compression"; import { IS_DEBUG, globalConfig } from "./config"; import { ExplainedResult } from "./explained_result"; @@ -85,7 +84,7 @@ export class ReadWriteProxy { * @param {object} obj */ static serializeObject(obj) { - const jsonString = JSON.stringify(compressObject(obj)); + const jsonString = JSON.stringify(obj); const checksum = computeCrc(jsonString + salt); return compressionPrefix + compressX64(checksum + jsonString); } @@ -117,8 +116,7 @@ export class ReadWriteProxy { } const parsed = JSON.parse(jsonString); - const decoded = decompressObject(parsed); - return decoded; + return parsed; } /** @@ -180,7 +178,7 @@ export class ReadWriteProxy { .then(rawData => { if (rawData == null) { // So, the file has not been found, use default data - return JSON.stringify(compressObject(this.getDefaultData())); + return JSON.stringify(this.getDefaultData()); } if (rawData.startsWith(compressionPrefix)) { @@ -233,9 +231,6 @@ export class ReadWriteProxy { } }) - // Decompress - .then(compressed => decompressObject(compressed)) - // Verify basic structure .then(contents => { const result = this.internalVerifyBasicStructure(contents); diff --git a/src/js/savegame/savegame_compressor.js b/src/js/savegame/savegame_compressor.js deleted file mode 100644 index d8797bad..00000000 --- a/src/js/savegame/savegame_compressor.js +++ /dev/null @@ -1,168 +0,0 @@ -const charmap = - "!#%&'()*+,-./:;<=>?@[]^_`{|}~¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -let compressionCache = {}; -let decompressionCache = {}; - -/** - * Compresses an integer into a tight string representation - * @param {number} i - * @returns {string} - */ -function compressInt(i) { - // Zero value breaks - i += 1; - - // save `i` as the cache key - // to avoid it being modified by the - // rest of the function. - const cache_key = i; - - if (compressionCache[cache_key]) { - return compressionCache[cache_key]; - } - let result = ""; - do { - result += charmap[i % charmap.length]; - i = Math.floor(i / charmap.length); - } while (i > 0); - return (compressionCache[cache_key] = result); -} - -/** - * Decompresses an integer from its tight string representation - * @param {string} s - * @returns {number} - */ -function decompressInt(s) { - if (decompressionCache[s]) { - return decompressionCache[s]; - } - s = "" + s; - let result = 0; - for (let i = s.length - 1; i >= 0; --i) { - result = result * charmap.length + charmap.indexOf(s.charAt(i)); - } - // Fixes zero value break fix from above - result -= 1; - return (decompressionCache[s] = result); -} - -// Sanity -if (G_IS_DEV) { - for (let i = 0; i < 10000; ++i) { - if (decompressInt(compressInt(i)) !== i) { - throw new Error( - "Bad compression for: " + - i + - " compressed: " + - compressInt(i) + - " decompressed: " + - decompressInt(compressInt(i)) - ); - } - } -} - -/** - * @param {any} obj - * @param {Map} keys - * @param {Map} values - * @returns {any[]|object|number|string} - */ -function compressObjectInternal(obj, keys, values) { - if (Array.isArray(obj)) { - let result = []; - for (let i = 0; i < obj.length; ++i) { - result.push(compressObjectInternal(obj[i], keys, values)); - } - return result; - } else if (typeof obj === "object" && obj !== null) { - let result = {}; - for (const key in obj) { - let index = keys.get(key); - if (index === undefined) { - index = keys.size; - keys.set(key, index); - } - const value = obj[key]; - result[compressInt(index)] = compressObjectInternal(value, keys, values); - } - return result; - } else if (typeof obj === "string") { - let index = values.get(obj); - if (index === undefined) { - index = values.size; - values.set(obj, index); - } - return compressInt(index); - } - return obj; -} - -/** - * @param {Map} hashMap - * @returns {Array} - */ -function indexMapToArray(hashMap) { - const result = new Array(hashMap.size); - hashMap.forEach((index, key) => { - result[index] = key; - }); - return result; -} - -/** - * @param {object} obj - */ -export function compressObject(obj) { - const keys = new Map(); - const values = new Map(); - const data = compressObjectInternal(obj, keys, values); - return { - keys: indexMapToArray(keys), - values: indexMapToArray(values), - data, - }; -} - -/** - * @param {object} obj - * @param {string[]} keys - * @param {any[]} values - * @returns {object} - */ -function decompressObjectInternal(obj, keys = [], values = []) { - if (Array.isArray(obj)) { - let result = []; - for (let i = 0; i < obj.length; ++i) { - result.push(decompressObjectInternal(obj[i], keys, values)); - } - return result; - } else if (typeof obj === "object" && obj !== null) { - let result = {}; - for (const key in obj) { - const realIndex = decompressInt(key); - const value = obj[key]; - result[keys[realIndex]] = decompressObjectInternal(value, keys, values); - } - return result; - } else if (typeof obj === "string") { - const realIndex = decompressInt(obj); - return values[realIndex]; - } - return obj; -} - -/** - * @param {object} obj - */ -export function decompressObject(obj) { - if (obj.keys && obj.values && obj.data) { - const keys = obj.keys; - const values = obj.values; - const result = decompressObjectInternal(obj.data, keys, values); - return result; - } - return obj; -} diff --git a/src/js/webworkers/compression.worker.js b/src/js/webworkers/compression.worker.js index e0414d7c..83862d10 100644 --- a/src/js/webworkers/compression.worker.js +++ b/src/js/webworkers/compression.worker.js @@ -1,7 +1,6 @@ import { globalConfig } from "../core/config"; import { compressX64 } from "../core/lzstring"; import { computeCrc } from "../core/sensitive_utils.encrypt"; -import { compressObject } from "../savegame/savegame_compressor"; self.addEventListener("message", event => { // @ts-ignore @@ -19,8 +18,7 @@ function performJob(job, data) { } case "compressObject": { - const optimized = compressObject(data.obj); - const stringified = JSON.stringify(optimized); + const stringified = JSON.stringify(data.obj); const checksum = computeCrc(stringified + globalConfig.info.file); return data.compressionPrefix + compressX64(checksum + stringified);