relative_pointer.h 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. #pragma once
  2. #include <ostream>
  3. #include <string>
  4. #include <string_view>
  5. #include <jvalidate/compat/expected.h>
  6. #include <jvalidate/detail/expect.h>
  7. #include <jvalidate/detail/number.h>
  8. #include <jvalidate/detail/pointer.h>
  9. #include <jvalidate/forward.h>
  10. namespace jvalidate::detail {
  11. class RelativePointer {
  12. public:
  13. static expected<RelativePointer, std::string> parse(std::string_view path) {
  14. if (path == "0") {
  15. return RelativePointer();
  16. }
  17. RelativePointer rval;
  18. if (auto pos = path.find('/'); pos != path.npos) {
  19. expected ptr = Pointer::parse(path.substr(pos));
  20. JVALIDATE_PROPIGATE_UNEXPECTED(ptr);
  21. rval.pointer_ = *std::move(ptr);
  22. path.remove_suffix(path.size() - pos);
  23. } else if (path.back() == '#') {
  24. rval.requests_key_ = true;
  25. path.remove_suffix(1);
  26. }
  27. if (path.find_first_not_of("0123456789") != std::string_view::npos) {
  28. return unexpected("RelativePointer must end in a pointer, or a '#'");
  29. }
  30. size_t read = 0;
  31. expected parent_steps = parse_integer<size_t>(path, {.read = read});
  32. JVALIDATE_PROPIGATE_UNEXPECTED(parent_steps.transform_error(to_message));
  33. EXPECT_M(read == path.size(), "Extra chars in RelativePointer");
  34. rval.parent_steps_ = *parent_steps;
  35. return rval;
  36. }
  37. template <Adapter A>
  38. std::variant<std::string, A> inspect(Pointer const & where, A const & root) const {
  39. if (requests_key_) {
  40. return where.parent(parent_steps_).back();
  41. }
  42. auto rval = where.parent(parent_steps_).walk(root);
  43. return pointer_.walk(rval);
  44. }
  45. friend std::ostream & operator<<(std::ostream & os, RelativePointer const & rel) {
  46. os << rel.parent_steps_;
  47. if (rel.requests_key_) {
  48. return os << '#';
  49. }
  50. os << rel.pointer_;
  51. return os;
  52. }
  53. private:
  54. size_t parent_steps_ = 0;
  55. bool requests_key_ = false;
  56. Pointer pointer_ = {};
  57. };
  58. }