relative_pointer.h 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. #pragma once
  2. #include <ostream>
  3. #include <string>
  4. #include <string_view>
  5. #include <jvalidate/detail/expect.h>
  6. #include <jvalidate/detail/pointer.h>
  7. #include <jvalidate/forward.h>
  8. namespace jvalidate::detail {
  9. class RelativePointer {
  10. public:
  11. RelativePointer(std::string_view path) {
  12. if (path == "0") {
  13. return;
  14. }
  15. if (auto pos = path.find('/'); pos != path.npos) {
  16. pointer_ = Pointer(path.substr(pos));
  17. path.remove_suffix(path.size() - pos);
  18. } else {
  19. EXPECT_M(not path.empty() && path.back() == '#',
  20. "RelativePointer must end in a pointer, or a '#'");
  21. requests_key_ = true;
  22. path.remove_suffix(1);
  23. }
  24. parent_steps_ = std::stoull(std::string(path));
  25. }
  26. template <Adapter A>
  27. std::variant<std::string, A> inspect(Pointer const & where, A const & root) const {
  28. if (requests_key_) {
  29. return where.parent(parent_steps_).back();
  30. }
  31. auto rval = where.parent(parent_steps_).walk(root);
  32. return pointer_ ? pointer_->walk(rval) : rval;
  33. }
  34. friend std::ostream & operator<<(std::ostream & os, RelativePointer const & rel) {
  35. os << rel.parent_steps_;
  36. if (rel.requests_key_) {
  37. return os << '#';
  38. }
  39. if (rel.pointer_) {
  40. os << *rel.pointer_;
  41. }
  42. return os;
  43. }
  44. private:
  45. size_t parent_steps_ = 0;
  46. bool requests_key_ = false;
  47. std::optional<Pointer> pointer_ = std::nullopt;
  48. };
  49. }