fix: try fix clang libcxx charconv issue.
- add compile checker in cmake to detect charconv support status. - and expose macro for yycc to enable different part of charconv repectively to prevent duplicated defines.
This commit is contained in:
@@ -26,6 +26,9 @@ set(YYCC_INSTALL_BIN_PATH ${CMAKE_INSTALL_BINDIR} CACHE PATH
|
|||||||
set(YYCC_INSTALL_DOC_PATH ${CMAKE_INSTALL_DOCDIR} CACHE PATH
|
set(YYCC_INSTALL_DOC_PATH ${CMAKE_INSTALL_DOCDIR} CACHE PATH
|
||||||
"Non-arch doc install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
|
"Non-arch doc install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
|
||||||
|
|
||||||
|
# Test charconv support due to shitty clang's libcxx.
|
||||||
|
include(${CMAKE_CURRENT_LIST_DIR}/cmake/check_charconv.cmake)
|
||||||
|
|
||||||
# Include dependency.
|
# Include dependency.
|
||||||
# GTest is required if we build test
|
# GTest is required if we build test
|
||||||
if (YYCC_BUILD_TEST)
|
if (YYCC_BUILD_TEST)
|
||||||
|
|||||||
30
cmake/check_charconv.cmake
Normal file
30
cmake/check_charconv.cmake
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
message(STATUS "Checking charconv implementation...")
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/chars_format.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_CHARS_FORMAT)
|
||||||
|
message(STATUS "Support std::chars_format: ${YYCC_CHARCONV_HAS_CHARS_FORMAT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/from_chars_result.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_FROM_CHARS_RESULT)
|
||||||
|
message(STATUS "Support std::from_chars_result: ${YYCC_CHARCONV_HAS_FROM_CHARS_RESULT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/to_chars_result.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_TO_CHARS_RESULT)
|
||||||
|
message(STATUS "Support std::to_chars_result: ${YYCC_CHARCONV_HAS_TO_CHARS_RESULT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/from_chars_int.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_FROM_CHARS_INT)
|
||||||
|
message(STATUS "Support std::from_chars with integral type: ${YYCC_CHARCONV_HAS_FROM_CHARS_INT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/from_chars_float.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_FROM_CHARS_FLOAT)
|
||||||
|
message(STATUS "Suppoer std::from_chars with float point type: ${YYCC_CHARCONV_HAS_FROM_CHARS_FLOAT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/to_chars_int.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_TO_CHARS_INT)
|
||||||
|
message(STATUS "Support std::to_chars with integral type: ${YYCC_CHARCONV_HAS_TO_CHARS_INT}")
|
||||||
|
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/check_charconv/to_chars_float.cpp" TEST_CODE_SNIPPET)
|
||||||
|
check_cxx_source_compiles("${TEST_CODE_SNIPPET}" YYCC_CHARCONV_HAS_TO_CHARS_FLOAT)
|
||||||
|
message(STATUS "Support std::to_chars with float point type: ${YYCC_CHARCONV_HAS_TO_CHARS_FLOAT}")
|
||||||
8
cmake/check_charconv/chars_format.cpp
Normal file
8
cmake/check_charconv/chars_format.cpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include <charconv>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
auto scientific = std::chars_format::scientific;
|
||||||
|
auto fixed = std::chars_format::fixed;
|
||||||
|
auto general = std::chars_format::general;
|
||||||
|
auto hex = std::chars_format::hex;
|
||||||
|
}
|
||||||
16
cmake/check_charconv/from_chars_float.cpp
Normal file
16
cmake/check_charconv/from_chars_float.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <charconv>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const char probe[] = "0.0";
|
||||||
|
const char* first = probe;
|
||||||
|
const char* last = first + sizeof(probe);
|
||||||
|
|
||||||
|
{
|
||||||
|
float value;
|
||||||
|
auto rv = std::from_chars(first, last, value, std::chars_format::general);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
double value;
|
||||||
|
auto rv = std::from_chars(first, last, value, std::chars_format::general);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
cmake/check_charconv/from_chars_int.cpp
Normal file
41
cmake/check_charconv/from_chars_int.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <charconv>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const char probe[] = "0";
|
||||||
|
const char* first = probe;
|
||||||
|
const char* last = first + sizeof(probe);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::int8_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int16_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int32_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int64_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint8_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint16_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint32_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint64_t value;
|
||||||
|
auto rv = std::from_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
cmake/check_charconv/from_chars_result.cpp
Normal file
9
cmake/check_charconv/from_chars_result.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include <charconv>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::from_chars_result result {
|
||||||
|
.ptr = nullptr,
|
||||||
|
.ec = std::errc{},
|
||||||
|
};
|
||||||
|
}
|
||||||
16
cmake/check_charconv/to_chars_float.cpp
Normal file
16
cmake/check_charconv/to_chars_float.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#include <charconv>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
char buffer[1024];
|
||||||
|
char* first = buffer;
|
||||||
|
char* last = first + sizeof(buffer);
|
||||||
|
|
||||||
|
{
|
||||||
|
float value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, std::chars_format::general, 6);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
double value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, std::chars_format::general, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
cmake/check_charconv/to_chars_int.cpp
Normal file
41
cmake/check_charconv/to_chars_int.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <charconv>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
char buffer[1024];
|
||||||
|
char* first = buffer;
|
||||||
|
char* last = first + sizeof(buffer);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::int8_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int16_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int32_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::int64_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint8_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint16_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint32_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::uint64_t value = 0;
|
||||||
|
auto rv = std::to_chars(first, last, value, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
cmake/check_charconv/to_chars_result.cpp
Normal file
9
cmake/check_charconv/to_chars_result.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include <charconv>
|
||||||
|
#include <system_error>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::to_chars_result result {
|
||||||
|
.ptr = nullptr,
|
||||||
|
.ec = std::errc{},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -167,6 +167,15 @@ PUBLIC
|
|||||||
# Fix Windows header file shit
|
# Fix Windows header file shit
|
||||||
$<$<BOOL:${WIN32}>:WIN32_LEAN_AND_MEAN>
|
$<$<BOOL:${WIN32}>:WIN32_LEAN_AND_MEAN>
|
||||||
$<$<BOOL:${WIN32}>:NOMINMAX>
|
$<$<BOOL:${WIN32}>:NOMINMAX>
|
||||||
|
PUBLIC
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_CHARS_FORMAT}>:YYCC_CHARCONV_HAS_CHARS_FORMAT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_FROM_CHARS_RESULT}>:YYCC_CHARCONV_HAS_FROM_CHARS_RESULT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_TO_CHARS_RESULT}>:YYCC_CHARCONV_HAS_TO_CHARS_RESULT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_FROM_CHARS_INT}>:YYCC_CHARCONV_HAS_FROM_CHARS_INT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_FROM_CHARS_FLOAT}>:YYCC_CHARCONV_HAS_FROM_CHARS_FLOAT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_TO_CHARS_INT}>:YYCC_CHARCONV_HAS_TO_CHARS_INT>
|
||||||
|
$<$<BOOL:${YYCC_CHARCONV_HAS_TO_CHARS_FLOAT}>:YYCC_CHARCONV_HAS_TO_CHARS_FLOAT>
|
||||||
|
|
||||||
)
|
)
|
||||||
target_compile_options(YYCCommonplace
|
target_compile_options(YYCCommonplace
|
||||||
PUBLIC
|
PUBLIC
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <expected>
|
#include <expected>
|
||||||
|
#include <charconv>
|
||||||
|
|
||||||
#if defined(YYCC_STL_CLANGSTL)
|
#if defined(YYCC_STL_CLANGSTL)
|
||||||
#include "patch/libcxx/charconv.hpp"
|
#include "../patch/libcxx/charconv.hpp"
|
||||||
#else
|
|
||||||
#include <charconv>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
||||||
|
|||||||
@@ -4,11 +4,10 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <charconv>
|
||||||
|
|
||||||
#if defined(YYCC_STL_CLANGSTL)
|
#if defined(YYCC_STL_CLANGSTL)
|
||||||
#include "patch/libcxx/charconv.hpp"
|
#include "../patch/libcxx/charconv.hpp"
|
||||||
#else
|
|
||||||
#include <charconv>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
#define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../../macro/stl_detector.hpp"
|
#include "../../macro/stl_detector.hpp"
|
||||||
|
|
||||||
#if defined(YYCC_STL_CLANGSTL)
|
//#if defined(YYCC_STL_CLANGSTL)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
* This polyfill is generated by AI.
|
* This polyfill is generated by AI.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <charconv>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
@@ -26,6 +27,8 @@
|
|||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_CHARS_FORMAT)
|
||||||
|
|
||||||
enum class chars_format : unsigned int {
|
enum class chars_format : unsigned int {
|
||||||
scientific = 1,
|
scientific = 1,
|
||||||
fixed = 2,
|
fixed = 2,
|
||||||
@@ -33,6 +36,10 @@ namespace std {
|
|||||||
general = fixed | scientific // This should be 6 (fixed|scientific)
|
general = fixed | scientific // This should be 6 (fixed|scientific)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_FROM_CHARS_RESULT)
|
||||||
|
|
||||||
struct from_chars_result {
|
struct from_chars_result {
|
||||||
const char* ptr;
|
const char* ptr;
|
||||||
std::errc ec;
|
std::errc ec;
|
||||||
@@ -41,6 +48,10 @@ namespace std {
|
|||||||
constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
|
constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_TO_CHARS_RESULT)
|
||||||
|
|
||||||
struct to_chars_result {
|
struct to_chars_result {
|
||||||
char* ptr;
|
char* ptr;
|
||||||
std::errc ec;
|
std::errc ec;
|
||||||
@@ -49,6 +60,10 @@ namespace std {
|
|||||||
constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
|
constexpr explicit operator bool() const noexcept { return ec == std::errc{}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_TO_CHARS_INT)
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
enum class __integral_type {
|
enum class __integral_type {
|
||||||
u8,
|
u8,
|
||||||
@@ -172,16 +187,21 @@ namespace std {
|
|||||||
// Use snprintf with appropriate format
|
// Use snprintf with appropriate format
|
||||||
const auto max_buffer_size = static_cast<size_t>(last - first);
|
const auto max_buffer_size = static_cast<size_t>(last - first);
|
||||||
const char* format_string = __get_int_format<integral_type>(integral_base_type);
|
const char* format_string = __get_int_format<integral_type>(integral_base_type);
|
||||||
int written = std::snprintf(first, max_buffer_size, format_string, val);
|
int written = std::snprintf(first, max_buffer_size, format_string, value);
|
||||||
if (written < 0 || static_cast<size_t>(written) >= max_buffer_size) {
|
if (written < 0 || static_cast<size_t>(written) >= max_buffer_size) {
|
||||||
return {last, std::errc::value_too_large};
|
return {last, std::errc::value_too_large};
|
||||||
}
|
}
|
||||||
return {first + written, std::errc{}};
|
return {first + written, std::errc{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_TO_CHARS_FLOAT)
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
enum class __float_type {
|
enum class __float_type {
|
||||||
f32, f64,
|
f32,
|
||||||
|
f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
@@ -195,12 +215,10 @@ namespace std {
|
|||||||
static_assert(false, "Unsupported floating point type");
|
static_assert(false, "Unsupported floating point type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
enum class __float_fmt_type {
|
enum class __float_fmt_type { general, scientific, fixed, hex };
|
||||||
general, scientific, fixed, hex
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
std::optional<__float_fmt_type> __classify_float_fmt(chars_format fmt) {
|
std::optional<__float_fmt_type> __classify_float_fmt(chars_format fmt) {
|
||||||
if (fmt == chars_format::general) {
|
if (fmt == chars_format::general) {
|
||||||
@@ -265,7 +283,7 @@ namespace std {
|
|||||||
const auto float_fmt_type = std::move(opt_float_fmt_type.value());
|
const auto float_fmt_type = std::move(opt_float_fmt_type.value());
|
||||||
|
|
||||||
const auto max_buffer_size = static_cast<size_t>(last - first);
|
const auto max_buffer_size = static_cast<size_t>(last - first);
|
||||||
const char *format_string = __get_float_format<float_type>(float_fmt_type);
|
const char* format_string = __get_float_format<float_type>(float_fmt_type);
|
||||||
int written = std::snprintf(first, max_buffer_size, format_string, precision, value);
|
int written = std::snprintf(first, max_buffer_size, format_string, precision, value);
|
||||||
if (written < 0 || static_cast<size_t>(written) >= max_buffer_size) {
|
if (written < 0 || static_cast<size_t>(written) >= max_buffer_size) {
|
||||||
return {last, std::errc::value_too_large};
|
return {last, std::errc::value_too_large};
|
||||||
@@ -273,10 +291,12 @@ namespace std {
|
|||||||
return {first + written, std::errc{}};
|
return {first + written, std::errc{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_FROM_CHARS_INT)
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
enum class __strtoi_cluster {
|
enum class __strtoi_cluster { tol, toll, toul, toull };
|
||||||
tol, toll, toul, toull
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -330,19 +350,19 @@ namespace std {
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
char* end_ptr = const_cast<char*>(first);
|
char* end_ptr = const_cast<char*>(first);
|
||||||
auto rv = __execute_strtoi<strtoi_cluster>(buffer.data(), &end_ptr, base);
|
auto result = __execute_strtoi<strtoi_cluster>(buffer.data(), &end_ptr, base);
|
||||||
if (errno == ERANGE) {
|
if (errno == ERANGE) {
|
||||||
return {end_ptr, std::errc::result_out_of_range};
|
return {end_ptr, std::errc::result_out_of_range};
|
||||||
}
|
}
|
||||||
|
|
||||||
using strtoi_cluster_rvtype = decltype(rv);
|
using strtoi_cluster_rvtype = decltype(result);
|
||||||
// Check if result fits in T
|
// Check if result fits in T
|
||||||
if (result < static_cast<strtoi_cluster_rvtype>(std::numeric_limits<T>::min())
|
if (result < static_cast<strtoi_cluster_rvtype>(std::numeric_limits<T>::min())
|
||||||
|| result > static_cast<strtoi_cluster_rvtype>(std::numeric_limits<T>::max())) {
|
|| result > static_cast<strtoi_cluster_rvtype>(std::numeric_limits<T>::max())) {
|
||||||
return {end_ptr, std::errc::result_out_of_range};
|
return {end_ptr, std::errc::result_out_of_range};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end_ptr == buffer.data) {
|
if (end_ptr == buffer.data()) {
|
||||||
return {first, std::errc::invalid_argument};
|
return {first, std::errc::invalid_argument};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,10 +375,12 @@ namespace std {
|
|||||||
return {first + (end_ptr - buffer.data()), std::errc{}};
|
return {first + (end_ptr - buffer.data()), std::errc{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(YYCC_CHARCONV_HAS_FROM_CHARS_FLOAT)
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
enum class __strtof_cluster {
|
enum class __strtof_cluster { tof, tod };
|
||||||
tof, tod
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @private
|
/// @private
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -399,12 +421,12 @@ namespace std {
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
char* end_ptr = const_cast<char*>(first);
|
char* end_ptr = const_cast<char*>(first);
|
||||||
auto rv = __execute_strtof<strtof_cluster>(buffer.data(), &end_ptr);
|
auto result = __execute_strtof<strtof_cluster>(buffer.data(), &end_ptr);
|
||||||
if (errno == ERANGE) {
|
if (errno == ERANGE) {
|
||||||
return {end_ptr, std::errc::result_out_of_range};
|
return {end_ptr, std::errc::result_out_of_range};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end_ptr == buffer.data) {
|
if (end_ptr == buffer.data()) {
|
||||||
return {first, std::errc::invalid_argument};
|
return {first, std::errc::invalid_argument};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,6 +439,8 @@ namespace std {
|
|||||||
return {first + (end_ptr - buffer.data()), std::errc{}};
|
return {first + (end_ptr - buffer.data()), std::errc{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#endif
|
//#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user