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 | |
8 | namespace simdjson { |
9 | |
10 | namespace internal { |
11 | template<typename T> |
12 | class string_builder; |
13 | } |
14 | namespace dom { |
15 | |
16 | class document; |
17 | class element; |
18 | |
19 | /** |
20 | * JSON array. |
21 | */ |
22 | class array { |
23 | public: |
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 | |
135 | private: |
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. */ |
148 | template<> |
149 | struct simdjson_result<dom::array> : public internal::simdjson_result_base<dom::array> { |
150 | public: |
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 | |
172 | namespace std { |
173 | namespace ranges { |
174 | template<> |
175 | inline constexpr bool enable_view<simdjson::dom::array> = true; |
176 | #if SIMDJSON_EXCEPTIONS |
177 | template<> |
178 | inline 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 | |