]> git.proxmox.com Git - wasi-libc.git/blob - libc-bottom-half/cloudlibc/src/common/parser_strtoint.h
fix macos filename, use https
[wasi-libc.git] / libc-bottom-half / cloudlibc / src / common / parser_strtoint.h
1 // Copyright (c) 2015 Nuxi, https://nuxi.nl/
2 //
3 // SPDX-License-Identifier: BSD-2-Clause
4
5 // Parser of integer literals as performed by strtol(), scanf(), etc.
6
7 // Result of parsing.
8 bool have_number = false;
9 bool have_overflow = false;
10 int_t number = 0;
11
12 {
13 // Negative or positive number?
14 bool negative = false;
15 if (allow_negative && PEEK(0) == '-') {
16 negative = true;
17 SKIP(1);
18 } else if (PEEK(0) == '+') {
19 SKIP(1);
20 }
21
22 // Determine the base.
23 if ((base == 0 || base == 16) && PEEK(0) == '0' &&
24 (PEEK(1) == 'x' || PEEK(1) == 'X') &&
25 ((PEEK(2) >= '0' && PEEK(2) <= '9') ||
26 (PEEK(2) >= 'A' && PEEK(2) <= 'F') ||
27 (PEEK(2) >= 'a' && PEEK(2) <= 'f'))) {
28 SKIP(2);
29 base = 16;
30 } else if (base == 0) {
31 base = PEEK(0) == '0' ? 8 : 10;
32 }
33
34 // Only perform conversion if the base is valid.
35 if (base >= 2 && base <= 36) {
36 uint_fast8_t radix = base;
37
38 // Determine the highest value up to which we can parse so that the
39 // next digit does not cause an overflow.
40 uintmax_t ceil;
41 uint_fast8_t last_digit;
42 if (negative) {
43 ceil = -(min / radix);
44 last_digit = -(min % radix);
45 } else {
46 ceil = max / radix;
47 last_digit = max % radix;
48 }
49
50 uintmax_t value = 0;
51 for (;;) {
52 // Parse next digit.
53 uint_fast8_t digit;
54 if (PEEK(0) >= '0' && PEEK(0) <= '9')
55 digit = PEEK(0) - '0';
56 else if (PEEK(0) >= 'A' && PEEK(0) <= 'Z')
57 digit = PEEK(0) - 'A' + 10;
58 else if (PEEK(0) >= 'a' && PEEK(0) <= 'z')
59 digit = PEEK(0) - 'a' + 10;
60 else
61 break;
62 if (digit >= radix)
63 break;
64 SKIP(1);
65
66 // Add it to result.
67 have_number = true;
68 if (value > ceil || (value == ceil && digit > last_digit)) {
69 // Addition of the new digit would cause an overflow.
70 have_overflow = true;
71 } else {
72 value = value * radix + digit;
73 }
74 }
75
76 if (have_overflow) {
77 // Set value to min or max depending whether the input is negative
78 // and whether the output type is signed.
79 number = (int_t)-1 >= 0 || !negative ? max : min;
80 } else {
81 // Return parsed value.
82 number = negative ? -value : value;
83 }
84 }
85 }