From 6d91804c5710238321417a5c9d9c11ed32de344f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 18 Feb 2024 17:04:19 +0300 Subject: [PATCH] implement float parsing to numFromString --- loader/include/Geode/utils/general.hpp | 31 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp index 1260197e..06dc5054 100644 --- a/loader/include/Geode/utils/general.hpp +++ b/loader/include/Geode/utils/general.hpp @@ -11,6 +11,7 @@ #include #include #include +#include // for some reason std::filesystem::path doesn't have std::hash defined in C++17 // and ghc seems to have inherited this limitation @@ -104,13 +105,29 @@ namespace geode { */ template Result numFromString(std::string_view const str, int base = 10) { - Num result; - auto [_, ec] = std::from_chars(str.data(), str.data() + str.size(), result, base); - switch (ec) { - case std::errc(): return Ok(result); - case std::errc::invalid_argument: return Err("String is not a number"); - case std::errc::result_out_of_range: return Err("Number is too large to fit"); - default: return Err("Unknown error"); + if constexpr (std::is_floating_point_v) { + Num val = {}; + char* strEnd; + errno = 0; + if (std::setlocale(LC_NUMERIC, "en_US.utf8")) { + if constexpr (std::is_same_v) val = std::strtof(str.data(), &strEnd); + else if constexpr (std::is_same_v) val = std::strtod(str.data(), &strEnd); + else if constexpr (std::is_same_v) val = std::strtold(str.data(), &strEnd); + if (errno == ERANGE) return Err("Number is too large to fit"); + else if (strEnd == str.data()) return Err("String is not a number"); + else return Ok(val); + } + else return Err("Failed to set locale"); + } + else { + Num result; + auto [_, ec] = std::from_chars(str.data(), str.data() + str.size(), result, base); + switch (ec) { + case std::errc(): return Ok(result); + case std::errc::invalid_argument: return Err("String is not a number"); + case std::errc::result_out_of_range: return Err("Number is too large to fit"); + default: return Err("Unknown error"); + } } }