2 * Copyright © 2023-2024 Nick Bowler
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 #ifndef CDECL99_INTCONV_H_
19 #define CDECL99_INTCONV_H_
24 enum { INTCONV_OCTAL = 8, INTCONV_DECIMAL = 10, INTCONV_HEXADECIMAL = 16 };
27 * Multiply *v by base, which must be one of the above enumeration constants,
28 * and add digit, updating *v with the result.
30 * If the result does not fit in cdecl_uintmax, then 0 is returned. Otherwise,
31 * a non-zero result is returned.
33 static inline bool intconv_shift(cdecl_uintmax *v, unsigned base, unsigned digit)
35 cdecl_uintmax old_v = *v;
37 if (old_v > (cdecl_uintmax)-1 / base)
41 return (*v = old_v + digit) >= old_v;
45 * Assuming d is a hexadecimal digit character (converted to unsigned char),
46 * return the corresponding value of that digit (between 0 and 15, inclusive).
48 static inline unsigned char intconv_digit(unsigned char d)
50 if (d >= '0' && d <= '9') {
53 #if ('A' & 7) == 1 && ('B' & 7) == 2 && ('C' & 7) == 3 \
54 && ('a' & 7) == 1 && ('b' & 7) == 2 && ('c' & 7) == 3 \
55 && ('D' & 7) == 4 && ('E' & 7) == 5 && ('F' & 7) == 6 \
56 && ('d' & 7) == 4 && ('e' & 7) == 5 && ('f' & 7) == 6
57 /* EBCDIC or ASCII-like encoding */
61 static const char idx[] = "abcdef..ABCDEF";
62 return 10 + (((char *)memchr(idx, d, sizeof idx) - idx) & 7);