From 9f11cab092ab77790660e6f0e54b0f1d9085a487 Mon Sep 17 00:00:00 2001 From: Vojtech Bubnik Date: Thu, 29 Oct 2020 11:31:59 +0100 Subject: [PATCH] Workaround for missing or partially implemented std::from_chars() --- src/libslic3r/GCode/GCodeProcessor.cpp | 47 +++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 4a971960b..6ee3eef20 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -9,7 +9,10 @@ #include #include -#include + +#if __has_include() + #include +#endif #if ENABLE_GCODE_VIEWER #include @@ -947,13 +950,47 @@ static inline bool starts_with(const std::string_view comment, const std::string return comment.size() >= tag_len && comment.substr(0, tag_len) == tag; } +#if __has_include() + template + struct is_from_chars_convertible : std::false_type {}; + template + struct is_from_chars_convertible(), declval(), declval()))>> : std::true_type {}; +#endif + // Returns true if the number was parsed correctly into out and the number spanned the whole input string. template -static inline bool parse_number(const std::string_view str, T &out) +[[nodiscard]] static inline bool parse_number(const std::string_view sv, T &out) { - auto str_end = str.data() + str.size(); - auto [end_ptr, error_code] = std::from_chars(str.data(), str_end, out); - return error_code == std::errc() && end_ptr == str_end; + // https://www.bfilipek.com/2019/07/detect-overload-from-chars.html#example-stdfromchars +#if __has_include() + // Visual Studio 19 supports from_chars all right. + // OSX compiler that we use only implements std::from_chars just for ints. + // GCC that we compile on does not provide at all. + if constexpr (is_from_chars_convertible::value) { + auto str_end = sv.data() + sv.size(); + auto [end_ptr, error_code] = std::from_chars(sv.data(), str_end, out); + return error_code == std::errc() && end_ptr == str_end; + } + else +#endif + { + // Legacy conversion, which is costly due to having to make a copy of the string before conversion. + try { + std::string str { str }; + size_t read = 0; + if constexpr (std::is_same_v) + out = std::stoi(str, &read); + else if constexpr (std::is_same_v) + out = std::stol(str, &read); + else if constexpr (std::is_same_v) + out = std::stof(str, &read); + else if constexpr (std::is_same_v) + out = std::stod(str, &read); + return str.size() == read; + } catch (...) { + return false; + } + } } void GCodeProcessor::process_tags(const std::string_view comment)