1#ifndef SIMDJSON_DOM_ARRAY_H
2#define SIMDJSON_DOM_ARRAY_H
3
4#include "simdjson/common_defs.h"
5#include "simdjson/error.h"
6#include "simdjson/internal/tape_ref.h"
7
8namespace simdjson {
9
10namespace internal {
11template<typename T>
12class string_builder;
13}
14namespace dom {
15
16class document;
17class element;
18
19/**
20 * JSON array.
21 */
22class array {
23public:
24 /** Create a new, invalid array */
25 simdjson_inline array() noexcept;
26
27 class iterator {
28 public:
29 using value_type = element;
30 using difference_type = std::ptrdiff_t;
31
32 /**
33 * Get the actual value
34 */
35 inline value_type operator*() const noexcept;
36 /**
37 * Get the next value.
38 *
39 * Part of the std::iterator interface.
40 */
41 inline iterator& operator++() noexcept;
42 /**
43 * Get the next value.
44 *
45 * Part of the std::iterator interface.
46 */
47 inline iterator operator++(int) noexcept;
48 /**
49 * Check if these values come from the same place in the JSON.
50 *
51 * Part of the std::iterator interface.
52 */
53 inline bool operator!=(const iterator& other) const noexcept;
54 inline bool operator==(const iterator& other) const noexcept;
55
56 inline bool operator<(const iterator& other) const noexcept;
57 inline bool operator<=(const iterator& other) const noexcept;
58 inline bool operator>=(const iterator& other) const noexcept;
59 inline bool operator>(const iterator& other) const noexcept;
60
61 iterator() noexcept = default;
62 iterator(const iterator&) noexcept = default;
63 iterator& operator=(const iterator&) noexcept = default;
64 private:
65 simdjson_inline iterator(const internal::tape_ref &tape) noexcept;
66 internal::tape_ref tape;
67 friend class array;
68 };
69
70 /**
71 * Return the first array element.
72 *
73 * Part of the std::iterable interface.
74 */
75 inline iterator begin() const noexcept;
76 /**
77 * One past the last array element.
78 *
79 * Part of the std::iterable interface.
80 */
81 inline iterator end() const noexcept;
82 /**
83 * Get the size of the array (number of immediate children).
84 * It is a saturated value with a maximum of 0xFFFFFF: if the value
85 * is 0xFFFFFF then the size is 0xFFFFFF or greater.
86 */
87 inline size_t size() const noexcept;
88 /**
89 * Get the total number of slots used by this array on the tape.
90 *
91 * Note that this is not the same thing as `size()`, which reports the
92 * number of actual elements within an array (not counting its children).
93 *
94 * Since an element can use 1 or 2 slots on the tape, you can only use this
95 * to figure out the total size of an array (including its children,
96 * recursively) if you know its structure ahead of time.
97 **/
98 inline size_t number_of_slots() const noexcept;
99 /**
100 * Get the value associated with the given JSON pointer. We use the RFC 6901
101 * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
102 * as the root of its own JSON document.
103 *
104 * dom::parser parser;
105 * array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded);
106 * a.at_pointer("/0/foo/a/1") == 20
107 * a.at_pointer("0")["foo"]["a"].at(1) == 20
108 *
109 * @return The value associated with the given JSON pointer, or:
110 * - NO_SUCH_FIELD if a field does not exist in an object
111 * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
112 * - INCORRECT_TYPE if a non-integer is used to access an array
113 * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
114 */
115 inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept;
116
117 /**
118 * Get the value at the given index. This function has linear-time complexity and
119 * is equivalent to the following:
120 *
121 * size_t i=0;
122 * for (auto element : *this) {
123 * if (i == index) { return element; }
124 * i++;
125 * }
126 * return INDEX_OUT_OF_BOUNDS;
127 *
128 * Avoid calling the at() function repeatedly.
129 *
130 * @return The value at the given index, or:
131 * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
132 */
133 inline simdjson_result<element> at(size_t index) const noexcept;
134
135private:
136 simdjson_inline array(const internal::tape_ref &tape) noexcept;
137 internal::tape_ref tape;
138 friend class element;
139 friend struct simdjson_result<element>;
140 template<typename T>
141 friend class simdjson::internal::string_builder;
142};
143
144
145} // namespace dom
146
147/** The result of a JSON conversion that may fail. */
148template<>
149struct simdjson_result<dom::array> : public internal::simdjson_result_base<dom::array> {
150public:
151 simdjson_inline simdjson_result() noexcept; ///< @private
152 simdjson_inline simdjson_result(dom::array value) noexcept; ///< @private
153 simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
154
155 inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept;
156 inline simdjson_result<dom::element> at(size_t index) const noexcept;
157
158#if SIMDJSON_EXCEPTIONS
159 inline dom::array::iterator begin() const noexcept(false);
160 inline dom::array::iterator end() const noexcept(false);
161 inline size_t size() const noexcept(false);
162#endif // SIMDJSON_EXCEPTIONS
163};
164
165
166
167} // namespace simdjson
168
169#if defined(__cpp_lib_ranges)
170#include <ranges>
171
172namespace std {
173namespace ranges {
174template<>
175inline constexpr bool enable_view<simdjson::dom::array> = true;
176#if SIMDJSON_EXCEPTIONS
177template<>
178inline constexpr bool enable_view<simdjson::simdjson_result<simdjson::dom::array>> = true;
179#endif // SIMDJSON_EXCEPTIONS
180} // namespace ranges
181} // namespace std
182#endif // defined(__cpp_lib_ranges)
183
184#endif // SIMDJSON_DOM_ARRAY_H
185