Skip to content
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions include/onnxruntime/core/common/parse_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#pragma once

#include <charconv>
#include <locale>
#include <sstream>
#include <string_view>
Expand All @@ -12,18 +13,45 @@

namespace onnxruntime {

namespace detail {

// Whether we will use std::from_chars() to parse to `T`.
#if defined(__ANDROID__)
// Note: As of Android NDK r27c, std::from_chars() doesn't support floating point types.
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

}

/**
* 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;
Expand Down
Loading