From c9781307a1679708819992237b550c40f04d3b04 Mon Sep 17 00:00:00 2001 From: Hiroki Tagato Date: Sun, 22 Mar 2026 21:12:26 +0900 Subject: [PATCH 1/2] Add missing includes. --- tests/os/Process.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/os/Process.cpp b/tests/os/Process.cpp index 7e65159..a24ca9f 100644 --- a/tests/os/Process.cpp +++ b/tests/os/Process.cpp @@ -2,6 +2,9 @@ #include +#include +#include + using namespace Hyprutils::OS; TEST(OS, process) { From 29520da0e052e8c5115f916fa6cbeda8c7f7c467 Mon Sep 17 00:00:00 2001 From: Hiroki Tagato Date: Sun, 22 Mar 2026 21:18:19 +0900 Subject: [PATCH 2/2] Add libc++ < 20 fallback for floating-point strToNumber libc++ prior to version 20 does not implement std::from_chars for floating point types, which causes builds to fail on systems using older libc++ versions (e.g. FreeBSD). Add a small fallback using strtof/strtod/strtold for building with libc++ < 20. While libstdc++, or libc++ 20 or later continue to use the existing std::from_chars implementation, this change restores compatibility with older libc++ versions. --- include/hyprutils/string/Numeric.hpp | 50 +++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/include/hyprutils/string/Numeric.hpp b/include/hyprutils/string/Numeric.hpp index a1239b4..256a063 100644 --- a/include/hyprutils/string/Numeric.hpp +++ b/include/hyprutils/string/Numeric.hpp @@ -5,6 +5,12 @@ #include #include +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 200000 +#include +#include +#include +#endif + namespace Hyprutils::String { enum eNumericParseResult : uint8_t { @@ -40,6 +46,47 @@ namespace Hyprutils::String { } } +#if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 200000 + // libc++ < 20 does not implement std::from_chars for floating point types + if constexpr (std::floating_point) { + std::string_view ts = sv; + if (ts.starts_with('+') || ts.starts_with('-')) + ts.remove_prefix(1); + if (ts.size() >= 2 && ts[0] == '0' && (ts[1] == 'x' || ts[1] == 'X')) + return std::unexpected(NUMERIC_PARSE_GARBAGE); + + std::string s{sv}; + char* endptr = nullptr; + errno = 0; + + if constexpr (std::same_as) + value = std::strtof(s.c_str(), &endptr); + else if constexpr (std::same_as) + value = std::strtod(s.c_str(), &endptr); + else + value = std::strtold(s.c_str(), &endptr); + + if (endptr == s.c_str()) + return std::unexpected(NUMERIC_PARSE_BAD); + if (errno == ERANGE) + return std::unexpected(NUMERIC_PARSE_OUT_OF_RANGE); + if (endptr != s.c_str() + s.size()) + return std::unexpected(NUMERIC_PARSE_GARBAGE); + + return value; + } else { + const auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), value); + + if (ec == std::errc::invalid_argument) + return std::unexpected(NUMERIC_PARSE_BAD); + if (ec == std::errc::result_out_of_range) + return std::unexpected(NUMERIC_PARSE_OUT_OF_RANGE); + if (ptr != sv.data() + sv.size()) + return std::unexpected(NUMERIC_PARSE_GARBAGE); + + return value; + } +#else const auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), value); if (ec == std::errc::invalid_argument) @@ -50,5 +97,6 @@ namespace Hyprutils::String { return std::unexpected(NUMERIC_PARSE_GARBAGE); return value; +#endif } -}; \ No newline at end of file +};