]> git.wincent.com - hextrapolate.git/blob - src/getDigits.js
ea828707fbba578d77d6dc87c1995a6b0fbec7dd
[hextrapolate.git] / src / getDigits.js
1 /**
2  * Copyright 2003-present Greg Hurrell. All rights reserved.
3  * Licensed under the terms of the MIT license.
4  *
5  * @flow
6  */
7
8 import DIGITS from './DIGITS';
9
10 const DIGITS_MAP = {};
11 DIGITS.split('').forEach((digit, i) => {
12   DIGITS_MAP[digit] = i;
13 });
14
15 /**
16  * Strips the leading prefix from `number` in `base` and returns the remaining
17  * part of the string.
18  *
19  * - "0x" (or "0X") for hexadecimal numbers.
20  * - "0" for octal numbers.
21  *
22  * For all bases, leading whitespace is stripped.
23  */
24 function stripPrefix(number: string, base: number): string {
25   if (base === 16) {
26     return number.replace(/^\s*0x/i, '');
27   } else if (base === 8) {
28     return number.replace(/^\s*0/, '');
29   } else {
30     return number.replace(/^\s*/, '');
31   }
32 }
33
34 function parse(digit: string, base: number) {
35   if (base > 36 && base <= 62) {
36     // This branch only called for serialization to/from the URL.
37     const position = DIGITS_MAP[digit];
38     return position !== -1 && position < base ? position + 1 : NaN;
39   } else {
40     return parseInt(digit, base);
41   }
42 }
43
44 /**
45  * Breaks the string repsentation of `number` in `base` into an array of decimal
46  * digits (from most significant to least significant) for easier manipulation.
47  *
48  * For example, the hexadecimal representation `"40fa"` becomes
49  * `[4, 0, 15, 10]`.
50  */
51 export default function getDigits(number: string, base: number): Array<number> {
52   return stripPrefix(number, base).trim().split('').map(digit => {
53     const result = parse(digit, base);
54     if (isNaN(result)) {
55       throw new Error('Invalid digit `' + digit + '` for base `' + base + '`');
56     }
57     return result;
58   });
59 }