1#ifndef SIMDJSON_INLINE_ARRAY_H
2#define SIMDJSON_INLINE_ARRAY_H
3
4// Inline implementations go in here.
5
6#include "simdjson/dom/array.h"
7#include "simdjson/dom/element.h"
8#include <utility>
9
10namespace simdjson {
11
12//
13// simdjson_result<dom::array> inline implementation
14//
15simdjson_inline simdjson_result<dom::array>::simdjson_result() noexcept
16 : internal::simdjson_result_base<dom::array>() {}
17simdjson_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
18 : internal::simdjson_result_base<dom::array>(std::forward<dom::array>(t&: value)) {}
19simdjson_inline simdjson_result<dom::array>::simdjson_result(error_code error) noexcept
20 : internal::simdjson_result_base<dom::array>(error) {}
21
22#if SIMDJSON_EXCEPTIONS
23
24inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
25 if (error()) { throw simdjson_error(error()); }
26 return first.begin();
27}
28inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
29 if (error()) { throw simdjson_error(error()); }
30 return first.end();
31}
32inline size_t simdjson_result<dom::array>::size() const noexcept(false) {
33 if (error()) { throw simdjson_error(error()); }
34 return first.size();
35}
36
37#endif // SIMDJSON_EXCEPTIONS
38
39inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std::string_view json_pointer) const noexcept {
40 if (error()) { return error(); }
41 return first.at_pointer(json_pointer);
42}
43inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept {
44 if (error()) { return error(); }
45 return first.at(index);
46}
47
48namespace dom {
49
50//
51// array inline implementation
52//
53simdjson_inline array::array() noexcept : tape{} {}
54simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
55inline array::iterator array::begin() const noexcept {
56 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
57 return internal::tape_ref(tape.doc, tape.json_index + 1);
58}
59inline array::iterator array::end() const noexcept {
60 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
61 return internal::tape_ref(tape.doc, tape.after_element() - 1);
62}
63inline size_t array::size() const noexcept {
64 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
65 return tape.scope_count();
66}
67inline size_t array::number_of_slots() const noexcept {
68 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
69 return tape.matching_brace_index() - tape.json_index;
70}
71inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
72 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
73 if(json_pointer.empty()) { // an empty string means that we return the current node
74 return element(this->tape); // copy the current node
75 } else if(json_pointer[0] != '/') { // otherwise there is an error
76 return INVALID_JSON_POINTER;
77 }
78 json_pointer = json_pointer.substr(pos: 1);
79 // - means "the append position" or "the element after the end of the array"
80 // We don't support this, because we're returning a real element, not a position.
81 if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
82
83 // Read the array index
84 size_t array_index = 0;
85 size_t i;
86 for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
87 uint8_t digit = uint8_t(json_pointer[i] - '0');
88 // Check for non-digit in array index. If it's there, we're trying to get a field in an object
89 if (digit > 9) { return INCORRECT_TYPE; }
90 array_index = array_index*10 + digit;
91 }
92
93 // 0 followed by other digits is invalid
94 if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
95
96 // Empty string is invalid; so is a "/" with no digits before it
97 if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
98
99 // Get the child
100 auto child = array(tape).at(index: array_index);
101 // If there is an error, it ends here
102 if(child.error()) {
103 return child;
104 }
105 // If there is a /, we're not done yet, call recursively.
106 if (i < json_pointer.length()) {
107 child = child.at_pointer(json_pointer: json_pointer.substr(pos: i));
108 }
109 return child;
110}
111
112inline simdjson_result<element> array::at(size_t index) const noexcept {
113 SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
114 size_t i=0;
115 for (auto element : *this) {
116 if (i == index) { return element; }
117 i++;
118 }
119 return INDEX_OUT_OF_BOUNDS;
120}
121
122//
123// array::iterator inline implementation
124//
125simdjson_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
126inline element array::iterator::operator*() const noexcept {
127 return element(tape);
128}
129inline array::iterator& array::iterator::operator++() noexcept {
130 tape.json_index = tape.after_element();
131 return *this;
132}
133inline array::iterator array::iterator::operator++(int) noexcept {
134 array::iterator out = *this;
135 ++*this;
136 return out;
137}
138inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
139 return tape.json_index != other.tape.json_index;
140}
141inline bool array::iterator::operator==(const array::iterator& other) const noexcept {
142 return tape.json_index == other.tape.json_index;
143}
144inline bool array::iterator::operator<(const array::iterator& other) const noexcept {
145 return tape.json_index < other.tape.json_index;
146}
147inline bool array::iterator::operator<=(const array::iterator& other) const noexcept {
148 return tape.json_index <= other.tape.json_index;
149}
150inline bool array::iterator::operator>=(const array::iterator& other) const noexcept {
151 return tape.json_index >= other.tape.json_index;
152}
153inline bool array::iterator::operator>(const array::iterator& other) const noexcept {
154 return tape.json_index > other.tape.json_index;
155}
156
157} // namespace dom
158
159
160} // namespace simdjson
161
162#include "simdjson/dom/element-inl.h"
163
164#if defined(__cpp_lib_ranges)
165static_assert(std::ranges::view<simdjson::dom::array>);
166static_assert(std::ranges::sized_range<simdjson::dom::array>);
167#if SIMDJSON_EXCEPTIONS
168static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::array>>);
169static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::array>>);
170#endif // SIMDJSON_EXCEPTIONS
171#endif // defined(__cpp_lib_ranges)
172
173#endif // SIMDJSON_INLINE_ARRAY_H
174