| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- #pragma once
- #include <ostream>
- #include <string>
- #include <string_view>
- #include <jvalidate/compat/expected.h>
- #include <jvalidate/detail/expect.h>
- #include <jvalidate/detail/number.h>
- #include <jvalidate/detail/pointer.h>
- #include <jvalidate/forward.h>
- namespace jvalidate::detail {
- class RelativePointer {
- public:
- static expected<RelativePointer, std::string> parse(std::string_view path) {
- if (path == "0") {
- return RelativePointer();
- }
- RelativePointer rval;
- if (auto pos = path.find('/'); pos != path.npos) {
- expected ptr = Pointer::parse(path.substr(pos));
- JVALIDATE_PROPIGATE_UNEXPECTED(ptr);
- rval.pointer_ = *std::move(ptr);
- path.remove_suffix(path.size() - pos);
- } else if (path.back() == '#') {
- rval.requests_key_ = true;
- path.remove_suffix(1);
- }
- if (path.find_first_not_of("0123456789") != std::string_view::npos) {
- return unexpected("RelativePointer must end in a pointer, or a '#'");
- }
- size_t read = 0;
- expected parent_steps = parse_integer<size_t>(path, {.read = read});
- JVALIDATE_PROPIGATE_UNEXPECTED(parent_steps.transform_error(to_message));
- EXPECT_M(read == path.size(), "Extra chars in RelativePointer");
- rval.parent_steps_ = *parent_steps;
- return rval;
- }
- template <Adapter A>
- std::variant<std::string, A> inspect(Pointer const & where, A const & root) const {
- if (requests_key_) {
- return where.parent(parent_steps_).back();
- }
- auto rval = where.parent(parent_steps_).walk(root);
- return pointer_.walk(rval);
- }
- friend std::ostream & operator<<(std::ostream & os, RelativePointer const & rel) {
- os << rel.parent_steps_;
- if (rel.requests_key_) {
- return os << '#';
- }
- os << rel.pointer_;
- return os;
- }
- private:
- size_t parent_steps_ = 0;
- bool requests_key_ = false;
- Pointer pointer_ = {};
- };
- }
|