This is an automated email from the ASF dual-hosted git repository.
gangwu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-cpp.git
The following commit(s) were added to refs/heads/main by this push:
new 98261472 fix: use strtod fallback when std::from_chars(float)
unavailable (#572)
98261472 is described below
commit 98261472fc3a5ac93e239bc91ad8ba1d7ecf3fd0
Author: Junwang Zhao <[email protected]>
AuthorDate: Wed Feb 25 17:38:18 2026 +0800
fix: use strtod fallback when std::from_chars(float) unavailable (#572)
---
src/iceberg/util/string_util.h | 36 +++++++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/src/iceberg/util/string_util.h b/src/iceberg/util/string_util.h
index 3528204e..fc202f0e 100644
--- a/src/iceberg/util/string_util.h
+++ b/src/iceberg/util/string_util.h
@@ -20,10 +20,12 @@
#pragma once
#include <algorithm>
+#include <cerrno>
#include <charconv>
#include <ranges>
#include <string>
#include <string_view>
+#include <type_traits>
#include <typeinfo>
#include <utility>
@@ -32,6 +34,9 @@
namespace iceberg {
+template <typename T>
+concept FromChars = requires(const char* p, T& v) { std::from_chars(p, p, v);
};
+
class ICEBERG_EXPORT StringUtils {
public:
static std::string ToLower(std::string_view str) {
@@ -68,7 +73,7 @@ class ICEBERG_EXPORT StringUtils {
}
template <typename T>
- requires std::is_arithmetic_v<T> && (!std::same_as<T, bool>)
+ requires std::is_arithmetic_v<T> && FromChars<T> && (!std::same_as<T,
bool>)
static Result<T> ParseNumber(std::string_view str) {
T value = 0;
auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(),
value);
@@ -85,6 +90,35 @@ class ICEBERG_EXPORT StringUtils {
}
std::unreachable();
}
+
+ template <typename T>
+ requires std::is_floating_point_v<T> && (!FromChars<T>)
+ static Result<T> ParseNumber(std::string_view str) {
+ T value{};
+ // strto* require null-terminated input; string_view does not guarantee it.
+ std::string owned(str);
+ const char* start = owned.c_str();
+ char* end = nullptr;
+ errno = 0;
+
+ if constexpr (std::same_as<T, float>) {
+ value = std::strtof(start, &end);
+ } else if constexpr (std::same_as<T, double>) {
+ value = std::strtod(start, &end);
+ } else {
+ value = std::strtold(start, &end);
+ }
+
+ if (end == start || end != start +
static_cast<std::ptrdiff_t>(owned.size())) {
+ return InvalidArgument("Failed to parse {} from string '{}': invalid
argument",
+ typeid(T).name(), str);
+ }
+ if (errno == ERANGE) {
+ return InvalidArgument("Failed to parse {} from string '{}': value out
of range",
+ typeid(T).name(), str);
+ }
+ return value;
+ }
};
/// \brief Transparent hash function that supports std::string_view as lookup
key