Skip to content
Snippets Groups Projects
Commit b973901b authored by Millicent Billette's avatar Millicent Billette
Browse files

reduce basex complexity

parent 554211c4
No related branches found
No related tags found
No related merge requests found
......@@ -4,48 +4,58 @@ export const b58 = basex(B58_ALPHABET);
export const b16 = basex('0123456789abcdef');
export default basex;
export function basex(ALPHABET) {
const ALPHABET_MAP = {};
const BASE = ALPHABET.length;
const LEADER = ALPHABET.charAt(0);
const config = {
ALPHABET_MAP: {},
BASE: ALPHABET.length,
LEADER: ALPHABET.charAt(0),
ALPHABET: ALPHABET
}
// Pre-compute lookup table
for (let z = 0; z < ALPHABET.length; z++) {
const x = ALPHABET.charAt(z);
if (ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous');
ALPHABET_MAP[x] = z;
for (let z = 0; z < config.ALPHABET.length; z++) {
const x = config.ALPHABET.charAt(z);
if (config.ALPHABET_MAP[x] !== undefined) throw new TypeError(x + ' is ambiguous');
config.ALPHABET_MAP[x] = z;
}
return {
encode:source=>encode(source,config),
decodeUnsafe:string=>decodeUnsafe(string,config),
decode:string=>decode(string,config)
};
}
function encode(source) {
function encode(source, config) {
if (source.length === 0) return '';
const digits = [0];
for (let carry of source) {
for (let j = 0; j < digits.length; ++j) {
carry += digits[j] << 8;
digits[j] = carry % BASE;
carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
digits[j] = carry % config.BASE;
carry = (carry / config.BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
}
while (carry > 0) {
digits.push(carry % BASE);
carry = (carry / BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
digits.push(carry % config.BASE);
carry = (carry / config.BASE) | 0; // eslint-disable-line unicorn/prefer-math-trunc
}
}
let string = '';
for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) string += LEADER; // Deal with leading zeros
for (let q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]]; // Convert digits to a string
for (let k = 0; source[k] === 0 && k < source.length - 1; ++k) string += config.LEADER; // Deal with leading zeros
for (let q = digits.length - 1; q >= 0; --q) string += config.ALPHABET[digits[q]]; // Convert digits to a string
return string;
}
function decodeUnsafe(string) {
function decodeUnsafe(string, config) {
if (typeof string !== 'string') throw new TypeError('Expected String');
if (string.length === 0) return new Uint8Array(0);
const bytes = [0];
for (const chr of string) {
const value = ALPHABET_MAP[chr];
const value = config.ALPHABET_MAP[chr];
if (value === undefined) return;
let carry = value;
for (let j = 0; j < bytes.length; ++j) {
carry += bytes[j] * BASE;
carry += bytes[j] * config.BASE;
bytes[j] = carry & 0xff;
carry >>= 8;
}
......@@ -56,15 +66,12 @@ export function basex(ALPHABET) {
}
}
for (let k = 0; string[k] === LEADER && k < string.length - 1; ++k) bytes.push(0); // Deal with leading zeros
for (let k = 0; string[k] === config.LEADER && k < string.length - 1; ++k) bytes.push(0); // Deal with leading zeros
return new Uint8Array(bytes.reverse());
}
function decode(string) {
const buffer = decodeUnsafe(string);
function decode(string, config) {
const buffer = decodeUnsafe(string, config);
if (buffer) return buffer;
throw new Error('Non-base' + BASE + ' character');
}
return {encode, decodeUnsafe, decode};
throw new Error('Non-base' + config.BASE + ' character');
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment