From dc2f7a9a0c4dc6c193ec817ea0d294254ffb30b0 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Thu, 30 Jan 2025 13:55:54 -0800 Subject: [PATCH] Add overload of `TryParseStringWithClassicLocale()` that uses `std::from_chars()` (#23541) Add overload of `TryParseStringWithClassicLocale()` that uses `std::from_chars()` for certain types. Reduce binary size. It recently increased after PR #23526. --- .../onnxruntime/core/common/parse_string.h | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/include/onnxruntime/core/common/parse_string.h b/include/onnxruntime/core/common/parse_string.h index 941e3f3377..6345b2a554 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;