diff options
author | Anton Kling <anton@kling.gg> | 2024-04-17 16:55:16 +0200 |
---|---|---|
committer | Anton Kling <anton@kling.gg> | 2024-04-17 16:55:16 +0200 |
commit | d0cca44913356f8ce15e15216b0e26c2e74b4d06 (patch) | |
tree | f85f5360e528da9914cd4c45f4719d454711f012 /userland/libc/stdlib | |
parent | d3f8196eb2cd57fec5f6e2691fdbc802c4d92fc8 (diff) |
LibC: Add more functions that support "long long" integers
Diffstat (limited to 'userland/libc/stdlib')
-rw-r--r-- | userland/libc/stdlib/atol.c | 5 | ||||
-rw-r--r-- | userland/libc/stdlib/atoll.c | 5 | ||||
-rw-r--r-- | userland/libc/stdlib/strtol.c | 11 | ||||
-rw-r--r-- | userland/libc/stdlib/strtoll.c | 56 |
4 files changed, 73 insertions, 4 deletions
diff --git a/userland/libc/stdlib/atol.c b/userland/libc/stdlib/atol.c new file mode 100644 index 0000000..7669457 --- /dev/null +++ b/userland/libc/stdlib/atol.c @@ -0,0 +1,5 @@ +#include <stdlib.h> + +long atol(const char *nptr) { + return strtol(nptr, (char **)NULL, 10); +} diff --git a/userland/libc/stdlib/atoll.c b/userland/libc/stdlib/atoll.c new file mode 100644 index 0000000..a7fc26a --- /dev/null +++ b/userland/libc/stdlib/atoll.c @@ -0,0 +1,5 @@ +#include <stdlib.h> + +long long atoll(const char *nptr) { + return strtoll(nptr, (char **)NULL, 10); +} diff --git a/userland/libc/stdlib/strtol.c b/userland/libc/stdlib/strtol.c index 09a5ad7..30d04ec 100644 --- a/userland/libc/stdlib/strtol.c +++ b/userland/libc/stdlib/strtol.c @@ -4,8 +4,7 @@ #include <limits.h> #include <stdlib.h> -extern int errno; -extern int get_value(char c, long base); +int get_value(char c, long base); // https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html long strtol(const char *str, char **restrict endptr, int base) { @@ -35,11 +34,15 @@ long strtol(const char *str, char **restrict endptr, int base) { if (2 <= base && 36 >= base) { for (; *str; str++) { + if (ret_value > LONG_MAX / base) { + errno = ERANGE; + return LONG_MAX; + } ret_value *= base; int val = get_value(*str, base); if (ret_value > LONG_MAX - val) { errno = ERANGE; - return 0; + return LONG_MAX; } ret_value += val; } @@ -48,6 +51,6 @@ long strtol(const char *str, char **restrict endptr, int base) { return 0; } if (endptr) - *endptr = (char*)str; + *endptr = (char *)str; return ret_value; } diff --git a/userland/libc/stdlib/strtoll.c b/userland/libc/stdlib/strtoll.c new file mode 100644 index 0000000..486f91d --- /dev/null +++ b/userland/libc/stdlib/strtoll.c @@ -0,0 +1,56 @@ +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <limits.h> +#include <stdlib.h> + +int get_value(char c, long base); + +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/strtoll.html +long long strtoll(const char *str, char **restrict endptr, int base) { + long long ret_value = 0; + if (endptr) + *endptr = (char *)str; + // Ignore inital white-space sequence + for (; *str && isspace(*str); str++) + ; + if (!*str) + return ret_value; + + // int sign = 0; + if ('-' == *str) { + // FIXME + // sign = 1; + str++; + assert(0); + } else if ('+' == *str) { + str++; + } + + if (0 == base) { + // FIXME + assert(0); + } + + if (2 <= base && 36 >= base) { + for (; *str; str++) { + if (ret_value > LLONG_MAX / base) { + errno = ERANGE; + return LLONG_MAX; + } + ret_value *= base; + int val = get_value(*str, base); + if (ret_value > LLONG_MAX - val) { + errno = ERANGE; + return LLONG_MAX; + } + ret_value += val; + } + } else { + errno = EINVAL; + return 0; + } + if (endptr) + *endptr = (char *)str; + return ret_value; +} |