Skip to content

Instantly share code, notes, and snippets.

@danielgindi
Created July 28, 2020 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielgindi/3f9b0f975d770e50f5b814252b1f9ca7 to your computer and use it in GitHub Desktop.
Save danielgindi/3f9b0f975d770e50f5b814252b1f9ca7 to your computer and use it in GitHub Desktop.
LZRW1
class LZRW1 {
static #FLAG_BYTES = 4;
static #FLAG_COMPRESS = 0;
static #FLAG_COPY = 1;
static #WORK_MEM_ALLOC = 4 * 4096 + 3;
static #WORKMEM = new Array(LZRW1.#WORK_MEM_ALLOC);
/** @returns {Buffer} */
static compress(/**@type Buffer*/input) {
const WORKMEM = this.#WORKMEM.fill(0);
const ITEMMAX = 18;
const TOPWORD = 0xFFFF0000;
let control = TOPWORD;
let p_src = 0;
let p_src_max1 = input.length - ITEMMAX;
let p_src_max16 = input.length - 16 * ITEMMAX;
let output = [];
output.push(LZRW1.#FLAG_COMPRESS);
for (let i = 1; i < LZRW1.#FLAG_BYTES; i++)
output.push(0);
let p_control = output.length;
output.push(0, 0);
while (true) {
let unroll = 16;
let offset = 0;
if (output.length > input.length) {
for (let i = 0; i < input.length; i++)
output[LZRW1.#FLAG_BYTES + i] = input[i];
output[0] = LZRW1.#FLAG_COPY;
output = output.slice(0, input.length + LZRW1.#FLAG_BYTES);
return Buffer.from(output);
}
let doLiteral = false;
if (p_src > p_src_max16) {
unroll = 1;
if (p_src > p_src_max1) {
if (p_src === input.length)
break;
doLiteral = true;
}
}
do {
if (doLiteral) {
doLiteral = false;
output.push(input[p_src++]);
control &= 0xFFFEFFFF;
} else {
let p_entry = ((40543 * ((((input[p_src] << 4 >>> 0) ^ input[p_src + 1]) << 4 >>> 0) ^ input[p_src + 2])) >> 4) & 0xFFF;
let p = WORKMEM[p_entry];
WORKMEM[p_entry] = p_src;
offset = p_src - p;
if (offset > 4095 || p < 0 || offset === 0 ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++]) {
p_src = WORKMEM[p_entry];
output.push(input[p_src++]);
control &= 0xFFFEFFFF;
} else {
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
input[p++] !== input[p_src++] ||
p_src++;
output.push(((offset & 0xF00) >>> 4) | (--p_src - WORKMEM[p_entry] - 3));
output.push(offset & 0xff);
}
}
control >>>= 1;
} while (--unroll);
if ((control & TOPWORD) === 0) {
output[p_control] = control & 0xff;
output[p_control + 1] = (control >>> 8) & 0xFF;
p_control = output.length;
output.push(0, 0);
control = TOPWORD;
}
}
while (control & TOPWORD)
control >>>= 1;
output[p_control++] = control & 0xff;
output[p_control++] = control >>> 8;
if (p_control === output.length) {
output.pop();
output.pop();
}
return new Buffer(output);
}
/** @returns {Buffer} */
static decompress(/**@type Buffer*/input) {
let p_src = LZRW1.#FLAG_BYTES;
let output = [];
let p_src_max16 = input.length - (16 * 2);
let control = 1;
if (input[0] === LZRW1.#FLAG_COPY) {
for (let i = LZRW1.#FLAG_BYTES; i < input.length; i++)
output.push(input[i]);
return Buffer.from(output);
}
while (p_src !== input.length) {
let unroll = 0;
if (control === 1) {
control = 0x10000 | input[p_src++];
control |= input[p_src++] << 8 >>> 0;
}
unroll = p_src <= p_src_max16 ? 16 : 1;
while (unroll--) {
if ((control & 1) !== 0) {
let lenmt = 0;
lenmt = input[p_src++];
let p = output.length - (((lenmt & 0xF0) << 4 >>> 0) | input[p_src++]);
output.push(output[p++]);
output.push(output[p++]);
output.push(output[p++]);
lenmt &= 0xF;
while (lenmt--)
output.push(output[p++]);
} else {
output.push(input[p_src++]);
}
control >>= 1;
}
}
return Buffer.from(output);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment