Skip to content

Instantly share code, notes, and snippets.

@robey
Created October 5, 2017 18:08
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 robey/9e5e9a1f40bd1d9ee80c046cfa20d09b to your computer and use it in GitHub Desktop.
Save robey/9e5e9a1f40bd1d9ee80c046cfa20d09b to your computer and use it in GitHub Desktop.
encode an array of ints (that tend to be close to zero) into a packed base64-ish string
/*
* zbase64 converts an array of integers to a string, and back.
* it assumes:
* - no integer will be bigger than about 2**24
* - most will be close to zero, small positive or negative numbers
* - the strings may be copy/pasted, or have poor (or zero) unicode support
*
* strategy:
* - zig-zag encode to turn small negative numbers into small positive
* numbers
* - use a 6-bit encoding, like base64
* - encode 5 bits at a time, with the high bit indicating more bits to
* come
*
* limitations:
* - 1-letter encodings: -16 to 15
* - 2-letter encodings: -512 to 511
* - maximum range: -2**30 to (2**30 - 1), 7 letters, limited by js numbers
*/
const SIXBIT = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
export function encodeZB64(n: number): string {
// js converts to 32-bit int when you use `<<`
n = (n << 1) ^ (n >> 31);
let rv = "";
while (n > 31) {
rv += SIXBIT[32 + (n & 31)];
n >>= 5;
}
rv += SIXBIT[n];
return rv;
}
export function decodeZB64(s: string): number {
let rv = 0;
let scale = 0;
for (let i = 0; i < s.length; i++) {
rv += (SIXBIT.indexOf(s[i]) & 31) << scale;
scale += 5;
}
rv = (rv >>> 1) ^ -(rv & 1);
return rv;
}
export function encodeArrayZB64(x: number[]): string {
return x.map(encodeZB64).join("");
}
export function decodeArrayZB64(s: string): number[] {
const rv: number[] = [];
for (let i = 0; i < s.length; i++) {
const start = i;
while (SIXBIT.indexOf(s[i]) > 31) i++;
rv.push(decodeZB64(s.slice(start, i + 1)));
}
return rv;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment