diff --git a/include/onnxruntime/core/common/parse_string.h b/include/onnxruntime/core/common/parse_string.h index 941e3f3377ecc..6345b2a55490d 100644 --- a/include/onnxruntime/core/common/parse_string.h +++ b/include/onnxruntime/core/common/parse_string.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include #include @@ -12,18 +13,45 @@ namespace onnxruntime { +namespace detail { + +// Whether we will use std::from_chars() to parse to `T`. +#if defined(_LIBCPP_VERSION) +// Note: Currently (e.g., in LLVM 19), libc++'s std::from_chars() doesn't support floating point types yet. +template +constexpr bool ParseWithFromChars = !std::is_same_v && std::is_integral_v; +#else +template +constexpr bool ParseWithFromChars = !std::is_same_v && (std::is_integral_v || std::is_floating_point_v); +#endif + +} // namespace detail + /** * Tries to parse a value from an entire string. + * If successful, sets `value` and returns true. Otherwise, does not modify `value` and returns false. */ template -bool TryParseStringWithClassicLocale(std::string_view str, T& value) { - if constexpr (std::is_integral::value && std::is_unsigned::value) { - // if T is unsigned integral type, reject negative values which will wrap - if (!str.empty() && str[0] == '-') { - return false; - } +std::enable_if_t, bool> +TryParseStringWithClassicLocale(std::string_view str, T& value) { + T parsed_value{}; + const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), parsed_value); + + if (ec != std::errc{}) { + return false; } + if (ptr != str.data() + str.size()) { + return false; + } + + value = parsed_value; + return true; +} + +template +std::enable_if_t, bool> +TryParseStringWithClassicLocale(std::string_view str, T& value) { // don't allow leading whitespace if (!str.empty() && std::isspace(str[0], std::locale::classic())) { return false;