Created
July 16, 2021 08:35
-
-
Save tail-call/f3d394279cbb1e0f5fb4d977a714aee7 to your computer and use it in GitHub Desktop.
Compress JS strings for fun and profit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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