58 lines
1.4 KiB
JavaScript
58 lines
1.4 KiB
JavaScript
export default class Compressor {
|
|
static compress(data, base) {
|
|
const dataFirst = data[0];
|
|
const dataRest = data.slice(1);
|
|
const baseFirst = base[0];
|
|
const baseRest = base.slice(1);
|
|
|
|
if (dataFirst !== baseFirst || dataRest.length !== baseRest.length) {
|
|
throw 'Cannot compress data, format does not match the base';
|
|
}
|
|
|
|
const compressed = [];
|
|
let stack = [];
|
|
for (let i in dataRest) {
|
|
if (dataRest[i] === baseRest[i]) {
|
|
stack.push(dataRest[i]);
|
|
continue;
|
|
}
|
|
|
|
if (stack.length) {
|
|
compressed.push('!' + stack.length);
|
|
}
|
|
stack = [];
|
|
compressed.push(dataRest[i]);
|
|
}
|
|
if (stack.length) {
|
|
compressed.push('!' + stack.length);
|
|
}
|
|
|
|
return [dataFirst, ...compressed];
|
|
}
|
|
|
|
static uncompress(data, base) {
|
|
if (!base) {
|
|
return data;
|
|
}
|
|
|
|
const uncompressed = [];
|
|
let i = 0;
|
|
for (let piece of data) {
|
|
const m = piece.match(/^!(\d+)$/)
|
|
if (!m) {
|
|
uncompressed.push(piece);
|
|
i++;
|
|
continue;
|
|
}
|
|
|
|
let skipped = parseInt(m[1]);
|
|
while(skipped--) {
|
|
uncompressed.push(base[i]);
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return uncompressed;
|
|
}
|
|
}
|