1#ifndef SOURCEMETA_CORE_JSONPOINTER_POINTER_H_
2#define SOURCEMETA_CORE_JSONPOINTER_POINTER_H_
4#include <sourcemeta/core/jsonpointer_token.h>
10#include <initializer_list>
18#include <sourcemeta/core/preprocessor.h>
20namespace sourcemeta::core {
57 : data{std::move(tokens)} {}
60 using value_type =
typename Container::value_type;
61 using allocator_type =
typename Container::allocator_type;
62 using size_type =
typename Container::size_type;
63 using difference_type =
typename Container::difference_type;
64 using reference =
typename Container::reference;
65 using const_reference =
typename Container::const_reference;
66 using pointer =
typename Container::pointer;
67 using const_pointer =
typename Container::const_pointer;
68 using iterator =
typename Container::iterator;
69 using const_iterator =
typename Container::const_iterator;
70 using reverse_iterator =
typename Container::reverse_iterator;
71 using const_reverse_iterator =
typename Container::const_reverse_iterator;
74 auto begin() noexcept -> iterator {
return this->data.begin(); }
76 auto end() noexcept -> iterator {
return this->data.end(); }
78 [[nodiscard]]
auto begin() const noexcept -> const_iterator {
79 return this->data.begin();
82 [[nodiscard]]
auto end() const noexcept -> const_iterator {
83 return this->data.end();
86 [[nodiscard]]
auto cbegin() const noexcept -> const_iterator {
87 return this->data.cbegin();
90 [[nodiscard]]
auto cend() const noexcept -> const_iterator {
91 return this->data.cend();
94 auto rbegin() noexcept -> reverse_iterator {
return this->data.rbegin(); }
96 auto rend() noexcept -> reverse_iterator {
return this->data.rend(); }
98 [[nodiscard]]
auto rbegin() const noexcept -> const_reverse_iterator {
99 return this->data.rbegin();
102 [[nodiscard]]
auto rend() const noexcept -> const_reverse_iterator {
103 return this->data.rend();
106 [[nodiscard]]
auto crbegin() const noexcept -> const_reverse_iterator {
107 return this->data.crbegin();
110 [[nodiscard]]
auto crend() const noexcept -> const_reverse_iterator {
111 return this->data.crend();
125 [[nodiscard]]
auto at(
const size_type index)
const -> const_reference {
126 assert(this->
size() > index);
127 return this->data[index];
141 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto back() const -> const_reference {
142 assert(!this->
empty());
143 return this->data.back();
156 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto size() const noexcept -> size_type {
157 return this->data.size();
172 [[nodiscard]] SOURCEMETA_FORCEINLINE
auto empty() const noexcept ->
bool {
173 return this->data.empty();
189 template <
class... Args>
190 SOURCEMETA_FORCEINLINE
auto emplace_back(Args &&...args) -> reference {
191 return this->data.emplace_back(std::forward<Args>(args)...);
202 auto reserve(
const typename Container::size_type capacity) ->
void {
203 this->data.reserve(capacity);
226 SOURCEMETA_FORCEINLINE
auto
230 }
else if (other.size() == 1) {
235 this->
reserve(this->data.size() + other.size());
237#if __cpp_lib_containers_ranges >= 202202L
238 this->data.append_range(other.data);
240 std::copy(other.data.cbegin(), other.data.cend(),
241 std::back_inserter(this->data));
269 }
else if (other.size() == 1) {
274 this->
reserve(this->data.size() + other.size());
275 std::move(other.data.begin(), other.data.end(),
276 std::back_inserter(this->data));
301 template <
typename OtherT>
302 SOURCEMETA_FORCEINLINE
auto
304 requires std::is_same_v<PropertyT, std::reference_wrapper<const OtherT>>
308 }
else if (other.size() == 1) {
309 const auto &token{other.back()};
310 if (token.is_property()) {
312 this->data.emplace_back(token.to_property(), token.property_hash());
314 this->data.emplace_back(token.to_index());
317 this->
reserve(this->data.size() + other.size());
318 for (
const auto &token : other) {
319 if (token.is_property()) {
321 this->data.emplace_back(token.to_property(), token.property_hash());
323 this->data.emplace_back(token.to_index());
347 SOURCEMETA_FORCEINLINE
auto
349 this->data.emplace_back(property);
371 this->data.emplace_back(std::move(property));
394 this->data.emplace_back(index);
410 assert(!this->
empty());
411 this->data.pop_back();
427 assert(this->
size() >= count);
428 for (std::size_t index = 0; index < count; index++) {
429 this->data.pop_back();
449 assert(!this->
empty());
471 [[nodiscard]]
auto slice(
const std::size_t index)
const
473 assert(index <= this->
size());
474 auto new_begin{this->data.cbegin()};
475 std::advance(new_begin, index);
479#if __cpp_lib_containers_ranges >= 202202L
480 result.data.append_range(
481 std::ranges::subrange(new_begin, this->data.cend()));
483 std::copy(new_begin, this->data.cend(), std::back_inserter(result.data));
505 [[nodiscard]]
auto slice(
const std::size_t start,
const std::size_t end)
const
507 assert(start <= end);
508 assert(end <= this->
size());
509 auto new_begin{this->data.cbegin()};
510 std::advance(new_begin, start);
511 auto new_end{this->data.cbegin()};
512 std::advance(new_end, end);
516#if __cpp_lib_containers_ranges >= 202202L
517 result.data.append_range(std::ranges::subrange(new_begin, new_end));
519 std::copy(new_begin, new_end, std::back_inserter(result.data));
590 return other.data.size() <= this->data.size() &&
591 std::equal(other.data.cbegin(), other.data.cend(),
592 this->data.cbegin());
608 const Token &tail)
const ->
bool {
609 if (other.size() == this->size() + 1) {
610 assert(!other.empty());
611 return other.starts_with(*
this) && other.back() == tail;
630 template <
typename StringT>
631 requires(!std::is_same_v<std::decay_t<StringT>,
Token>)
633 const StringT &tail)
const ->
bool {
634 const auto prefix_size{other.
size()};
636 this->data[prefix_size].is_property() &&
637 this->data[prefix_size].to_property() == tail;
653 template <
typename StringLeftT,
typename StringRightT>
654 requires(!std::is_same_v<std::decay_t<StringLeftT>,
Token> &&
655 !std::is_same_v<std::decay_t<StringRightT>,
Token>)
657 const StringLeftT &tail_left,
658 const StringRightT &tail_right)
const ->
bool {
659 const auto prefix_size{other.
size()};
660 return this->
size() > prefix_size + 1 &&
662 this->data[prefix_size + 1].is_property() &&
663 this->data[prefix_size + 1].to_property() == tail_right;
679 const size_type prefix_size)
const ->
bool {
680 return this->data.size() >= prefix_size &&
681 other.data.size() >= prefix_size &&
682 std::equal(this->data.cbegin(),
683 std::next(this->data.cbegin(),
684 static_cast<difference_type
>(prefix_size)),
685 other.data.cbegin());
703 return this->data.size() > other.data.size() &&
721 const auto prefix_size{other.
size()};
722 if (prefix_size == 0) {
724 }
else if (this->
size() < prefix_size - 1) {
728 for (std::size_t index = 0; index < prefix_size - 1; index++) {
729 if (this->data[index] != other.data[index]) {
754 typename Container::size_type index{0};
755 while (index < prefix.size()) {
756 if (index >= this->
size() || prefix.data[index] != this->data[index]) {
763 assert(index == prefix.size());
765 auto new_begin{this->data.cbegin()};
766 std::advance(new_begin, index);
769#if __cpp_lib_containers_ranges >= 202202L
770 result.data.append_range(
771 std::ranges::subrange(new_begin, this->data.cend()));
773 std::copy(new_begin, this->data.cend(), std::back_inserter(result.data));
799 typename Container::size_type index{0};
800 while (index < base.size()) {
801 if (index >= this->
size() || base.data[index] != this->data[index]) {
809 auto new_begin{this->data.cbegin()};
810 std::advance(new_begin, index);
812 const auto remaining{
static_cast<typename Container::size_type
>(
813 this->data.cend() - new_begin)};
814 result.data.reserve(remaining);
816#if __cpp_lib_containers_ranges >= 202202L
817 result.data.append_range(
818 std::ranges::subrange(new_begin, this->data.cend()));
820 std::copy(new_begin, this->data.cend(), std::back_inserter(result.data));
829 return this->data == other.data;
835 &other)
const noexcept ->
bool {
836 return this->data == other.get().data;
844 return this->data < other.data;
850 &other)
const noexcept ->
bool {
851 return this->data < other.get().data;
856 using is_transparent = void;
861 const auto size{pointer.size()};
866 const auto &first{pointer.at(0)};
867 const auto &middle{pointer.at(
size / 2)};
868 const auto &last{pointer.at(
size - 1)};
871 (first.is_property() ? property_hash(first.property_hash())
872 : first.to_index()) +
873 (middle.is_property() ? property_hash(middle.property_hash())
874 : middle.to_index()) +
875 (last.is_property() ? property_hash(last.property_hash())
881 &reference)
const noexcept -> std::size_t {
882 return (*
this)(reference.get());
888 static auto property_hash(
const typename Hash::hash_type &hash)
noexcept
890 return static_cast<std::size_t
>(hash.a) ^
891 static_cast<std::size_t
>(hash.a >> 64);
897 using is_transparent = void;
902 return left == right;
909 &right)
const noexcept ->
bool {
910 return left.get() == right.get();
917 return left.get() == right;
923 &right)
const noexcept ->
bool {
924 return left == right.get();
930 auto result{Value::make_array()};
931 for (
const auto &token : this->data) {
932 result.push_back(token.to_json());
940 -> std::optional<GenericPointer<PropertyT, Hash>>
941 requires std::is_same_v<PropertyT, typename Value::String>
943 if (!value.is_array()) {
948 for (
const auto &element : value.as_array()) {
949 if (element.is_string()) {
951 }
else if (element.is_integer() && element.to_integer() >= 0) {
953 static_cast<typename
Token::Index>(element.to_integer()));
typename Value::Array::size_type Index
The stored type of an array index token.
Definition jsonpointer_token.h:20
auto rebase(const GenericPointer< PropertyT, Hash > &prefix, const GenericPointer< PropertyT, Hash > &replacement) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:751
auto slice(const std::size_t start, const std::size_t end) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:505
SOURCEMETA_FORCEINLINE auto push_back(const typename Token::Property &property) -> void
Definition jsonpointer_pointer.h:348
auto shares_prefix(const GenericPointer< PropertyT, Hash > &other, const size_type prefix_size) const -> bool
Definition jsonpointer_pointer.h:678
static auto from_json(const Value &value) -> std::optional< GenericPointer< PropertyT, Hash > >
Deserialise a JSON Pointer from a JSON array of tokens.
Definition jsonpointer_pointer.h:939
auto slice(const std::size_t index) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:471
JSON Value
The JSON value type these tokens convert to.
Definition jsonpointer_token.h:16
auto concat(const GenericPointer< PropertyT, Hash > &other) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:536
SOURCEMETA_FORCEINLINE auto push_back(GenericPointer< PropertyT, Hash > &&other) -> void
Definition jsonpointer_pointer.h:265
auto resolve_from(const GenericPointer< PropertyT, Hash > &base) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:793
auto starts_with_initial(const GenericPointer< PropertyT, Hash > &other) const -> bool
Definition jsonpointer_pointer.h:719
auto starts_with(const GenericPointer< PropertyT, Hash > &other, const Token &tail) const -> bool
Definition jsonpointer_pointer.h:607
SOURCEMETA_FORCEINLINE auto emplace_back(Args &&...args) -> reference
Definition jsonpointer_pointer.h:190
auto pop_back() -> void
Definition jsonpointer_pointer.h:409
auto concat(const typename Token::Property &property) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:553
typename Token::Value Value
Definition jsonpointer_pointer.h:30
auto concat(const typename Token::Index &index) const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:570
SOURCEMETA_FORCEINLINE auto push_back(const GenericPointer< PropertyT, Hash > &other) -> void
Definition jsonpointer_pointer.h:227
auto at(const size_type index) const -> const_reference
Definition jsonpointer_pointer.h:125
SOURCEMETA_FORCEINLINE auto push_back(const typename Token::Index &index) -> void
Definition jsonpointer_pointer.h:392
SOURCEMETA_FORCEINLINE auto empty() const noexcept -> bool
Definition jsonpointer_pointer.h:172
auto starts_with(const GenericPointer< PropertyT, Hash > &other) const -> bool
Definition jsonpointer_pointer.h:589
auto reserve(const typename Container::size_type capacity) -> void
Definition jsonpointer_pointer.h:202
auto starts_with_strict(const GenericPointer< PropertyT, Hash > &other) const -> bool
Definition jsonpointer_pointer.h:701
GenericPointer() noexcept
Definition jsonpointer_pointer.h:43
SOURCEMETA_FORCEINLINE auto back() const -> const_reference
Definition jsonpointer_pointer.h:141
GenericToken< JSON::String, PropertyHashJSON< JSON::String > > Token
Definition jsonpointer_pointer.h:28
GenericPointer(std::initializer_list< Token > tokens)
Definition jsonpointer_pointer.h:56
auto to_json() const -> Value
Serialise a JSON Pointer as a JSON array of tokens.
Definition jsonpointer_pointer.h:929
auto pop_back(const size_type count) -> void
Definition jsonpointer_pointer.h:426
SOURCEMETA_FORCEINLINE auto push_back(typename Token::Property &&property) -> void
Definition jsonpointer_pointer.h:369
SOURCEMETA_FORCEINLINE auto push_back(const GenericPointer< OtherT, Hash > &other) -> void
Definition jsonpointer_pointer.h:303
SOURCEMETA_FORCEINLINE auto size() const noexcept -> size_type
Definition jsonpointer_pointer.h:156
std::vector< Token > Container
Definition jsonpointer_pointer.h:32
auto starts_with(const GenericPointer< PropertyT, Hash > &other, const StringT &tail) const -> bool
Definition jsonpointer_pointer.h:632
PropertyT Property
The stored type of an object property token.
Definition jsonpointer_token.h:18
auto initial() const -> GenericPointer< PropertyT, Hash >
Definition jsonpointer_pointer.h:448
auto starts_with(const GenericPointer< PropertyT, Hash > &other, const StringLeftT &tail_left, const StringRightT &tail_right) const -> bool
Definition jsonpointer_pointer.h:656