mirror of
https://git.planet-casio.com/Vhex-Kernel-Core/fxlibc.git
synced 2024-12-28 04:23:38 +01:00
stdlib: add and test strtoull (DONE)
This commit is contained in:
parent
41ab197ba2
commit
b1dc3e77de
4 changed files with 111 additions and 1 deletions
|
@ -106,6 +106,7 @@ set(SOURCES
|
|||
src/libc/stdlib/llabs.c
|
||||
src/libc/stdlib/lldiv.c
|
||||
src/libc/stdlib/reallocarray.c
|
||||
src/libc/stdlib/strtoull.c
|
||||
# string
|
||||
src/libc/string/strchr.c
|
||||
src/libc/string/strcpy.c
|
||||
|
|
8
STATUS
8
STATUS
|
@ -67,6 +67,8 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
|
|||
files in /usr/share/i18n/locales
|
||||
-> Implement setlocale() and localeconv() properly (not hard)
|
||||
-> Probably support nl_langinfo(), which is much better than localeconv()
|
||||
-> Fix the "TODO: locale: ..." messages wherever assumptions on the locale
|
||||
are made in the code
|
||||
|
||||
7.12 <math.h>
|
||||
Provided by Lephenixnoir's port of OpenLibm.
|
||||
|
@ -95,7 +97,11 @@ DONE: Function/symbol/macro is defined, builds, links, and is tested
|
|||
TODO (will give the full list later on)
|
||||
|
||||
7.20 <stdlib.h>
|
||||
7.20.1 Numeric conversion functions: TODO
|
||||
7.20.1.1 atof: TODO
|
||||
7.20.1.2 atoi, atol, atoll: TODO
|
||||
7.20.1.3 strtod, strtof, strtold: TODO
|
||||
7.20.1.4 strtol, strtoul, strtoll: TODO
|
||||
strtoull: DONE
|
||||
7.20.2 Pseudo-random sequence generation functions: TODO
|
||||
7.20.3 Memory management functions: TODO (check existing code first)
|
||||
7.20.4 Communication with the environment: TODO
|
||||
|
|
|
@ -63,4 +63,45 @@ div_t div(int __num, int __denom);
|
|||
ldiv_t ldiv(long int __num, long int __denom);
|
||||
lldiv_t lldiv(long long int __num, long long int __denom);
|
||||
|
||||
/* Numeric conversion functions. */
|
||||
|
||||
/* Parse a long int from a string. */
|
||||
extern long int strtol(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr,
|
||||
int __base);
|
||||
|
||||
/* Parse a long unsigned int from a string. */
|
||||
extern unsigned long int strtoul(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr,
|
||||
int __base);
|
||||
|
||||
/* Parse a long long int from a string. */
|
||||
extern long long int strtoll(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr,
|
||||
int __base);
|
||||
|
||||
/* Parse a long long unsigned int from a string. */
|
||||
extern unsigned long long int strtoull(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr,
|
||||
int __base);
|
||||
|
||||
/* Parse a double from a string. */
|
||||
extern double strtod(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr);
|
||||
|
||||
/* Parse a float from a string. */
|
||||
extern float strtof(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr);
|
||||
|
||||
/* Parse a long double from a string. */
|
||||
extern long double strtold(
|
||||
char const * restrict __ptr,
|
||||
char ** restrict __endptr);
|
||||
|
||||
#endif /*__STDLIB_H__*/
|
||||
|
|
62
src/libc/stdlib/strtoull.c
Normal file
62
src/libc/stdlib/strtoull.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
unsigned long long int strtoull(char const * restrict ptr,
|
||||
char ** restrict endptr, int base)
|
||||
{
|
||||
/* Save the value of ptr in endptr now in case the format is invalid */
|
||||
if(endptr) *endptr = (char *)ptr;
|
||||
|
||||
/* Skip initial whitespace */
|
||||
while(isspace(*ptr)) ptr++;
|
||||
|
||||
/* Accept a sign character */
|
||||
bool negative = false;
|
||||
if(*ptr == '-') negative = true;
|
||||
if(*ptr == '-' || *ptr == '+') ptr++;
|
||||
|
||||
unsigned long long x = 0;
|
||||
bool valid = false;
|
||||
|
||||
/* Read prefixes and determine base */
|
||||
if((base == 0 || base == 16) && ptr[0]=='0' && tolower(ptr[1])=='x') {
|
||||
ptr += 2;
|
||||
base = 16;
|
||||
}
|
||||
else if(base == 0 && ptr[0] == '0') {
|
||||
ptr++;
|
||||
base = 8;
|
||||
}
|
||||
else if(base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
/* Read digits */
|
||||
while(1) {
|
||||
int v = -1;
|
||||
if(isdigit(*ptr)) v = *ptr - '0';
|
||||
if(islower(*ptr)) v = *ptr - 'a' + 10;
|
||||
if(v == -1 || v >= base) break;
|
||||
|
||||
/* The value is valid as long as there is at least one digit */
|
||||
valid = true;
|
||||
|
||||
/* (x = base*x + v) but with overflow checks */
|
||||
if(__builtin_umulll_overflow(x, base, &x))
|
||||
errno = ERANGE;
|
||||
if(__builtin_uaddll_overflow(x, v, &x))
|
||||
errno = ERANGE;
|
||||
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if(negative) {
|
||||
if(x != 0) errno = ERANGE;
|
||||
x = -x;
|
||||
}
|
||||
|
||||
if(endptr && valid) *endptr = (char *)ptr;
|
||||
return x;
|
||||
}
|
Loading…
Reference in a new issue