diff --git a/deps/simdjson/simdjson.cpp b/deps/simdjson/simdjson.cpp index cbcd9f1e6bc017..64b42aab8941b7 100644 --- a/deps/simdjson/simdjson.cpp +++ b/deps/simdjson/simdjson.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */ +/* auto-generated on 2026-04-17 11:03:09 -0400. version 4.6.2 Do not edit! */ /* including simdjson.cpp: */ /* begin file simdjson.cpp */ #define SIMDJSON_SRC_SIMDJSON_CPP diff --git a/deps/simdjson/simdjson.h b/deps/simdjson/simdjson.h index 0a021531346106..b31a801876ce59 100644 --- a/deps/simdjson/simdjson.h +++ b/deps/simdjson/simdjson.h @@ -1,4 +1,4 @@ -/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */ +/* auto-generated on 2026-04-17 11:03:09 -0400. version 4.6.2 Do not edit! */ /* including simdjson.h: */ /* begin file simdjson.h */ #ifndef SIMDJSON_H @@ -2538,7 +2538,7 @@ namespace std { #define SIMDJSON_SIMDJSON_VERSION_H /** The version of simdjson being used (major.minor.revision) */ -#define SIMDJSON_VERSION "4.6.1" +#define SIMDJSON_VERSION "4.6.2" namespace simdjson { enum { @@ -2553,7 +2553,7 @@ enum { /** * The revision (major.minor.REVISION) of simdjson being used. */ - SIMDJSON_VERSION_REVISION = 1 + SIMDJSON_VERSION_REVISION = 2 }; } // namespace simdjson @@ -63512,13 +63512,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -63711,9 +63719,23 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + arm64::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -65216,13 +65238,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -65346,7 +65376,13 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -66246,21 +66282,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -66481,7 +66520,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -66567,7 +66612,13 @@ struct simdjson_result : public arm64::implementation simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -66652,7 +66703,13 @@ struct simdjson_result : public arm64::impl simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -67305,13 +67362,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -67461,7 +67526,13 @@ struct simdjson_result : public arm64::implementation_s simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -68475,46 +68546,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -68522,16 +68581,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -68594,9 +68650,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -69017,14 +69079,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -69288,12 +69356,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -69669,8 +69743,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -69678,9 +69758,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -70017,9 +70097,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -70130,7 +70216,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -70395,11 +70487,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -71977,9 +72075,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -71989,34 +72091,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -72147,9 +72237,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -76788,13 +76884,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -76987,9 +77091,23 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + fallback::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -78492,13 +78610,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -78622,7 +78748,13 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -79522,21 +79654,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -79757,7 +79892,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -79843,7 +79984,13 @@ struct simdjson_result : public fallback::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -79928,7 +80075,13 @@ struct simdjson_result : public fallback simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -80581,13 +80734,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -80737,7 +80898,13 @@ struct simdjson_result : public fallback::implementa simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -81751,46 +81918,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -81798,16 +81953,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -81870,9 +82022,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -82293,14 +82451,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -82564,12 +82728,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -82945,8 +83115,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -82954,9 +83130,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -83293,9 +83469,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -83406,7 +83588,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -83671,11 +83859,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -85253,9 +85447,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -85265,34 +85463,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -85423,9 +85609,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -90551,13 +90743,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -90750,9 +90950,23 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + haswell::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -92255,13 +92469,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -92385,7 +92607,13 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -93285,21 +93513,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -93520,7 +93751,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -93606,7 +93843,13 @@ struct simdjson_result : public haswell::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -93691,7 +93934,13 @@ struct simdjson_result : public haswell:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -94344,13 +94593,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -94500,7 +94757,13 @@ struct simdjson_result : public haswell::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -95514,46 +95777,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -95561,16 +95812,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -95633,9 +95881,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -96056,14 +96310,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -96327,12 +96587,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -96708,8 +96974,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -96717,9 +96989,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -97056,9 +97328,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -97169,7 +97447,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -97434,11 +97718,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -99016,9 +99306,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -99028,34 +99322,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -99186,9 +99468,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -104314,13 +104602,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -104513,9 +104809,23 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + icelake::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -106018,13 +106328,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -106148,7 +106466,13 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -107048,21 +107372,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -107283,7 +107610,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -107369,7 +107702,13 @@ struct simdjson_result : public icelake::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -107454,7 +107793,13 @@ struct simdjson_result : public icelake:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -108107,13 +108452,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -108263,7 +108616,13 @@ struct simdjson_result : public icelake::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -109277,46 +109636,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -109324,16 +109671,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -109396,9 +109740,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -109819,14 +110169,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -110090,12 +110446,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -110471,8 +110833,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -110480,9 +110848,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -110819,9 +111187,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -110932,7 +111306,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -111197,11 +111577,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -112779,9 +113165,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -112791,34 +113181,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -112949,9 +113327,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -118192,13 +118576,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -118391,9 +118783,23 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + ppc64::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -119896,13 +120302,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -120026,7 +120440,13 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -120926,21 +121346,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -121161,7 +121584,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -121247,7 +121676,13 @@ struct simdjson_result : public ppc64::implementation simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -121332,7 +121767,13 @@ struct simdjson_result : public ppc64::impl simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -121985,13 +122426,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -122141,7 +122590,13 @@ struct simdjson_result : public ppc64::implementation_s simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -123155,46 +123610,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -123202,16 +123645,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -123274,9 +123714,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -123697,14 +124143,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -123968,12 +124420,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -124349,8 +124807,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -124358,9 +124822,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -124697,9 +125161,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -124810,7 +125280,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -125075,11 +125551,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -126657,9 +127139,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -126669,34 +127155,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -126827,9 +127301,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -132387,13 +132867,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -132586,9 +133074,23 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + westmere::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -134091,13 +134593,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -134221,7 +134731,13 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -135121,21 +135637,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -135356,7 +135875,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -135442,7 +135967,13 @@ struct simdjson_result : public westmere::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -135527,7 +136058,13 @@ struct simdjson_result : public westmere simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -136180,13 +136717,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -136336,7 +136881,13 @@ struct simdjson_result : public westmere::implementa simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -137350,46 +137901,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -137397,16 +137936,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -137469,9 +138005,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -137892,14 +138434,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -138163,12 +138711,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -138544,8 +139098,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -138553,9 +139113,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -138892,9 +139452,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -139005,7 +139571,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -139270,11 +139842,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -140852,9 +141430,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -140864,34 +141446,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -141022,9 +141592,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -146056,13 +146632,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -146255,9 +146839,23 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + lsx::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -147760,13 +148358,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -147890,7 +148496,13 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -148790,21 +149402,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -149025,7 +149640,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -149111,7 +149732,13 @@ struct simdjson_result : public lsx::implementation_sim simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -149196,7 +149823,13 @@ struct simdjson_result : public lsx::implemen simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -149849,13 +150482,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -150005,7 +150646,13 @@ struct simdjson_result : public lsx::implementation_simdj simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -151019,46 +151666,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -151066,16 +151701,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -151138,9 +151770,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -151561,14 +152199,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -151832,12 +152476,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -152213,8 +152863,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -152222,9 +152878,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -152561,9 +153217,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -152674,7 +153336,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -152939,11 +153607,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -154521,9 +155195,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -154533,34 +155211,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -154691,9 +155357,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -159748,13 +160420,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -159947,9 +160627,23 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + lasx::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -161452,13 +162146,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -161582,7 +162284,13 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -162482,21 +163190,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -162717,7 +163428,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -162803,7 +163520,13 @@ struct simdjson_result : public lasx::implementation_s simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -162888,7 +163611,13 @@ struct simdjson_result : public lasx::implem simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -163541,13 +164270,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -163697,7 +164434,13 @@ struct simdjson_result : public lasx::implementation_sim simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -164711,46 +165454,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -164758,16 +165489,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -164830,9 +165558,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -165253,14 +165987,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -165524,12 +166264,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -165905,8 +166651,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -165914,9 +166666,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -166253,9 +167005,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -166366,7 +167124,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -166631,11 +167395,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -168213,9 +168983,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -168225,34 +168999,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -168383,9 +169145,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept { @@ -173444,13 +174212,21 @@ class value { simdjson_inline simdjson_result at_path(std::string_view at_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard character (*) for arrays or ".*" for objects. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; protected: /** @@ -173643,9 +174419,23 @@ struct simdjson_result : public rvv_vls::implementatio simdjson_inline simdjson_result current_depth() const noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; }; +// Forward-declare explicit specializations so MSVC /permissive- sees them before +// any template instantiation that would resolve element.get(val) to the primary. +template<> simdjson_inline error_code +simdjson_result::get( + rvv_vls::ondemand::value &out) noexcept; +template<> simdjson_inline simdjson_result +simdjson_result::get() noexcept; + } // namespace simdjson #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H @@ -175148,13 +175938,21 @@ class array { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like "[*]" to match all array elements. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the array and returns a string_view instance corresponding to the @@ -175278,7 +176076,13 @@ struct simdjson_result : public rvv_vls::implementatio simdjson_inline simdjson_result at(size_t index) noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; simdjson_inline simdjson_result raw_json() noexcept; #if SIMDJSON_SUPPORTS_CONCEPTS // TODO: move this code into object-inl.h @@ -176178,21 +176982,24 @@ class document { simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * * Supports wildcard patterns like "$.array[*]" or "$.object.*" to match multiple elements. * - * This method materializes all matching values into a vector. * The document will be consumed after this call. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern, or: - * - INVALID_JSON_POINTER if the JSONPath cannot be parsed - * - NO_SUCH_FIELD if a field does not exist - * - INDEX_OUT_OF_BOUNDS if an array index is out of bounds - * - INCORRECT_TYPE if path traversal encounters wrong type + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Consumes the document and returns a string_view instance corresponding to the @@ -176413,7 +177220,13 @@ class document_reference { simdjson_inline simdjson_result raw_json_token() noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; private: document *doc{nullptr}; @@ -176499,7 +177312,13 @@ struct simdjson_result : public rvv_vls::implementa simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -176584,7 +177403,13 @@ struct simdjson_result : public rvv_vls:: simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; #if SIMDJSON_STATIC_REFLECTION template requires(std::is_class_v && (sizeof...(FieldNames) > 0)) @@ -177237,13 +178062,21 @@ class object { inline simdjson_result at_path(std::string_view json_path) noexcept; /** - * Get all values matching the given JSONPath expression with wildcard support. + * Call the provided callback for each value matching the given JSONPath + * expression with wildcard support. * Supports wildcard patterns like ".*" to match all object fields. * * @param json_path JSONPath expression with wildcards - * @return Vector of values matching the wildcard pattern + * @param callback Function called for each matching value + * @return error_code indicating success or failure */ - inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; /** * Reset the iterator so that we are pointing back at the @@ -177393,7 +178226,13 @@ struct simdjson_result : public rvv_vls::implementati simdjson_inline simdjson_result operator[](std::string_view key) && noexcept; simdjson_inline simdjson_result at_pointer(std::string_view json_pointer) noexcept; simdjson_inline simdjson_result at_path(std::string_view json_path) noexcept; - simdjson_inline simdjson_result> at_path_with_wildcard(std::string_view json_path) noexcept; +#if SIMDJSON_SUPPORTS_CONCEPTS + template + requires std::invocable +#else + template +#endif + simdjson_inline error_code for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept; inline simdjson_result reset() noexcept; inline simdjson_result is_empty() noexcept; inline simdjson_result count_fields() & noexcept; @@ -178407,46 +179246,34 @@ inline simdjson_result array::at_path(std::string_view json_path) noexcep return at_pointer(json_pointer); } -inline simdjson_result> array::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code array::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; // Wildcard case - if(key=="*"){ - for(auto element: *this){ - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - // Use value_unsafe() because we've already checked for errors above. - // The 'element' is a simdjson_result wrapper, and we need to extract - // the underlying value. value_unsafe() is safe here because error() returned false. - result.push_back(std::move(element).value_unsafe()); - - }else{ - auto nested_result = element.at_path_with_wildcard(remaining_path); - - if(nested_result.error()){ - return nested_result.error(); - } - // Same logic as above. - std::vector nested_matches = std::move(nested_result).value_unsafe(); - - result.insert(result.end(), - std::make_move_iterator(nested_matches.begin()), - std::make_move_iterator(nested_matches.end())); + if (key=="*"){ + for(auto element: *this) { + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()) { + callback(val); + } else { + error_code err = element.for_each_at_path_with_wildcard(remaining_path, callback); + if(err) { return err; } } } - return result; - }else{ + return SUCCESS; + } else { // Specific index case in which we access the element at the given index - size_t idx=0; + size_t idx = 0; - for(char c:key){ + for (char c : key) { if(c < '0' || c > '9'){ return INVALID_JSON_POINTER; } @@ -178454,16 +179281,13 @@ inline simdjson_result> array::at_path_with_wildcard(std::str } auto element = at(idx); - - if(element.error()){ - return element.error(); - } - - if(remaining_path.empty()){ - result.push_back(std::move(element).value_unsafe()); - return result; - }else{ - return element.at_path_with_wildcard(remaining_path); + value val; + SIMDJSON_TRY(element.get(val)); + if (remaining_path.empty()){ + callback(val); + return SUCCESS; + } else { + return element.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -178526,9 +179350,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } @@ -178949,14 +179779,20 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path } } -inline simdjson_result> value::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code value::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -179220,12 +180056,18 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard( - std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code simdjson_result::for_each_at_path_with_wildcard( + std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } } // namespace simdjson @@ -179601,8 +180443,14 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p } } -simdjson_inline simdjson_result> document::at_path_with_wildcard(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_path_with_wildcard is called +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { + rewind(); // Rewind the document each time for_each_at_path_with_wildcard is called if (json_path.empty()) { return INVALID_JSON_POINTER; } @@ -179610,9 +180458,9 @@ simdjson_inline simdjson_result> document::at_path_with_wildc SIMDJSON_TRY(type().get(t)); switch (t) { case json_type::array: - return (*this).get_array().at_path_with_wildcard(json_path); + return (*this).get_array().for_each_at_path_with_wildcard(json_path, std::forward(callback)); case json_type::object: - return (*this).get_object().at_path_with_wildcard(json_path); + return (*this).get_object().for_each_at_path_with_wildcard(json_path, std::forward(callback)); default: return INVALID_JSON_POINTER; } @@ -179949,9 +180797,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION @@ -180062,7 +180916,13 @@ simdjson_inline simdjson_result document_reference::get_number() noexcep simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result> document_reference::at_path_with_wildcard(std::string_view json_path) noexcept { return doc->at_path_with_wildcard(json_path); } +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code document_reference::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { return doc->for_each_at_path_with_wildcard(json_path, std::forward(callback)); } simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} simdjson_inline document_reference::operator document&() const noexcept { return *doc; } #if SIMDJSON_SUPPORTS_CONCEPTS && SIMDJSON_STATIC_REFLECTION @@ -180327,11 +181187,17 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } #if SIMDJSON_STATIC_REFLECTION template @@ -181909,9 +182775,13 @@ inline simdjson_result object::at_path(std::string_view json_path) noexce return at_pointer(json_pointer); } -inline simdjson_result> object::at_path_with_wildcard(std::string_view json_path) noexcept { - std::vector result; - +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +inline error_code object::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { auto result_pair = get_next_key_and_json_path(json_path); std::string_view key = result_pair.first; std::string_view remaining_path = result_pair.second; @@ -181921,34 +182791,22 @@ inline simdjson_result> object::at_path_with_wildcard(std::st for (auto field : *this) { value val; SIMDJSON_TRY(field.value().get(val)); - if (remaining_path.empty()) { - result.push_back(std::move(val)); + callback(val); } else { - auto nested_result = val.at_path_with_wildcard(remaining_path); - - if (nested_result.error()) { - return nested_result.error(); - } - // Extract and append all nested matches to our result - std::vector nested_vec; - SIMDJSON_TRY(std::move(nested_result).get(nested_vec)); - - result.insert(result.end(), - std::make_move_iterator(nested_vec.begin()), - std::make_move_iterator(nested_vec.end())); + SIMDJSON_TRY(val.for_each_at_path_with_wildcard(remaining_path, callback)); } } - return result; + return SUCCESS; } else { value val; SIMDJSON_TRY(find_field(key).get(val)); if (remaining_path.empty()) { - result.push_back(std::move(val)); - return result; + callback(val); + return SUCCESS; } else { - return val.at_path_with_wildcard(remaining_path); + return val.for_each_at_path_with_wildcard(remaining_path, callback); } } } @@ -182079,9 +182937,15 @@ simdjson_inline simdjson_result simdjson_result> simdjson_result::at_path_with_wildcard(std::string_view json_path) noexcept { +#if SIMDJSON_SUPPORTS_CONCEPTS +template + requires std::invocable +#else +template +#endif +simdjson_inline error_code simdjson_result::for_each_at_path_with_wildcard(std::string_view json_path, Func&& callback) noexcept { if (error()) { return error(); } - return first.at_path_with_wildcard(json_path); + return first.for_each_at_path_with_wildcard(json_path, std::forward(callback)); } inline simdjson_result simdjson_result::reset() noexcept {