diff --git a/include/inttypes.h b/include/inttypes.h index e9177c7e89..f8fe433723 100644 --- a/include/inttypes.h +++ b/include/inttypes.h @@ -177,13 +177,13 @@ extern "C" * macros. Function prototypes shall be provided." */ -intmax_t imaxabs(intmax_t); -imaxdiv_t imaxdiv(intmax_t, intmax_t); -intmax_t strtoimax(const char *, char **, int); -uintmax_t strtoumax(const char *, char **, int); +intmax_t imaxabs(intmax_t j); +imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom); +intmax_t strtoimax(FAR const char *nptr, FAR char **endptr, int base); +uintmax_t strtoumax(FAR const char *nptr, FAR char **endptr, int base); -intmax_t wcstoimax(const wchar_t *, wchar_t **, int); -uintmax_t wcstoumax(const wchar_t *, wchar_t **, int); +intmax_t wcstoimax(FAR const wchar_t *nptr, FAR wchar_t **endptr, int base); +uintmax_t wcstoumax(FAR const wchar_t *nptr, FAR wchar_t **endptr, int base); #undef EXTERN #ifdef __cplusplus diff --git a/libc/inttypes/Make.defs b/libc/inttypes/Make.defs index d41d30ccb7..c10d4382f7 100644 --- a/libc/inttypes/Make.defs +++ b/libc/inttypes/Make.defs @@ -35,7 +35,7 @@ # Add the inttypes C files to the build -CSRCS += lib_imaxabs.c +CSRCS += lib_imaxabs.c lib_strtoimax.c lib_strtoumax.c # Add the inttypes directory to the build diff --git a/libc/inttypes/lib_strtoimax.c b/libc/inttypes/lib_strtoimax.c new file mode 100644 index 0000000000..2862e7f8eb --- /dev/null +++ b/libc/inttypes/lib_strtoimax.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * libc/inttypes/lib_strtoimax.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtoimax + * + * Description: + * The strtoimax() function converts the initial part of the string in + * nptr to a intmax_t integer value according to the given base, which + * must be between 2 and 36 inclusive, or be the special value 0. + * + * Returns: + * - The converted value, if the base and number are valid + * - 0 if an error occurs, and set errno to: + * * EINVAL if base < 2 or base > 36 + * - INTMAX_MIN or INTMAX_MAX, of correct sign, if an overflow occurs, + * and set errno to: + * * ERANGE if the number cannot be represented using intmax_t + * + ****************************************************************************/ + +intmax_t strtoimax(FAR const char *nptr, FAR char **endptr, int base) +{ + uintmax_t accum = 0; + bool negate = false; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for leading + or - */ + + if (*nptr == '-') + { + negate = true; + nptr++; + } + else if (*nptr == '+') + { + nptr++; + } + + /* Get the unsigned value */ + + accum = strtoull(nptr, endptr, base); + + /* Correct the sign of the result and check for overflow */ + + if (negate) + { + const uintmax_t limit = ((uintmax_t)-(INTMAX_MIN + 1)) + 1; + + if (accum > limit) + { + set_errno(ERANGE); + return INTMAX_MIN; + } + + return (accum == limit) ? INTMAX_MIN : -(intmax_t)accum; + } + + if (accum > INTMAX_MAX) + { + set_errno(ERANGE); + return INTMAX_MAX; + } + } + + return (intmax_t)accum; +} diff --git a/libc/inttypes/lib_strtoumax.c b/libc/inttypes/lib_strtoumax.c new file mode 100644 index 0000000000..9440908c93 --- /dev/null +++ b/libc/inttypes/lib_strtoumax.c @@ -0,0 +1,118 @@ +/**************************************************************************** + * /libc/inttypes/lib_strtoumax.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include + +#include "libc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: strtoumax + * + * Description: + * The strtoumax() function converts the initial part of the string in + * nptr to a long unsigned integer value according to the given base, which + * must be between 2 and 36 inclusive, or be the special value 0. + * + * Returns: + * - The converted value, if the base and number are valid + * - 0 if an error occurs, and set errno to: + * * EINVAL if base < 2 or base > 36 + * - UINTMAX_MAX if an overflow occurs, and set errno to: + * * ERANGE if the number cannot be represented using uintmax_t + * + ****************************************************************************/ + +uintmax_t strtoumax(FAR const char *nptr, FAR char **endptr, int base) +{ + uintmax_t accum = 0; + uintmax_t prev; + int value; + + if (nptr) + { + /* Skip leading spaces */ + + lib_skipspace(&nptr); + + /* Check for unspecified base */ + + base = lib_checkbase(base, &nptr); + + if (base < 0) + { + set_errno(EINVAL); + return 0; + } + + /* Accumulate each "digit" */ + + while (lib_isbasedigit(*nptr, base, &value)) + { + prev = accum; + accum = accum*base + value; + nptr++; + + /* Check for overflow */ + + if (accum < prev) + { + set_errno(ERANGE); + accum = UINTMAX_MAX; + break; + } + } + + /* Return the final pointer to the unused value */ + + if (endptr) + { + *endptr = (char *)nptr; + } + } + + return accum; +}