Procházet zdrojové kódy

refactor: create Pointer::parse using expected

Sam Jaffe před 3 měsíci
rodič
revize
2742b8c4d9

+ 9 - 0
include/jvalidate/detail/expect.h

@@ -97,3 +97,12 @@
   if (JVALIDATE_UNLIKELY(!(condition))) {                                                          \
     return __VA_ARGS__;                                                                            \
   }
+
+/**
+ * @brief Assert that a std::expected (or jvalidate::detail::expected) contains
+ * a real value, or else return the unexpected (error).
+ *
+ * @param exp The std::expected
+ */
+#define JVALIDATE_PROPIGATE_UNEXPECTED(exp)                                                        \
+  RETURN_UNLESS(exp.has_value(), jvalidate::detail::unexpected(std::move(exp).error()))

+ 27 - 0
include/jvalidate/detail/pointer.h

@@ -67,6 +67,33 @@ public:
     tokens_.push_back(parse_token(std::string(path)).value());
   }
 
+  static expected<Pointer, std::string> parse(std::string_view path) {
+    if (path.empty()) {
+      return Pointer();
+    }
+
+    // JSON-Pointers are required to start with a '/' although we only enforce
+    // that rule in Reference.
+    path.remove_prefix(1);
+    // The rules of JSON-Pointer is that if a token were to contain a '/' as a
+    // strict character: then that character would be escaped, using the above
+    // rules. We take advantage of string_view's sliding view to make iteration
+    // easy.
+    Pointer rval;
+    for (size_t p = path.find('/'); p != std::string::npos;
+         path.remove_prefix(p + 1), p = path.find('/')) {
+      expected token = parse_token(std::string(path.substr(0, p)));
+      JVALIDATE_PROPIGATE_UNEXPECTED(token);
+      rval.tokens_.push_back(*token);
+    }
+
+    expected token = parse_token(std::string(path));
+    JVALIDATE_PROPIGATE_UNEXPECTED(token);
+    rval.tokens_.push_back(*token);
+
+    return rval;
+  }
+
   template <typename T>
   static expected<T, std::string> parse_integer(std::string_view in, int base = 10) {
     T rval = 0;