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.
This commit is contained in:
Edward Chen 2025-01-30 13:55:54 -08:00 committed by GitHub
parent 5407c69028
commit dc2f7a9a0c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,6 +3,7 @@
#pragma once
#include <charconv>
#include <locale>
#include <sstream>
#include <string_view>
@ -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 <typename T>
constexpr bool ParseWithFromChars = !std::is_same_v<bool, T> && std::is_integral_v<T>;
#else
template <typename T>
constexpr bool ParseWithFromChars = !std::is_same_v<bool, T> && (std::is_integral_v<T> || std::is_floating_point_v<T>);
#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 <typename T>
bool TryParseStringWithClassicLocale(std::string_view str, T& value) {
if constexpr (std::is_integral<T>::value && std::is_unsigned<T>::value) {
// if T is unsigned integral type, reject negative values which will wrap
if (!str.empty() && str[0] == '-') {
return false;
}
std::enable_if_t<detail::ParseWithFromChars<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 <typename T>
std::enable_if_t<!detail::ParseWithFromChars<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;