SimpleKernel 1.17.0
Loading...
Searching...
No Matches
sk_stdlib.c
Go to the documentation of this file.
1
5#include "sk_stdlib.h"
6
7#include <limits.h>
8#include <stdbool.h>
9#include <stddef.h>
10#include <stdint.h>
11
12#include "sk_ctype.h"
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
19uint64_t __stack_chk_guard = 0x595E9FBD94FDA766;
20
22[[noreturn]] void __stack_chk_fail() { while (true); }
23
24// Internal helper for string to number conversion
25// Parses magnitude into unsigned long long.
26// handles base detection, whitespace, signs.
27static unsigned long long strtox_main(const char* nptr, char** endptr, int base,
28 int* sign_out, int* overflow) {
29 const char* s = nptr;
30 unsigned long long acc = 0;
31 int c;
32 unsigned long long cutoff;
33 int cutlim;
34 int any = 0;
35 int negative = 0;
36
37 *overflow = 0;
38
39 // Skip whitespace
40 while (isspace(*s)) s++;
41
42 // Check sign
43 if (*s == '-') {
44 negative = 1;
45 s++;
46 } else if (*s == '+') {
47 s++;
48 }
49 if (sign_out) *sign_out = negative;
50
51 // Detect base
52 if ((base == 0 || base == 16) && *s == '0' && (s[1] == 'x' || s[1] == 'X')) {
53 // Hex prefix
54 // We speculatively consume it.
55 if (isxdigit(s[2])) {
56 s += 2;
57 base = 16;
58 } else {
59 // '0x' followed by non-hex.
60 // if base==0, it's octal 0.
61 if (base == 0) base = 8;
62 }
63 }
64 if (base == 0) {
65 base = *s == '0' ? 8 : 10;
66 }
67
68 if (base < 2 || base > 36) {
69 if (endptr) *endptr = (char*)nptr; // Invalid base
70 return 0;
71 }
72
73 cutoff = ULLONG_MAX / (unsigned long long)base;
74 cutlim = ULLONG_MAX % (unsigned long long)base;
75
76 for (;; s++) {
77 c = *s;
78 if (isdigit(c))
79 c -= '0';
80 else if (isalpha(c))
81 c = toupper(c) - 'A' + 10;
82 else
83 break;
84
85 if (c >= base) break;
86
87 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) {
88 any = -1; // overflow
89 } else {
90 any = 1;
91 acc = acc * base + c;
92 }
93 }
94
95 if (any < 0) {
96 *overflow = 1;
97 acc = ULLONG_MAX;
98 }
99
100 // Set endptr
101 if (endptr) {
102 *endptr = (char*)(any ? s : nptr);
103 }
104 return acc;
105}
106
107unsigned long long int strtoull(const char* nptr, char** endptr, int base) {
108 int negative;
109 int overflow;
110 unsigned long long acc =
111 strtox_main(nptr, endptr, base, &negative, &overflow);
112
113 if (overflow) return ULLONG_MAX;
114 return negative ? -acc : acc;
115}
116
117long long int strtoll(const char* nptr, char** endptr, int base) {
118 int negative;
119 int overflow;
120 unsigned long long acc =
121 strtox_main(nptr, endptr, base, &negative, &overflow);
122
123 if (overflow) {
124 return negative ? LLONG_MIN : LLONG_MAX;
125 }
126
127 if (negative) {
128 if (acc > (unsigned long long)LLONG_MAX + 1) return LLONG_MIN;
129 return -(long long)acc;
130 } else {
131 if (acc > LLONG_MAX) return LLONG_MAX;
132 return (long long)acc;
133 }
134}
135
136long int strtol(const char* nptr, char** endptr, int base) {
137 long long int val = strtoll(nptr, endptr, base);
138#if LONG_MAX != LLONG_MAX
139 if (val > LONG_MAX) return LONG_MAX;
140 if (val < LONG_MIN) return LONG_MIN;
141#endif
142 return (long int)val;
143}
144
145unsigned long int strtoul(const char* nptr, char** endptr, int base) {
146 unsigned long long int val = strtoull(nptr, endptr, base);
147#if ULONG_MAX != ULLONG_MAX
148 if (val > ULONG_MAX) return ULONG_MAX;
149#endif
150 return (unsigned long int)val;
151}
152
153int atoi(const char* nptr) { return (int)strtol(nptr, NULL, 10); }
154
155long int atol(const char* nptr) { return strtol(nptr, NULL, 10); }
156
157long long int atoll(const char* nptr) { return strtoll(nptr, NULL, 10); }
158
159#if (defined(__x86_64__) && defined(__SSE__)) || \
160 (defined(__aarch64__) && defined(__ARM_FP)) || defined(__riscv)
161double strtod(const char* nptr, char** endptr) {
162 const char* s = nptr;
163 double acc = 0.0;
164 int sign = 1;
165
166 while (isspace(*s)) s++;
167
168 if (*s == '-') {
169 sign = -1;
170 s++;
171 } else if (*s == '+') {
172 s++;
173 }
174
175 int any = 0;
176 while (isdigit(*s)) {
177 any = 1;
178 acc = acc * 10.0 + (*s - '0');
179 s++;
180 }
181
182 if (*s == '.') {
183 s++;
184 double k = 0.1;
185 while (isdigit(*s)) {
186 any = 1;
187 acc += (*s - '0') * k;
188 k *= 0.1;
189 s++;
190 }
191 }
192
193 if (any && (*s == 'e' || *s == 'E')) {
194 int esign = 1;
195 int exp = 0;
196 const char* eptr = s + 1;
197
198 if (*eptr == '-') {
199 esign = -1;
200 eptr++;
201 } else if (*eptr == '+') {
202 eptr++;
203 }
204
205 if (isdigit(*eptr)) {
206 while (isdigit(*eptr)) {
207 exp = exp * 10 + (*eptr - '0');
208 eptr++;
209 }
210 s = eptr;
211 double p = 1.0;
212 double b = 10.0;
213 while (exp) {
214 if (exp & 1) p *= b;
215 b *= b;
216 exp >>= 1;
217 }
218 if (esign > 0)
219 acc *= p;
220 else
221 acc /= p;
222 }
223 }
224
225 if (endptr) *endptr = (char*)(any ? s : nptr);
226 return sign * acc;
227}
228
229float strtof(const char* nptr, char** endptr) {
230 return (float)strtod(nptr, endptr);
231}
232
233double atof(const char* nptr) { return strtod(nptr, NULL); }
234#endif
235
236#ifdef __cplusplus
237}
238#endif
#define isxdigit
#define isdigit
#define isspace
#define toupper
#define isalpha
#define atof
#define strtod
#define strtoul
#define strtoll
#define strtof
#define atol
#define atoi
#define strtoull
#define atoll
#define strtol
static unsigned long long strtox_main(const char *nptr, char **endptr, int base, int *sign_out, int *overflow)
Definition sk_stdlib.c:27
uint64_t __stack_chk_guard
栈保护
Definition sk_stdlib.c:19
void __stack_chk_fail()
栈保护检查失败后进入死循环
Definition sk_stdlib.c:22