pointer.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. #pragma once
  2. #include <cstdint>
  3. #include <iostream>
  4. #include <string>
  5. #include <string_view>
  6. #include <variant>
  7. #include <vector>
  8. #include <jvalidate/detail/compare.h>
  9. #include <jvalidate/forward.h>
  10. namespace jvalidate::detail {
  11. class Pointer {
  12. public:
  13. Pointer() = default;
  14. Pointer(std::vector<std::variant<std::string, size_t>> const & tokens) : tokens_(tokens) {}
  15. Pointer(std::string_view path) {
  16. auto append_with_parse = [this](std::string in) {
  17. if (in.find_first_not_of("0123456789") == std::string::npos) {
  18. tokens_.push_back(std::stoull(in));
  19. } else {
  20. tokens_.push_back(std::move(in));
  21. }
  22. };
  23. path.remove_prefix(1);
  24. size_t p = path.find('/');
  25. for (; p != std::string::npos; path.remove_prefix(p + 1), p = path.find('/')) {
  26. append_with_parse(std::string(path.substr(0, p)));
  27. }
  28. if (not path.empty()) {
  29. append_with_parse(std::string(path));
  30. }
  31. }
  32. template <Adapter A> A walk(A document) const {
  33. for (auto const & token : tokens_) {
  34. document = std::visit([&document](auto const & next) { return document[next]; }, token);
  35. }
  36. return document;
  37. }
  38. Pointer parent() const { return Pointer({tokens_.begin(), tokens_.end() - 1}); }
  39. Pointer & operator/=(Pointer const & relative) {
  40. tokens_.insert(tokens_.end(), relative.tokens_.begin(), relative.tokens_.end());
  41. return *this;
  42. }
  43. Pointer operator/(Pointer const & relative) const { return Pointer(*this) /= relative; }
  44. Pointer & operator/=(std::string_view key) {
  45. tokens_.emplace_back(std::string(key));
  46. return *this;
  47. }
  48. Pointer operator/(std::string_view key) const { return Pointer(*this) /= key; }
  49. Pointer & operator/=(size_t index) {
  50. tokens_.emplace_back(index);
  51. return *this;
  52. }
  53. Pointer operator/(size_t index) const { return Pointer(*this) /= index; }
  54. friend std::ostream & operator<<(std::ostream & os, Pointer const & self) {
  55. for (auto const & elem : self.tokens_) {
  56. std::visit([&os](auto const & v) { os << '/' << v; }, elem);
  57. }
  58. return os;
  59. }
  60. auto operator<=>(Pointer const &) const = default;
  61. private:
  62. std::vector<std::variant<std::string, size_t>> tokens_{};
  63. };
  64. }