#ifndef SIMDJSON_DOM_ARRAY_H #define SIMDJSON_DOM_ARRAY_H #include #include "simdjson/dom/base.h" #include "simdjson/internal/tape_ref.h" namespace simdjson { namespace dom { /** * JSON array. */ class array { public: /** Create a new, invalid array */ simdjson_inline array() noexcept; class iterator { public: using value_type = element; using difference_type = std::ptrdiff_t; using pointer = void; using reference = value_type; using iterator_category = std::forward_iterator_tag; /** * Get the actual value */ inline reference operator*() const noexcept; /** * Get the next value. * * Part of the std::iterator interface. */ inline iterator& operator++() noexcept; /** * Get the next value. * * Part of the std::iterator interface. */ inline iterator operator++(int) noexcept; /** * Check if these values come from the same place in the JSON. * * Part of the std::iterator interface. */ inline bool operator!=(const iterator& other) const noexcept; inline bool operator==(const iterator& other) const noexcept; inline bool operator<(const iterator& other) const noexcept; inline bool operator<=(const iterator& other) const noexcept; inline bool operator>=(const iterator& other) const noexcept; inline bool operator>(const iterator& other) const noexcept; iterator() noexcept = default; iterator(const iterator&) noexcept = default; iterator& operator=(const iterator&) noexcept = default; private: simdjson_inline iterator(const internal::tape_ref &tape) noexcept; internal::tape_ref tape{}; friend class array; }; /** * Return the first array element. * * Part of the std::iterable interface. */ inline iterator begin() const noexcept; /** * One past the last array element. * * Part of the std::iterable interface. */ inline iterator end() const noexcept; /** * Get the size of the array (number of immediate children). * It is a saturated value with a maximum of 0xFFFFFF: if the value * is 0xFFFFFF then the size is 0xFFFFFF or greater. */ inline size_t size() const noexcept; /** * Get the total number of slots used by this array on the tape. * * Note that this is not the same thing as `size()`, which reports the * number of actual elements within an array (not counting its children). * * Since an element can use 1 or 2 slots on the tape, you can only use this * to figure out the total size of an array (including its children, * recursively) if you know its structure ahead of time. **/ inline size_t number_of_slots() const noexcept; /** * Get the value associated with the given JSON pointer. We use the RFC 6901 * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node * as the root of its own JSON document. * * dom::parser parser; * array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded); * a.at_pointer("/0/foo/a/1") == 20 * a.at_pointer("0")["foo"]["a"].at(1) == 20 * * @return The value associated with the given JSON pointer, or: * - NO_SUCH_FIELD if a field does not exist in an object * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length * - INCORRECT_TYPE if a non-integer is used to access an array * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed */ inline simdjson_result at_pointer(std::string_view json_pointer) const noexcept; /** * Recursive function which processes the JSON path of each child element */ inline void process_json_path_of_child_elements(std::vector::iterator& current, std::vector::iterator& end, const std::string_view& path_suffix, std::vector& accumulator) const noexcept; /** * Adds support for JSONPath expression with wildcards '*' */ inline simdjson_result> at_path_with_wildcard(std::string_view json_path) const noexcept; /** * Get the value associated with the given JSONPath expression. We only support * JSONPath queries that trivially convertible to JSON Pointer queries: key * names and array indices. * * https://www.rfc-editor.org/rfc/rfc9535 (RFC 9535) * * @return The value associated with the given JSONPath expression, or: * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails * - NO_SUCH_FIELD if a field does not exist in an object * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length * - INCORRECT_TYPE if a non-integer is used to access an array */ inline simdjson_result at_path(std::string_view json_path) const noexcept; /** * Get the value at the given index. This function has linear-time complexity and * is equivalent to the following: * * size_t i=0; * for (auto element : *this) { * if (i == index) { return element; } * i++; * } * return INDEX_OUT_OF_BOUNDS; * * Avoid calling the at() function repeatedly. * * @return The value at the given index, or: * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length */ inline simdjson_result at(size_t index) const noexcept; /** * Gets the values of items in an array element * This function has linear-time complexity: the values are checked one by one. * * @return The child elements of an array */ inline std::vector& get_values(std::vector& out) const noexcept; /** * Implicitly convert object to element */ inline operator element() const noexcept; private: simdjson_inline array(const internal::tape_ref &tape) noexcept; internal::tape_ref tape{}; friend class element; friend struct simdjson_result; template friend class simdjson::internal::string_builder; }; } // namespace dom /** The result of a JSON conversion that may fail. */ template<> struct simdjson_result : public internal::simdjson_result_base { public: simdjson_inline simdjson_result() noexcept; ///< @private simdjson_inline simdjson_result(dom::array value) noexcept; ///< @private simdjson_inline simdjson_result(error_code error) noexcept; ///< @private inline simdjson_result at_pointer(std::string_view json_pointer) const noexcept; inline void process_json_path_of_child_elements(std::vector::iterator& current, std::vector::iterator& end, const std::string_view& path_suffix, std::vector& accumulator) const noexcept; inline simdjson_result> at_path_with_wildcard(std::string_view json_path) const noexcept; inline simdjson_result at_path(std::string_view json_path) const noexcept; inline simdjson_result at(size_t index) const noexcept; inline std::vector& get_values(std::vector& out) const noexcept; #if SIMDJSON_EXCEPTIONS inline dom::array::iterator begin() const noexcept(false); inline dom::array::iterator end() const noexcept(false); inline size_t size() const noexcept(false); #endif // SIMDJSON_EXCEPTIONS }; } // namespace simdjson #if SIMDJSON_SUPPORTS_RANGES namespace std { namespace ranges { template<> inline constexpr bool enable_view = true; #if SIMDJSON_EXCEPTIONS template<> inline constexpr bool enable_view> = true; #endif // SIMDJSON_EXCEPTIONS } // namespace ranges } // namespace std #endif // SIMDJSON_SUPPORTS_RANGES #endif // SIMDJSON_DOM_ARRAY_H