)
add_header_library(
- str_conv_utils
+ str_to_integer
+ HDRS
+ str_to_integer.h
+ DEPENDS
+ .ctype_utils
+ libc.include.errno
+ libc.src.errno.__errno_location
+ libc.src.__support.CPP.standalone_cpp
+)
+
+add_header_library(
+ str_to_float
HDRS
- str_conv_utils.h
str_to_float.h
DEPENDS
+ .str_to_integer
.ctype_utils
.high_precision_decimal
libc.include.errno
// and contains the 128 bit mantissa approximations of the powers of 10 from
// -348 to 347. The exponents are implied by a linear expression with slope
// 217706.0/65536.0 ≈ log(10)/log(2). This is used by the Eisel-Lemire algorithm
-// in str_conv_utils.h.
+// in str_to_float.h.
constexpr int32_t DETAILED_POWERS_OF_TEN_MIN_EXP_10 = -348;
constexpr int32_t DETAILED_POWERS_OF_TEN_MAX_EXP_10 = 347;
#define LIBC_SRC_SUPPORT_HIGH_PRECISION_DECIMAL_H
#include "src/__support/ctype_utils.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
#include <stdint.h>
namespace __llvm_libc {
+++ /dev/null
-//===-- Stdlib utils --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LIBC_SRC_STDLIB_STDLIB_UTILS_H
-#define LIBC_SRC_STDLIB_STDLIB_UTILS_H
-
-#include "src/__support/CPP/Limits.h"
-#include "src/__support/ctype_utils.h"
-#include <errno.h>
-#include <limits.h>
-
-namespace __llvm_libc {
-namespace internal {
-
-// Returns a pointer to the first character in src that is not a whitespace
-// character (as determined by isspace())
-static inline const char *first_non_whitespace(const char *__restrict src) {
- while (internal::isspace(*src)) {
- ++src;
- }
- return src;
-}
-
-static inline int b36_char_to_int(char input) {
- if (isdigit(input))
- return input - '0';
- if (isalpha(input))
- return (input | 32) + 10 - 'a';
- return 0;
-}
-
-// checks if the next 3 characters of the string pointer are the start of a
-// hexadecimal number. Does not advance the string pointer.
-static inline bool is_hex_start(const char *__restrict src) {
- return *src == '0' && (*(src + 1) | 32) == 'x' && isalnum(*(src + 2)) &&
- b36_char_to_int(*(src + 2)) < 16;
-}
-
-// Takes the address of the string pointer and parses the base from the start of
-// it. This function will advance |src| to the first valid digit in the inferred
-// base.
-static inline int infer_base(const char *__restrict *__restrict src) {
- // A hexadecimal number is defined as "the prefix 0x or 0X followed by a
- // sequence of the deimal digits and the letters a (or A) through f (or F)
- // with values 10 through 15 respectively." (C standard 6.4.4.1)
- if (is_hex_start(*src)) {
- (*src) += 2;
- return 16;
- } // An octal number is defined as "the prefix 0 optionally followed by a
- // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any
- // number that starts with 0, including just 0, is an octal number.
- else if (**src == '0') {
- return 8;
- } // A decimal number is defined as beginning "with a nonzero digit and
- // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1)
- else {
- return 10;
- }
-}
-
-// Takes a pointer to a string, a pointer to a string pointer, and the base to
-// convert to. This function is used as the backend for all of the string to int
-// functions.
-template <class T>
-static inline T strtointeger(const char *__restrict src,
- char **__restrict str_end, int base) {
- unsigned long long result = 0;
- bool is_number = false;
- const char *original_src = src;
-
- if (base < 0 || base == 1 || base > 36) {
- errno = EINVAL; // NOLINT
- return 0;
- }
-
- src = first_non_whitespace(src);
-
- char result_sign = '+';
- if (*src == '+' || *src == '-') {
- result_sign = *src;
- ++src;
- }
-
- if (base == 0) {
- base = infer_base(&src);
- } else if (base == 16 && is_hex_start(src)) {
- src = src + 2;
- }
-
- constexpr bool is_unsigned = (__llvm_libc::cpp::NumericLimits<T>::min() == 0);
- const bool is_positive = (result_sign == '+');
- unsigned long long constexpr NEGATIVE_MAX =
- !is_unsigned ? static_cast<unsigned long long>(
- __llvm_libc::cpp::NumericLimits<T>::max()) +
- 1
- : __llvm_libc::cpp::NumericLimits<T>::max();
- unsigned long long const ABS_MAX =
- (is_positive ? __llvm_libc::cpp::NumericLimits<T>::max() : NEGATIVE_MAX);
- unsigned long long const ABS_MAX_DIV_BY_BASE = ABS_MAX / base;
- while (isalnum(*src)) {
- int cur_digit = b36_char_to_int(*src);
- if (cur_digit >= base)
- break;
-
- is_number = true;
- ++src;
-
- // If the number has already hit the maximum value for the current type then
- // the result cannot change, but we still need to advance src to the end of
- // the number.
- if (result == ABS_MAX) {
- errno = ERANGE; // NOLINT
- continue;
- }
-
- if (result > ABS_MAX_DIV_BY_BASE) {
- result = ABS_MAX;
- errno = ERANGE; // NOLINT
- } else {
- result = result * base;
- }
- if (result > ABS_MAX - cur_digit) {
- result = ABS_MAX;
- errno = ERANGE; // NOLINT
- } else {
- result = result + cur_digit;
- }
- }
-
- if (str_end != nullptr)
- *str_end = const_cast<char *>(is_number ? src : original_src);
-
- if (result == ABS_MAX) {
- if (is_positive || is_unsigned)
- return __llvm_libc::cpp::NumericLimits<T>::max();
- else // T is signed and there is a negative overflow
- return __llvm_libc::cpp::NumericLimits<T>::min();
- }
-
- return is_positive ? static_cast<T>(result) : -static_cast<T>(result);
-}
-
-} // namespace internal
-} // namespace __llvm_libc
-
-#endif // LIBC_SRC_STDLIB_STDLIB_UTILS_H
#include "src/__support/ctype_utils.h"
#include "src/__support/detailed_powers_of_ten.h"
#include "src/__support/high_precision_decimal.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
#include <errno.h>
namespace __llvm_libc {
--- /dev/null
+//===-- String to integer conversion utils ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIBC_SRC_SUPPORT_STR_TO_INTEGER_H
+#define LIBC_SRC_SUPPORT_STR_TO_INTEGER_H
+
+#include "src/__support/CPP/Limits.h"
+#include "src/__support/ctype_utils.h"
+#include <errno.h>
+#include <limits.h>
+
+namespace __llvm_libc {
+namespace internal {
+
+// Returns a pointer to the first character in src that is not a whitespace
+// character (as determined by isspace())
+static inline const char *first_non_whitespace(const char *__restrict src) {
+ while (internal::isspace(*src)) {
+ ++src;
+ }
+ return src;
+}
+
+static inline int b36_char_to_int(char input) {
+ if (isdigit(input))
+ return input - '0';
+ if (isalpha(input))
+ return (input | 32) + 10 - 'a';
+ return 0;
+}
+
+// checks if the next 3 characters of the string pointer are the start of a
+// hexadecimal number. Does not advance the string pointer.
+static inline bool is_hex_start(const char *__restrict src) {
+ return *src == '0' && (*(src + 1) | 32) == 'x' && isalnum(*(src + 2)) &&
+ b36_char_to_int(*(src + 2)) < 16;
+}
+
+// Takes the address of the string pointer and parses the base from the start of
+// it. This function will advance |src| to the first valid digit in the inferred
+// base.
+static inline int infer_base(const char *__restrict *__restrict src) {
+ // A hexadecimal number is defined as "the prefix 0x or 0X followed by a
+ // sequence of the deimal digits and the letters a (or A) through f (or F)
+ // with values 10 through 15 respectively." (C standard 6.4.4.1)
+ if (is_hex_start(*src)) {
+ (*src) += 2;
+ return 16;
+ } // An octal number is defined as "the prefix 0 optionally followed by a
+ // sequence of the digits 0 through 7 only" (C standard 6.4.4.1) and so any
+ // number that starts with 0, including just 0, is an octal number.
+ else if (**src == '0') {
+ return 8;
+ } // A decimal number is defined as beginning "with a nonzero digit and
+ // consist[ing] of a sequence of decimal digits." (C standard 6.4.4.1)
+ else {
+ return 10;
+ }
+}
+
+// Takes a pointer to a string, a pointer to a string pointer, and the base to
+// convert to. This function is used as the backend for all of the string to int
+// functions.
+template <class T>
+static inline T strtointeger(const char *__restrict src,
+ char **__restrict str_end, int base) {
+ unsigned long long result = 0;
+ bool is_number = false;
+ const char *original_src = src;
+
+ if (base < 0 || base == 1 || base > 36) {
+ errno = EINVAL; // NOLINT
+ return 0;
+ }
+
+ src = first_non_whitespace(src);
+
+ char result_sign = '+';
+ if (*src == '+' || *src == '-') {
+ result_sign = *src;
+ ++src;
+ }
+
+ if (base == 0) {
+ base = infer_base(&src);
+ } else if (base == 16 && is_hex_start(src)) {
+ src = src + 2;
+ }
+
+ constexpr bool is_unsigned = (__llvm_libc::cpp::NumericLimits<T>::min() == 0);
+ const bool is_positive = (result_sign == '+');
+ unsigned long long constexpr NEGATIVE_MAX =
+ !is_unsigned ? static_cast<unsigned long long>(
+ __llvm_libc::cpp::NumericLimits<T>::max()) +
+ 1
+ : __llvm_libc::cpp::NumericLimits<T>::max();
+ unsigned long long const ABS_MAX =
+ (is_positive ? __llvm_libc::cpp::NumericLimits<T>::max() : NEGATIVE_MAX);
+ unsigned long long const ABS_MAX_DIV_BY_BASE = ABS_MAX / base;
+ while (isalnum(*src)) {
+ int cur_digit = b36_char_to_int(*src);
+ if (cur_digit >= base)
+ break;
+
+ is_number = true;
+ ++src;
+
+ // If the number has already hit the maximum value for the current type then
+ // the result cannot change, but we still need to advance src to the end of
+ // the number.
+ if (result == ABS_MAX) {
+ errno = ERANGE; // NOLINT
+ continue;
+ }
+
+ if (result > ABS_MAX_DIV_BY_BASE) {
+ result = ABS_MAX;
+ errno = ERANGE; // NOLINT
+ } else {
+ result = result * base;
+ }
+ if (result > ABS_MAX - cur_digit) {
+ result = ABS_MAX;
+ errno = ERANGE; // NOLINT
+ } else {
+ result = result + cur_digit;
+ }
+ }
+
+ if (str_end != nullptr)
+ *str_end = const_cast<char *>(is_number ? src : original_src);
+
+ if (result == ABS_MAX) {
+ if (is_positive || is_unsigned)
+ return __llvm_libc::cpp::NumericLimits<T>::max();
+ else // T is signed and there is a negative overflow
+ return __llvm_libc::cpp::NumericLimits<T>::min();
+ }
+
+ return is_positive ? static_cast<T>(result) : -static_cast<T>(result);
+}
+
+} // namespace internal
+} // namespace __llvm_libc
+
+#endif // LIBC_SRC_SUPPORT_STR_TO_INTEGER_H
HDRS
strtoimax.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
strtoumax.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
#include "src/inttypes/strtoimax.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/inttypes/strtoumax.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
HDRS
atoi.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
atof.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_float
)
add_entrypoint_object(
HDRS
atol.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
atoll.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
strtof.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_float
)
add_entrypoint_object(
HDRS
strtod.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_float
)
add_entrypoint_object(
HDRS
strtol.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
strtoll.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
strtoul.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
HDRS
strtoull.h
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_integer
)
add_entrypoint_object(
#include "src/stdlib/atoi.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/atol.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/atoll.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/strtol.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/strtoll.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/strtoul.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
#include "src/stdlib/strtoull.h"
#include "src/__support/common.h"
-#include "src/__support/str_conv_utils.h"
+#include "src/__support/str_to_integer.h"
namespace __llvm_libc {
SRCS
str_to_float_test.cpp
DEPENDS
- libc.src.__support.str_conv_utils
+ libc.src.__support.str_to_float
)
add_executable(