4 * Copyright (C) 2019 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #define DEFINE_XTOA(t, p, s) \
26 char *__CRT_PUBLIC(p##toa)(t value, char *str, int base) \
29 if (base < 2 || base > 36) return NULL; \
45 for (temp = value; temp > 0##s; temp /= (t)base) ptr++; \
48 while (value > 0##s) \
50 *--ptr = all_digits[value % (t)base]; \
57 char *__CRT_PUBLIC(u##p##toa)(unsigned t value, char *str, int base) \
60 if (base < 2 || base > 36) return NULL; \
70 for (temp = value; temp > 0U##s; temp /= (unsigned t)base) ptr++; \
73 while (value > 0U##s) \
75 *--ptr = all_digits[value % (unsigned t)base]; \
76 value /= (unsigned t)base; \
82 #define DEFINE_ATOX(t, n, p, s) \
83 t __CRT_PUBLIC(ato##p)(const char *str) \
85 return __CRT_PUBLIC(strto##p)(str, NULL, 10); \
88 t __CRT_PUBLIC(strto##p)(const char *str, char **endptr, int base) \
92 int overflow = 0, negative = 0; \
94 if (base < 2 || base > 36) return 0; \
105 for (ptr = str; *ptr; ptr++) \
107 char *digit_ptr = __CRT_PUBLIC(strchr)(all_digits, __CRT_PUBLIC(toupper)(*ptr)); \
108 if (digit_ptr == NULL) break; \
110 t digit = (t)(digit_ptr - all_digits); \
111 if (digit >= base) break; \
113 t new_result = result * (t)base + digit; \
114 if (new_result < result) overflow = 1; \
115 result = new_result; \
120 __CRT_PUBLIC(errno) = ERANGE; \
121 return negative ? n##_MIN : n##_MAX; \
124 if (negative) result = -result; \
125 if (endptr) *endptr = (char*)ptr; \
129 unsigned t __CRT_PUBLIC(strtou##p)(const char *str, char **endptr, int base) \
132 unsigned t result = 0UL; \
135 if (base < 2 || base > 36) return 0; \
137 for (ptr = str; *ptr; ptr++) \
139 char *digit_ptr = __CRT_PUBLIC(strchr)(all_digits, __CRT_PUBLIC(toupper)(*ptr)); \
140 if (digit_ptr == NULL) break; \
142 unsigned t digit = (unsigned t)(digit_ptr - all_digits); \
143 if (digit >= base) break; \
145 unsigned t new_result = result * (unsigned t)base + digit; \
146 if (new_result < result) overflow = 1; \
147 result = new_result; \
152 __CRT_PUBLIC(errno) = ERANGE; \
156 if (endptr) *endptr = (char*)ptr; \
160 static const char all_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
162 DEFINE_XTOA(int, i, );
163 DEFINE_XTOA(long, l, L);
164 DEFINE_XTOA(long long, ll, LL);
166 DEFINE_ATOX(long, LONG, l, L);
167 DEFINE_ATOX(long long, LLONG, ll, LL);
169 int __CRT_PUBLIC(atoi)(const char *str)
171 return (int)__CRT_PUBLIC(strtol)(str, NULL, 10);