diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -116,6 +116,10 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON // According to the Standard, `bitset::operator[] const` returns bool # define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL +// Remove the base 10 implementation of std::to_chars from the dylib. +// The implementation moved to the header, but we still export the symbols from +// the dylib for backwards compatibility. +# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/src/charconv.cpp b/libcxx/src/charconv.cpp --- a/libcxx/src/charconv.cpp +++ b/libcxx/src/charconv.cpp @@ -9,141 +9,31 @@ #include #include -#include "include/ryu/digit_table.h" #include "include/to_chars_floating_point.h" _LIBCPP_BEGIN_NAMESPACE_STD -namespace __itoa -{ - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append1(char* buffer, T i) noexcept -{ - *buffer = '0' + static_cast(i); - return buffer + 1; -} - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append2(char* buffer, T i) noexcept -{ - memcpy(buffer, &__DIGIT_TABLE[(i)*2], 2); - return buffer + 2; -} - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append3(char* buffer, T i) noexcept -{ - return append2(append1(buffer, (i) / 100), (i) % 100); -} +#ifndef _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 -template -inline _LIBCPP_INLINE_VISIBILITY char* -append4(char* buffer, T i) noexcept -{ - return append2(append2(buffer, (i) / 100), (i) % 100); -} - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append2_no_zeros(char* buffer, T v) noexcept -{ - if (v < 10) - return append1(buffer, v); - else - return append2(buffer, v); -} - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append4_no_zeros(char* buffer, T v) noexcept -{ - if (v < 100) - return append2_no_zeros(buffer, v); - else if (v < 1000) - return append3(buffer, v); - else - return append4(buffer, v); -} - -template -inline _LIBCPP_INLINE_VISIBILITY char* -append8_no_zeros(char* buffer, T v) noexcept +namespace __itoa { - if (v < 10000) - { - buffer = append4_no_zeros(buffer, v); - } - else - { - buffer = append4_no_zeros(buffer, v / 10000); - buffer = append4(buffer, v % 10000); - } - return buffer; -} _LIBCPP_FUNC_VIS char* __u32toa(uint32_t value, char* buffer) noexcept { - if (value < 100000000) - { - buffer = append8_no_zeros(buffer, value); - } - else - { - // value = aabbbbcccc in decimal - const uint32_t a = value / 100000000; // 1 to 42 - value %= 100000000; - - buffer = append2_no_zeros(buffer, a); - buffer = append4(buffer, value / 10000); - buffer = append4(buffer, value % 10000); - } - - return buffer; + return __base_10_u32(value, buffer); } _LIBCPP_FUNC_VIS char* __u64toa(uint64_t value, char* buffer) noexcept { - if (value < 100000000) - { - uint32_t v = static_cast(value); - buffer = append8_no_zeros(buffer, v); - } - else if (value < 10000000000000000) - { - const uint32_t v0 = static_cast(value / 100000000); - const uint32_t v1 = static_cast(value % 100000000); - - buffer = append8_no_zeros(buffer, v0); - buffer = append4(buffer, v1 / 10000); - buffer = append4(buffer, v1 % 10000); - } - else - { - const uint32_t a = - static_cast(value / 10000000000000000); // 1 to 1844 - value %= 10000000000000000; - - buffer = append4_no_zeros(buffer, a); - - const uint32_t v0 = static_cast(value / 100000000); - const uint32_t v1 = static_cast(value % 100000000); - buffer = append4(buffer, v0 / 10000); - buffer = append4(buffer, v0 % 10000); - buffer = append4(buffer, v1 / 10000); - buffer = append4(buffer, v1 % 10000); - } - - return buffer; + return __base_10_u64(value, buffer); } } // namespace __itoa +#endif // _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 + // The original version of floating-point to_chars was written by Microsoft and // contributed with the following license. diff --git a/libcxx/src/include/ryu/digit_table.h b/libcxx/src/include/ryu/digit_table.h --- a/libcxx/src/include/ryu/digit_table.h +++ b/libcxx/src/include/ryu/digit_table.h @@ -39,30 +39,19 @@ #ifndef _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H #define _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H -// Avoid formatting to keep the changes with the original code minimal. -// clang-format off - +#include <__charconv/tables.h> #include <__config> _LIBCPP_BEGIN_NAMESPACE_STD // A table of all two-digit numbers. This is used to speed up decimal digit // generation by copying pairs of digits into the final output. -inline constexpr char __DIGIT_TABLE[200] = { - '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9', - '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9', - '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9', - '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9', - '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9', - '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9', - '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9', - '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9', - '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9', - '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9' -}; +// +// In order to minimize the diff in the Ryu code between MSVC STL and libc++ +// the code uses the name __DIGIT_TABLE. In order to avoid code duplication it +// reuses the table already available in libc++. +inline constexpr auto& __DIGIT_TABLE = __itoa::__digits_base_10<>::__value; _LIBCPP_END_NAMESPACE_STD -// clang-format on - #endif // _LIBCPP_SRC_INCLUDE_RYU_DIGIT_TABLE_H