]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
enhance(util): Add parse_double function
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 4 Aug 2021 19:39:08 +0000 (21:39 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 4 Aug 2021 19:39:08 +0000 (21:39 +0200)
src/util/string.cpp
src/util/string.hpp
unittest/test_util_string.cpp

index 87055605eb184971566847593ef1ba778e9ed470..38df7d99af23c28578197bef0c3ccf8c4a498d5d 100644 (file)
 
 namespace util {
 
+nonstd::expected<double, std::string>
+parse_double(const std::string& value)
+{
+  size_t end;
+  double result;
+  bool failed = false;
+  try {
+    result = std::stod(value, &end);
+  } catch (const std::exception&) {
+    failed = true;
+  }
+
+  if (failed || end != value.size()) {
+    return nonstd::make_unexpected(
+      FMT("invalid floating point: \"{}\"", value));
+  } else {
+    return result;
+  }
+}
+
 nonstd::expected<int64_t, std::string>
 parse_signed(const std::string& value,
              const nonstd::optional<int64_t> min_value,
index c3a15e8816db05263b412954c34998f15e08557f..62b0670bb35f3fc1006163dd2160280b69443a2e 100644 (file)
@@ -47,6 +47,11 @@ template<typename T>
 std::string
 join(const T& begin, const T& end, const nonstd::string_view delimiter);
 
+// Parse a string into a double.
+//
+// Returns an error string if `value` cannot be parsed as a double.
+nonstd::expected<double, std::string> parse_double(const std::string& value);
+
 // Parse a string into a signed integer.
 //
 // Returns an error string if `value` cannot be parsed as an int64_t or if the
index 294cdb1eac11609834cfabf9628411077dd075bd..27543041343ffb9bcec246b040298cb6f4e6dd8a 100644 (file)
@@ -72,6 +72,19 @@ TEST_CASE("util::join")
   }
 }
 
+TEST_CASE("util::parse_double")
+{
+  CHECK(*util::parse_double("0") == doctest::Approx(0.0));
+  CHECK(*util::parse_double(".0") == doctest::Approx(0.0));
+  CHECK(*util::parse_double("0.") == doctest::Approx(0.0));
+  CHECK(*util::parse_double("0.0") == doctest::Approx(0.0));
+  CHECK(*util::parse_double("2.1") == doctest::Approx(2.1));
+  CHECK(*util::parse_double("-42.789") == doctest::Approx(-42.789));
+
+  CHECK(util::parse_double("").error() == "invalid floating point: \"\"");
+  CHECK(util::parse_double("x").error() == "invalid floating point: \"x\"");
+}
+
 TEST_CASE("util::parse_signed")
 {
   CHECK(*util::parse_signed("0") == 0);