/**
* A function for converting hex <-> dec w/o loss of precision.
* By Dan Vanderkam http://www.danvk.org/hex2dec.html
*/
/**
* Adds two arrays for the given base (10 or 16), returning the result.
* This turns out to be the only "primitive" operation we need.
* @param {any[]} x
* @param {any[]} y
* @param {number} base
* @private
* @return {number[]}
*/
function add(x: any[], y: any[], base: number): number[] {
const z = [];
const n = Math.max(x.length, y.length);
let carry = 0;
let i = 0;
while(i < n || carry) {
const xi = i < x.length ? x[i] : 0;
const yi = i < y.length ? y[i] : 0;
const zi = carry + xi + yi;
z.push(zi % base);
carry = Math.floor(zi / base);
i++;
}
return z;
}
/**
* Returns a*x, where x is an array of decimal digits and a is an ordinary
* JavaScript number. base is the number base of the array x.
* @param {number} num
* @param {number[]} x
* @param {number} base
* @private
* @return {number[]}
*/
function multiplyByNumber(num: number, x: number[], base: number): number[] {
if(num < 0) return [];
if(num == 0) return [];
let result: number[] = [];
let power = x;
while(true) {
if(num & 1) {
result = add(result, power, base);
}
num = num >> 1;
if(num === 0) break;
power = add(power, power, base);
}
return result;
}
/**
* Parses string into array of digits
* @param {string} str to parse
* @param {number} base
* @private
* @return {number[] | null}
*/
function parseToDigitsArray(str: string, base: number): number[] | null {
const digits = str.split("");
const ary = [];
for(let i = digits.length - 1; i >= 0; i--) {
const n = parseInt(digits[i], base);
if(isNaN(n)) return null;
ary.push(n);
}
return ary;
}
/**
* Converts base
* @param {string} str to convert
* @param {number} fromBase
* @param {number} toBase
* @private
* @return {string}
*/
function convertBase(str: string, fromBase: number, toBase: number): string | null {
const digits = parseToDigitsArray(str, fromBase);
if(digits === null) return null;
let outArray: number[] = [];
let power = [1];
for(var i = 0; i < digits.length; i++) {
// invariant: at this point, fromBase^i = power
if(digits[i]) {
outArray = add(
outArray,
multiplyByNumber(digits[i], power, toBase),
toBase
);
}
power = multiplyByNumber(fromBase, power, toBase);
}
let out = "";
for(var i = outArray.length - 1; i >= 0; i--) {
out += outArray[i].toString(toBase);
}
return out;
}
/**
* Converts hex to decimal
* @param {string} hexStr Hex string to convert
* @return {string | null}
*/
function hexToDec(hexStr: string): string | null {
if(hexStr.substring(0, 2) === "0x") hexStr = hexStr.substring(2);
hexStr = hexStr.toLowerCase();
return convertBase(hexStr, 16, 10);
}
export { hexToDec };
Source