Skip to content

Commit efdeced

Browse files
committed
Use strtod_l for locale-independent float parsing in cli::Reader
std::from_chars for floating-point types is unavailable in Apple libc++. std::strtod depends on the C locale (LC_NUMERIC), so "3.14" fails under locales that use comma as decimal separator. Use strtod_l with an explicit "C" locale on all platforms. Windows uses _strtod_l/_create_locale, POSIX uses strtod_l/newlocale.
1 parent 890c8e2 commit efdeced

1 file changed

Lines changed: 18 additions & 5 deletions

File tree

include/rfl/cli/Reader.hpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
#include <charconv>
55
#include <concepts>
6+
#include <clocale>
7+
#include <cstdlib>
68
#include <map>
79
#include <optional>
810
#include <set>
@@ -57,18 +59,29 @@ rfl::Result<T> parse_value(
5759
"Could not cast '" + _str + "' to boolean for key '" + _path + "'.");
5860
}
5961

62+
// std::from_chars for float/double is unavailable in Apple libc++.
63+
// std::strtod depends on the C locale (LC_NUMERIC), so "3.14" can fail
64+
// under locales that use comma as decimal separator.
65+
// Use strtod_l with an explicit "C" locale on all platforms for consistency.
6066
template <class T> requires (std::is_floating_point_v<T>)
6167
rfl::Result<T> parse_value(
6268
const std::string& _str, const std::string& _path
6369
) noexcept {
64-
T value;
65-
const auto [ptr, ec] =
66-
std::from_chars(_str.data(), _str.data() + _str.size(), value);
67-
if (ec != std::errc() || ptr != _str.data() + _str.size()) {
70+
char* end = nullptr;
71+
#ifdef _WIN32
72+
const auto c_locale = _create_locale(LC_NUMERIC, "C");
73+
const double value = _strtod_l(_str.c_str(), &end, c_locale);
74+
_free_locale(c_locale);
75+
#else
76+
const auto c_locale = newlocale(LC_NUMERIC_MASK, "C", nullptr);
77+
const double value = strtod_l(_str.c_str(), &end, c_locale);
78+
freelocale(c_locale);
79+
#endif
80+
if (end != _str.c_str() + _str.size()) {
6881
return error(
6982
"Could not cast '" + _str + "' to floating point for key '" + _path + "'.");
7083
}
71-
return value;
84+
return static_cast<T>(value);
7285
}
7386

7487
template <class T> requires (std::is_integral_v<T> && !std::same_as<T, bool>)

0 commit comments

Comments
 (0)