Skip to content

Instantly share code, notes, and snippets.

@tail-call
Created July 16, 2021 08:35
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 tail-call/f3d394279cbb1e0f5fb4d977a714aee7 to your computer and use it in GitHub Desktop.
Save tail-call/f3d394279cbb1e0f5fb4d977a714aee7 to your computer and use it in GitHub Desktop.
Compress JS strings for fun and profit
const maxCharCode = 2 ** 16 - 1;
export function compress(input: string): string {
let output = "";
for (let pos = 0; pos < input.length; pos++) {
const maxLookBack = Math.min(pos, maxCharCode);
let didOutputMatch = false;
let charsToSkip = 0;
for (let back = 0; back < maxLookBack; back++) {
let backLen = 0;
let isMatching = false;
const maxBackLen = Math.min(input.length - pos, back);
// Compare backstring and posstring
while (backLen < maxBackLen) {
if (input[pos - back + backLen] === input[pos + backLen]) {
isMatching = true;
backLen++;
} else {
break;
}
}
// If has a match, write it and keep going
if (isMatching && backLen > 3) {
output += '\0';
output += String.fromCharCode(back);
output += String.fromCharCode(backLen);
didOutputMatch = true;
charsToSkip = backLen - 1;
break;
}
}
if (!didOutputMatch) {
output += input[pos];
}
pos += charsToSkip;
}
return output;
}
export function uncompress(input: string): string {
let output = "";
for (let pos = 0; pos < input.length; pos++) {
const char = input[pos];
if (char === '\0') {
const back = input.charCodeAt(pos + 1);
const backLen = input.charCodeAt(pos + 2);
const delta = output.slice(
output.length - back,
output.length - back + backLen
);
output += delta;
pos += 3 - 1;
} else {
output += char;
}
}
return output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment