aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authorgrigoriypisar <grigoriypisar@yandex-team.com>2024-10-04 16:06:42 +0300
committergrigoriypisar <grigoriypisar@yandex-team.com>2024-10-04 16:16:23 +0300
commit878b50bb2ed42fd7ce11c383bb2a0966c8281eed (patch)
treeaf8206d9c6caf4a2b72ff65c0840e1f36c8e1957 /contrib/libs
parent5d32f79de3c53b2eaebca9be84a7399d479f8549 (diff)
downloadydb-878b50bb2ed42fd7ce11c383bb2a0966c8281eed.tar.gz
ydblib: fix simdjson interface import
Added path simdjson/include commit_hash:45ec98b09ff78925e6e1fc11b540780c258e0fbb
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/simdjson/include/simdjson.h57
-rw-r--r--contrib/libs/simdjson/include/simdjson/arm64/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/builtin.h33
-rw-r--r--contrib/libs/simdjson/include/simdjson/builtin/base.h41
-rw-r--r--contrib/libs/simdjson/include/simdjson/builtin/implementation.h42
-rw-r--r--contrib/libs/simdjson/include/simdjson/builtin/ondemand.h40
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom.h23
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/array-inl.h181
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/array.h183
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/document-inl.h159
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/document_stream-inl.h348
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/document_stream.h322
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/element-inl.h473
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/element.h552
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/object-inl.h263
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/object.h274
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/parser-inl.h258
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/parser.h650
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/serialization-inl.h536
-rw-r--r--contrib/libs/simdjson/include/simdjson/dom/serialization.h260
-rw-r--r--contrib/libs/simdjson/include/simdjson/fallback/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h42
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h283
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h216
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator-inl.h78
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator.h96
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/base.h47
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h17
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h917
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h914
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h433
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream.h337
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/field-inl.h129
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/field.h113
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator-inl.h444
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator.h338
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type-inl.h117
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type.h160
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/logger-inl.h225
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/logger.h58
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/object-inl.h276
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/object.h258
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator-inl.h138
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator.h80
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/parser-inl.h205
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h372
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string-inl.h203
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string.h206
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization-inl.h233
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization.h103
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator-inl.h94
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator.h158
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h542
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h781
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h1091
-rw-r--r--contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator.h492
-rw-r--r--contrib/libs/simdjson/include/simdjson/haswell/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/icelake/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/internal/jsonformatutils.h64
-rw-r--r--contrib/libs/simdjson/include/simdjson/internal/tape_ref-inl.h118
-rw-r--r--contrib/libs/simdjson/include/simdjson/internal/tape_ref.h49
-rw-r--r--contrib/libs/simdjson/include/simdjson/jsonioutil.h22
-rw-r--r--contrib/libs/simdjson/include/simdjson/lasx.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/lasx/end.h6
-rw-r--r--contrib/libs/simdjson/include/simdjson/lasx/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/lsx.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/lsx/end.h6
-rw-r--r--contrib/libs/simdjson/include/simdjson/lsx/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/minify.h30
-rw-r--r--contrib/libs/simdjson/include/simdjson/ondemand.h13
-rw-r--r--contrib/libs/simdjson/include/simdjson/padded_string-inl.h190
-rw-r--r--contrib/libs/simdjson/include/simdjson/padded_string.h183
-rw-r--r--contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h59
-rw-r--r--contrib/libs/simdjson/include/simdjson/padded_string_view.h88
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/base.h26
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/begin.h10
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/bitmanipulation.h78
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/bitmask.h46
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/end.h6
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/implementation.h40
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/intrinsics.h23
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h65
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/ondemand.h8
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/simd.h472
-rw-r--r--contrib/libs/simdjson/include/simdjson/ppc64/stringparsing_defs.h65
-rw-r--r--contrib/libs/simdjson/include/simdjson/simdjson.h11
-rw-r--r--contrib/libs/simdjson/include/simdjson/simdjson_version.h26
-rw-r--r--contrib/libs/simdjson/include/simdjson/westmere/ondemand.h8
89 files changed, 16675 insertions, 0 deletions
diff --git a/contrib/libs/simdjson/include/simdjson.h b/contrib/libs/simdjson/include/simdjson.h
new file mode 100644
index 0000000000..f77ab12b3e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson.h
@@ -0,0 +1,57 @@
+#ifndef SIMDJSON_H
+#define SIMDJSON_H
+
+/**
+ * @mainpage
+ *
+ * Check the [README.md](https://github.com/simdjson/simdjson/blob/master/README.md#simdjson--parsing-gigabytes-of-json-per-second).
+ *
+ * Sample code. See https://github.com/simdjson/simdjson/blob/master/doc/basics.md for more examples.
+
+ #include "simdjson.h"
+
+ int main(void) {
+ // load from `twitter.json` file:
+ simdjson::dom::parser parser;
+ simdjson::dom::element tweets = parser.load("twitter.json");
+ std::cout << tweets["search_metadata"]["count"] << " results." << std::endl;
+
+ // Parse and iterate through an array of objects
+ auto abstract_json = R"( [
+ { "12345" : {"a":12.34, "b":56.78, "c": 9998877} },
+ { "12545" : {"a":11.44, "b":12.78, "c": 11111111} }
+ ] )"_padded;
+
+ for (simdjson::dom::object obj : parser.parse(abstract_json)) {
+ for(const auto key_value : obj) {
+ cout << "key: " << key_value.key << " : ";
+ simdjson::dom::object innerobj = key_value.value;
+ cout << "a: " << double(innerobj["a"]) << ", ";
+ cout << "b: " << double(innerobj["b"]) << ", ";
+ cout << "c: " << int64_t(innerobj["c"]) << endl;
+ }
+ }
+ }
+ */
+
+#include "simdjson/common_defs.h"
+
+// This provides the public API for simdjson.
+// DOM and ondemand are amalgamated separately, in simdjson.h
+#include "simdjson/simdjson_version.h"
+
+#include "simdjson/base.h"
+
+#include "simdjson/error.h"
+#include "simdjson/error-inl.h"
+#include "simdjson/implementation.h"
+#include "simdjson/minify.h"
+#include "simdjson/padded_string.h"
+#include "simdjson/padded_string-inl.h"
+#include "simdjson/padded_string_view.h"
+#include "simdjson/padded_string_view-inl.h"
+
+#include "simdjson/dom.h"
+#include "simdjson/ondemand.h"
+
+#endif // SIMDJSON_H
diff --git a/contrib/libs/simdjson/include/simdjson/arm64/ondemand.h b/contrib/libs/simdjson/include/simdjson/arm64/ondemand.h
new file mode 100644
index 0000000000..6713439467
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/arm64/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_ARM64_ONDEMAND_H
+#define SIMDJSON_ARM64_ONDEMAND_H
+
+#include "simdjson/arm64/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/arm64/end.h"
+
+#endif // SIMDJSON_ARM64_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/builtin.h b/contrib/libs/simdjson/include/simdjson/builtin.h
new file mode 100644
index 0000000000..4788007f88
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/builtin.h
@@ -0,0 +1,33 @@
+#ifndef SIMDJSON_BUILTIN_H
+#define SIMDJSON_BUILTIN_H
+
+#include "simdjson/builtin/base.h"
+#include "simdjson/builtin/implementation.h"
+
+#include "simdjson/generic/dependencies.h"
+
+#define SIMDJSON_CONDITIONAL_INCLUDE
+
+#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
+#include "simdjson/arm64.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
+#include "simdjson/fallback.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
+#include "simdjson/haswell.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
+#include "simdjson/icelake.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
+#include "simdjson/ppc64.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
+#include "simdjson/westmere.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx)
+#include "simdjson/lsx.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
+#include "simdjson/lasx.h"
+#else
+#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
+#endif
+
+#undef SIMDJSON_CONDITIONAL_INCLUDE
+
+#endif // SIMDJSON_BUILTIN_H
diff --git a/contrib/libs/simdjson/include/simdjson/builtin/base.h b/contrib/libs/simdjson/include/simdjson/builtin/base.h
new file mode 100644
index 0000000000..ce1678013e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/builtin/base.h
@@ -0,0 +1,41 @@
+#ifndef SIMDJSON_BUILTIN_BASE_H
+#define SIMDJSON_BUILTIN_BASE_H
+
+#include "simdjson/base.h"
+#include "simdjson/implementation_detection.h"
+
+namespace simdjson {
+#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
+ namespace arm64 {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
+ namespace fallback {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
+ namespace haswell {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
+ namespace icelake {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
+ namespace ppc64 {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
+ namespace westmere {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx)
+ namespace lsx {}
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
+ namespace lasx {}
+#else
+#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
+#endif
+
+ /**
+ * Represents the best statically linked simdjson implementation that can be used by the compiling
+ * program.
+ *
+ * Detects what options the program is compiled against, and picks the minimum implementation that
+ * will work on any computer that can run the program. For example, if you compile with g++
+ * -march=westmere, it will pick the westmere implementation. The haswell implementation will
+ * still be available, and can be selected at runtime, but the builtin implementation (and any
+ * code that uses it) will use westmere.
+ */
+ namespace builtin = SIMDJSON_BUILTIN_IMPLEMENTATION;
+} // namespace simdjson
+
+#endif // SIMDJSON_BUILTIN_BASE_H
diff --git a/contrib/libs/simdjson/include/simdjson/builtin/implementation.h b/contrib/libs/simdjson/include/simdjson/builtin/implementation.h
new file mode 100644
index 0000000000..68a175d07a
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/builtin/implementation.h
@@ -0,0 +1,42 @@
+#ifndef SIMDJSON_BUILTIN_IMPLEMENTATION_H
+#define SIMDJSON_BUILTIN_IMPLEMENTATION_H
+
+#include "simdjson/builtin/base.h"
+
+#include "simdjson/generic/dependencies.h"
+
+#define SIMDJSON_CONDITIONAL_INCLUDE
+
+#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
+#include "simdjson/arm64/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
+#include "simdjson/fallback/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
+#include "simdjson/haswell/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
+#include "simdjson/icelake/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
+#error #include "simdjson/ppc64/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
+#include "simdjson/westmere/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx)
+#include "simdjson/lsx/implementation.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
+#include "simdjson/lasx/implementation.h"
+#else
+#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
+#endif
+
+#undef SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+ /**
+ * Function which returns a pointer to an implementation matching the "builtin" implementation.
+ * The builtin implementation is the best statically linked simdjson implementation that can be used by the compiling
+ * program. If you compile with g++ -march=haswell, this will return the haswell implementation.
+ * It is handy to be able to check what builtin was used: builtin_implementation()->name().
+ */
+ const implementation * builtin_implementation();
+} // namespace simdjson
+
+#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/builtin/ondemand.h b/contrib/libs/simdjson/include/simdjson/builtin/ondemand.h
new file mode 100644
index 0000000000..483fa8760a
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/builtin/ondemand.h
@@ -0,0 +1,40 @@
+#ifndef SIMDJSON_BUILTIN_ONDEMAND_H
+#define SIMDJSON_BUILTIN_ONDEMAND_H
+
+#include "simdjson/builtin.h"
+#include "simdjson/builtin/base.h"
+
+#include "simdjson/generic/ondemand/dependencies.h"
+
+#define SIMDJSON_CONDITIONAL_INCLUDE
+
+#if SIMDJSON_BUILTIN_IMPLEMENTATION_IS(arm64)
+#include "simdjson/arm64/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(fallback)
+#include "simdjson/fallback/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(haswell)
+#include "simdjson/haswell/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(icelake)
+#include "simdjson/icelake/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(ppc64)
+#error #include "simdjson/ppc64/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(westmere)
+#include "simdjson/westmere/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx)
+#include "simdjson/lsx/ondemand.h"
+#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
+#include "simdjson/lasx/ondemand.h"
+#else
+#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
+#endif
+
+#undef SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+ /**
+ * @copydoc simdjson::SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand
+ */
+ namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand;
+} // namespace simdjson
+
+#endif // SIMDJSON_BUILTIN_ONDEMAND_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/dom.h b/contrib/libs/simdjson/include/simdjson/dom.h
new file mode 100644
index 0000000000..bcf22ac22d
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom.h
@@ -0,0 +1,23 @@
+#ifndef SIMDJSON_DOM_H
+#define SIMDJSON_DOM_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/array.h"
+#include "simdjson/dom/document_stream.h"
+#include "simdjson/dom/document.h"
+#include "simdjson/dom/element.h"
+#include "simdjson/dom/object.h"
+#include "simdjson/dom/parser.h"
+#include "simdjson/dom/serialization.h"
+
+// Inline functions
+#include "simdjson/dom/array-inl.h"
+#include "simdjson/dom/document_stream-inl.h"
+#include "simdjson/dom/document-inl.h"
+#include "simdjson/dom/element-inl.h"
+#include "simdjson/dom/object-inl.h"
+#include "simdjson/dom/parser-inl.h"
+#include "simdjson/internal/tape_ref-inl.h"
+#include "simdjson/dom/serialization-inl.h"
+
+#endif // SIMDJSON_DOM_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/array-inl.h b/contrib/libs/simdjson/include/simdjson/dom/array-inl.h
new file mode 100644
index 0000000000..6a29ef8553
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/array-inl.h
@@ -0,0 +1,181 @@
+#ifndef SIMDJSON_ARRAY_INL_H
+#define SIMDJSON_ARRAY_INL_H
+
+#include <utility>
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/array.h"
+#include "simdjson/dom/element.h"
+#include "simdjson/error-inl.h"
+#include "simdjson/internal/tape_ref-inl.h"
+
+#include <limits>
+
+namespace simdjson {
+
+//
+// simdjson_result<dom::array> inline implementation
+//
+simdjson_inline simdjson_result<dom::array>::simdjson_result() noexcept
+ : internal::simdjson_result_base<dom::array>() {}
+simdjson_inline simdjson_result<dom::array>::simdjson_result(dom::array value) noexcept
+ : internal::simdjson_result_base<dom::array>(std::forward<dom::array>(value)) {}
+simdjson_inline simdjson_result<dom::array>::simdjson_result(error_code error) noexcept
+ : internal::simdjson_result_base<dom::array>(error) {}
+
+#if SIMDJSON_EXCEPTIONS
+
+inline dom::array::iterator simdjson_result<dom::array>::begin() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.begin();
+}
+inline dom::array::iterator simdjson_result<dom::array>::end() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.end();
+}
+inline size_t simdjson_result<dom::array>::size() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.size();
+}
+
+#endif // SIMDJSON_EXCEPTIONS
+
+inline simdjson_result<dom::element> simdjson_result<dom::array>::at_pointer(std::string_view json_pointer) const noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+inline simdjson_result<dom::element> simdjson_result<dom::array>::at(size_t index) const noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+
+namespace dom {
+
+//
+// array inline implementation
+//
+simdjson_inline array::array() noexcept : tape{} {}
+simdjson_inline array::array(const internal::tape_ref &_tape) noexcept : tape{_tape} {}
+inline array::iterator array::begin() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return internal::tape_ref(tape.doc, tape.json_index + 1);
+}
+inline array::iterator array::end() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return internal::tape_ref(tape.doc, tape.after_element() - 1);
+}
+inline size_t array::size() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return tape.scope_count();
+}
+inline size_t array::number_of_slots() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return tape.matching_brace_index() - tape.json_index;
+}
+inline simdjson_result<element> array::at_pointer(std::string_view json_pointer) const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ if(json_pointer.empty()) { // an empty string means that we return the current node
+ return element(this->tape); // copy the current node
+ } else if(json_pointer[0] != '/') { // otherwise there is an error
+ return INVALID_JSON_POINTER;
+ }
+ json_pointer = json_pointer.substr(1);
+ // - means "the append position" or "the element after the end of the array"
+ // We don't support this, because we're returning a real element, not a position.
+ if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
+
+ // Read the array index
+ size_t array_index = 0;
+ size_t i;
+ for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
+ uint8_t digit = uint8_t(json_pointer[i] - '0');
+ // Check for non-digit in array index. If it's there, we're trying to get a field in an object
+ if (digit > 9) { return INCORRECT_TYPE; }
+ array_index = array_index*10 + digit;
+ }
+
+ // 0 followed by other digits is invalid
+ if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
+
+ // Empty string is invalid; so is a "/" with no digits before it
+ if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
+
+ // Get the child
+ auto child = array(tape).at(array_index);
+ // If there is an error, it ends here
+ if(child.error()) {
+ return child;
+ }
+ // If there is a /, we're not done yet, call recursively.
+ if (i < json_pointer.length()) {
+ child = child.at_pointer(json_pointer.substr(i));
+ }
+ return child;
+}
+
+inline simdjson_result<element> array::at(size_t index) const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ size_t i=0;
+ for (auto element : *this) {
+ if (i == index) { return element; }
+ i++;
+ }
+ return INDEX_OUT_OF_BOUNDS;
+}
+
+inline array::operator element() const noexcept {
+ return element(tape);
+}
+
+//
+// array::iterator inline implementation
+//
+simdjson_inline array::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
+inline element array::iterator::operator*() const noexcept {
+ return element(tape);
+}
+inline array::iterator& array::iterator::operator++() noexcept {
+ tape.json_index = tape.after_element();
+ return *this;
+}
+inline array::iterator array::iterator::operator++(int) noexcept {
+ array::iterator out = *this;
+ ++*this;
+ return out;
+}
+inline bool array::iterator::operator!=(const array::iterator& other) const noexcept {
+ return tape.json_index != other.tape.json_index;
+}
+inline bool array::iterator::operator==(const array::iterator& other) const noexcept {
+ return tape.json_index == other.tape.json_index;
+}
+inline bool array::iterator::operator<(const array::iterator& other) const noexcept {
+ return tape.json_index < other.tape.json_index;
+}
+inline bool array::iterator::operator<=(const array::iterator& other) const noexcept {
+ return tape.json_index <= other.tape.json_index;
+}
+inline bool array::iterator::operator>=(const array::iterator& other) const noexcept {
+ return tape.json_index >= other.tape.json_index;
+}
+inline bool array::iterator::operator>(const array::iterator& other) const noexcept {
+ return tape.json_index > other.tape.json_index;
+}
+
+} // namespace dom
+
+
+} // namespace simdjson
+
+#include "simdjson/dom/element-inl.h"
+
+#if defined(__cpp_lib_ranges)
+static_assert(std::ranges::view<simdjson::dom::array>);
+static_assert(std::ranges::sized_range<simdjson::dom::array>);
+#if SIMDJSON_EXCEPTIONS
+static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::array>>);
+static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::array>>);
+#endif // SIMDJSON_EXCEPTIONS
+#endif // defined(__cpp_lib_ranges)
+
+#endif // SIMDJSON_ARRAY_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/array.h b/contrib/libs/simdjson/include/simdjson/dom/array.h
new file mode 100644
index 0000000000..a90813a450
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/array.h
@@ -0,0 +1,183 @@
+#ifndef SIMDJSON_DOM_ARRAY_H
+#define SIMDJSON_DOM_ARRAY_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/internal/tape_ref.h"
+
+namespace simdjson {
+namespace dom {
+
+/**
+ * JSON array.
+ */
+class array {
+public:
+ /** Create a new, invalid array */
+ simdjson_inline array() noexcept;
+
+ class iterator {
+ public:
+ using value_type = element;
+ using difference_type = std::ptrdiff_t;
+ using pointer = void;
+ using reference = value_type;
+ using iterator_category = std::forward_iterator_tag;
+
+ /**
+ * Get the actual value
+ */
+ inline reference operator*() const noexcept;
+ /**
+ * Get the next value.
+ *
+ * Part of the std::iterator interface.
+ */
+ inline iterator& operator++() noexcept;
+ /**
+ * Get the next value.
+ *
+ * Part of the std::iterator interface.
+ */
+ inline iterator operator++(int) noexcept;
+ /**
+ * Check if these values come from the same place in the JSON.
+ *
+ * Part of the std::iterator interface.
+ */
+ inline bool operator!=(const iterator& other) const noexcept;
+ inline bool operator==(const iterator& other) const noexcept;
+
+ inline bool operator<(const iterator& other) const noexcept;
+ inline bool operator<=(const iterator& other) const noexcept;
+ inline bool operator>=(const iterator& other) const noexcept;
+ inline bool operator>(const iterator& other) const noexcept;
+
+ iterator() noexcept = default;
+ iterator(const iterator&) noexcept = default;
+ iterator& operator=(const iterator&) noexcept = default;
+ private:
+ simdjson_inline iterator(const internal::tape_ref &tape) noexcept;
+ internal::tape_ref tape;
+ friend class array;
+ };
+
+ /**
+ * Return the first array element.
+ *
+ * Part of the std::iterable interface.
+ */
+ inline iterator begin() const noexcept;
+ /**
+ * One past the last array element.
+ *
+ * Part of the std::iterable interface.
+ */
+ inline iterator end() const noexcept;
+ /**
+ * Get the size of the array (number of immediate children).
+ * It is a saturated value with a maximum of 0xFFFFFF: if the value
+ * is 0xFFFFFF then the size is 0xFFFFFF or greater.
+ */
+ inline size_t size() const noexcept;
+ /**
+ * Get the total number of slots used by this array on the tape.
+ *
+ * Note that this is not the same thing as `size()`, which reports the
+ * number of actual elements within an array (not counting its children).
+ *
+ * Since an element can use 1 or 2 slots on the tape, you can only use this
+ * to figure out the total size of an array (including its children,
+ * recursively) if you know its structure ahead of time.
+ **/
+ inline size_t number_of_slots() const noexcept;
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
+ * as the root of its own JSON document.
+ *
+ * dom::parser parser;
+ * array a = parser.parse(R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded);
+ * a.at_pointer("/0/foo/a/1") == 20
+ * a.at_pointer("0")["foo"]["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value at the given index. This function has linear-time complexity and
+ * is equivalent to the following:
+ *
+ * size_t i=0;
+ * for (auto element : *this) {
+ * if (i == index) { return element; }
+ * i++;
+ * }
+ * return INDEX_OUT_OF_BOUNDS;
+ *
+ * Avoid calling the at() function repeatedly.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline simdjson_result<element> at(size_t index) const noexcept;
+
+ /**
+ * Implicitly convert object to element
+ */
+ inline operator element() const noexcept;
+
+private:
+ simdjson_inline array(const internal::tape_ref &tape) noexcept;
+ internal::tape_ref tape;
+ friend class element;
+ friend struct simdjson_result<element>;
+ template<typename T>
+ friend class simdjson::internal::string_builder;
+};
+
+
+} // namespace dom
+
+/** The result of a JSON conversion that may fail. */
+template<>
+struct simdjson_result<dom::array> : public internal::simdjson_result_base<dom::array> {
+public:
+ simdjson_inline simdjson_result() noexcept; ///< @private
+ simdjson_inline simdjson_result(dom::array value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+
+ inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept;
+ inline simdjson_result<dom::element> at(size_t index) const noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ inline dom::array::iterator begin() const noexcept(false);
+ inline dom::array::iterator end() const noexcept(false);
+ inline size_t size() const noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+};
+
+
+
+} // namespace simdjson
+
+#if defined(__cpp_lib_ranges)
+#include <ranges>
+
+namespace std {
+namespace ranges {
+template<>
+inline constexpr bool enable_view<simdjson::dom::array> = true;
+#if SIMDJSON_EXCEPTIONS
+template<>
+inline constexpr bool enable_view<simdjson::simdjson_result<simdjson::dom::array>> = true;
+#endif // SIMDJSON_EXCEPTIONS
+} // namespace ranges
+} // namespace std
+#endif // defined(__cpp_lib_ranges)
+
+#endif // SIMDJSON_DOM_ARRAY_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/document-inl.h b/contrib/libs/simdjson/include/simdjson/dom/document-inl.h
new file mode 100644
index 0000000000..40d74b999e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/document-inl.h
@@ -0,0 +1,159 @@
+#ifndef SIMDJSON_DOCUMENT_INL_H
+#define SIMDJSON_DOCUMENT_INL_H
+
+// Inline implementations go in here.
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/document.h"
+#include "simdjson/dom/element-inl.h"
+#include "simdjson/internal/tape_ref-inl.h"
+#include "simdjson/internal/jsonformatutils.h"
+
+#include <cstring>
+
+namespace simdjson {
+namespace dom {
+
+//
+// document inline implementation
+//
+inline element document::root() const noexcept {
+ return element(internal::tape_ref(this, 1));
+}
+simdjson_warn_unused
+inline size_t document::capacity() const noexcept {
+ return allocated_capacity;
+}
+
+simdjson_warn_unused
+inline error_code document::allocate(size_t capacity) noexcept {
+ if (capacity == 0) {
+ string_buf.reset();
+ tape.reset();
+ allocated_capacity = 0;
+ return SUCCESS;
+ }
+
+ // a pathological input like "[[[[..." would generate capacity tape elements, so
+ // need a capacity of at least capacity + 1, but it is also possible to do
+ // worse with "[7,7,7,7,6,7,7,7,6,7,7,6,[7,7,7,7,6,7,7,7,6,7,7,6,7,7,7,7,7,7,6"
+ //where capacity + 1 tape elements are
+ // generated, see issue https://github.com/simdjson/simdjson/issues/345
+ size_t tape_capacity = SIMDJSON_ROUNDUP_N(capacity + 3, 64);
+ // a document with only zero-length strings... could have capacity/3 string
+ // and we would need capacity/3 * 5 bytes on the string buffer
+ size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * capacity / 3 + SIMDJSON_PADDING, 64);
+ string_buf.reset( new (std::nothrow) uint8_t[string_capacity]);
+ tape.reset(new (std::nothrow) uint64_t[tape_capacity]);
+ if(!(string_buf && tape)) {
+ allocated_capacity = 0;
+ string_buf.reset();
+ tape.reset();
+ return MEMALLOC;
+ }
+ // Technically the allocated_capacity might be larger than capacity
+ // so the next line is pessimistic.
+ allocated_capacity = capacity;
+ return SUCCESS;
+}
+
+inline bool document::dump_raw_tape(std::ostream &os) const noexcept {
+ uint32_t string_length;
+ size_t tape_idx = 0;
+ uint64_t tape_val = tape[tape_idx];
+ uint8_t type = uint8_t(tape_val >> 56);
+ os << tape_idx << " : " << type;
+ tape_idx++;
+ size_t how_many = 0;
+ if (type == 'r') {
+ how_many = size_t(tape_val & internal::JSON_VALUE_MASK);
+ } else {
+ // Error: no starting root node?
+ return false;
+ }
+ os << "\t// pointing to " << how_many << " (right after last node)\n";
+ uint64_t payload;
+ for (; tape_idx < how_many; tape_idx++) {
+ os << tape_idx << " : ";
+ tape_val = tape[tape_idx];
+ payload = tape_val & internal::JSON_VALUE_MASK;
+ type = uint8_t(tape_val >> 56);
+ switch (type) {
+ case '"': // we have a string
+ os << "string \"";
+ std::memcpy(&string_length, string_buf.get() + payload, sizeof(uint32_t));
+ os << internal::escape_json_string(std::string_view(
+ reinterpret_cast<const char *>(string_buf.get() + payload + sizeof(uint32_t)),
+ string_length
+ ));
+ os << '"';
+ os << '\n';
+ break;
+ case 'l': // we have a long int
+ if (tape_idx + 1 >= how_many) {
+ return false;
+ }
+ os << "integer " << static_cast<int64_t>(tape[++tape_idx]) << "\n";
+ break;
+ case 'u': // we have a long uint
+ if (tape_idx + 1 >= how_many) {
+ return false;
+ }
+ os << "unsigned integer " << tape[++tape_idx] << "\n";
+ break;
+ case 'd': // we have a double
+ os << "float ";
+ if (tape_idx + 1 >= how_many) {
+ return false;
+ }
+ double answer;
+ std::memcpy(&answer, &tape[++tape_idx], sizeof(answer));
+ os << answer << '\n';
+ break;
+ case 'n': // we have a null
+ os << "null\n";
+ break;
+ case 't': // we have a true
+ os << "true\n";
+ break;
+ case 'f': // we have a false
+ os << "false\n";
+ break;
+ case '{': // we have an object
+ os << "{\t// pointing to next tape location " << uint32_t(payload)
+ << " (first node after the scope), "
+ << " saturated count "
+ << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
+ break; case '}': // we end an object
+ os << "}\t// pointing to previous tape location " << uint32_t(payload)
+ << " (start of the scope)\n";
+ break;
+ case '[': // we start an array
+ os << "[\t// pointing to next tape location " << uint32_t(payload)
+ << " (first node after the scope), "
+ << " saturated count "
+ << ((payload >> 32) & internal::JSON_COUNT_MASK)<< "\n";
+ break;
+ case ']': // we end an array
+ os << "]\t// pointing to previous tape location " << uint32_t(payload)
+ << " (start of the scope)\n";
+ break;
+ case 'r': // we start and end with the root node
+ // should we be hitting the root node?
+ return false;
+ default:
+ return false;
+ }
+ }
+ tape_val = tape[tape_idx];
+ payload = tape_val & internal::JSON_VALUE_MASK;
+ type = uint8_t(tape_val >> 56);
+ os << tape_idx << " : " << type << "\t// pointing to " << payload
+ << " (start root)\n";
+ return true;
+}
+
+} // namespace dom
+} // namespace simdjson
+
+#endif // SIMDJSON_DOCUMENT_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/document_stream-inl.h b/contrib/libs/simdjson/include/simdjson/dom/document_stream-inl.h
new file mode 100644
index 0000000000..b7062481f2
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/document_stream-inl.h
@@ -0,0 +1,348 @@
+#ifndef SIMDJSON_DOCUMENT_STREAM_INL_H
+#define SIMDJSON_DOCUMENT_STREAM_INL_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/document_stream.h"
+#include "simdjson/dom/element-inl.h"
+#include "simdjson/dom/parser-inl.h"
+#include "simdjson/error-inl.h"
+#include "simdjson/internal/dom_parser_implementation.h"
+
+namespace simdjson {
+namespace dom {
+
+#ifdef SIMDJSON_THREADS_ENABLED
+
+inline void stage1_worker::finish() {
+ // After calling "run" someone would call finish() to wait
+ // for the end of the processing.
+ // This function will wait until either the thread has done
+ // the processing or, else, the destructor has been called.
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ cond_var.wait(lock, [this]{return has_work == false;});
+}
+
+inline stage1_worker::~stage1_worker() {
+ // The thread may never outlive the stage1_worker instance
+ // and will always be stopped/joined before the stage1_worker
+ // instance is gone.
+ stop_thread();
+}
+
+inline void stage1_worker::start_thread() {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ if(thread.joinable()) {
+ return; // This should never happen but we never want to create more than one thread.
+ }
+ thread = std::thread([this]{
+ while(true) {
+ std::unique_lock<std::mutex> thread_lock(locking_mutex);
+ // We wait for either "run" or "stop_thread" to be called.
+ cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
+ // If, for some reason, the stop_thread() method was called (i.e., the
+ // destructor of stage1_worker is called, then we want to immediately destroy
+ // the thread (and not do any more processing).
+ if(!can_work) {
+ break;
+ }
+ this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
+ this->_next_batch_start);
+ this->has_work = false;
+ // The condition variable call should be moved after thread_lock.unlock() for performance
+ // reasons but thread sanitizers may report it as a data race if we do.
+ // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
+ cond_var.notify_one(); // will notify "finish"
+ thread_lock.unlock();
+ }
+ }
+ );
+}
+
+
+inline void stage1_worker::stop_thread() {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ // We have to make sure that all locks can be released.
+ can_work = false;
+ has_work = false;
+ cond_var.notify_all();
+ lock.unlock();
+ if(thread.joinable()) {
+ thread.join();
+ }
+}
+
+inline void stage1_worker::run(document_stream * ds, dom::parser * stage1, size_t next_batch_start) {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ owner = ds;
+ _next_batch_start = next_batch_start;
+ stage1_thread_parser = stage1;
+ has_work = true;
+ // The condition variable call should be moved after thread_lock.unlock() for performance
+ // reasons but thread sanitizers may report it as a data race if we do.
+ // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
+ cond_var.notify_one(); // will notify the thread lock that we have work
+ lock.unlock();
+}
+#endif
+
+simdjson_inline document_stream::document_stream(
+ dom::parser &_parser,
+ const uint8_t *_buf,
+ size_t _len,
+ size_t _batch_size
+) noexcept
+ : parser{&_parser},
+ buf{_buf},
+ len{_len},
+ batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
+ error{SUCCESS}
+#ifdef SIMDJSON_THREADS_ENABLED
+ , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
+#endif
+{
+#ifdef SIMDJSON_THREADS_ENABLED
+ if(worker.get() == nullptr) {
+ error = MEMALLOC;
+ }
+#endif
+}
+
+simdjson_inline document_stream::document_stream() noexcept
+ : parser{nullptr},
+ buf{nullptr},
+ len{0},
+ batch_size{0},
+ error{UNINITIALIZED}
+#ifdef SIMDJSON_THREADS_ENABLED
+ , use_thread(false)
+#endif
+{
+}
+
+simdjson_inline document_stream::~document_stream() noexcept {
+#ifdef SIMDJSON_THREADS_ENABLED
+ worker.reset();
+#endif
+}
+
+simdjson_inline document_stream::iterator::iterator() noexcept
+ : stream{nullptr}, finished{true} {
+}
+
+simdjson_inline document_stream::iterator document_stream::begin() noexcept {
+ start();
+ // If there are no documents, we're finished.
+ return iterator(this, error == EMPTY);
+}
+
+simdjson_inline document_stream::iterator document_stream::end() noexcept {
+ return iterator(this, true);
+}
+
+simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
+ : stream{_stream}, finished{is_end} {
+}
+
+simdjson_inline document_stream::iterator::reference document_stream::iterator::operator*() noexcept {
+ // Note that in case of error, we do not yet mark
+ // the iterator as "finished": this detection is done
+ // in the operator++ function since it is possible
+ // to call operator++ repeatedly while omitting
+ // calls to operator*.
+ if (stream->error) { return stream->error; }
+ return stream->parser->doc.root();
+}
+
+simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
+ // If there is an error, then we want the iterator
+ // to be finished, no matter what. (E.g., we do not
+ // keep generating documents with errors, or go beyond
+ // a document with errors.)
+ //
+ // Users do not have to call "operator*()" when they use operator++,
+ // so we need to end the stream in the operator++ function.
+ //
+ // Note that setting finished = true is essential otherwise
+ // we would enter an infinite loop.
+ if (stream->error) { finished = true; }
+ // Note that stream->error() is guarded against error conditions
+ // (it will immediately return if stream->error casts to false).
+ // In effect, this next function does nothing when (stream->error)
+ // is true (hence the risk of an infinite loop).
+ stream->next();
+ // If that was the last document, we're finished.
+ // It is the only type of error we do not want to appear
+ // in operator*.
+ if (stream->error == EMPTY) { finished = true; }
+ // If we had any other kind of error (not EMPTY) then we want
+ // to pass it along to the operator* and we cannot mark the result
+ // as "finished" just yet.
+ return *this;
+}
+
+simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
+ return finished != other.finished;
+}
+
+inline void document_stream::start() noexcept {
+ if (error) { return; }
+ error = parser->ensure_capacity(batch_size);
+ if (error) { return; }
+ // Always run the first stage 1 parse immediately
+ batch_start = 0;
+ error = run_stage1(*parser, batch_start);
+ while(error == EMPTY) {
+ // In exceptional cases, we may start with an empty block
+ batch_start = next_batch_start();
+ if (batch_start >= len) { return; }
+ error = run_stage1(*parser, batch_start);
+ }
+ if (error) { return; }
+#ifdef SIMDJSON_THREADS_ENABLED
+ if (use_thread && next_batch_start() < len) {
+ // Kick off the first thread if needed
+ error = stage1_thread_parser.ensure_capacity(batch_size);
+ if (error) { return; }
+ worker->start_thread();
+ start_stage1_thread();
+ if (error) { return; }
+ }
+#endif // SIMDJSON_THREADS_ENABLED
+ next();
+}
+
+simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
+ return stream->doc_index;
+}
+
+simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
+ const char* start = reinterpret_cast<const char*>(stream->buf) + current_index();
+ bool object_or_array = ((*start == '[') || (*start == '{'));
+ if(object_or_array) {
+ size_t next_doc_index = stream->batch_start + stream->parser->implementation->structural_indexes[stream->parser->implementation->next_structural_index - 1];
+ return std::string_view(start, next_doc_index - current_index() + 1);
+ } else {
+ size_t next_doc_index = stream->batch_start + stream->parser->implementation->structural_indexes[stream->parser->implementation->next_structural_index];
+ size_t svlen = next_doc_index - current_index();
+ while(svlen > 1 && (std::isspace(start[svlen-1]) || start[svlen-1] == '\0')) {
+ svlen--;
+ }
+ return std::string_view(start, svlen);
+ }
+}
+
+
+inline void document_stream::next() noexcept {
+ // We always exit at once, once in an error condition.
+ if (error) { return; }
+
+ // Load the next document from the batch
+ doc_index = batch_start + parser->implementation->structural_indexes[parser->implementation->next_structural_index];
+ error = parser->implementation->stage2_next(parser->doc);
+ // If that was the last document in the batch, load another batch (if available)
+ while (error == EMPTY) {
+ batch_start = next_batch_start();
+ if (batch_start >= len) { break; }
+
+#ifdef SIMDJSON_THREADS_ENABLED
+ if(use_thread) {
+ load_from_stage1_thread();
+ } else {
+ error = run_stage1(*parser, batch_start);
+ }
+#else
+ error = run_stage1(*parser, batch_start);
+#endif
+ if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
+ // Run stage 2 on the first document in the batch
+ doc_index = batch_start + parser->implementation->structural_indexes[parser->implementation->next_structural_index];
+ error = parser->implementation->stage2_next(parser->doc);
+ }
+}
+inline size_t document_stream::size_in_bytes() const noexcept {
+ return len;
+}
+
+inline size_t document_stream::truncated_bytes() const noexcept {
+ if(error == CAPACITY) { return len - batch_start; }
+ return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
+}
+
+inline size_t document_stream::next_batch_start() const noexcept {
+ return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
+}
+
+inline error_code document_stream::run_stage1(dom::parser &p, size_t _batch_start) noexcept {
+ size_t remaining = len - _batch_start;
+ if (remaining <= batch_size) {
+ return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
+ } else {
+ return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
+ }
+}
+
+#ifdef SIMDJSON_THREADS_ENABLED
+
+inline void document_stream::load_from_stage1_thread() noexcept {
+ worker->finish();
+ // Swap to the parser that was loaded up in the thread. Make sure the parser has
+ // enough memory to swap to, as well.
+ std::swap(*parser, stage1_thread_parser);
+ error = stage1_thread_error;
+ if (error) { return; }
+
+ // If there's anything left, start the stage 1 thread!
+ if (next_batch_start() < len) {
+ start_stage1_thread();
+ }
+}
+
+inline void document_stream::start_stage1_thread() noexcept {
+ // we call the thread on a lambda that will update
+ // this->stage1_thread_error
+ // there is only one thread that may write to this value
+ // TODO this is NOT exception-safe.
+ this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
+ size_t _next_batch_start = this->next_batch_start();
+
+ worker->run(this, & this->stage1_thread_parser, _next_batch_start);
+}
+
+#endif // SIMDJSON_THREADS_ENABLED
+
+} // namespace dom
+
+simdjson_inline simdjson_result<dom::document_stream>::simdjson_result() noexcept
+ : simdjson_result_base() {
+}
+simdjson_inline simdjson_result<dom::document_stream>::simdjson_result(error_code error) noexcept
+ : simdjson_result_base(error) {
+}
+simdjson_inline simdjson_result<dom::document_stream>::simdjson_result(dom::document_stream &&value) noexcept
+ : simdjson_result_base(std::forward<dom::document_stream>(value)) {
+}
+
+#if SIMDJSON_EXCEPTIONS
+simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::begin() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.begin();
+}
+simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::end() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.end();
+}
+#else // SIMDJSON_EXCEPTIONS
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::begin() noexcept {
+ first.error = error();
+ return first.begin();
+}
+simdjson_inline dom::document_stream::iterator simdjson_result<dom::document_stream>::end() noexcept {
+ first.error = error();
+ return first.end();
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+#endif // SIMDJSON_EXCEPTIONS
+
+} // namespace simdjson
+#endif // SIMDJSON_DOCUMENT_STREAM_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/document_stream.h b/contrib/libs/simdjson/include/simdjson/dom/document_stream.h
new file mode 100644
index 0000000000..308f20e25a
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/document_stream.h
@@ -0,0 +1,322 @@
+#ifndef SIMDJSON_DOCUMENT_STREAM_H
+#define SIMDJSON_DOCUMENT_STREAM_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/parser.h"
+
+#ifdef SIMDJSON_THREADS_ENABLED
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#endif
+
+namespace simdjson {
+namespace dom {
+
+#ifdef SIMDJSON_THREADS_ENABLED
+/** @private Custom worker class **/
+struct stage1_worker {
+ stage1_worker() noexcept = default;
+ stage1_worker(const stage1_worker&) = delete;
+ stage1_worker(stage1_worker&&) = delete;
+ stage1_worker operator=(const stage1_worker&) = delete;
+ ~stage1_worker();
+ /**
+ * We only start the thread when it is needed, not at object construction, this may throw.
+ * You should only call this once.
+ **/
+ void start_thread();
+ /**
+ * Start a stage 1 job. You should first call 'run', then 'finish'.
+ * You must call start_thread once before.
+ */
+ void run(document_stream * ds, dom::parser * stage1, size_t next_batch_start);
+ /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
+ void finish();
+
+private:
+
+ /**
+ * Normally, we would never stop the thread. But we do in the destructor.
+ * This function is only safe assuming that you are not waiting for results. You
+ * should have called run, then finish, and be done.
+ **/
+ void stop_thread();
+
+ std::thread thread{};
+ /** These three variables define the work done by the thread. **/
+ dom::parser * stage1_thread_parser{};
+ size_t _next_batch_start{};
+ document_stream * owner{};
+ /**
+ * We have two state variables. This could be streamlined to one variable in the future but
+ * we use two for clarity.
+ */
+ bool has_work{false};
+ bool can_work{true};
+
+ /**
+ * We lock using a mutex.
+ */
+ std::mutex locking_mutex{};
+ std::condition_variable cond_var{};
+};
+#endif
+
+/**
+ * A forward-only stream of documents.
+ *
+ * Produced by parser::parse_many.
+ *
+ */
+class document_stream {
+public:
+ /**
+ * Construct an uninitialized document_stream.
+ *
+ * ```c++
+ * document_stream docs;
+ * error = parser.parse_many(json).get(docs);
+ * ```
+ */
+ simdjson_inline document_stream() noexcept;
+ /** Move one document_stream to another. */
+ simdjson_inline document_stream(document_stream &&other) noexcept = default;
+ /** Move one document_stream to another. */
+ simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
+
+ simdjson_inline ~document_stream() noexcept;
+ /**
+ * Returns the input size in bytes.
+ */
+ inline size_t size_in_bytes() const noexcept;
+ /**
+ * After iterating through the stream, this method
+ * returns the number of bytes that were not parsed at the end
+ * of the stream. If truncated_bytes() differs from zero,
+ * then the input was truncated maybe because incomplete JSON
+ * documents were found at the end of the stream. You
+ * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
+ *
+ * You should only call truncated_bytes() after streaming through all
+ * documents, like so:
+ *
+ * document_stream stream = parser.parse_many(json,window);
+ * for(auto doc : stream) {
+ * // do something with doc
+ * }
+ * size_t truncated = stream.truncated_bytes();
+ *
+ */
+ inline size_t truncated_bytes() const noexcept;
+ /**
+ * An iterator through a forward-only stream of documents.
+ */
+ class iterator {
+ public:
+ using value_type = simdjson_result<element>;
+ using reference = value_type;
+
+ using difference_type = std::ptrdiff_t;
+
+ using iterator_category = std::input_iterator_tag;
+
+ /**
+ * Default constructor.
+ */
+ simdjson_inline iterator() noexcept;
+ /**
+ * Get the current document (or error).
+ */
+ simdjson_inline reference operator*() noexcept;
+ /**
+ * Advance to the next document (prefix).
+ */
+ inline iterator& operator++() noexcept;
+ /**
+ * Check if we're at the end yet.
+ * @param other the end iterator to compare to.
+ */
+ simdjson_inline bool operator!=(const iterator &other) const noexcept;
+ /**
+ * @private
+ *
+ * Gives the current index in the input document in bytes.
+ *
+ * document_stream stream = parser.parse_many(json,window);
+ * for(auto i = stream.begin(); i != stream.end(); ++i) {
+ * auto doc = *i;
+ * size_t index = i.current_index();
+ * }
+ *
+ * This function (current_index()) is experimental and the usage
+ * may change in future versions of simdjson: we find the API somewhat
+ * awkward and we would like to offer something friendlier.
+ */
+ simdjson_inline size_t current_index() const noexcept;
+ /**
+ * @private
+ *
+ * Gives a view of the current document.
+ *
+ * document_stream stream = parser.parse_many(json,window);
+ * for(auto i = stream.begin(); i != stream.end(); ++i) {
+ * auto doc = *i;
+ * std::string_view v = i->source();
+ * }
+ *
+ * The returned string_view instance is simply a map to the (unparsed)
+ * source string: it may thus include white-space characters and all manner
+ * of padding.
+ *
+ * This function (source()) is experimental and the usage
+ * may change in future versions of simdjson: we find the API somewhat
+ * awkward and we would like to offer something friendlier.
+ */
+ simdjson_inline std::string_view source() const noexcept;
+
+ private:
+ simdjson_inline iterator(document_stream *s, bool finished) noexcept;
+ /** The document_stream we're iterating through. */
+ document_stream* stream;
+ /** Whether we're finished or not. */
+ bool finished;
+ friend class document_stream;
+ };
+
+ /**
+ * Start iterating the documents in the stream.
+ */
+ simdjson_inline iterator begin() noexcept;
+ /**
+ * The end of the stream, for iterator comparison purposes.
+ */
+ simdjson_inline iterator end() noexcept;
+
+private:
+
+ document_stream &operator=(const document_stream &) = delete; // Disallow copying
+ document_stream(const document_stream &other) = delete; // Disallow copying
+
+ /**
+ * Construct a document_stream. Does not allocate or parse anything until the iterator is
+ * used.
+ *
+ * @param parser is a reference to the parser instance used to generate this document_stream
+ * @param buf is the raw byte buffer we need to process
+ * @param len is the length of the raw byte buffer in bytes
+ * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
+ */
+ simdjson_inline document_stream(
+ dom::parser &parser,
+ const uint8_t *buf,
+ size_t len,
+ size_t batch_size
+ ) noexcept;
+
+ /**
+ * Parse the first document in the buffer. Used by begin(), to handle allocation and
+ * initialization.
+ */
+ inline void start() noexcept;
+
+ /**
+ * Parse the next document found in the buffer previously given to document_stream.
+ *
+ * The content should be a valid JSON document encoded as UTF-8. If there is a
+ * UTF-8 BOM, the parser skips it.
+ *
+ * You do NOT need to pre-allocate a parser. This function takes care of
+ * pre-allocating a capacity defined by the batch_size defined when creating the
+ * document_stream object.
+ *
+ * The function returns simdjson::EMPTY if there is no more data to be parsed.
+ *
+ * The function returns simdjson::SUCCESS (as integer = 0) in case of success
+ * and indicates that the buffer has successfully been parsed to the end.
+ * Every document it contained has been parsed without error.
+ *
+ * The function returns an error code from simdjson/simdjson.h in case of failure
+ * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
+ * the simdjson::error_message function converts these error codes into a string).
+ *
+ * You can also check validity by calling parser.is_valid(). The same parser can
+ * and should be reused for the other documents in the buffer.
+ */
+ inline void next() noexcept;
+
+ /**
+ * Pass the next batch through stage 1 and return when finished.
+ * When threads are enabled, this may wait for the stage 1 thread to finish.
+ */
+ inline void load_batch() noexcept;
+
+ /** Get the next document index. */
+ inline size_t next_batch_start() const noexcept;
+
+ /** Pass the next batch through stage 1 with the given parser. */
+ inline error_code run_stage1(dom::parser &p, size_t batch_start) noexcept;
+
+ dom::parser *parser;
+ const uint8_t *buf;
+ size_t len;
+ size_t batch_size;
+ /** The error (or lack thereof) from the current document. */
+ error_code error;
+ size_t batch_start{0};
+ size_t doc_index{};
+#ifdef SIMDJSON_THREADS_ENABLED
+ /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
+ bool use_thread;
+
+ inline void load_from_stage1_thread() noexcept;
+
+ /** Start a thread to run stage 1 on the next batch. */
+ inline void start_stage1_thread() noexcept;
+
+ /** Wait for the stage 1 thread to finish and capture the results. */
+ inline void finish_stage1_thread() noexcept;
+
+ /** The error returned from the stage 1 thread. */
+ error_code stage1_thread_error{UNINITIALIZED};
+ /** The thread used to run stage 1 against the next batch in the background. */
+ friend struct stage1_worker;
+ std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
+ /**
+ * The parser used to run stage 1 in the background. Will be swapped
+ * with the regular parser when finished.
+ */
+ dom::parser stage1_thread_parser{};
+#endif // SIMDJSON_THREADS_ENABLED
+
+ friend class dom::parser;
+ friend struct simdjson_result<dom::document_stream>;
+ friend struct internal::simdjson_result_base<dom::document_stream>;
+
+}; // class document_stream
+
+} // namespace dom
+
+template<>
+struct simdjson_result<dom::document_stream> : public internal::simdjson_result_base<dom::document_stream> {
+public:
+ simdjson_inline simdjson_result() noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result(dom::document_stream &&value) noexcept; ///< @private
+
+#if SIMDJSON_EXCEPTIONS
+ simdjson_inline dom::document_stream::iterator begin() noexcept(false);
+ simdjson_inline dom::document_stream::iterator end() noexcept(false);
+#else // SIMDJSON_EXCEPTIONS
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+ [[deprecated("parse_many() and load_many() may return errors. Use document_stream stream; error = parser.parse_many().get(doc); instead.")]]
+ simdjson_inline dom::document_stream::iterator begin() noexcept;
+ [[deprecated("parse_many() and load_many() may return errors. Use document_stream stream; error = parser.parse_many().get(doc); instead.")]]
+ simdjson_inline dom::document_stream::iterator end() noexcept;
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+#endif // SIMDJSON_EXCEPTIONS
+}; // struct simdjson_result<dom::document_stream>
+
+} // namespace simdjson
+
+#endif // SIMDJSON_DOCUMENT_STREAM_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/element-inl.h b/contrib/libs/simdjson/include/simdjson/dom/element-inl.h
new file mode 100644
index 0000000000..cab313beb9
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/element-inl.h
@@ -0,0 +1,473 @@
+#ifndef SIMDJSON_ELEMENT_INL_H
+#define SIMDJSON_ELEMENT_INL_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/element.h"
+#include "simdjson/dom/document.h"
+#include "simdjson/dom/object.h"
+#include "simdjson/internal/tape_type.h"
+
+#include "simdjson/dom/object-inl.h"
+#include "simdjson/error-inl.h"
+
+#include <ostream>
+#include <limits>
+
+namespace simdjson {
+
+//
+// simdjson_result<dom::element> inline implementation
+//
+simdjson_inline simdjson_result<dom::element>::simdjson_result() noexcept
+ : internal::simdjson_result_base<dom::element>() {}
+simdjson_inline simdjson_result<dom::element>::simdjson_result(dom::element &&value) noexcept
+ : internal::simdjson_result_base<dom::element>(std::forward<dom::element>(value)) {}
+simdjson_inline simdjson_result<dom::element>::simdjson_result(error_code error) noexcept
+ : internal::simdjson_result_base<dom::element>(error) {}
+inline simdjson_result<dom::element_type> simdjson_result<dom::element>::type() const noexcept {
+ if (error()) { return error(); }
+ return first.type();
+}
+
+template<typename T>
+simdjson_inline bool simdjson_result<dom::element>::is() const noexcept {
+ return !error() && first.is<T>();
+}
+template<typename T>
+simdjson_inline simdjson_result<T> simdjson_result<dom::element>::get() const noexcept {
+ if (error()) { return error(); }
+ return first.get<T>();
+}
+template<typename T>
+simdjson_warn_unused simdjson_inline error_code simdjson_result<dom::element>::get(T &value) const noexcept {
+ if (error()) { return error(); }
+ return first.get<T>(value);
+}
+
+simdjson_inline simdjson_result<dom::array> simdjson_result<dom::element>::get_array() const noexcept {
+ if (error()) { return error(); }
+ return first.get_array();
+}
+simdjson_inline simdjson_result<dom::object> simdjson_result<dom::element>::get_object() const noexcept {
+ if (error()) { return error(); }
+ return first.get_object();
+}
+simdjson_inline simdjson_result<const char *> simdjson_result<dom::element>::get_c_str() const noexcept {
+ if (error()) { return error(); }
+ return first.get_c_str();
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<dom::element>::get_string_length() const noexcept {
+ if (error()) { return error(); }
+ return first.get_string_length();
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<dom::element>::get_string() const noexcept {
+ if (error()) { return error(); }
+ return first.get_string();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<dom::element>::get_int64() const noexcept {
+ if (error()) { return error(); }
+ return first.get_int64();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<dom::element>::get_uint64() const noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64();
+}
+simdjson_inline simdjson_result<double> simdjson_result<dom::element>::get_double() const noexcept {
+ if (error()) { return error(); }
+ return first.get_double();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<dom::element>::get_bool() const noexcept {
+ if (error()) { return error(); }
+ return first.get_bool();
+}
+
+simdjson_inline bool simdjson_result<dom::element>::is_array() const noexcept {
+ return !error() && first.is_array();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_object() const noexcept {
+ return !error() && first.is_object();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_string() const noexcept {
+ return !error() && first.is_string();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_int64() const noexcept {
+ return !error() && first.is_int64();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_uint64() const noexcept {
+ return !error() && first.is_uint64();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_double() const noexcept {
+ return !error() && first.is_double();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_number() const noexcept {
+ return !error() && first.is_number();
+}
+simdjson_inline bool simdjson_result<dom::element>::is_bool() const noexcept {
+ return !error() && first.is_bool();
+}
+
+simdjson_inline bool simdjson_result<dom::element>::is_null() const noexcept {
+ return !error() && first.is_null();
+}
+
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::operator[](const char *key) const noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_pointer(const std::string_view json_pointer) const noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+[[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at(const std::string_view json_pointer) const noexcept {
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_DEPRECATED_WARNING
+ if (error()) { return error(); }
+ return first.at(json_pointer);
+SIMDJSON_POP_DISABLE_WARNINGS
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at(size_t index) const noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key(std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first.at_key(key);
+}
+simdjson_inline simdjson_result<dom::element> simdjson_result<dom::element>::at_key_case_insensitive(std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first.at_key_case_insensitive(key);
+}
+
+#if SIMDJSON_EXCEPTIONS
+
+simdjson_inline simdjson_result<dom::element>::operator bool() const noexcept(false) {
+ return get<bool>();
+}
+simdjson_inline simdjson_result<dom::element>::operator const char *() const noexcept(false) {
+ return get<const char *>();
+}
+simdjson_inline simdjson_result<dom::element>::operator std::string_view() const noexcept(false) {
+ return get<std::string_view>();
+}
+simdjson_inline simdjson_result<dom::element>::operator uint64_t() const noexcept(false) {
+ return get<uint64_t>();
+}
+simdjson_inline simdjson_result<dom::element>::operator int64_t() const noexcept(false) {
+ return get<int64_t>();
+}
+simdjson_inline simdjson_result<dom::element>::operator double() const noexcept(false) {
+ return get<double>();
+}
+simdjson_inline simdjson_result<dom::element>::operator dom::array() const noexcept(false) {
+ return get<dom::array>();
+}
+simdjson_inline simdjson_result<dom::element>::operator dom::object() const noexcept(false) {
+ return get<dom::object>();
+}
+
+simdjson_inline dom::array::iterator simdjson_result<dom::element>::begin() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.begin();
+}
+simdjson_inline dom::array::iterator simdjson_result<dom::element>::end() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.end();
+}
+
+#endif // SIMDJSON_EXCEPTIONS
+
+namespace dom {
+
+//
+// element inline implementation
+//
+simdjson_inline element::element() noexcept : tape{} {}
+simdjson_inline element::element(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
+
+inline element_type element::type() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ auto tape_type = tape.tape_ref_type();
+ return tape_type == internal::tape_type::FALSE_VALUE ? element_type::BOOL : static_cast<element_type>(tape_type);
+}
+
+inline simdjson_result<bool> element::get_bool() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ if(tape.is_true()) {
+ return true;
+ } else if(tape.is_false()) {
+ return false;
+ }
+ return INCORRECT_TYPE;
+}
+inline simdjson_result<const char *> element::get_c_str() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::STRING: {
+ return tape.get_c_str();
+ }
+ default:
+ return INCORRECT_TYPE;
+ }
+}
+inline simdjson_result<size_t> element::get_string_length() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::STRING: {
+ return tape.get_string_length();
+ }
+ default:
+ return INCORRECT_TYPE;
+ }
+}
+inline simdjson_result<std::string_view> element::get_string() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::STRING:
+ return tape.get_string_view();
+ default:
+ return INCORRECT_TYPE;
+ }
+}
+inline simdjson_result<uint64_t> element::get_uint64() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ if(simdjson_unlikely(!tape.is_uint64())) { // branch rarely taken
+ if(tape.is_int64()) {
+ int64_t result = tape.next_tape_value<int64_t>();
+ if (result < 0) {
+ return NUMBER_OUT_OF_RANGE;
+ }
+ return uint64_t(result);
+ }
+ return INCORRECT_TYPE;
+ }
+ return tape.next_tape_value<int64_t>();
+}
+inline simdjson_result<int64_t> element::get_int64() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ if(simdjson_unlikely(!tape.is_int64())) { // branch rarely taken
+ if(tape.is_uint64()) {
+ uint64_t result = tape.next_tape_value<uint64_t>();
+ // Wrapping max in parens to handle Windows issue: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
+ if (result > uint64_t((std::numeric_limits<int64_t>::max)())) {
+ return NUMBER_OUT_OF_RANGE;
+ }
+ return static_cast<int64_t>(result);
+ }
+ return INCORRECT_TYPE;
+ }
+ return tape.next_tape_value<int64_t>();
+}
+inline simdjson_result<double> element::get_double() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ // Performance considerations:
+ // 1. Querying tape_ref_type() implies doing a shift, it is fast to just do a straight
+ // comparison.
+ // 2. Using a switch-case relies on the compiler guessing what kind of code generation
+ // we want... But the compiler cannot know that we expect the type to be "double"
+ // most of the time.
+ // We can expect get<double> to refer to a double type almost all the time.
+ // It is important to craft the code accordingly so that the compiler can use this
+ // information. (This could also be solved with profile-guided optimization.)
+ if(simdjson_unlikely(!tape.is_double())) { // branch rarely taken
+ if(tape.is_uint64()) {
+ return double(tape.next_tape_value<uint64_t>());
+ } else if(tape.is_int64()) {
+ return double(tape.next_tape_value<int64_t>());
+ }
+ return INCORRECT_TYPE;
+ }
+ // this is common:
+ return tape.next_tape_value<double>();
+}
+inline simdjson_result<array> element::get_array() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::START_ARRAY:
+ return array(tape);
+ default:
+ return INCORRECT_TYPE;
+ }
+}
+inline simdjson_result<object> element::get_object() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::START_OBJECT:
+ return object(tape);
+ default:
+ return INCORRECT_TYPE;
+ }
+}
+
+template<typename T>
+simdjson_warn_unused simdjson_inline error_code element::get(T &value) const noexcept {
+ return get<T>().get(value);
+}
+// An element-specific version prevents recursion with simdjson_result::get<element>(value)
+template<>
+simdjson_warn_unused simdjson_inline error_code element::get<element>(element &value) const noexcept {
+ value = element(tape);
+ return SUCCESS;
+}
+template<typename T>
+inline void element::tie(T &value, error_code &error) && noexcept {
+ error = get<T>(value);
+}
+
+template<typename T>
+simdjson_inline bool element::is() const noexcept {
+ auto result = get<T>();
+ return !result.error();
+}
+
+template<> inline simdjson_result<array> element::get<array>() const noexcept { return get_array(); }
+template<> inline simdjson_result<object> element::get<object>() const noexcept { return get_object(); }
+template<> inline simdjson_result<const char *> element::get<const char *>() const noexcept { return get_c_str(); }
+template<> inline simdjson_result<std::string_view> element::get<std::string_view>() const noexcept { return get_string(); }
+template<> inline simdjson_result<int64_t> element::get<int64_t>() const noexcept { return get_int64(); }
+template<> inline simdjson_result<uint64_t> element::get<uint64_t>() const noexcept { return get_uint64(); }
+template<> inline simdjson_result<double> element::get<double>() const noexcept { return get_double(); }
+template<> inline simdjson_result<bool> element::get<bool>() const noexcept { return get_bool(); }
+
+inline bool element::is_array() const noexcept { return is<array>(); }
+inline bool element::is_object() const noexcept { return is<object>(); }
+inline bool element::is_string() const noexcept { return is<std::string_view>(); }
+inline bool element::is_int64() const noexcept { return is<int64_t>(); }
+inline bool element::is_uint64() const noexcept { return is<uint64_t>(); }
+inline bool element::is_double() const noexcept { return is<double>(); }
+inline bool element::is_bool() const noexcept { return is<bool>(); }
+inline bool element::is_number() const noexcept { return is_int64() || is_uint64() || is_double(); }
+
+inline bool element::is_null() const noexcept {
+ return tape.is_null_on_tape();
+}
+
+#if SIMDJSON_EXCEPTIONS
+
+inline element::operator bool() const noexcept(false) { return get<bool>(); }
+inline element::operator const char*() const noexcept(false) { return get<const char *>(); }
+inline element::operator std::string_view() const noexcept(false) { return get<std::string_view>(); }
+inline element::operator uint64_t() const noexcept(false) { return get<uint64_t>(); }
+inline element::operator int64_t() const noexcept(false) { return get<int64_t>(); }
+inline element::operator double() const noexcept(false) { return get<double>(); }
+inline element::operator array() const noexcept(false) { return get<array>(); }
+inline element::operator object() const noexcept(false) { return get<object>(); }
+
+inline array::iterator element::begin() const noexcept(false) {
+ return get<array>().begin();
+}
+inline array::iterator element::end() const noexcept(false) {
+ return get<array>().end();
+}
+
+#endif // SIMDJSON_EXCEPTIONS
+
+inline simdjson_result<element> element::operator[](std::string_view key) const noexcept {
+ return at_key(key);
+}
+inline simdjson_result<element> element::operator[](const char *key) const noexcept {
+ return at_key(key);
+}
+
+inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept {
+ if (simdjson_unlikely(json_pointer[0] != '/')) {
+ return false;
+ }
+ size_t escape = json_pointer.find('~');
+ if (escape == std::string_view::npos) {
+ return true;
+ }
+ if (escape == json_pointer.size() - 1) {
+ return false;
+ }
+ if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') {
+ return false;
+ }
+ return true;
+}
+
+inline simdjson_result<element> element::at_pointer(std::string_view json_pointer) const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ switch (tape.tape_ref_type()) {
+ case internal::tape_type::START_OBJECT:
+ return object(tape).at_pointer(json_pointer);
+ case internal::tape_type::START_ARRAY:
+ return array(tape).at_pointer(json_pointer);
+ default: {
+ if (!json_pointer.empty()) { // a non-empty string can be invalid, or accessing a primitive (issue 2154)
+ if (is_pointer_well_formed(json_pointer)) {
+ return NO_SUCH_FIELD;
+ }
+ return INVALID_JSON_POINTER;
+ }
+ // an empty string means that we return the current node
+ dom::element copy(*this);
+ return simdjson_result<element>(std::move(copy));
+ }
+ }
+}
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+[[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
+inline simdjson_result<element> element::at(std::string_view json_pointer) const noexcept {
+ // version 0.4 of simdjson allowed non-compliant pointers
+ auto std_pointer = (json_pointer.empty() ? "" : "/") + std::string(json_pointer.begin(), json_pointer.end());
+ return at_pointer(std_pointer);
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+
+inline simdjson_result<element> element::at(size_t index) const noexcept {
+ return get<array>().at(index);
+}
+inline simdjson_result<element> element::at_key(std::string_view key) const noexcept {
+ return get<object>().at_key(key);
+}
+inline simdjson_result<element> element::at_key_case_insensitive(std::string_view key) const noexcept {
+ return get<object>().at_key_case_insensitive(key);
+}
+inline bool element::operator<(const element &other) const noexcept {
+ return tape.json_index < other.tape.json_index;
+}
+inline bool element::operator==(const element &other) const noexcept {
+ return tape.json_index == other.tape.json_index;
+}
+
+inline bool element::dump_raw_tape(std::ostream &out) const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return tape.doc->dump_raw_tape(out);
+}
+
+
+inline std::ostream& operator<<(std::ostream& out, element_type type) {
+ switch (type) {
+ case element_type::ARRAY:
+ return out << "array";
+ case element_type::OBJECT:
+ return out << "object";
+ case element_type::INT64:
+ return out << "int64_t";
+ case element_type::UINT64:
+ return out << "uint64_t";
+ case element_type::DOUBLE:
+ return out << "double";
+ case element_type::STRING:
+ return out << "string";
+ case element_type::BOOL:
+ return out << "bool";
+ case element_type::NULL_VALUE:
+ return out << "null";
+ default:
+ return out << "unexpected content!!!"; // abort() usage is forbidden in the library
+ }
+}
+
+} // namespace dom
+
+} // namespace simdjson
+
+#endif // SIMDJSON_ELEMENT_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/element.h b/contrib/libs/simdjson/include/simdjson/dom/element.h
new file mode 100644
index 0000000000..732b89e41a
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/element.h
@@ -0,0 +1,552 @@
+#ifndef SIMDJSON_DOM_ELEMENT_H
+#define SIMDJSON_DOM_ELEMENT_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/array.h"
+
+namespace simdjson {
+namespace dom {
+
+/**
+ * The actual concrete type of a JSON element
+ * This is the type it is most easily cast to with get<>.
+ */
+enum class element_type {
+ ARRAY = '[', ///< dom::array
+ OBJECT = '{', ///< dom::object
+ INT64 = 'l', ///< int64_t
+ UINT64 = 'u', ///< uint64_t: any integer that fits in uint64_t but *not* int64_t
+ DOUBLE = 'd', ///< double: Any number with a "." or "e" that fits in double.
+ STRING = '"', ///< std::string_view
+ BOOL = 't', ///< bool
+ NULL_VALUE = 'n' ///< null
+};
+
+/**
+ * A JSON element.
+ *
+ * References an element in a JSON document, representing a JSON null, boolean, string, number,
+ * array or object.
+ */
+class element {
+public:
+ /** Create a new, invalid element. */
+ simdjson_inline element() noexcept;
+
+ /** The type of this element. */
+ simdjson_inline element_type type() const noexcept;
+
+ /**
+ * Cast this element to an array.
+ *
+ * @returns An object that can be used to iterate the array, or:
+ * INCORRECT_TYPE if the JSON element is not an array.
+ */
+ inline simdjson_result<array> get_array() const noexcept;
+ /**
+ * Cast this element to an object.
+ *
+ * @returns An object that can be used to look up or iterate the object's fields, or:
+ * INCORRECT_TYPE if the JSON element is not an object.
+ */
+ inline simdjson_result<object> get_object() const noexcept;
+ /**
+ * Cast this element to a null-terminated C string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * The length of the string is given by get_string_length(). Because JSON strings
+ * may contain null characters, it may be incorrect to use strlen to determine the
+ * string length.
+ *
+ * It is possible to get a single string_view instance which represents both the string
+ * content and its length: see get_string().
+ *
+ * @returns A pointer to a null-terminated UTF-8 string. This string is stored in the parser and will
+ * be invalidated the next time it parses a document or when it is destroyed.
+ * Returns INCORRECT_TYPE if the JSON element is not a string.
+ */
+ inline simdjson_result<const char *> get_c_str() const noexcept;
+ /**
+ * Gives the length in bytes of the string.
+ *
+ * It is possible to get a single string_view instance which represents both the string
+ * content and its length: see get_string().
+ *
+ * @returns A string length in bytes.
+ * Returns INCORRECT_TYPE if the JSON element is not a string.
+ */
+ inline simdjson_result<size_t> get_string_length() const noexcept;
+ /**
+ * Cast this element to a string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next time it
+ * parses a document or when it is destroyed.
+ * Returns INCORRECT_TYPE if the JSON element is not a string.
+ */
+ inline simdjson_result<std::string_view> get_string() const noexcept;
+ /**
+ * Cast this element to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
+ * if it is negative.
+ */
+ inline simdjson_result<int64_t> get_int64() const noexcept;
+ /**
+ * Cast this element to an unsigned integer.
+ *
+ * @returns An unsigned 64-bit integer.
+ * Returns INCORRECT_TYPE if the JSON element is not an integer, or NUMBER_OUT_OF_RANGE
+ * if it is too large.
+ */
+ inline simdjson_result<uint64_t> get_uint64() const noexcept;
+ /**
+ * Cast this element to a double floating-point.
+ *
+ * @returns A double value.
+ * Returns INCORRECT_TYPE if the JSON element is not a number.
+ */
+ inline simdjson_result<double> get_double() const noexcept;
+ /**
+ * Cast this element to a bool.
+ *
+ * @returns A bool value.
+ * Returns INCORRECT_TYPE if the JSON element is not a boolean.
+ */
+ inline simdjson_result<bool> get_bool() const noexcept;
+
+ /**
+ * Whether this element is a json array.
+ *
+ * Equivalent to is<array>().
+ */
+ inline bool is_array() const noexcept;
+ /**
+ * Whether this element is a json object.
+ *
+ * Equivalent to is<object>().
+ */
+ inline bool is_object() const noexcept;
+ /**
+ * Whether this element is a json string.
+ *
+ * Equivalent to is<std::string_view>() or is<const char *>().
+ */
+ inline bool is_string() const noexcept;
+ /**
+ * Whether this element is a json number that fits in a signed 64-bit integer.
+ *
+ * Equivalent to is<int64_t>().
+ */
+ inline bool is_int64() const noexcept;
+ /**
+ * Whether this element is a json number that fits in an unsigned 64-bit integer.
+ *
+ * Equivalent to is<uint64_t>().
+ */
+ inline bool is_uint64() const noexcept;
+ /**
+ * Whether this element is a json number that fits in a double.
+ *
+ * Equivalent to is<double>().
+ */
+ inline bool is_double() const noexcept;
+
+ /**
+ * Whether this element is a json number.
+ *
+ * Both integers and floating points will return true.
+ */
+ inline bool is_number() const noexcept;
+
+ /**
+ * Whether this element is a json `true` or `false`.
+ *
+ * Equivalent to is<bool>().
+ */
+ inline bool is_bool() const noexcept;
+ /**
+ * Whether this element is a json `null`.
+ */
+ inline bool is_null() const noexcept;
+
+ /**
+ * Tell whether the value can be cast to provided type (T).
+ *
+ * Supported types:
+ * - Boolean: bool
+ * - Number: double, uint64_t, int64_t
+ * - String: std::string_view, const char *
+ * - Array: dom::array
+ * - Object: dom::object
+ *
+ * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
+ */
+ template<typename T>
+ simdjson_inline bool is() const noexcept;
+
+ /**
+ * Get the value as the provided type (T).
+ *
+ * Supported types:
+ * - Boolean: bool
+ * - Number: double, uint64_t, int64_t
+ * - String: std::string_view, const char *
+ * - Array: dom::array
+ * - Object: dom::object
+ *
+ * You may use get_double(), get_bool(), get_uint64(), get_int64(),
+ * get_object(), get_array() or get_string() instead.
+ *
+ * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
+ *
+ * @returns The value cast to the given type, or:
+ * INCORRECT_TYPE if the value cannot be cast to the given type.
+ */
+
+ template<typename T>
+ inline simdjson_result<T> get() const noexcept {
+ // Unless the simdjson library provides an inline implementation, calling this method should
+ // immediately fail.
+ static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
+ "The supported types are Boolean (bool), numbers (double, uint64_t, int64_t), "
+ "strings (std::string_view, const char *), arrays (dom::array) and objects (dom::object). "
+ "We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
+ "get_object(), get_array() or get_string() instead of the get template.");
+ }
+
+ /**
+ * Get the value as the provided type (T).
+ *
+ * Supported types:
+ * - Boolean: bool
+ * - Number: double, uint64_t, int64_t
+ * - String: std::string_view, const char *
+ * - Array: dom::array
+ * - Object: dom::object
+ *
+ * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
+ *
+ * @param value The variable to set to the value. May not be set if there is an error.
+ *
+ * @returns The error that occurred, or SUCCESS if there was no error.
+ */
+ template<typename T>
+ simdjson_warn_unused simdjson_inline error_code get(T &value) const noexcept;
+
+ /**
+ * Get the value as the provided type (T), setting error if it's not the given type.
+ *
+ * Supported types:
+ * - Boolean: bool
+ * - Number: double, uint64_t, int64_t
+ * - String: std::string_view, const char *
+ * - Array: dom::array
+ * - Object: dom::object
+ *
+ * @tparam T bool, double, uint64_t, int64_t, std::string_view, const char *, dom::array, dom::object
+ *
+ * @param value The variable to set to the given type. value is undefined if there is an error.
+ * @param error The variable to store the error. error is set to error_code::SUCCEED if there is an error.
+ */
+ template<typename T>
+ inline void tie(T &value, error_code &error) && noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ /**
+ * Read this element as a boolean.
+ *
+ * @return The boolean value
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a boolean.
+ */
+ inline operator bool() const noexcept(false);
+
+ /**
+ * Read this element as a null-terminated UTF-8 string.
+ *
+ * Be mindful that JSON allows strings to contain null characters.
+ *
+ * Does *not* convert other types to a string; requires that the JSON type of the element was
+ * an actual string.
+ *
+ * @return The string value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
+ */
+ inline explicit operator const char*() const noexcept(false);
+
+ /**
+ * Read this element as a null-terminated UTF-8 string.
+ *
+ * Does *not* convert other types to a string; requires that the JSON type of the element was
+ * an actual string.
+ *
+ * @return The string value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a string.
+ */
+ inline operator std::string_view() const noexcept(false);
+
+ /**
+ * Read this element as an unsigned integer.
+ *
+ * @return The integer value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
+ * @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer does not fit in 64 bits or is negative
+ */
+ inline operator uint64_t() const noexcept(false);
+ /**
+ * Read this element as an signed integer.
+ *
+ * @return The integer value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an integer
+ * @exception simdjson_error(NUMBER_OUT_OF_RANGE) if the integer does not fit in 64 bits
+ */
+ inline operator int64_t() const noexcept(false);
+ /**
+ * Read this element as an double.
+ *
+ * @return The double value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not a number
+ */
+ inline operator double() const noexcept(false);
+ /**
+ * Read this element as a JSON array.
+ *
+ * @return The JSON array.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
+ */
+ inline operator array() const noexcept(false);
+ /**
+ * Read this element as a JSON object (key/value pairs).
+ *
+ * @return The JSON object.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an object
+ */
+ inline operator object() const noexcept(false);
+
+ /**
+ * Iterate over each element in this array.
+ *
+ * @return The beginning of the iteration.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
+ */
+ inline dom::array::iterator begin() const noexcept(false);
+
+ /**
+ * Iterate over each element in this array.
+ *
+ * @return The end of the iteration.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON element is not an array
+ */
+ inline dom::array::iterator end() const noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ * - INCORRECT_TYPE if this is not an object
+ */
+ inline simdjson_result<element> operator[](std::string_view key) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ * - INCORRECT_TYPE if this is not an object
+ */
+ inline simdjson_result<element> operator[](const char *key) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard.
+ *
+ * dom::parser parser;
+ * element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
+ * doc.at_pointer("/foo/a/1") == 20
+ * doc.at_pointer("/foo")["a"].at(1) == 20
+ * doc.at_pointer("")["foo"]["a"].at(1) == 20
+ *
+ * It is allowed for a key to be the empty string:
+ *
+ * dom::parser parser;
+ * object obj = parser.parse(R"({ "": { "a": [ 10, 20, 30 ] }})"_padded);
+ * obj.at_pointer("//a/1") == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline simdjson_result<element> at_pointer(const std::string_view json_pointer) const noexcept;
+
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+ /**
+ *
+ * Version 0.4 of simdjson used an incorrect interpretation of the JSON Pointer standard
+ * and allowed the following :
+ *
+ * dom::parser parser;
+ * element doc = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
+ * doc.at("foo/a/1") == 20
+ *
+ * Though it is intuitive, it is not compliant with RFC 6901
+ * https://tools.ietf.org/html/rfc6901
+ *
+ * For standard compliance, use the at_pointer function instead.
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
+ inline simdjson_result<element> at(const std::string_view json_pointer) const noexcept;
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+
+ /**
+ * Get the value at the given index.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ inline simdjson_result<element> at(size_t index) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline simdjson_result<element> at_key(std::string_view key) const noexcept;
+
+ /**
+ * Get the value associated with the given key in a case-insensitive manner.
+ *
+ * Note: The key will be matched against **unescaped** JSON.
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
+
+ /**
+ * operator< defines a total order for element allowing to use them in
+ * ordered C++ STL containers
+ *
+ * @return TRUE if the key appears before the other one in the tape
+ */
+ inline bool operator<(const element &other) const noexcept;
+
+ /**
+ * operator== allows to verify if two element values reference the
+ * same JSON item
+ *
+ * @return TRUE if the two values references the same JSON element
+ */
+ inline bool operator==(const element &other) const noexcept;
+
+ /** @private for debugging. Prints out the root element. */
+ inline bool dump_raw_tape(std::ostream &out) const noexcept;
+
+private:
+ simdjson_inline element(const internal::tape_ref &tape) noexcept;
+ internal::tape_ref tape;
+ friend class document;
+ friend class object;
+ friend class array;
+ friend struct simdjson_result<element>;
+ template<typename T>
+ friend class simdjson::internal::string_builder;
+
+};
+
+} // namespace dom
+
+/** The result of a JSON navigation that may fail. */
+template<>
+struct simdjson_result<dom::element> : public internal::simdjson_result_base<dom::element> {
+public:
+ simdjson_inline simdjson_result() noexcept; ///< @private
+ simdjson_inline simdjson_result(dom::element &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+
+ simdjson_inline simdjson_result<dom::element_type> type() const noexcept;
+ template<typename T>
+ simdjson_inline bool is() const noexcept;
+ template<typename T>
+ simdjson_inline simdjson_result<T> get() const noexcept;
+ template<typename T>
+ simdjson_warn_unused simdjson_inline error_code get(T &value) const noexcept;
+
+ simdjson_inline simdjson_result<dom::array> get_array() const noexcept;
+ simdjson_inline simdjson_result<dom::object> get_object() const noexcept;
+ simdjson_inline simdjson_result<const char *> get_c_str() const noexcept;
+ simdjson_inline simdjson_result<size_t> get_string_length() const noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_string() const noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64() const noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64() const noexcept;
+ simdjson_inline simdjson_result<double> get_double() const noexcept;
+ simdjson_inline simdjson_result<bool> get_bool() const noexcept;
+
+ simdjson_inline bool is_array() const noexcept;
+ simdjson_inline bool is_object() const noexcept;
+ simdjson_inline bool is_string() const noexcept;
+ simdjson_inline bool is_int64() const noexcept;
+ simdjson_inline bool is_uint64() const noexcept;
+ simdjson_inline bool is_double() const noexcept;
+ simdjson_inline bool is_number() const noexcept;
+ simdjson_inline bool is_bool() const noexcept;
+ simdjson_inline bool is_null() const noexcept;
+
+ simdjson_inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
+ simdjson_inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
+ simdjson_inline simdjson_result<dom::element> at_pointer(const std::string_view json_pointer) const noexcept;
+ [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]]
+ simdjson_inline simdjson_result<dom::element> at(const std::string_view json_pointer) const noexcept;
+ simdjson_inline simdjson_result<dom::element> at(size_t index) const noexcept;
+ simdjson_inline simdjson_result<dom::element> at_key(std::string_view key) const noexcept;
+ simdjson_inline simdjson_result<dom::element> at_key_case_insensitive(std::string_view key) const noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ simdjson_inline operator bool() const noexcept(false);
+ simdjson_inline explicit operator const char*() const noexcept(false);
+ simdjson_inline operator std::string_view() const noexcept(false);
+ simdjson_inline operator uint64_t() const noexcept(false);
+ simdjson_inline operator int64_t() const noexcept(false);
+ simdjson_inline operator double() const noexcept(false);
+ simdjson_inline operator dom::array() const noexcept(false);
+ simdjson_inline operator dom::object() const noexcept(false);
+
+ simdjson_inline dom::array::iterator begin() const noexcept(false);
+ simdjson_inline dom::array::iterator end() const noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_DOM_DOCUMENT_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/object-inl.h b/contrib/libs/simdjson/include/simdjson/dom/object-inl.h
new file mode 100644
index 0000000000..c72ab3feb4
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/object-inl.h
@@ -0,0 +1,263 @@
+#ifndef SIMDJSON_OBJECT_INL_H
+#define SIMDJSON_OBJECT_INL_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/object.h"
+#include "simdjson/dom/document.h"
+
+#include "simdjson/dom/element-inl.h"
+#include "simdjson/error-inl.h"
+
+#include <cstring>
+
+namespace simdjson {
+
+//
+// simdjson_result<dom::object> inline implementation
+//
+simdjson_inline simdjson_result<dom::object>::simdjson_result() noexcept
+ : internal::simdjson_result_base<dom::object>() {}
+simdjson_inline simdjson_result<dom::object>::simdjson_result(dom::object value) noexcept
+ : internal::simdjson_result_base<dom::object>(std::forward<dom::object>(value)) {}
+simdjson_inline simdjson_result<dom::object>::simdjson_result(error_code error) noexcept
+ : internal::simdjson_result_base<dom::object>(error) {}
+
+inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+inline simdjson_result<dom::element> simdjson_result<dom::object>::operator[](const char *key) const noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+inline simdjson_result<dom::element> simdjson_result<dom::object>::at_pointer(std::string_view json_pointer) const noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key(std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first.at_key(key);
+}
+inline simdjson_result<dom::element> simdjson_result<dom::object>::at_key_case_insensitive(std::string_view key) const noexcept {
+ if (error()) { return error(); }
+ return first.at_key_case_insensitive(key);
+}
+
+#if SIMDJSON_EXCEPTIONS
+
+inline dom::object::iterator simdjson_result<dom::object>::begin() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.begin();
+}
+inline dom::object::iterator simdjson_result<dom::object>::end() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.end();
+}
+inline size_t simdjson_result<dom::object>::size() const noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first.size();
+}
+
+#endif // SIMDJSON_EXCEPTIONS
+
+namespace dom {
+
+//
+// object inline implementation
+//
+simdjson_inline object::object() noexcept : tape{} {}
+simdjson_inline object::object(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
+inline object::iterator object::begin() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return internal::tape_ref(tape.doc, tape.json_index + 1);
+}
+inline object::iterator object::end() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return internal::tape_ref(tape.doc, tape.after_element() - 1);
+}
+inline size_t object::size() const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ return tape.scope_count();
+}
+
+inline simdjson_result<element> object::operator[](std::string_view key) const noexcept {
+ return at_key(key);
+}
+inline simdjson_result<element> object::operator[](const char *key) const noexcept {
+ return at_key(key);
+}
+inline simdjson_result<element> object::at_pointer(std::string_view json_pointer) const noexcept {
+ SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914
+ if(json_pointer.empty()) { // an empty string means that we return the current node
+ return element(this->tape); // copy the current node
+ } else if(json_pointer[0] != '/') { // otherwise there is an error
+ return INVALID_JSON_POINTER;
+ }
+ json_pointer = json_pointer.substr(1);
+ size_t slash = json_pointer.find('/');
+ std::string_view key = json_pointer.substr(0, slash);
+ // Grab the child with the given key
+ simdjson_result<element> child;
+
+ // If there is an escape character in the key, unescape it and then get the child.
+ size_t escape = key.find('~');
+ if (escape != std::string_view::npos) {
+ // Unescape the key
+ std::string unescaped(key);
+ do {
+ switch (unescaped[escape+1]) {
+ case '0':
+ unescaped.replace(escape, 2, "~");
+ break;
+ case '1':
+ unescaped.replace(escape, 2, "/");
+ break;
+ default:
+ return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
+ }
+ escape = unescaped.find('~', escape+1);
+ } while (escape != std::string::npos);
+ child = at_key(unescaped);
+ } else {
+ child = at_key(key);
+ }
+ if(child.error()) {
+ return child; // we do not continue if there was an error
+ }
+ // If there is a /, we have to recurse and look up more of the path
+ if (slash != std::string_view::npos) {
+ child = child.at_pointer(json_pointer.substr(slash));
+ }
+ return child;
+}
+
+inline simdjson_result<element> object::at_key(std::string_view key) const noexcept {
+ iterator end_field = end();
+ for (iterator field = begin(); field != end_field; ++field) {
+ if (field.key_equals(key)) {
+ return field.value();
+ }
+ }
+ return NO_SUCH_FIELD;
+}
+// In case you wonder why we need this, please see
+// https://github.com/simdjson/simdjson/issues/323
+// People do seek keys in a case-insensitive manner.
+inline simdjson_result<element> object::at_key_case_insensitive(std::string_view key) const noexcept {
+ iterator end_field = end();
+ for (iterator field = begin(); field != end_field; ++field) {
+ if (field.key_equals_case_insensitive(key)) {
+ return field.value();
+ }
+ }
+ return NO_SUCH_FIELD;
+}
+
+inline object::operator element() const noexcept {
+ return element(tape);
+}
+
+//
+// object::iterator inline implementation
+//
+simdjson_inline object::iterator::iterator(const internal::tape_ref &_tape) noexcept : tape{_tape} { }
+inline const key_value_pair object::iterator::operator*() const noexcept {
+ return key_value_pair(key(), value());
+}
+inline bool object::iterator::operator!=(const object::iterator& other) const noexcept {
+ return tape.json_index != other.tape.json_index;
+}
+inline bool object::iterator::operator==(const object::iterator& other) const noexcept {
+ return tape.json_index == other.tape.json_index;
+}
+inline bool object::iterator::operator<(const object::iterator& other) const noexcept {
+ return tape.json_index < other.tape.json_index;
+}
+inline bool object::iterator::operator<=(const object::iterator& other) const noexcept {
+ return tape.json_index <= other.tape.json_index;
+}
+inline bool object::iterator::operator>=(const object::iterator& other) const noexcept {
+ return tape.json_index >= other.tape.json_index;
+}
+inline bool object::iterator::operator>(const object::iterator& other) const noexcept {
+ return tape.json_index > other.tape.json_index;
+}
+inline object::iterator& object::iterator::operator++() noexcept {
+ tape.json_index++;
+ tape.json_index = tape.after_element();
+ return *this;
+}
+inline object::iterator object::iterator::operator++(int) noexcept {
+ object::iterator out = *this;
+ ++*this;
+ return out;
+}
+inline std::string_view object::iterator::key() const noexcept {
+ return tape.get_string_view();
+}
+inline uint32_t object::iterator::key_length() const noexcept {
+ return tape.get_string_length();
+}
+inline const char* object::iterator::key_c_str() const noexcept {
+ return reinterpret_cast<const char *>(&tape.doc->string_buf[size_t(tape.tape_value()) + sizeof(uint32_t)]);
+}
+inline element object::iterator::value() const noexcept {
+ return element(internal::tape_ref(tape.doc, tape.json_index + 1));
+}
+
+/**
+ * Design notes:
+ * Instead of constructing a string_view and then comparing it with a
+ * user-provided strings, it is probably more performant to have dedicated
+ * functions taking as a parameter the string we want to compare against
+ * and return true when they are equal. That avoids the creation of a temporary
+ * std::string_view. Though it is possible for the compiler to avoid entirely
+ * any overhead due to string_view, relying too much on compiler magic is
+ * problematic: compiler magic sometimes fail, and then what do you do?
+ * Also, enticing users to rely on high-performance function is probably better
+ * on the long run.
+ */
+
+inline bool object::iterator::key_equals(std::string_view o) const noexcept {
+ // We use the fact that the key length can be computed quickly
+ // without access to the string buffer.
+ const uint32_t len = key_length();
+ if(o.size() == len) {
+ // We avoid construction of a temporary string_view instance.
+ return (memcmp(o.data(), key_c_str(), len) == 0);
+ }
+ return false;
+}
+
+inline bool object::iterator::key_equals_case_insensitive(std::string_view o) const noexcept {
+ // We use the fact that the key length can be computed quickly
+ // without access to the string buffer.
+ const uint32_t len = key_length();
+ if(o.size() == len) {
+ // See For case-insensitive string comparisons, avoid char-by-char functions
+ // https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/
+ // Note that it might be worth rolling our own strncasecmp function, with vectorization.
+ return (simdjson_strncasecmp(o.data(), key_c_str(), len) == 0);
+ }
+ return false;
+}
+//
+// key_value_pair inline implementation
+//
+inline key_value_pair::key_value_pair(std::string_view _key, element _value) noexcept :
+ key(_key), value(_value) {}
+
+} // namespace dom
+
+} // namespace simdjson
+
+#if defined(__cpp_lib_ranges)
+static_assert(std::ranges::view<simdjson::dom::object>);
+static_assert(std::ranges::sized_range<simdjson::dom::object>);
+#if SIMDJSON_EXCEPTIONS
+static_assert(std::ranges::view<simdjson::simdjson_result<simdjson::dom::object>>);
+static_assert(std::ranges::sized_range<simdjson::simdjson_result<simdjson::dom::object>>);
+#endif // SIMDJSON_EXCEPTIONS
+#endif // defined(__cpp_lib_ranges)
+
+#endif // SIMDJSON_OBJECT_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/object.h b/contrib/libs/simdjson/include/simdjson/dom/object.h
new file mode 100644
index 0000000000..8f6884baf1
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/object.h
@@ -0,0 +1,274 @@
+#ifndef SIMDJSON_DOM_OBJECT_H
+#define SIMDJSON_DOM_OBJECT_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/element.h"
+#include "simdjson/internal/tape_ref.h"
+
+namespace simdjson {
+namespace dom {
+
+/**
+ * JSON object.
+ */
+class object {
+public:
+ /** Create a new, invalid object */
+ simdjson_inline object() noexcept;
+
+ class iterator {
+ public:
+ using value_type = const key_value_pair;
+ using difference_type = std::ptrdiff_t;
+ using pointer = void;
+ using reference = value_type;
+ using iterator_category = std::forward_iterator_tag;
+
+ /**
+ * Get the actual key/value pair
+ */
+ inline reference operator*() const noexcept;
+ /**
+ * Get the next key/value pair.
+ *
+ * Part of the std::iterator interface.
+ *
+ */
+ inline iterator& operator++() noexcept;
+ /**
+ * Get the next key/value pair.
+ *
+ * Part of the std::iterator interface.
+ *
+ */
+ inline iterator operator++(int) noexcept;
+ /**
+ * Check if these values come from the same place in the JSON.
+ *
+ * Part of the std::iterator interface.
+ */
+ inline bool operator!=(const iterator& other) const noexcept;
+ inline bool operator==(const iterator& other) const noexcept;
+
+ inline bool operator<(const iterator& other) const noexcept;
+ inline bool operator<=(const iterator& other) const noexcept;
+ inline bool operator>=(const iterator& other) const noexcept;
+ inline bool operator>(const iterator& other) const noexcept;
+ /**
+ * Get the key of this key/value pair.
+ */
+ inline std::string_view key() const noexcept;
+ /**
+ * Get the length (in bytes) of the key in this key/value pair.
+ * You should expect this function to be faster than key().size().
+ */
+ inline uint32_t key_length() const noexcept;
+ /**
+ * Returns true if the key in this key/value pair is equal
+ * to the provided string_view.
+ */
+ inline bool key_equals(std::string_view o) const noexcept;
+ /**
+ * Returns true if the key in this key/value pair is equal
+ * to the provided string_view in a case-insensitive manner.
+ * Case comparisons may only be handled correctly for ASCII strings.
+ */
+ inline bool key_equals_case_insensitive(std::string_view o) const noexcept;
+ /**
+ * Get the key of this key/value pair.
+ */
+ inline const char *key_c_str() const noexcept;
+ /**
+ * Get the value of this key/value pair.
+ */
+ inline element value() const noexcept;
+
+ iterator() noexcept = default;
+ iterator(const iterator&) noexcept = default;
+ iterator& operator=(const iterator&) noexcept = default;
+ private:
+ simdjson_inline iterator(const internal::tape_ref &tape) noexcept;
+
+ internal::tape_ref tape;
+
+ friend class object;
+ };
+
+ /**
+ * Return the first key/value pair.
+ *
+ * Part of the std::iterable interface.
+ */
+ inline iterator begin() const noexcept;
+ /**
+ * One past the last key/value pair.
+ *
+ * Part of the std::iterable interface.
+ */
+ inline iterator end() const noexcept;
+ /**
+ * Get the size of the object (number of keys).
+ * It is a saturated value with a maximum of 0xFFFFFF: if the value
+ * is 0xFFFFFF then the size is 0xFFFFFF or greater.
+ */
+ inline size_t size() const noexcept;
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * This function has linear-time complexity: the keys are checked one by one.
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ * - INCORRECT_TYPE if this is not an object
+ */
+ inline simdjson_result<element> operator[](std::string_view key) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * This function has linear-time complexity: the keys are checked one by one.
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ * - INCORRECT_TYPE if this is not an object
+ */
+ inline simdjson_result<element> operator[](const char *key) const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
+ * as the root of its own JSON document.
+ *
+ * dom::parser parser;
+ * object obj = parser.parse(R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded);
+ * obj.at_pointer("/foo/a/1") == 20
+ * obj.at_pointer("/foo")["a"].at(1) == 20
+ *
+ * It is allowed for a key to be the empty string:
+ *
+ * dom::parser parser;
+ * object obj = parser.parse(R"({ "": { "a": [ 10, 20, 30 ] }})"_padded);
+ * obj.at_pointer("//a/1") == 20
+ * obj.at_pointer("/")["a"].at(1) == 20
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline simdjson_result<element> at_pointer(std::string_view json_pointer) const noexcept;
+
+ /**
+ * Get the value associated with the given key.
+ *
+ * The key will be matched against **unescaped** JSON:
+ *
+ * dom::parser parser;
+ * int64_t(parser.parse(R"({ "a\n": 1 })"_padded)["a\n"]) == 1
+ * parser.parse(R"({ "a\n": 1 })"_padded)["a\\n"].get_uint64().error() == NO_SUCH_FIELD
+ *
+ * This function has linear-time complexity: the keys are checked one by one.
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline simdjson_result<element> at_key(std::string_view key) const noexcept;
+
+ /**
+ * Get the value associated with the given key in a case-insensitive manner.
+ * It is only guaranteed to work over ASCII inputs.
+ *
+ * Note: The key will be matched against **unescaped** JSON.
+ *
+ * This function has linear-time complexity: the keys are checked one by one.
+ *
+ * @return The value associated with this field, or:
+ * - NO_SUCH_FIELD if the field does not exist in the object
+ */
+ inline simdjson_result<element> at_key_case_insensitive(std::string_view key) const noexcept;
+
+ /**
+ * Implicitly convert object to element
+ */
+ inline operator element() const noexcept;
+
+private:
+ simdjson_inline object(const internal::tape_ref &tape) noexcept;
+
+ internal::tape_ref tape;
+
+ friend class element;
+ friend struct simdjson_result<element>;
+ template<typename T>
+ friend class simdjson::internal::string_builder;
+};
+
+/**
+ * Key/value pair in an object.
+ */
+class key_value_pair {
+public:
+ /** key in the key-value pair **/
+ std::string_view key;
+ /** value in the key-value pair **/
+ element value;
+
+private:
+ simdjson_inline key_value_pair(std::string_view _key, element _value) noexcept;
+ friend class object;
+};
+
+} // namespace dom
+
+/** The result of a JSON conversion that may fail. */
+template<>
+struct simdjson_result<dom::object> : public internal::simdjson_result_base<dom::object> {
+public:
+ simdjson_inline simdjson_result() noexcept; ///< @private
+ simdjson_inline simdjson_result(dom::object value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+
+ inline simdjson_result<dom::element> operator[](std::string_view key) const noexcept;
+ inline simdjson_result<dom::element> operator[](const char *key) const noexcept;
+ inline simdjson_result<dom::element> at_pointer(std::string_view json_pointer) const noexcept;
+ inline simdjson_result<dom::element> at_key(std::string_view key) const noexcept;
+ inline simdjson_result<dom::element> at_key_case_insensitive(std::string_view key) const noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ inline dom::object::iterator begin() const noexcept(false);
+ inline dom::object::iterator end() const noexcept(false);
+ inline size_t size() const noexcept(false);
+#endif // SIMDJSON_EXCEPTIONS
+};
+
+} // namespace simdjson
+
+#if defined(__cpp_lib_ranges)
+#include <ranges>
+
+namespace std {
+namespace ranges {
+template<>
+inline constexpr bool enable_view<simdjson::dom::object> = true;
+#if SIMDJSON_EXCEPTIONS
+template<>
+inline constexpr bool enable_view<simdjson::simdjson_result<simdjson::dom::object>> = true;
+#endif // SIMDJSON_EXCEPTIONS
+} // namespace ranges
+} // namespace std
+#endif // defined(__cpp_lib_ranges)
+
+#endif // SIMDJSON_DOM_OBJECT_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/parser-inl.h b/contrib/libs/simdjson/include/simdjson/dom/parser-inl.h
new file mode 100644
index 0000000000..14ba6c8333
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/parser-inl.h
@@ -0,0 +1,258 @@
+#ifndef SIMDJSON_PARSER_INL_H
+#define SIMDJSON_PARSER_INL_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/document_stream.h"
+#include "simdjson/implementation.h"
+#include "simdjson/internal/dom_parser_implementation.h"
+
+#include "simdjson/error-inl.h"
+#include "simdjson/padded_string-inl.h"
+#include "simdjson/dom/document_stream-inl.h"
+#include "simdjson/dom/element-inl.h"
+
+#include <climits>
+#include <cstring> /* memcmp */
+
+namespace simdjson {
+namespace dom {
+
+//
+// parser inline implementation
+//
+simdjson_inline parser::parser(size_t max_capacity) noexcept
+ : _max_capacity{max_capacity},
+ loaded_bytes(nullptr) {
+}
+simdjson_inline parser::parser(parser &&other) noexcept = default;
+simdjson_inline parser &parser::operator=(parser &&other) noexcept = default;
+
+inline bool parser::is_valid() const noexcept { return valid; }
+inline int parser::get_error_code() const noexcept { return error; }
+inline std::string parser::get_error_message() const noexcept { return error_message(error); }
+
+inline bool parser::dump_raw_tape(std::ostream &os) const noexcept {
+ return valid ? doc.dump_raw_tape(os) : false;
+}
+
+inline simdjson_result<size_t> parser::read_file(const std::string &path) noexcept {
+ // Open the file
+ SIMDJSON_PUSH_DISABLE_WARNINGS
+ SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
+ std::FILE *fp = std::fopen(path.c_str(), "rb");
+ SIMDJSON_POP_DISABLE_WARNINGS
+
+ if (fp == nullptr) {
+ return IO_ERROR;
+ }
+
+ // Get the file size
+ int ret;
+#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
+ ret = _fseeki64(fp, 0, SEEK_END);
+#else
+ ret = std::fseek(fp, 0, SEEK_END);
+#endif // _WIN64
+ if(ret < 0) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
+ __int64 len = _ftelli64(fp);
+ if(len == -1L) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#else
+ long len = std::ftell(fp);
+ if((len < 0) || (len == LONG_MAX)) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#endif
+
+ // Make sure we have enough capacity to load the file
+ if (_loaded_bytes_capacity < size_t(len)) {
+ loaded_bytes.reset( internal::allocate_padded_buffer(len) );
+ if (!loaded_bytes) {
+ std::fclose(fp);
+ return MEMALLOC;
+ }
+ _loaded_bytes_capacity = len;
+ }
+
+ // Read the string
+ std::rewind(fp);
+ size_t bytes_read = std::fread(loaded_bytes.get(), 1, len, fp);
+ if (std::fclose(fp) != 0 || bytes_read != size_t(len)) {
+ return IO_ERROR;
+ }
+
+ return bytes_read;
+}
+
+inline simdjson_result<element> parser::load(const std::string &path) & noexcept {
+ return load_into_document(doc, path);
+}
+
+inline simdjson_result<element> parser::load_into_document(document& provided_doc, const std::string &path) & noexcept {
+ size_t len;
+ auto _error = read_file(path).get(len);
+ if (_error) { return _error; }
+ return parse_into_document(provided_doc, loaded_bytes.get(), len, false);
+}
+
+inline simdjson_result<document_stream> parser::load_many(const std::string &path, size_t batch_size) noexcept {
+ size_t len;
+ auto _error = read_file(path).get(len);
+ if (_error) { return _error; }
+ if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
+ return document_stream(*this, reinterpret_cast<const uint8_t*>(loaded_bytes.get()), len, batch_size);
+}
+
+inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
+ // Important: we need to ensure that document has enough capacity.
+ // Important: It is possible that provided_doc is actually the internal 'doc' within the parser!!!
+ error_code _error = ensure_capacity(provided_doc, len);
+ if (_error) { return _error; }
+ if (realloc_if_needed) {
+ // Make sure we have enough capacity to copy len bytes
+ if (!loaded_bytes || _loaded_bytes_capacity < len) {
+ loaded_bytes.reset( internal::allocate_padded_buffer(len) );
+ if (!loaded_bytes) {
+ return MEMALLOC;
+ }
+ _loaded_bytes_capacity = len;
+ }
+ std::memcpy(static_cast<void *>(loaded_bytes.get()), buf, len);
+ buf = reinterpret_cast<const uint8_t*>(loaded_bytes.get());
+ }
+
+ if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
+ buf += 3;
+ len -= 3;
+ }
+ _error = implementation->parse(buf, len, provided_doc);
+
+ if (_error) { return _error; }
+
+ return provided_doc.root();
+}
+
+simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const char *buf, size_t len, bool realloc_if_needed) & noexcept {
+ return parse_into_document(provided_doc, reinterpret_cast<const uint8_t *>(buf), len, realloc_if_needed);
+}
+simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const std::string &s) & noexcept {
+ return parse_into_document(provided_doc, s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
+}
+simdjson_inline simdjson_result<element> parser::parse_into_document(document& provided_doc, const padded_string &s) & noexcept {
+ return parse_into_document(provided_doc, s.data(), s.length(), false);
+}
+
+
+inline simdjson_result<element> parser::parse(const uint8_t *buf, size_t len, bool realloc_if_needed) & noexcept {
+ return parse_into_document(doc, buf, len, realloc_if_needed);
+}
+
+simdjson_inline simdjson_result<element> parser::parse(const char *buf, size_t len, bool realloc_if_needed) & noexcept {
+ return parse(reinterpret_cast<const uint8_t *>(buf), len, realloc_if_needed);
+}
+simdjson_inline simdjson_result<element> parser::parse(const std::string &s) & noexcept {
+ return parse(s.data(), s.length(), s.capacity() - s.length() < SIMDJSON_PADDING);
+}
+simdjson_inline simdjson_result<element> parser::parse(const padded_string &s) & noexcept {
+ return parse(s.data(), s.length(), false);
+}
+simdjson_inline simdjson_result<element> parser::parse(const padded_string_view &v) & noexcept {
+ return parse(v.data(), v.length(), false);
+}
+
+inline simdjson_result<document_stream> parser::parse_many(const uint8_t *buf, size_t len, size_t batch_size) noexcept {
+ if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
+ if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
+ buf += 3;
+ len -= 3;
+ }
+ return document_stream(*this, buf, len, batch_size);
+}
+inline simdjson_result<document_stream> parser::parse_many(const char *buf, size_t len, size_t batch_size) noexcept {
+ return parse_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size);
+}
+inline simdjson_result<document_stream> parser::parse_many(const std::string &s, size_t batch_size) noexcept {
+ return parse_many(s.data(), s.length(), batch_size);
+}
+inline simdjson_result<document_stream> parser::parse_many(const padded_string &s, size_t batch_size) noexcept {
+ return parse_many(s.data(), s.length(), batch_size);
+}
+
+simdjson_inline size_t parser::capacity() const noexcept {
+ return implementation ? implementation->capacity() : 0;
+}
+simdjson_inline size_t parser::max_capacity() const noexcept {
+ return _max_capacity;
+}
+simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept {
+ return implementation ? implementation->max_depth() : DEFAULT_MAX_DEPTH;
+}
+
+simdjson_warn_unused
+inline error_code parser::allocate(size_t capacity, size_t max_depth) noexcept {
+ //
+ // Reallocate implementation if needed
+ //
+ error_code err;
+ if (implementation) {
+ err = implementation->allocate(capacity, max_depth);
+ } else {
+ err = simdjson::get_active_implementation()->create_dom_parser_implementation(capacity, max_depth, implementation);
+ }
+ if (err) { return err; }
+ return SUCCESS;
+}
+
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+simdjson_warn_unused
+inline bool parser::allocate_capacity(size_t capacity, size_t max_depth) noexcept {
+ return !allocate(capacity, max_depth);
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+
+inline error_code parser::ensure_capacity(size_t desired_capacity) noexcept {
+ return ensure_capacity(doc, desired_capacity);
+}
+
+
+inline error_code parser::ensure_capacity(document& target_document, size_t desired_capacity) noexcept {
+ // 1. It is wasteful to allocate a document and a parser for documents spanning less than MINIMAL_DOCUMENT_CAPACITY bytes.
+ // 2. If we allow desired_capacity = 0 then it is possible to exit this function with implementation == nullptr.
+ if(desired_capacity < MINIMAL_DOCUMENT_CAPACITY) { desired_capacity = MINIMAL_DOCUMENT_CAPACITY; }
+ // If we don't have enough capacity, (try to) automatically bump it.
+ // If the document needs allocation, do it too.
+ // Both in one if statement to minimize unlikely branching.
+ //
+ // Note: we must make sure that this function is called if capacity() == 0. We do so because we
+ // ensure that desired_capacity > 0.
+ if (simdjson_unlikely(capacity() < desired_capacity || target_document.capacity() < desired_capacity)) {
+ if (desired_capacity > max_capacity()) {
+ return error = CAPACITY;
+ }
+ error_code err1 = target_document.capacity() < desired_capacity ? target_document.allocate(desired_capacity) : SUCCESS;
+ error_code err2 = capacity() < desired_capacity ? allocate(desired_capacity, max_depth()) : SUCCESS;
+ if(err1 != SUCCESS) { return error = err1; }
+ if(err2 != SUCCESS) { return error = err2; }
+ }
+ return SUCCESS;
+}
+
+simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
+ if(max_capacity > MINIMAL_DOCUMENT_CAPACITY) {
+ _max_capacity = max_capacity;
+ } else {
+ _max_capacity = MINIMAL_DOCUMENT_CAPACITY;
+ }
+}
+
+} // namespace dom
+} // namespace simdjson
+
+#endif // SIMDJSON_PARSER_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/parser.h b/contrib/libs/simdjson/include/simdjson/dom/parser.h
new file mode 100644
index 0000000000..a22a1a68b1
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/parser.h
@@ -0,0 +1,650 @@
+#ifndef SIMDJSON_DOM_PARSER_H
+#define SIMDJSON_DOM_PARSER_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/document.h"
+
+namespace simdjson {
+
+namespace dom {
+
+/**
+ * A persistent document parser.
+ *
+ * The parser is designed to be reused, holding the internal buffers necessary to do parsing,
+ * as well as memory for a single document. The parsed document is overwritten on each parse.
+ *
+ * This class cannot be copied, only moved, to avoid unintended allocations.
+ *
+ * @note Moving a parser instance may invalidate "dom::element" instances. If you need to
+ * preserve both the "dom::element" instances and the parser, consider wrapping the parser
+ * instance in a std::unique_ptr instance:
+ *
+ * std::unique_ptr<dom::parser> parser(new dom::parser{});
+ * auto error = parser->load(f).get(root);
+ *
+ * You can then move std::unique_ptr safely.
+ *
+ * @note This is not thread safe: one parser cannot produce two documents at the same time!
+ */
+class parser {
+public:
+ /**
+ * Create a JSON parser.
+ *
+ * The new parser will have zero capacity.
+ *
+ * @param max_capacity The maximum document length the parser can automatically handle. The parser
+ * will allocate more capacity on an as needed basis (when it sees documents too big to handle)
+ * up to this amount. The parser still starts with zero capacity no matter what this number is:
+ * to allocate an initial capacity, call allocate() after constructing the parser.
+ * Defaults to SIMDJSON_MAXSIZE_BYTES (the largest single document simdjson can process).
+ */
+ simdjson_inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
+ /**
+ * Take another parser's buffers and state.
+ *
+ * @param other The parser to take. Its capacity is zeroed.
+ */
+ simdjson_inline parser(parser &&other) noexcept;
+ parser(const parser &) = delete; ///< @private Disallow copying
+ /**
+ * Take another parser's buffers and state.
+ *
+ * @param other The parser to take. Its capacity is zeroed.
+ */
+ simdjson_inline parser &operator=(parser &&other) noexcept;
+ parser &operator=(const parser &) = delete; ///< @private Disallow copying
+
+ /** Deallocate the JSON parser. */
+ ~parser()=default;
+
+ /**
+ * Load a JSON document from a file and return a reference to it.
+ *
+ * dom::parser parser;
+ * const element doc = parser.load("jsonexamples/twitter.json");
+ *
+ * The function is eager: the file's content is loaded in memory inside the parser instance
+ * and immediately parsed. The file can be deleted after the `parser.load` call.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * The JSON document still lives in the parser: this is the most efficient way to parse JSON
+ * documents because it reuses the same buffers, but you *must* use the document before you
+ * destroy the parser or call parse() again.
+ *
+ * Moving the parser instance is safe, but it invalidates the element instances. You may store
+ * the parser instance without moving it by wrapping it inside an `unique_ptr` instance like
+ * so: `std::unique_ptr<dom::parser> parser(new dom::parser{});`.
+ *
+ * ### Parser Capacity
+ *
+ * If the parser's current capacity is less than the file length, it will allocate enough capacity
+ * to handle it (up to max_capacity).
+ *
+ * ## Windows and Unicode
+ *
+ * Windows users who need to read files with non-ANSI characters in the
+ * name should set their code page to UTF-8 (65001) before calling this
+ * function. This should be the default with Windows 11 and better.
+ * Further, they may use the AreFileApisANSI function to determine whether
+ * the filename is interpreted using the ANSI or the system default OEM
+ * codepage, and they may call SetFileApisToOEM accordingly.
+ *
+ * @param path The path to load.
+ * @return The document, or an error:
+ * - IO_ERROR if there was an error opening or reading the file.
+ * Be mindful that on some 32-bit systems,
+ * the file size might be limited to 2 GB.
+ * - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
+ * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<element> load(const std::string &path) & noexcept;
+ inline simdjson_result<element> load(const std::string &path) && = delete ;
+
+ /**
+ * Load a JSON document from a file into a provide document instance and return a temporary reference to it.
+ * It is similar to the function `load` except that instead of parsing into the internal
+ * `document` instance associated with the parser, it allows the user to provide a document
+ * instance.
+ *
+ * dom::parser parser;
+ * dom::document doc;
+ * element doc_root = parser.load_into_document(doc, "jsonexamples/twitter.json");
+ *
+ * The function is eager: the file's content is loaded in memory inside the parser instance
+ * and immediately parsed. The file can be deleted after the `parser.load_into_document` call.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * After the call to load_into_document, the parser is no longer needed.
+ *
+ * The JSON document lives in the document instance: you must keep the document
+ * instance alive while you navigate through it (i.e., used the returned value from
+ * load_into_document). You are encourage to reuse the document instance
+ * many times with new data to avoid reallocations:
+ *
+ * dom::document doc;
+ * element doc_root1 = parser.load_into_document(doc, "jsonexamples/twitter.json");
+ * //... doc_root1 is a pointer inside doc
+ * element doc_root2 = parser.load_into_document(doc, "jsonexamples/twitter.json");
+ * //... doc_root2 is a pointer inside doc
+ * // at this point doc_root1 is no longer safe
+ *
+ * Moving the document instance is safe, but it invalidates the element instances. After
+ * moving a document, you can recover safe access to the document root with its `root()` method.
+ *
+ * @param doc The document instance where the parsed data will be stored (on success).
+ * @param path The path to load.
+ * @return The document, or an error:
+ * - IO_ERROR if there was an error opening or reading the file.
+ * Be mindful that on some 32-bit systems,
+ * the file size might be limited to 2 GB.
+ * - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
+ * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<element> load_into_document(document& doc, const std::string &path) & noexcept;
+ inline simdjson_result<element> load_into_document(document& doc, const std::string &path) && =delete;
+
+ /**
+ * Parse a JSON document and return a temporary reference to it.
+ *
+ * dom::parser parser;
+ * element doc_root = parser.parse(buf, len);
+ *
+ * The function eagerly parses the input: the input can be modified and discarded after
+ * the `parser.parse(buf, len)` call has completed.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * The JSON document still lives in the parser: this is the most efficient way to parse JSON
+ * documents because it reuses the same buffers, but you *must* use the document before you
+ * destroy the parser or call parse() again.
+ *
+ * Moving the parser instance is safe, but it invalidates the element instances. You may store
+ * the parser instance without moving it by wrapping it inside an `unique_ptr` instance like
+ * so: `std::unique_ptr<dom::parser> parser(new dom::parser{});`.
+ *
+ * ### REQUIRED: Buffer Padding
+ *
+ * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
+ * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
+ * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
+ * SIMDJSON_PADDING bytes to avoid runtime warnings.
+ *
+ * If realloc_if_needed is true (the default), it is assumed that the buffer does *not* have enough padding,
+ * and it is copied into an enlarged temporary buffer before parsing. Thus the following is safe:
+ *
+ * const char *json = R"({"key":"value"})";
+ * const size_t json_len = std::strlen(json);
+ * simdjson::dom::parser parser;
+ * simdjson::dom::element element = parser.parse(json, json_len);
+ *
+ * If you set realloc_if_needed to false (e.g., parser.parse(json, json_len, false)),
+ * you must provide a buffer with at least SIMDJSON_PADDING extra bytes at the end.
+ * The benefit of setting realloc_if_needed to false is that you avoid a temporary
+ * memory allocation and a copy.
+ *
+ * The padded bytes may be read. It is not important how you initialize
+ * these bytes though we recommend a sensible default like null character values or spaces.
+ * For example, the following low-level code is safe:
+ *
+ * const char *json = R"({"key":"value"})";
+ * const size_t json_len = std::strlen(json);
+ * std::unique_ptr<char[]> padded_json_copy{new char[json_len + SIMDJSON_PADDING]};
+ * std::memcpy(padded_json_copy.get(), json, json_len);
+ * std::memset(padded_json_copy.get() + json_len, '\0', SIMDJSON_PADDING);
+ * simdjson::dom::parser parser;
+ * simdjson::dom::element element = parser.parse(padded_json_copy.get(), json_len, false);
+ *
+ * ### Parser Capacity
+ *
+ * If the parser's current capacity is less than len, it will allocate enough capacity
+ * to handle it (up to max_capacity).
+ *
+ * @param buf The JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes, unless
+ * realloc_if_needed is true.
+ * @param len The length of the JSON.
+ * @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
+ * @return An element pointing at the root of the document, or an error:
+ * - MEMALLOC if realloc_if_needed is true or the parser does not have enough capacity,
+ * and memory allocation fails.
+ * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<element> parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) & noexcept;
+ inline simdjson_result<element> parse(const uint8_t *buf, size_t len, bool realloc_if_needed = true) && =delete;
+ /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse(const char *buf, size_t len, bool realloc_if_needed = true) & noexcept;
+ simdjson_inline simdjson_result<element> parse(const char *buf, size_t len, bool realloc_if_needed = true) && =delete;
+ /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse(const std::string &s) & noexcept;
+ simdjson_inline simdjson_result<element> parse(const std::string &s) && =delete;
+ /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse(const padded_string &s) & noexcept;
+ simdjson_inline simdjson_result<element> parse(const padded_string &s) && =delete;
+ /** @overload parse(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse(const padded_string_view &v) & noexcept;
+ simdjson_inline simdjson_result<element> parse(const padded_string_view &v) && =delete;
+
+ /** @private We do not want to allow implicit conversion from C string to std::string. */
+ simdjson_inline simdjson_result<element> parse(const char *buf) noexcept = delete;
+
+ /**
+ * Parse a JSON document into a provide document instance and return a temporary reference to it.
+ * It is similar to the function `parse` except that instead of parsing into the internal
+ * `document` instance associated with the parser, it allows the user to provide a document
+ * instance.
+ *
+ * dom::parser parser;
+ * dom::document doc;
+ * element doc_root = parser.parse_into_document(doc, buf, len);
+ *
+ * The function eagerly parses the input: the input can be modified and discarded after
+ * the `parser.parse(buf, len)` call has completed.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * After the call to parse_into_document, the parser is no longer needed.
+ *
+ * The JSON document lives in the document instance: you must keep the document
+ * instance alive while you navigate through it (i.e., used the returned value from
+ * parse_into_document). You are encourage to reuse the document instance
+ * many times with new data to avoid reallocations:
+ *
+ * dom::document doc;
+ * element doc_root1 = parser.parse_into_document(doc, buf1, len);
+ * //... doc_root1 is a pointer inside doc
+ * element doc_root2 = parser.parse_into_document(doc, buf1, len);
+ * //... doc_root2 is a pointer inside doc
+ * // at this point doc_root1 is no longer safe
+ *
+ * Moving the document instance is safe, but it invalidates the element instances. After
+ * moving a document, you can recover safe access to the document root with its `root()` method.
+ *
+ * @param doc The document instance where the parsed data will be stored (on success).
+ * @param buf The JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes, unless
+ * realloc_if_needed is true.
+ * @param len The length of the JSON.
+ * @param realloc_if_needed Whether to reallocate and enlarge the JSON buffer to add padding.
+ * @return An element pointing at the root of document, or an error:
+ * - MEMALLOC if realloc_if_needed is true or the parser does not have enough capacity,
+ * and memory allocation fails.
+ * - CAPACITY if the parser does not have enough capacity and len > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<element> parse_into_document(document& doc, const uint8_t *buf, size_t len, bool realloc_if_needed = true) & noexcept;
+ inline simdjson_result<element> parse_into_document(document& doc, const uint8_t *buf, size_t len, bool realloc_if_needed = true) && =delete;
+ /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf, size_t len, bool realloc_if_needed = true) & noexcept;
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf, size_t len, bool realloc_if_needed = true) && =delete;
+ /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const std::string &s) & noexcept;
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const std::string &s) && =delete;
+ /** @overload parse_into_document(const uint8_t *buf, size_t len, bool realloc_if_needed) */
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const padded_string &s) & noexcept;
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const padded_string &s) && =delete;
+
+ /** @private We do not want to allow implicit conversion from C string to std::string. */
+ simdjson_inline simdjson_result<element> parse_into_document(document& doc, const char *buf) noexcept = delete;
+
+ /**
+ * Load a file containing many JSON documents.
+ *
+ * dom::parser parser;
+ * for (const element doc : parser.load_many(path)) {
+ * cout << std::string(doc["title"]) << endl;
+ * }
+ *
+ * The file is loaded in memory and can be safely deleted after the `parser.load_many(path)`
+ * function has returned. The memory is held by the `parser` instance.
+ *
+ * The function is lazy: it may be that no more than one JSON document at a time is parsed.
+ * And, possibly, no document many have been parsed when the `parser.load_many(path)` function
+ * returned.
+ *
+ * If there is a UTF-8 BOM, the parser skips it.
+ *
+ * ### Format
+ *
+ * The file must contain a series of one or more JSON documents, concatenated into a single
+ * buffer, separated by whitespace. It effectively parses until it has a fully valid document,
+ * then starts parsing the next document at that point. (It does this with more parallelism and
+ * lookahead than you might think, though.)
+ *
+ * Documents that consist of an object or array may omit the whitespace between them, concatenating
+ * with no separator. documents that consist of a single primitive (i.e. documents that are not
+ * arrays or objects) MUST be separated with whitespace.
+ *
+ * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
+ * Setting batch_size to excessively large or excesively small values may impact negatively the
+ * performance.
+ *
+ * ### Error Handling
+ *
+ * All errors are returned during iteration: if there is a global error such as memory allocation,
+ * it will be yielded as the first result. Iteration always stops after the first error.
+ *
+ * As with all other simdjson methods, non-exception error handling is readily available through
+ * the same interface, requiring you to check the error before using the document:
+ *
+ * dom::parser parser;
+ * dom::document_stream docs;
+ * auto error = parser.load_many(path).get(docs);
+ * if (error) { cerr << error << endl; exit(1); }
+ * for (auto doc : docs) {
+ * std::string_view title;
+ * if ((error = doc["title"].get(title)) { cerr << error << endl; exit(1); }
+ * cout << title << endl;
+ * }
+ *
+ * ### Threads
+ *
+ * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
+ * hood to do some lookahead.
+ *
+ * ### Parser Capacity
+ *
+ * If the parser's current capacity is less than batch_size, it will allocate enough capacity
+ * to handle it (up to max_capacity).
+ *
+ * @param path File name pointing at the concatenated JSON to parse.
+ * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
+ * spot is cache-related: small enough to fit in cache, yet big enough to
+ * parse as many documents as possible in one tight loop.
+ * Defaults to 1MB (as simdjson::dom::DEFAULT_BATCH_SIZE), which has been a reasonable sweet
+ * spot in our tests.
+ * If you set the batch_size to a value smaller than simdjson::dom::MINIMAL_BATCH_SIZE
+ * (currently 32B), it will be replaced by simdjson::dom::MINIMAL_BATCH_SIZE.
+ * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
+ * - IO_ERROR if there was an error opening or reading the file.
+ * - MEMALLOC if the parser does not have enough capacity and memory allocation fails.
+ * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<document_stream> load_many(const std::string &path, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
+
+ /**
+ * Parse a buffer containing many JSON documents.
+ *
+ * dom::parser parser;
+ * for (element doc : parser.parse_many(buf, len)) {
+ * cout << std::string(doc["title"]) << endl;
+ * }
+ *
+ * No copy of the input buffer is made.
+ *
+ * The function is lazy: it may be that no more than one JSON document at a time is parsed.
+ * And, possibly, no document many have been parsed when the `parser.load_many(path)` function
+ * returned.
+ *
+ * The caller is responsabile to ensure that the input string data remains unchanged and is
+ * not deleted during the loop. In particular, the following is unsafe and will not compile:
+ *
+ * auto docs = parser.parse_many("[\"temporary data\"]"_padded);
+ * // here the string "[\"temporary data\"]" may no longer exist in memory
+ * // the parser instance may not have even accessed the input yet
+ * for (element doc : docs) {
+ * cout << std::string(doc["title"]) << endl;
+ * }
+ *
+ * The following is safe:
+ *
+ * auto json = "[\"temporary data\"]"_padded;
+ * auto docs = parser.parse_many(json);
+ * for (element doc : docs) {
+ * cout << std::string(doc["title"]) << endl;
+ * }
+ *
+ * If there is a UTF-8 BOM, the parser skips it.
+ *
+ * ### Format
+ *
+ * The buffer must contain a series of one or more JSON documents, concatenated into a single
+ * buffer, separated by whitespace. It effectively parses until it has a fully valid document,
+ * then starts parsing the next document at that point. (It does this with more parallelism and
+ * lookahead than you might think, though.)
+ *
+ * documents that consist of an object or array may omit the whitespace between them, concatenating
+ * with no separator. documents that consist of a single primitive (i.e. documents that are not
+ * arrays or objects) MUST be separated with whitespace.
+ *
+ * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
+ * Setting batch_size to excessively large or excesively small values may impact negatively the
+ * performance.
+ *
+ * ### Error Handling
+ *
+ * All errors are returned during iteration: if there is a global error such as memory allocation,
+ * it will be yielded as the first result. Iteration always stops after the first error.
+ *
+ * As with all other simdjson methods, non-exception error handling is readily available through
+ * the same interface, requiring you to check the error before using the document:
+ *
+ * dom::parser parser;
+ * dom::document_stream docs;
+ * auto error = parser.load_many(path).get(docs);
+ * if (error) { cerr << error << endl; exit(1); }
+ * for (auto doc : docs) {
+ * std::string_view title;
+ * if ((error = doc["title"].get(title)) { cerr << error << endl; exit(1); }
+ * cout << title << endl;
+ * }
+ *
+ * ### REQUIRED: Buffer Padding
+ *
+ * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
+ * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
+ * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
+ * SIMDJSON_PADDING bytes to avoid runtime warnings.
+ *
+ * ### Threads
+ *
+ * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
+ * hood to do some lookahead.
+ *
+ * ### Parser Capacity
+ *
+ * If the parser's current capacity is less than batch_size, it will allocate enough capacity
+ * to handle it (up to max_capacity).
+ *
+ * @param buf The concatenated JSON to parse. Must have at least len + SIMDJSON_PADDING allocated bytes.
+ * @param len The length of the concatenated JSON.
+ * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
+ * spot is cache-related: small enough to fit in cache, yet big enough to
+ * parse as many documents as possible in one tight loop.
+ * Defaults to 10MB, which has been a reasonable sweet spot in our tests.
+ * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
+ * - MEMALLOC if the parser does not have enough capacity and memory allocation fails
+ * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<document_stream> parse_many(const uint8_t *buf, size_t len, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> parse_many(const char *buf, size_t len, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> parse_many(const std::string &s, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
+ inline simdjson_result<document_stream> parse_many(const std::string &&s, size_t batch_size) = delete;// unsafe
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> parse_many(const padded_string &s, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept;
+ inline simdjson_result<document_stream> parse_many(const padded_string &&s, size_t batch_size) = delete;// unsafe
+
+ /** @private We do not want to allow implicit conversion from C string to std::string. */
+ simdjson_result<document_stream> parse_many(const char *buf, size_t batch_size = dom::DEFAULT_BATCH_SIZE) noexcept = delete;
+
+ /**
+ * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
+ * and `max_depth` depth.
+ *
+ * @param capacity The new capacity.
+ * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
+ * @return The error, if there is one.
+ */
+ simdjson_warn_unused inline error_code allocate(size_t capacity, size_t max_depth = DEFAULT_MAX_DEPTH) noexcept;
+
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+ /**
+ * @private deprecated because it returns bool instead of error_code, which is our standard for
+ * failures. Use allocate() instead.
+ *
+ * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
+ * and `max_depth` depth.
+ *
+ * @param capacity The new capacity.
+ * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
+ * @return true if successful, false if allocation failed.
+ */
+ [[deprecated("Use allocate() instead.")]]
+ simdjson_warn_unused inline bool allocate_capacity(size_t capacity, size_t max_depth = DEFAULT_MAX_DEPTH) noexcept;
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+ /**
+ * The largest document this parser can support without reallocating.
+ *
+ * @return Current capacity, in bytes.
+ */
+ simdjson_inline size_t capacity() const noexcept;
+
+ /**
+ * The largest document this parser can automatically support.
+ *
+ * The parser may reallocate internal buffers as needed up to this amount.
+ *
+ * @return Maximum capacity, in bytes.
+ */
+ simdjson_inline size_t max_capacity() const noexcept;
+
+ /**
+ * The maximum level of nested object and arrays supported by this parser.
+ *
+ * @return Maximum depth, in bytes.
+ */
+ simdjson_pure simdjson_inline size_t max_depth() const noexcept;
+
+ /**
+ * Set max_capacity. This is the largest document this parser can automatically support.
+ *
+ * The parser may reallocate internal buffers as needed up to this amount as documents are passed
+ * to it.
+ *
+ * Note: To avoid limiting the memory to an absurd value, such as zero or two bytes,
+ * iff you try to set max_capacity to a value lower than MINIMAL_DOCUMENT_CAPACITY,
+ * then the maximal capacity is set to MINIMAL_DOCUMENT_CAPACITY.
+ *
+ * This call will not allocate or deallocate, even if capacity is currently above max_capacity.
+ *
+ * @param max_capacity The new maximum capacity, in bytes.
+ */
+ simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
+
+#ifdef SIMDJSON_THREADS_ENABLED
+ /**
+ * The parser instance can use threads when they are available to speed up some
+ * operations. It is enabled by default. Changing this attribute will change the
+ * behavior of the parser for future operations.
+ */
+ bool threaded{true};
+#endif
+ /** @private Use the new DOM API instead */
+ class Iterator;
+ /** @private Use simdjson_error instead */
+ using InvalidJSON [[deprecated("Use simdjson_error instead")]] = simdjson_error;
+
+ /** @private [for benchmarking access] The implementation to use */
+ std::unique_ptr<internal::dom_parser_implementation> implementation{};
+
+ /** @private Use `if (parser.parse(...).error())` instead */
+ bool valid{false};
+ /** @private Use `parser.parse(...).error()` instead */
+ error_code error{UNINITIALIZED};
+
+ /** @private Use `parser.parse(...).value()` instead */
+ document doc{};
+
+ /** @private returns true if the document parsed was valid */
+ [[deprecated("Use the result of parser.parse() instead")]]
+ inline bool is_valid() const noexcept;
+
+ /**
+ * @private return an error code corresponding to the last parsing attempt, see
+ * simdjson.h will return UNINITIALIZED if no parsing was attempted
+ */
+ [[deprecated("Use the result of parser.parse() instead")]]
+ inline int get_error_code() const noexcept;
+
+ /** @private return the string equivalent of "get_error_code" */
+ [[deprecated("Use error_message() on the result of parser.parse() instead, or cout << error")]]
+ inline std::string get_error_message() const noexcept;
+
+ /** @private */
+ [[deprecated("Use cout << on the result of parser.parse() instead")]]
+ inline bool print_json(std::ostream &os) const noexcept;
+
+ /** @private Private and deprecated: use `parser.parse(...).doc.dump_raw_tape()` instead */
+ inline bool dump_raw_tape(std::ostream &os) const noexcept;
+
+
+private:
+ /**
+ * The maximum document length this parser will automatically support.
+ *
+ * The parser will not be automatically allocated above this amount.
+ */
+ size_t _max_capacity;
+
+ /**
+ * The loaded buffer (reused each time load() is called)
+ */
+ std::unique_ptr<char[]> loaded_bytes;
+
+ /** Capacity of loaded_bytes buffer. */
+ size_t _loaded_bytes_capacity{0};
+
+ // all nodes are stored on the doc.tape using a 64-bit word.
+ //
+ // strings, double and ints are stored as
+ // a 64-bit word with a pointer to the actual value
+ //
+ //
+ //
+ // for objects or arrays, store [ or { at the beginning and } and ] at the
+ // end. For the openings ([ or {), we annotate them with a reference to the
+ // location on the doc.tape of the end, and for then closings (} and ]), we
+ // annotate them with a reference to the location of the opening
+ //
+ //
+
+ /**
+ * Ensure we have enough capacity to handle at least desired_capacity bytes,
+ * and auto-allocate if not. This also allocates memory if needed in the
+ * internal document.
+ */
+ inline error_code ensure_capacity(size_t desired_capacity) noexcept;
+ /**
+ * Ensure we have enough capacity to handle at least desired_capacity bytes,
+ * and auto-allocate if not. This also allocates memory if needed in the
+ * provided document.
+ */
+ inline error_code ensure_capacity(document& doc, size_t desired_capacity) noexcept;
+
+ /** Read the file into loaded_bytes */
+ inline simdjson_result<size_t> read_file(const std::string &path) noexcept;
+
+ friend class parser::Iterator;
+ friend class document_stream;
+
+
+}; // class parser
+
+} // namespace dom
+} // namespace simdjson
+
+#endif // SIMDJSON_DOM_PARSER_H
diff --git a/contrib/libs/simdjson/include/simdjson/dom/serialization-inl.h b/contrib/libs/simdjson/include/simdjson/dom/serialization-inl.h
new file mode 100644
index 0000000000..0c52a26cb1
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/serialization-inl.h
@@ -0,0 +1,536 @@
+
+#ifndef SIMDJSON_SERIALIZATION_INL_H
+#define SIMDJSON_SERIALIZATION_INL_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/serialization.h"
+#include "simdjson/dom/parser.h"
+#include "simdjson/internal/tape_type.h"
+
+#include "simdjson/dom/array-inl.h"
+#include "simdjson/dom/object-inl.h"
+#include "simdjson/internal/tape_ref-inl.h"
+
+#include <cstring>
+
+namespace simdjson {
+namespace dom {
+inline bool parser::print_json(std::ostream &os) const noexcept {
+ if (!valid) { return false; }
+ simdjson::internal::string_builder<> sb;
+ sb.append(doc.root());
+ std::string_view answer = sb.str();
+ os << answer;
+ return true;
+}
+
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value) {
+ simdjson::internal::string_builder<> sb;
+ sb.append(value);
+ return (out << sb.str());
+}
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#endif
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value) {
+ simdjson::internal::string_builder<> sb;
+ sb.append(value);
+ return (out << sb.str());
+}
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#endif
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value) {
+ simdjson::internal::string_builder<> sb;
+ sb.append(value);
+ return (out << sb.str());
+}
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#endif
+
+} // namespace dom
+
+/***
+ * Number utility functions
+ **/
+namespace {
+/**@private
+ * Escape sequence like \b or \u0001
+ * We expect that most compilers will use 8 bytes for this data structure.
+ **/
+struct escape_sequence {
+ uint8_t length;
+ const char string[7]; // technically, we only ever need 6 characters, we pad to 8
+};
+/**@private
+ * This converts a signed integer into a character sequence.
+ * The caller is responsible for providing enough memory (at least
+ * 20 characters.)
+ * Though various runtime libraries provide itoa functions,
+ * it is not part of the C++ standard. The C++17 standard
+ * adds the to_chars functions which would do as well, but
+ * we want to support C++11.
+ */
+static char *fast_itoa(char *output, int64_t value) noexcept {
+ // This is a standard implementation of itoa.
+ char buffer[20];
+ uint64_t value_positive;
+ // In general, negating a signed integer is unsafe.
+ if(value < 0) {
+ *output++ = '-';
+ // Doing value_positive = -value; while avoiding
+ // undefined behavior warnings.
+ // It assumes two complement's which is universal at this
+ // point in time.
+ std::memcpy(&value_positive, &value, sizeof(value));
+ value_positive = (~value_positive) + 1; // this is a negation
+ } else {
+ value_positive = value;
+ }
+ // We work solely with value_positive. It *might* be easier
+ // for an optimizing compiler to deal with an unsigned variable
+ // as far as performance goes.
+ const char *const end_buffer = buffer + 20;
+ char *write_pointer = buffer + 19;
+ // A faster approach is possible if we expect large integers:
+ // unroll the loop (work in 100s, 1000s) and use some kind of
+ // memoization.
+ while(value_positive >= 10) {
+ *write_pointer-- = char('0' + (value_positive % 10));
+ value_positive /= 10;
+ }
+ *write_pointer = char('0' + value_positive);
+ size_t len = end_buffer - write_pointer;
+ std::memcpy(output, write_pointer, len);
+ return output + len;
+}
+/**@private
+ * This converts an unsigned integer into a character sequence.
+ * The caller is responsible for providing enough memory (at least
+ * 19 characters.)
+ * Though various runtime libraries provide itoa functions,
+ * it is not part of the C++ standard. The C++17 standard
+ * adds the to_chars functions which would do as well, but
+ * we want to support C++11.
+ */
+static char *fast_itoa(char *output, uint64_t value) noexcept {
+ // This is a standard implementation of itoa.
+ char buffer[20];
+ const char *const end_buffer = buffer + 20;
+ char *write_pointer = buffer + 19;
+ // A faster approach is possible if we expect large integers:
+ // unroll the loop (work in 100s, 1000s) and use some kind of
+ // memoization.
+ while(value >= 10) {
+ *write_pointer-- = char('0' + (value % 10));
+ value /= 10;
+ };
+ *write_pointer = char('0' + value);
+ size_t len = end_buffer - write_pointer;
+ std::memcpy(output, write_pointer, len);
+ return output + len;
+}
+
+
+} // anonymous namespace
+namespace internal {
+
+/***
+ * Minifier/formatter code.
+ **/
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::number(uint64_t x) {
+ char number_buffer[24];
+ char *newp = fast_itoa(number_buffer, x);
+ buffer.insert(buffer.end(), number_buffer, newp);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::number(int64_t x) {
+ char number_buffer[24];
+ char *newp = fast_itoa(number_buffer, x);
+ buffer.insert(buffer.end(), number_buffer, newp);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::number(double x) {
+ char number_buffer[24];
+ // Currently, passing the nullptr to the second argument is
+ // safe because our implementation does not check the second
+ // argument.
+ char *newp = internal::to_chars(number_buffer, nullptr, x);
+ buffer.insert(buffer.end(), number_buffer, newp);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::start_array() { one_char('['); }
+
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::end_array() { one_char(']'); }
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::start_object() { one_char('{'); }
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::end_object() { one_char('}'); }
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::comma() { one_char(','); }
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::true_atom() {
+ const char * s = "true";
+ buffer.insert(buffer.end(), s, s + 4);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::false_atom() {
+ const char * s = "false";
+ buffer.insert(buffer.end(), s, s + 5);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::null_atom() {
+ const char * s = "null";
+ buffer.insert(buffer.end(), s, s + 4);
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::one_char(char c) { buffer.push_back(c); }
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::key(std::string_view unescaped) {
+ string(unescaped);
+ one_char(':');
+}
+
+template<class formatter>
+simdjson_inline void base_formatter<formatter>::string(std::string_view unescaped) {
+ one_char('\"');
+ size_t i = 0;
+ // Fast path for the case where we have no control character, no ", and no backslash.
+ // This should include most keys.
+ //
+ // We would like to use 'bool' but some compilers take offense to bitwise operation
+ // with bool types.
+ constexpr static char needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ for(;i + 8 <= unescaped.length(); i += 8) {
+ // Poor's man vectorization. This could get much faster if we used SIMD.
+ //
+ // It is not the case that replacing '|' with '||' would be neutral performance-wise.
+ if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
+ | needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
+ | needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
+ | needs_escaping[uint8_t(unescaped[i+6])] | needs_escaping[uint8_t(unescaped[i+7])]
+ ) { break; }
+ }
+ for(;i < unescaped.length(); i++) {
+ if(needs_escaping[uint8_t(unescaped[i])]) { break; }
+ }
+ // The following is also possible and omits a 256-byte table, but it is slower:
+ // for (; (i < unescaped.length()) && (uint8_t(unescaped[i]) > 0x1F)
+ // && (unescaped[i] != '\"') && (unescaped[i] != '\\'); i++) {}
+
+ // At least for long strings, the following should be fast. We could
+ // do better by integrating the checks and the insertion.
+ buffer.insert(buffer.end(), unescaped.data(), unescaped.data() + i);
+ // We caught a control character if we enter this loop (slow).
+ // Note that we are do not restart from the beginning, but rather we continue
+ // from the point where we encountered something that requires escaping.
+ for (; i < unescaped.length(); i++) {
+ switch (unescaped[i]) {
+ case '\"':
+ {
+ const char * s = "\\\"";
+ buffer.insert(buffer.end(), s, s + 2);
+ }
+ break;
+ case '\\':
+ {
+ const char * s = "\\\\";
+ buffer.insert(buffer.end(), s, s + 2);
+ }
+ break;
+ default:
+ if (uint8_t(unescaped[i]) <= 0x1F) {
+ // If packed, this uses 8 * 32 bytes.
+ // Note that we expect most compilers to embed this code in the data
+ // section.
+ constexpr static escape_sequence escaped[32] = {
+ {6, "\\u0000"}, {6, "\\u0001"}, {6, "\\u0002"}, {6, "\\u0003"},
+ {6, "\\u0004"}, {6, "\\u0005"}, {6, "\\u0006"}, {6, "\\u0007"},
+ {2, "\\b"}, {2, "\\t"}, {2, "\\n"}, {6, "\\u000b"},
+ {2, "\\f"}, {2, "\\r"}, {6, "\\u000e"}, {6, "\\u000f"},
+ {6, "\\u0010"}, {6, "\\u0011"}, {6, "\\u0012"}, {6, "\\u0013"},
+ {6, "\\u0014"}, {6, "\\u0015"}, {6, "\\u0016"}, {6, "\\u0017"},
+ {6, "\\u0018"}, {6, "\\u0019"}, {6, "\\u001a"}, {6, "\\u001b"},
+ {6, "\\u001c"}, {6, "\\u001d"}, {6, "\\u001e"}, {6, "\\u001f"}};
+ auto u = escaped[uint8_t(unescaped[i])];
+ buffer.insert(buffer.end(), u.string, u.string + u.length);
+ } else {
+ one_char(unescaped[i]);
+ }
+ } // switch
+ } // for
+ one_char('\"');
+}
+
+
+template<class formatter>
+inline void base_formatter<formatter>::clear() {
+ buffer.clear();
+}
+
+template<class formatter>
+simdjson_inline std::string_view base_formatter<formatter>::str() const {
+ return std::string_view(buffer.data(), buffer.size());
+}
+
+simdjson_inline void mini_formatter::print_newline() {
+ return;
+}
+
+simdjson_inline void mini_formatter::print_indents(size_t depth) {
+ (void)depth;
+ return;
+}
+
+simdjson_inline void mini_formatter::print_space() {
+ return;
+}
+
+simdjson_inline void pretty_formatter::print_newline() {
+ one_char('\n');
+}
+
+simdjson_inline void pretty_formatter::print_indents(size_t depth) {
+ if(this->indent_step <= 0) {
+ return;
+ }
+ for(size_t i = 0; i < this->indent_step * depth; i++) {
+ one_char(' ');
+ }
+}
+
+simdjson_inline void pretty_formatter::print_space() {
+ one_char(' ');
+}
+
+/***
+ * String building code.
+ **/
+
+template <class serializer>
+inline void string_builder<serializer>::append(simdjson::dom::element value) {
+ // using tape_type = simdjson::internal::tape_type;
+ size_t depth = 0;
+ constexpr size_t MAX_DEPTH = 16;
+ bool is_object[MAX_DEPTH];
+ is_object[0] = false;
+ bool after_value = false;
+
+ internal::tape_ref iter(value.tape);
+ do {
+ // print commas after each value
+ if (after_value) {
+ format.comma();
+ format.print_newline();
+ }
+
+ format.print_indents(depth);
+
+ // If we are in an object, print the next key and :, and skip to the next
+ // value.
+ if (is_object[depth]) {
+ format.key(iter.get_string_view());
+ format.print_space();
+ iter.json_index++;
+ }
+ switch (iter.tape_ref_type()) {
+
+ // Arrays
+ case tape_type::START_ARRAY: {
+ // If we're too deep, we need to recurse to go deeper.
+ depth++;
+ if (simdjson_unlikely(depth >= MAX_DEPTH)) {
+ append(simdjson::dom::array(iter));
+ iter.json_index = iter.matching_brace_index() - 1; // Jump to the ]
+ depth--;
+ break;
+ }
+
+ // Output start [
+ format.start_array();
+ iter.json_index++;
+
+ // Handle empty [] (we don't want to come back around and print commas)
+ if (iter.tape_ref_type() == tape_type::END_ARRAY) {
+ format.end_array();
+ depth--;
+ break;
+ }
+
+ is_object[depth] = false;
+ after_value = false;
+ format.print_newline();
+ continue;
+ }
+
+ // Objects
+ case tape_type::START_OBJECT: {
+ // If we're too deep, we need to recurse to go deeper.
+ depth++;
+ if (simdjson_unlikely(depth >= MAX_DEPTH)) {
+ append(simdjson::dom::object(iter));
+ iter.json_index = iter.matching_brace_index() - 1; // Jump to the }
+ depth--;
+ break;
+ }
+
+ // Output start {
+ format.start_object();
+ iter.json_index++;
+
+ // Handle empty {} (we don't want to come back around and print commas)
+ if (iter.tape_ref_type() == tape_type::END_OBJECT) {
+ format.end_object();
+ depth--;
+ break;
+ }
+
+ is_object[depth] = true;
+ after_value = false;
+ format.print_newline();
+ continue;
+ }
+
+ // Scalars
+ case tape_type::STRING:
+ format.string(iter.get_string_view());
+ break;
+ case tape_type::INT64:
+ format.number(iter.next_tape_value<int64_t>());
+ iter.json_index++; // numbers take up 2 spots, so we need to increment
+ // extra
+ break;
+ case tape_type::UINT64:
+ format.number(iter.next_tape_value<uint64_t>());
+ iter.json_index++; // numbers take up 2 spots, so we need to increment
+ // extra
+ break;
+ case tape_type::DOUBLE:
+ format.number(iter.next_tape_value<double>());
+ iter.json_index++; // numbers take up 2 spots, so we need to increment
+ // extra
+ break;
+ case tape_type::TRUE_VALUE:
+ format.true_atom();
+ break;
+ case tape_type::FALSE_VALUE:
+ format.false_atom();
+ break;
+ case tape_type::NULL_VALUE:
+ format.null_atom();
+ break;
+
+ // These are impossible
+ case tape_type::END_ARRAY:
+ case tape_type::END_OBJECT:
+ case tape_type::ROOT:
+ SIMDJSON_UNREACHABLE();
+ }
+ iter.json_index++;
+ after_value = true;
+
+ // Handle multiple ends in a row
+ while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
+ iter.tape_ref_type() == tape_type::END_OBJECT)) {
+ format.print_newline();
+ depth--;
+ format.print_indents(depth);
+ if (iter.tape_ref_type() == tape_type::END_ARRAY) {
+ format.end_array();
+ } else {
+ format.end_object();
+ }
+ iter.json_index++;
+ }
+
+ // Stop when we're at depth 0
+ } while (depth != 0);
+
+ format.print_newline();
+}
+
+template <class serializer>
+inline void string_builder<serializer>::append(simdjson::dom::object value) {
+ format.start_object();
+ auto pair = value.begin();
+ auto end = value.end();
+ if (pair != end) {
+ append(*pair);
+ for (++pair; pair != end; ++pair) {
+ format.comma();
+ append(*pair);
+ }
+ }
+ format.end_object();
+}
+
+template <class serializer>
+inline void string_builder<serializer>::append(simdjson::dom::array value) {
+ format.start_array();
+ auto iter = value.begin();
+ auto end = value.end();
+ if (iter != end) {
+ append(*iter);
+ for (++iter; iter != end; ++iter) {
+ format.comma();
+ append(*iter);
+ }
+ }
+ format.end_array();
+}
+
+template <class serializer>
+simdjson_inline void string_builder<serializer>::append(simdjson::dom::key_value_pair kv) {
+ format.key(kv.key);
+ append(kv.value);
+}
+
+template <class serializer>
+simdjson_inline void string_builder<serializer>::clear() {
+ format.clear();
+}
+
+template <class serializer>
+simdjson_inline std::string_view string_builder<serializer>::str() const {
+ return format.str();
+}
+
+
+} // namespace internal
+} // namespace simdjson
+
+#endif
diff --git a/contrib/libs/simdjson/include/simdjson/dom/serialization.h b/contrib/libs/simdjson/include/simdjson/dom/serialization.h
new file mode 100644
index 0000000000..87c735bbbd
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/dom/serialization.h
@@ -0,0 +1,260 @@
+#ifndef SIMDJSON_SERIALIZATION_H
+#define SIMDJSON_SERIALIZATION_H
+
+#include "simdjson/dom/base.h"
+#include "simdjson/dom/element.h"
+#include "simdjson/dom/object.h"
+
+#include <vector>
+
+namespace simdjson {
+
+/**
+ * The string_builder template and mini_formatter class
+ * are not part of our public API and are subject to change
+ * at any time!
+ */
+namespace internal {
+
+template<class formatter>
+class base_formatter {
+public:
+ /** Add a comma **/
+ simdjson_inline void comma();
+ /** Start an array, prints [ **/
+ simdjson_inline void start_array();
+ /** End an array, prints ] **/
+ simdjson_inline void end_array();
+ /** Start an array, prints { **/
+ simdjson_inline void start_object();
+ /** Start an array, prints } **/
+ simdjson_inline void end_object();
+ /** Prints a true **/
+ simdjson_inline void true_atom();
+ /** Prints a false **/
+ simdjson_inline void false_atom();
+ /** Prints a null **/
+ simdjson_inline void null_atom();
+ /** Prints a number **/
+ simdjson_inline void number(int64_t x);
+ /** Prints a number **/
+ simdjson_inline void number(uint64_t x);
+ /** Prints a number **/
+ simdjson_inline void number(double x);
+ /** Prints a key (string + colon) **/
+ simdjson_inline void key(std::string_view unescaped);
+ /** Prints a string. The string is escaped as needed. **/
+ simdjson_inline void string(std::string_view unescaped);
+ /** Clears out the content. **/
+ simdjson_inline void clear();
+ /**
+ * Get access to the buffer, it is owned by the instance, but
+ * the user can make a copy.
+ **/
+ simdjson_inline std::string_view str() const;
+
+ /** Prints one character **/
+ simdjson_inline void one_char(char c);
+
+ simdjson_inline void call_print_newline() {
+ static_cast<formatter*>(this)->print_newline();
+ }
+
+ simdjson_inline void call_print_indents(size_t depth) {
+ static_cast<formatter*>(this)->print_indents(depth);
+ }
+
+ simdjson_inline void call_print_space() {
+ static_cast<formatter*>(this)->print_space();
+ }
+
+protected:
+ // implementation details (subject to change)
+ /** Backing buffer **/
+ std::vector<char> buffer{}; // not ideal!
+};
+
+
+/**
+ * @private This is the class that we expect to use with the string_builder
+ * template. It tries to produce a compact version of the JSON element
+ * as quickly as possible.
+ */
+class mini_formatter : public base_formatter<mini_formatter> {
+public:
+ simdjson_inline void print_newline();
+
+ simdjson_inline void print_indents(size_t depth);
+
+ simdjson_inline void print_space();
+};
+
+class pretty_formatter : public base_formatter<pretty_formatter> {
+public:
+ simdjson_inline void print_newline();
+
+ simdjson_inline void print_indents(size_t depth);
+
+ simdjson_inline void print_space();
+
+protected:
+ int indent_step = 4;
+};
+
+/**
+ * @private The string_builder template allows us to construct
+ * a string from a document element. It is parametrized
+ * by a "formatter" which handles the details. Thus
+ * the string_builder template could support both minification
+ * and prettification, and various other tradeoffs.
+ */
+template <class formatter = mini_formatter>
+class string_builder {
+public:
+ /** Construct an initially empty builder, would print the empty string **/
+ string_builder() = default;
+ /** Append an element to the builder (to be printed) **/
+ inline void append(simdjson::dom::element value);
+ /** Append an array to the builder (to be printed) **/
+ inline void append(simdjson::dom::array value);
+ /** Append an object to the builder (to be printed) **/
+ inline void append(simdjson::dom::object value);
+ /** Reset the builder (so that it would print the empty string) **/
+ simdjson_inline void clear();
+ /**
+ * Get access to the string. The string_view is owned by the builder
+ * and it is invalid to use it after the string_builder has been
+ * destroyed.
+ * However you can make a copy of the string_view on memory that you
+ * own.
+ */
+ simdjson_inline std::string_view str() const;
+ /** Append a key_value_pair to the builder (to be printed) **/
+ simdjson_inline void append(simdjson::dom::key_value_pair value);
+private:
+ formatter format{};
+};
+
+} // internal
+
+namespace dom {
+
+/**
+ * Print JSON to an output stream.
+ *
+ * @param out The output stream.
+ * @param value The element.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::element value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::element> x);
+#endif
+/**
+ * Print JSON to an output stream.
+ *
+ * @param out The output stream.
+ * @param value The array.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::array value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::array> x);
+#endif
+/**
+ * Print JSON to an output stream.
+ *
+ * @param out The output stream.
+ * @param value The object.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::dom::object value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::dom::object> x);
+#endif
+} // namespace dom
+
+/**
+ * Converts JSON to a string.
+ *
+ * dom::parser parser;
+ * element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
+ * cout << to_string(doc) << endl; // prints [1,2,3]
+ *
+ */
+template <class T>
+std::string to_string(T x) {
+ // in C++, to_string is standard: http://www.cplusplus.com/reference/string/to_string/
+ // Currently minify and to_string are identical but in the future, they may
+ // differ.
+ simdjson::internal::string_builder<> sb;
+ sb.append(x);
+ std::string_view answer = sb.str();
+ return std::string(answer.data(), answer.size());
+}
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+std::string to_string(simdjson_result<T> x) {
+ if (x.error()) { throw simdjson_error(x.error()); }
+ return to_string(x.value());
+}
+#endif
+
+/**
+ * Minifies a JSON element or document, printing the smallest possible valid JSON.
+ *
+ * dom::parser parser;
+ * element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
+ * cout << minify(doc) << endl; // prints [1,2,3]
+ *
+ */
+template <class T>
+std::string minify(T x) {
+ return to_string(x);
+}
+
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+std::string minify(simdjson_result<T> x) {
+ if (x.error()) { throw simdjson_error(x.error()); }
+ return to_string(x.value());
+}
+#endif
+
+/**
+ * Prettifies a JSON element or document, printing the valid JSON with indentation.
+ *
+ * dom::parser parser;
+ * element doc = parser.parse(" [ 1 , 2 , 3 ] "_padded);
+ *
+ * // Prints:
+ * // {
+ * // [
+ * // 1,
+ * // 2,
+ * // 3
+ * // ]
+ * // }
+ * cout << prettify(doc) << endl;
+ *
+ */
+template <class T>
+std::string prettify(T x) {
+ simdjson::internal::string_builder<simdjson::internal::pretty_formatter> sb;
+ sb.append(x);
+ std::string_view answer = sb.str();
+ return std::string(answer.data(), answer.size());
+}
+
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+std::string prettify(simdjson_result<T> x) {
+ if (x.error()) { throw simdjson_error(x.error()); }
+ return to_string(x.value());
+}
+#endif
+
+} // namespace simdjson
+
+
+#endif
diff --git a/contrib/libs/simdjson/include/simdjson/fallback/ondemand.h b/contrib/libs/simdjson/include/simdjson/fallback/ondemand.h
new file mode 100644
index 0000000000..513b7483fd
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/fallback/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_FALLBACK_ONDEMAND_H
+#define SIMDJSON_FALLBACK_ONDEMAND_H
+
+#include "simdjson/fallback/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/fallback/end.h"
+
+#endif // SIMDJSON_FALLBACK_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h
new file mode 100644
index 0000000000..d53e7316df
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/amalgamated.h
@@ -0,0 +1,42 @@
+#if defined(SIMDJSON_CONDITIONAL_INCLUDE) && !defined(SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H)
+#error simdjson/generic/ondemand/dependencies.h must be included before simdjson/generic/ondemand/amalgamated.h!
+#endif
+
+// Stuff other things depend on
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#include "simdjson/generic/ondemand/value.h"
+#include "simdjson/generic/ondemand/logger.h"
+#include "simdjson/generic/ondemand/token_iterator.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/json_type.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/parser.h"
+
+// All other declarations
+#include "simdjson/generic/ondemand/array.h"
+#include "simdjson/generic/ondemand/array_iterator.h"
+#include "simdjson/generic/ondemand/document.h"
+#include "simdjson/generic/ondemand/document_stream.h"
+#include "simdjson/generic/ondemand/field.h"
+#include "simdjson/generic/ondemand/object.h"
+#include "simdjson/generic/ondemand/object_iterator.h"
+#include "simdjson/generic/ondemand/serialization.h"
+
+// Inline definitions
+#include "simdjson/generic/ondemand/array-inl.h"
+#include "simdjson/generic/ondemand/array_iterator-inl.h"
+#include "simdjson/generic/ondemand/document-inl.h"
+#include "simdjson/generic/ondemand/document_stream-inl.h"
+#include "simdjson/generic/ondemand/field-inl.h"
+#include "simdjson/generic/ondemand/json_iterator-inl.h"
+#include "simdjson/generic/ondemand/json_type-inl.h"
+#include "simdjson/generic/ondemand/logger-inl.h"
+#include "simdjson/generic/ondemand/object-inl.h"
+#include "simdjson/generic/ondemand/object_iterator-inl.h"
+#include "simdjson/generic/ondemand/parser-inl.h"
+#include "simdjson/generic/ondemand/raw_json_string-inl.h"
+#include "simdjson/generic/ondemand/serialization-inl.h"
+#include "simdjson/generic/ondemand/token_iterator-inl.h"
+#include "simdjson/generic/ondemand/value-inl.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h
new file mode 100644
index 0000000000..b699ea4a03
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array-inl.h
@@ -0,0 +1,283 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/array.h"
+#include "simdjson/generic/ondemand/array_iterator-inl.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/value.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+//
+// ### Live States
+//
+// While iterating or looking up values, depth >= iter->depth. at_start may vary. Error is
+// always SUCCESS:
+//
+// - Start: This is the state when the array is first found and the iterator is just past the `{`.
+// In this state, at_start == true.
+// - Next: After we hand a scalar value to the user, or an array/object which they then fully
+// iterate over, the iterator is at the `,` before the next value (or `]`). In this state,
+// depth == iter->depth, at_start == false, and error == SUCCESS.
+// - Unfinished Business: When we hand an array/object to the user which they do not fully
+// iterate over, we need to finish that iteration by skipping child values until we reach the
+// Next state. In this state, depth > iter->depth, at_start == false, and error == SUCCESS.
+//
+// ## Error States
+//
+// In error states, we will yield exactly one more value before stopping. iter->depth == depth
+// and at_start is always false. We decrement after yielding the error, moving to the Finished
+// state.
+//
+// - Chained Error: When the array iterator is part of an error chain--for example, in
+// `for (auto tweet : doc["tweets"])`, where the tweet element may be missing or not be an
+// array--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
+// iter->depth == depth, and at_start == false. We decrement depth when we yield the error.
+// - Missing Comma Error: When the iterator ++ method discovers there is no comma between elements,
+// we flag that as an error and treat it exactly the same as a Chained Error. In this state,
+// error == TAPE_ERROR, iter->depth == depth, and at_start == false.
+//
+// ## Terminal State
+//
+// The terminal state has iter->depth < depth. at_start is always false.
+//
+// - Finished: When we have reached a `]` or have reported an error, we are finished. We signal this
+// by decrementing depth. In this state, iter->depth < depth, at_start == false, and
+// error == SUCCESS.
+//
+
+simdjson_inline array::array(const value_iterator &_iter) noexcept
+ : iter{_iter}
+{
+}
+
+simdjson_inline simdjson_result<array> array::start(value_iterator &iter) noexcept {
+ // We don't need to know if the array is empty to start iteration, but we do want to know if there
+ // is an error--thus `simdjson_unused`.
+ simdjson_unused bool has_value;
+ SIMDJSON_TRY( iter.start_array().get(has_value) );
+ return array(iter);
+}
+simdjson_inline simdjson_result<array> array::start_root(value_iterator &iter) noexcept {
+ simdjson_unused bool has_value;
+ SIMDJSON_TRY( iter.start_root_array().get(has_value) );
+ return array(iter);
+}
+simdjson_inline simdjson_result<array> array::started(value_iterator &iter) noexcept {
+ bool has_value;
+ SIMDJSON_TRY(iter.started_array().get(has_value));
+ return array(iter);
+}
+
+simdjson_inline simdjson_result<array_iterator> array::begin() noexcept {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ return array_iterator(iter);
+}
+simdjson_inline simdjson_result<array_iterator> array::end() noexcept {
+ return array_iterator(iter);
+}
+simdjson_inline error_code array::consume() noexcept {
+ auto error = iter.json_iter().skip_child(iter.depth()-1);
+ if(error) { iter.abandon(); }
+ return error;
+}
+
+simdjson_inline simdjson_result<std::string_view> array::raw_json() noexcept {
+ const uint8_t * starting_point{iter.peek_start()};
+ auto error = consume();
+ if(error) { return error; }
+ // After 'consume()', we could be left pointing just beyond the document, but that
+ // is ok because we are not going to dereference the final pointer position, we just
+ // use it to compute the length in bytes.
+ const uint8_t * final_point{iter._json_iter->unsafe_pointer()};
+ return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
+}
+
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+simdjson_inline simdjson_result<size_t> array::count_elements() & noexcept {
+ size_t count{0};
+ // Important: we do not consume any of the values.
+ for(simdjson_unused auto v : *this) { count++; }
+ // The above loop will always succeed, but we want to report errors.
+ if(iter.error()) { return iter.error(); }
+ // We need to move back at the start because we expect users to iterate through
+ // the array after counting the number of elements.
+ iter.reset_array();
+ return count;
+}
+SIMDJSON_POP_DISABLE_WARNINGS
+
+simdjson_inline simdjson_result<bool> array::is_empty() & noexcept {
+ bool is_not_empty;
+ auto error = iter.reset_array().get(is_not_empty);
+ if(error) { return error; }
+ return !is_not_empty;
+}
+
+inline simdjson_result<bool> array::reset() & noexcept {
+ return iter.reset_array();
+}
+
+inline simdjson_result<value> array::at_pointer(std::string_view json_pointer) noexcept {
+ if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
+ json_pointer = json_pointer.substr(1);
+ // - means "the append position" or "the element after the end of the array"
+ // We don't support this, because we're returning a real element, not a position.
+ if (json_pointer == "-") { return INDEX_OUT_OF_BOUNDS; }
+
+ // Read the array index
+ size_t array_index = 0;
+ size_t i;
+ for (i = 0; i < json_pointer.length() && json_pointer[i] != '/'; i++) {
+ uint8_t digit = uint8_t(json_pointer[i] - '0');
+ // Check for non-digit in array index. If it's there, we're trying to get a field in an object
+ if (digit > 9) { return INCORRECT_TYPE; }
+ array_index = array_index*10 + digit;
+ }
+
+ // 0 followed by other digits is invalid
+ if (i > 1 && json_pointer[0] == '0') { return INVALID_JSON_POINTER; } // "JSON pointer array index has other characters after 0"
+
+ // Empty string is invalid; so is a "/" with no digits before it
+ if (i == 0) { return INVALID_JSON_POINTER; } // "Empty string in JSON pointer array index"
+ // Get the child
+ auto child = at(array_index);
+ // If there is an error, it ends here
+ if(child.error()) {
+ return child;
+ }
+
+ // If there is a /, we're not done yet, call recursively.
+ if (i < json_pointer.length()) {
+ child = child.at_pointer(json_pointer.substr(i));
+ }
+ return child;
+}
+
+inline std::string json_path_to_pointer_conversion(std::string_view json_path) {
+ if (json_path.empty() || (json_path.front() != '.' &&
+ json_path.front() != '[')) {
+ return "-1"; // This is just a sentinel value, the caller should check for this and return an error.
+ }
+
+ std::string result;
+ // Reserve space to reduce allocations, adjusting for potential increases due
+ // to escaping.
+ result.reserve(json_path.size() * 2);
+
+ size_t i = 0;
+
+ while (i < json_path.length()) {
+ if (json_path[i] == '.') {
+ result += '/';
+ } else if (json_path[i] == '[') {
+ result += '/';
+ ++i; // Move past the '['
+ while (i < json_path.length() && json_path[i] != ']') {
+ if (json_path[i] == '~') {
+ result += "~0";
+ } else if (json_path[i] == '/') {
+ result += "~1";
+ } else {
+ result += json_path[i];
+ }
+ ++i;
+ }
+ if (i == json_path.length() || json_path[i] != ']') {
+ return "-1"; // Using sentinel value that will be handled as an error by the caller.
+ }
+ } else {
+ if (json_path[i] == '~') {
+ result += "~0";
+ } else if (json_path[i] == '/') {
+ result += "~1";
+ } else {
+ result += json_path[i];
+ }
+ }
+ ++i;
+ }
+
+ return result;
+}
+
+inline simdjson_result<value> array::at_path(std::string_view json_path) noexcept {
+ auto json_pointer = json_path_to_pointer_conversion(json_path);
+ if (json_pointer == "-1") { return INVALID_JSON_POINTER; }
+ return at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<value> array::at(size_t index) noexcept {
+ size_t i = 0;
+ for (auto value : *this) {
+ if (i == index) { return value; }
+ i++;
+ }
+ return INDEX_OUT_OF_BOUNDS;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::array &&value
+) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array>(
+ std::forward<SIMDJSON_IMPLEMENTATION::ondemand::array>(value)
+ )
+{
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::simdjson_result(
+ error_code error
+) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array>(error)
+{
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::begin() noexcept {
+ if (error()) { return error(); }
+ return first.begin();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::end() noexcept {
+ if (error()) { return error(); }
+ return first.end();
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::count_elements() & noexcept {
+ if (error()) { return error(); }
+ return first.count_elements();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::is_empty() & noexcept {
+ if (error()) { return error(); }
+ return first.is_empty();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::at(size_t index) noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::at_pointer(std::string_view json_pointer) noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::at_path(std::string_view json_path) noexcept {
+ if (error()) { return error(); }
+ return first.at_path(json_path);
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array>::raw_json() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json();
+}
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h
new file mode 100644
index 0000000000..e6095d27c2
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array.h
@@ -0,0 +1,216 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A forward-only JSON array.
+ */
+class array {
+public:
+ /**
+ * Create a new invalid array.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline array() noexcept = default;
+
+ /**
+ * Begin array iteration.
+ *
+ * Part of the std::iterable interface.
+ */
+ simdjson_inline simdjson_result<array_iterator> begin() noexcept;
+ /**
+ * Sentinel representing the end of the array.
+ *
+ * Part of the std::iterable interface.
+ */
+ simdjson_inline simdjson_result<array_iterator> end() noexcept;
+ /**
+ * This method scans the array and counts the number of elements.
+ * The count_elements method should always be called before you have begun
+ * iterating through the array: it is expected that you are pointing at
+ * the beginning of the array.
+ * The runtime complexity is linear in the size of the array. After
+ * calling this function, if successful, the array is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ *
+ * To check that an array is empty, it is more performant to use
+ * the is_empty() method.
+ */
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ /**
+ * This method scans the beginning of the array and checks whether the
+ * array is empty.
+ * The runtime complexity is constant time. After
+ * calling this function, if successful, the array is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ */
+ simdjson_inline simdjson_result<bool> is_empty() & noexcept;
+ /**
+ * Reset the iterator so that we are pointing back at the
+ * beginning of the array. You should still consume values only once even if you
+ * can iterate through the array more than once. If you unescape a string
+ * within the array more than once, you have unsafe code. Note that rewinding
+ * an array means that you may need to reparse it anew: it is not a free
+ * operation.
+ *
+ * @returns true if the array contains some elements (not empty)
+ */
+ inline simdjson_result<bool> reset() & noexcept;
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
+ * as the root of its own JSON document.
+ *
+ * ondemand::parser parser;
+ * auto json = R"([ { "foo": { "a": [ 10, 20, 30 ] }} ])"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("/0/foo/a/1") == 20
+ *
+ * Note that at_pointer() called on the document automatically calls the document's rewind
+ * method between each call. It invalidates all previously accessed arrays, objects and values
+ * that have not been consumed. Yet it is not the case when calling at_pointer on an array
+ * instance: there is no rewind and no invalidation.
+ *
+ * You may only call at_pointer on an array after it has been created, but before it has
+ * been first accessed. When calling at_pointer on an array, the pointer is advanced to
+ * the location indicated by the JSON pointer (in case of success). It is no longer possible
+ * to call at_pointer on the same array.
+ *
+ * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
+
+ /**
+ * Get the value associated with the given JSONPath expression. We only support
+ * JSONPath queries that trivially convertible to JSON Pointer queries: key
+ * names and array indices.
+ *
+ * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
+ *
+ * @return The value associated with the given JSONPath expression, or:
+ * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ */
+ inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
+
+ /**
+ * Consumes the array and returns a string_view instance corresponding to the
+ * array as represented in JSON. It points inside the original document.
+ */
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+
+ /**
+ * Get the value at the given index. This function has linear-time complexity.
+ * This function should only be called once on an array instance since the array iterator is not reset between each call.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ simdjson_inline simdjson_result<value> at(size_t index) noexcept;
+protected:
+ /**
+ * Go to the end of the array, no matter where you are right now.
+ */
+ simdjson_inline error_code consume() noexcept;
+
+ /**
+ * Begin array iteration.
+ *
+ * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
+ * resulting array.
+ * @error INCORRECT_TYPE if the iterator is not at [.
+ */
+ static simdjson_inline simdjson_result<array> start(value_iterator &iter) noexcept;
+ /**
+ * Begin array iteration from the root.
+ *
+ * @param iter The iterator. Must be where the initial [ is expected. Will be *moved* into the
+ * resulting array.
+ * @error INCORRECT_TYPE if the iterator is not at [.
+ * @error TAPE_ERROR if there is no closing ] at the end of the document.
+ */
+ static simdjson_inline simdjson_result<array> start_root(value_iterator &iter) noexcept;
+ /**
+ * Begin array iteration.
+ *
+ * This version of the method should be called after the initial [ has been verified, and is
+ * intended for use by switch statements that check the type of a value.
+ *
+ * @param iter The iterator. Must be after the initial [. Will be *moved* into the resulting array.
+ */
+ static simdjson_inline simdjson_result<array> started(value_iterator &iter) noexcept;
+
+ /**
+ * Create an array at the given Internal array creation. Call array::start() or array::started() instead of this.
+ *
+ * @param iter The iterator. Must either be at the start of the first element with iter.is_alive()
+ * == true, or past the [] with is_alive() == false if the array is empty. Will be *moved*
+ * into the resulting array.
+ */
+ simdjson_inline array(const value_iterator &iter) noexcept;
+
+ /**
+ * Iterator marking current position.
+ *
+ * iter.is_alive() == false indicates iteration is complete.
+ */
+ value_iterator iter{};
+
+ friend class value;
+ friend class document;
+ friend struct simdjson_result<value>;
+ friend struct simdjson_result<array>;
+ friend class array_iterator;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::array &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() noexcept;
+ inline simdjson_result<size_t> count_elements() & noexcept;
+ inline simdjson_result<bool> is_empty() & noexcept;
+ inline simdjson_result<bool> reset() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_path(std::string_view json_path) noexcept;
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator-inl.h
new file mode 100644
index 0000000000..6e4ba8140d
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator-inl.h
@@ -0,0 +1,78 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/array_iterator.h"
+#include "simdjson/generic/ondemand/value-inl.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline array_iterator::array_iterator(const value_iterator &_iter) noexcept
+ : iter{_iter}
+{}
+
+simdjson_inline simdjson_result<value> array_iterator::operator*() noexcept {
+ if (iter.error()) { iter.abandon(); return iter.error(); }
+ return value(iter.child());
+}
+simdjson_inline bool array_iterator::operator==(const array_iterator &other) const noexcept {
+ return !(*this != other);
+}
+simdjson_inline bool array_iterator::operator!=(const array_iterator &) const noexcept {
+ return iter.is_open();
+}
+simdjson_inline array_iterator &array_iterator::operator++() noexcept {
+ error_code error;
+ // PERF NOTE this is a safety rail ... users should exit loops as soon as they receive an error, so we'll never get here.
+ // However, it does not seem to make a perf difference, so we add it out of an abundance of caution.
+ if (( error = iter.error() )) { return *this; }
+ if (( error = iter.skip_child() )) { return *this; }
+ if (( error = iter.has_next_element().error() )) { return *this; }
+ return *this;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::array_iterator &&value
+) noexcept
+ : SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>(value))
+{
+ first.iter.assert_is_valid();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::simdjson_result(error_code error) noexcept
+ : SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>({}, error)
+{
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator*() noexcept {
+ if (error()) { return error(); }
+ return *first;
+}
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &other) const noexcept {
+ if (!first.iter.is_valid()) { return !error(); }
+ return first == other.first;
+}
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &other) const noexcept {
+ if (!first.iter.is_valid()) { return error(); }
+ return first != other.first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator>::operator++() noexcept {
+ // Clear the error if there is one, so we don't yield it twice
+ if (error()) { second = SUCCESS; return *this; }
+ ++(first);
+ return *this;
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator.h
new file mode 100644
index 0000000000..0957be9c79
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/array_iterator.h
@@ -0,0 +1,96 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A forward-only JSON array.
+ *
+ * This is an input_iterator, meaning:
+ * - It is forward-only
+ * - * must be called exactly once per element.
+ * - ++ must be called exactly once in between each * (*, ++, *, ++, * ...)
+ */
+class array_iterator {
+public:
+ /** Create a new, invalid array iterator. */
+ simdjson_inline array_iterator() noexcept = default;
+
+ //
+ // Iterator interface
+ //
+
+ /**
+ * Get the current element.
+ *
+ * Part of the std::iterator interface.
+ */
+ simdjson_inline simdjson_result<value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
+ /**
+ * Check if we are at the end of the JSON.
+ *
+ * Part of the std::iterator interface.
+ *
+ * @return true if there are no more elements in the JSON array.
+ */
+ simdjson_inline bool operator==(const array_iterator &) const noexcept;
+ /**
+ * Check if there are more elements in the JSON array.
+ *
+ * Part of the std::iterator interface.
+ *
+ * @return true if there are more elements in the JSON array.
+ */
+ simdjson_inline bool operator!=(const array_iterator &) const noexcept;
+ /**
+ * Move to the next element.
+ *
+ * Part of the std::iterator interface.
+ */
+ simdjson_inline array_iterator &operator++() noexcept;
+
+private:
+ value_iterator iter{};
+
+ simdjson_inline array_iterator(const value_iterator &iter) noexcept;
+
+ friend class array;
+ friend class value;
+ friend struct simdjson_result<array_iterator>;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::array_iterator &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ //
+ // Iterator interface
+ //
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
+ simdjson_inline bool operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &) const noexcept;
+ simdjson_inline bool operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &) const noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> &operator++() noexcept;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/base.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/base.h
new file mode 100644
index 0000000000..89bd0c01bb
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/base.h
@@ -0,0 +1,47 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_BASE_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_BASE_H
+#include "simdjson/generic/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+/**
+ * A fast, simple, DOM-like interface that parses JSON as you use it.
+ *
+ * Designed for maximum speed and a lower memory profile.
+ */
+namespace ondemand {
+
+/** Represents the depth of a JSON value (number of nested arrays/objects). */
+using depth_t = int32_t;
+
+/** @copydoc simdjson::SIMDJSON_IMPLEMENTATION::number_type */
+using number_type = simdjson::SIMDJSON_IMPLEMENTATION::number_type;
+
+/** @private Position in the JSON buffer indexes */
+using token_position = const uint32_t *;
+
+class array;
+class array_iterator;
+class document;
+class document_reference;
+class document_stream;
+class field;
+class json_iterator;
+enum class json_type;
+struct number;
+class object;
+class object_iterator;
+class parser;
+class raw_json_string;
+class token_iterator;
+class value;
+class value_iterator;
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h
new file mode 100644
index 0000000000..7fd9da72ef
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/dependencies.h
@@ -0,0 +1,17 @@
+#ifdef SIMDJSON_CONDITIONAL_INCLUDE
+#error simdjson/generic/ondemand/dependencies.h must be included before defining SIMDJSON_CONDITIONAL_INCLUDE!
+#endif
+
+#ifndef SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
+#define SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H
+
+// Internal headers needed for ondemand generics.
+// All includes not under simdjson/generic/ondemand must be here!
+// Otherwise, amalgamation will fail.
+#include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY
+#include "simdjson/implementation.h"
+#include "simdjson/padded_string.h"
+#include "simdjson/padded_string_view.h"
+#include "simdjson/internal/dom_parser_implementation.h"
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h
new file mode 100644
index 0000000000..3af60b0877
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document-inl.h
@@ -0,0 +1,917 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/array_iterator.h"
+#include "simdjson/generic/ondemand/document.h"
+#include "simdjson/generic/ondemand/json_type.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/value.h"
+#include "simdjson/generic/ondemand/array-inl.h"
+#include "simdjson/generic/ondemand/json_iterator-inl.h"
+#include "simdjson/generic/ondemand/object-inl.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept
+ : iter{std::forward<json_iterator>(_iter)}
+{
+ logger::log_start_value(iter, "document");
+}
+
+simdjson_inline document document::start(json_iterator &&iter) noexcept {
+ return document(std::forward<json_iterator>(iter));
+}
+
+inline void document::rewind() noexcept {
+ iter.rewind();
+}
+
+inline std::string document::to_debug_string() noexcept {
+ return iter.to_string();
+}
+
+inline simdjson_result<const char *> document::current_location() const noexcept {
+ return iter.current_location();
+}
+
+inline int32_t document::current_depth() const noexcept {
+ return iter.depth();
+}
+
+inline bool document::at_end() const noexcept {
+ return iter.at_end();
+}
+
+
+inline bool document::is_alive() noexcept {
+ return iter.is_alive();
+}
+simdjson_inline value_iterator document::resume_value_iterator() noexcept {
+ return value_iterator(&iter, 1, iter.root_position());
+}
+simdjson_inline value_iterator document::get_root_value_iterator() noexcept {
+ return resume_value_iterator();
+}
+simdjson_inline simdjson_result<object> document::start_or_resume_object() noexcept {
+ if (iter.at_root()) {
+ return get_object();
+ } else {
+ return object::resume(resume_value_iterator());
+ }
+}
+simdjson_inline simdjson_result<value> document::get_value() noexcept {
+ // Make sure we start any arrays or objects before returning, so that start_root_<object/array>()
+ // gets called.
+
+ // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether
+ // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error.
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ // assert_at_root() serves two purposes: in Debug mode, whether or not
+ // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of
+ // the document (this will typically be redundant). In release mode, it generates
+ // SIMDJSON_ASSUME statements to allow the compiler to make assumptions.
+ iter.assert_at_root();
+ switch (*iter.peek()) {
+ case '[': {
+ // The following lines check that the document ends with ].
+ auto value_iterator = get_root_value_iterator();
+ auto error = value_iterator.check_root_array();
+ if(error) { return error; }
+ return value(get_root_value_iterator());
+ }
+ case '{': {
+ // The following lines would check that the document ends with }.
+ auto value_iterator = get_root_value_iterator();
+ auto error = value_iterator.check_root_object();
+ if(error) { return error; }
+ return value(get_root_value_iterator());
+ }
+ default:
+ // Unfortunately, scalar documents are a special case in simdjson and they cannot
+ // be safely converted to value instances.
+ return SCALAR_DOCUMENT_AS_VALUE;
+ }
+}
+simdjson_inline simdjson_result<array> document::get_array() & noexcept {
+ auto value = get_root_value_iterator();
+ return array::start_root(value);
+}
+simdjson_inline simdjson_result<object> document::get_object() & noexcept {
+ auto value = get_root_value_iterator();
+ return object::start_root(value);
+}
+
+/**
+ * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
+ * give an error, so we check for trailing content. We want to disallow trailing
+ * content.
+ * Thus, in several implementations below, we pass a 'true' parameter value to
+ * a get_root_value_iterator() method: this indicates that we disallow trailing content.
+ */
+
+simdjson_inline simdjson_result<uint64_t> document::get_uint64() noexcept {
+ return get_root_value_iterator().get_root_uint64(true);
+}
+simdjson_inline simdjson_result<uint64_t> document::get_uint64_in_string() noexcept {
+ return get_root_value_iterator().get_root_uint64_in_string(true);
+}
+simdjson_inline simdjson_result<int64_t> document::get_int64() noexcept {
+ return get_root_value_iterator().get_root_int64(true);
+}
+simdjson_inline simdjson_result<int64_t> document::get_int64_in_string() noexcept {
+ return get_root_value_iterator().get_root_int64_in_string(true);
+}
+simdjson_inline simdjson_result<double> document::get_double() noexcept {
+ return get_root_value_iterator().get_root_double(true);
+}
+simdjson_inline simdjson_result<double> document::get_double_in_string() noexcept {
+ return get_root_value_iterator().get_root_double_in_string(true);
+}
+simdjson_inline simdjson_result<std::string_view> document::get_string(bool allow_replacement) noexcept {
+ return get_root_value_iterator().get_root_string(true, allow_replacement);
+}
+template <typename string_type>
+simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ return get_root_value_iterator().get_root_string(receiver, true, allow_replacement);
+}
+simdjson_inline simdjson_result<std::string_view> document::get_wobbly_string() noexcept {
+ return get_root_value_iterator().get_root_wobbly_string(true);
+}
+simdjson_inline simdjson_result<raw_json_string> document::get_raw_json_string() noexcept {
+ return get_root_value_iterator().get_root_raw_json_string(true);
+}
+simdjson_inline simdjson_result<bool> document::get_bool() noexcept {
+ return get_root_value_iterator().get_root_bool(true);
+}
+simdjson_inline simdjson_result<bool> document::is_null() noexcept {
+ return get_root_value_iterator().is_root_null(true);
+}
+
+template<> simdjson_inline simdjson_result<array> document::get() & noexcept { return get_array(); }
+template<> simdjson_inline simdjson_result<object> document::get() & noexcept { return get_object(); }
+template<> simdjson_inline simdjson_result<raw_json_string> document::get() & noexcept { return get_raw_json_string(); }
+template<> simdjson_inline simdjson_result<std::string_view> document::get() & noexcept { return get_string(false); }
+template<> simdjson_inline simdjson_result<double> document::get() & noexcept { return get_double(); }
+template<> simdjson_inline simdjson_result<uint64_t> document::get() & noexcept { return get_uint64(); }
+template<> simdjson_inline simdjson_result<int64_t> document::get() & noexcept { return get_int64(); }
+template<> simdjson_inline simdjson_result<bool> document::get() & noexcept { return get_bool(); }
+template<> simdjson_inline simdjson_result<value> document::get() & noexcept { return get_value(); }
+
+template<> simdjson_deprecated simdjson_inline simdjson_result<raw_json_string> document::get() && noexcept { return get_raw_json_string(); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<std::string_view> document::get() && noexcept { return get_string(false); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<double> document::get() && noexcept { return std::forward<document>(*this).get_double(); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<uint64_t> document::get() && noexcept { return std::forward<document>(*this).get_uint64(); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<int64_t> document::get() && noexcept { return std::forward<document>(*this).get_int64(); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<bool> document::get() && noexcept { return std::forward<document>(*this).get_bool(); }
+template<> simdjson_deprecated simdjson_inline simdjson_result<value> document::get() && noexcept { return get_value(); }
+
+template<typename T> simdjson_inline error_code document::get(T &out) & noexcept {
+ return get<T>().get(out);
+}
+template<typename T> simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept {
+ return std::forward<document>(*this).get<T>().get(out);
+}
+
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get<T>(); }
+template <class T>
+simdjson_inline document::operator T() & noexcept(false) { return get<T>(); }
+simdjson_inline document::operator array() & noexcept(false) { return get_array(); }
+simdjson_inline document::operator object() & noexcept(false) { return get_object(); }
+simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); }
+simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); }
+simdjson_inline document::operator double() noexcept(false) { return get_double(); }
+simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); }
+simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
+simdjson_inline document::operator bool() noexcept(false) { return get_bool(); }
+simdjson_inline document::operator value() noexcept(false) { return get_value(); }
+
+#endif
+simdjson_inline simdjson_result<size_t> document::count_elements() & noexcept {
+ auto a = get_array();
+ simdjson_result<size_t> answer = a.count_elements();
+ /* If there was an array, we are now left pointing at its first element. */
+ if(answer.error() == SUCCESS) { rewind(); }
+ return answer;
+}
+simdjson_inline simdjson_result<size_t> document::count_fields() & noexcept {
+ auto a = get_object();
+ simdjson_result<size_t> answer = a.count_fields();
+ /* If there was an object, we are now left pointing at its first element. */
+ if(answer.error() == SUCCESS) { rewind(); }
+ return answer;
+}
+simdjson_inline simdjson_result<value> document::at(size_t index) & noexcept {
+ auto a = get_array();
+ return a.at(index);
+}
+simdjson_inline simdjson_result<array_iterator> document::begin() & noexcept {
+ return get_array().begin();
+}
+simdjson_inline simdjson_result<array_iterator> document::end() & noexcept {
+ return {};
+}
+
+simdjson_inline simdjson_result<value> document::find_field(std::string_view key) & noexcept {
+ return start_or_resume_object().find_field(key);
+}
+simdjson_inline simdjson_result<value> document::find_field(const char *key) & noexcept {
+ return start_or_resume_object().find_field(key);
+}
+simdjson_inline simdjson_result<value> document::find_field_unordered(std::string_view key) & noexcept {
+ return start_or_resume_object().find_field_unordered(key);
+}
+simdjson_inline simdjson_result<value> document::find_field_unordered(const char *key) & noexcept {
+ return start_or_resume_object().find_field_unordered(key);
+}
+simdjson_inline simdjson_result<value> document::operator[](std::string_view key) & noexcept {
+ return start_or_resume_object()[key];
+}
+simdjson_inline simdjson_result<value> document::operator[](const char *key) & noexcept {
+ return start_or_resume_object()[key];
+}
+
+simdjson_inline error_code document::consume() noexcept {
+ auto error = iter.skip_child(0);
+ if(error) { iter.abandon(); }
+ return error;
+}
+
+simdjson_inline simdjson_result<std::string_view> document::raw_json() noexcept {
+ auto _iter = get_root_value_iterator();
+ const uint8_t * starting_point{_iter.peek_start()};
+ auto error = consume();
+ if(error) { return error; }
+ // After 'consume()', we could be left pointing just beyond the document, but that
+ // is ok because we are not going to dereference the final pointer position, we just
+ // use it to compute the length in bytes.
+ const uint8_t * final_point{iter.unsafe_pointer()};
+ return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
+}
+
+simdjson_inline simdjson_result<json_type> document::type() noexcept {
+ return get_root_value_iterator().type();
+}
+
+simdjson_inline simdjson_result<bool> document::is_scalar() noexcept {
+ json_type this_type;
+ auto error = type().get(this_type);
+ if(error) { return error; }
+ return ! ((this_type == json_type::array) || (this_type == json_type::object));
+}
+
+simdjson_inline simdjson_result<bool> document::is_string() noexcept {
+ json_type this_type;
+ auto error = type().get(this_type);
+ if(error) { return error; }
+ return (this_type == json_type::string);
+}
+
+simdjson_inline bool document::is_negative() noexcept {
+ return get_root_value_iterator().is_root_negative();
+}
+
+simdjson_inline simdjson_result<bool> document::is_integer() noexcept {
+ return get_root_value_iterator().is_root_integer(true);
+}
+
+simdjson_inline simdjson_result<number_type> document::get_number_type() noexcept {
+ return get_root_value_iterator().get_root_number_type(true);
+}
+
+simdjson_inline simdjson_result<number> document::get_number() noexcept {
+ return get_root_value_iterator().get_root_number(true);
+}
+
+
+simdjson_inline simdjson_result<std::string_view> document::raw_json_token() noexcept {
+ auto _iter = get_root_value_iterator();
+ return std::string_view(reinterpret_cast<const char*>(_iter.peek_start()), _iter.peek_root_length());
+}
+
+simdjson_inline simdjson_result<value> document::at_pointer(std::string_view json_pointer) noexcept {
+ rewind(); // Rewind the document each time at_pointer is called
+ if (json_pointer.empty()) {
+ return this->get_value();
+ }
+ json_type t;
+ SIMDJSON_TRY(type().get(t));
+ switch (t)
+ {
+ case json_type::array:
+ return (*this).get_array().at_pointer(json_pointer);
+ case json_type::object:
+ return (*this).get_object().at_pointer(json_pointer);
+ default:
+ return INVALID_JSON_POINTER;
+ }
+}
+
+simdjson_inline simdjson_result<value> document::at_path(std::string_view json_path) noexcept {
+ rewind(); // Rewind the document each time at_pointer is called
+ if (json_path.empty()) {
+ return this->get_value();
+ }
+ json_type t;
+ SIMDJSON_TRY(type().get(t));
+ switch (t) {
+ case json_type::array:
+ return (*this).get_array().at_path(json_path);
+ case json_type::object:
+ return (*this).get_object().at_path(json_path);
+ default:
+ return INVALID_JSON_POINTER;
+ }
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::document &&value
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document>(
+ std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document>(value)
+ )
+{
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::simdjson_result(
+ error_code error
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document>(
+ error
+ )
+{
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::count_elements() & noexcept {
+ if (error()) { return error(); }
+ return first.count_elements();
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::count_fields() & noexcept {
+ if (error()) { return error(); }
+ return first.count_fields();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::at(size_t index) & noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::rewind() noexcept {
+ if (error()) { return error(); }
+ first.rewind();
+ return SUCCESS;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::begin() & noexcept {
+ if (error()) { return error(); }
+ return first.begin();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::end() & noexcept {
+ return {};
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field_unordered(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field_unordered(const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator[](std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator[](const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::find_field(const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_array() & noexcept {
+ if (error()) { return error(); }
+ return first.get_array();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_object() & noexcept {
+ if (error()) { return error(); }
+ return first.get_object();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_uint64() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_uint64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64_in_string();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_int64() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_int64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64_in_string();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double() noexcept {
+ if (error()) { return error(); }
+ return first.get_double();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_double_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_double_in_string();
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_string(bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(allow_replacement);
+}
+template <typename string_type>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(receiver, allow_replacement);
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_wobbly_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_wobbly_string();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_raw_json_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_raw_json_string();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_bool() noexcept {
+ if (error()) { return error(); }
+ return first.get_bool();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_value() noexcept {
+ if (error()) { return error(); }
+ return first.get_value();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_null() noexcept {
+ if (error()) { return error(); }
+ return first.is_null();
+}
+
+template<typename T>
+simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get() & noexcept {
+ if (error()) { return error(); }
+ return first.get<T>();
+}
+template<typename T>
+simdjson_deprecated simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get() && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document>(first).get<T>();
+}
+template<typename T>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get(T &out) & noexcept {
+ if (error()) { return error(); }
+ return first.get<T>(out);
+}
+template<typename T>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get(T &out) && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document>(first).get<T>(out);
+}
+
+template<> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get<SIMDJSON_IMPLEMENTATION::ondemand::document>() & noexcept = delete;
+template<> simdjson_deprecated simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get<SIMDJSON_IMPLEMENTATION::ondemand::document>() && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document>(first);
+}
+template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get<SIMDJSON_IMPLEMENTATION::ondemand::document>(SIMDJSON_IMPLEMENTATION::ondemand::document &out) & noexcept = delete;
+template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get<SIMDJSON_IMPLEMENTATION::ondemand::document>(SIMDJSON_IMPLEMENTATION::ondemand::document &out) && noexcept {
+ if (error()) { return error(); }
+ out = std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document>(first);
+ return SUCCESS;
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::type() noexcept {
+ if (error()) { return error(); }
+ return first.type();
+}
+
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_scalar() noexcept {
+ if (error()) { return error(); }
+ return first.is_scalar();
+}
+
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_string() noexcept {
+ if (error()) { return error(); }
+ return first.is_string();
+}
+
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_negative() noexcept {
+ if (error()) { return error(); }
+ return first.is_negative();
+}
+
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::is_integer() noexcept {
+ if (error()) { return error(); }
+ return first.is_integer();
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_number_type() noexcept {
+ if (error()) { return error(); }
+ return first.get_number_type();
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::get_number() noexcept {
+ if (error()) { return error(); }
+ return first.get_number();
+}
+
+
+#if SIMDJSON_EXCEPTIONS
+template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document>::value == false>::type>
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator T() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator uint64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator int64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator double() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator std::string_view() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator bool() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+#endif
+
+
+simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::current_location() noexcept {
+ if (error()) { return error(); }
+ return first.current_location();
+}
+
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::at_end() const noexcept {
+ if (error()) { return error(); }
+ return first.at_end();
+}
+
+
+simdjson_inline int32_t simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::current_depth() const noexcept {
+ if (error()) { return error(); }
+ return first.current_depth();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::raw_json_token() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json_token();
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::at_pointer(std::string_view json_pointer) noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::at_path(std::string_view json_path) noexcept {
+ if (error()) { return error(); }
+ return first.at_path(json_path);
+}
+
+} // namespace simdjson
+
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {}
+simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {}
+simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); }
+simdjson_inline simdjson_result<array> document_reference::get_array() & noexcept { return doc->get_array(); }
+simdjson_inline simdjson_result<object> document_reference::get_object() & noexcept { return doc->get_object(); }
+/**
+ * The document_reference instances are used primarily/solely for streams of JSON
+ * documents.
+ * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should
+ * give an error, so we check for trailing content.
+ *
+ * However, for streams of JSON documents, we want to be able to start from
+ * "321" "321" "321"
+ * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string()
+ * successfully each time.
+ *
+ * To achieve this result, we pass a 'false' to a get_root_value_iterator() method:
+ * this indicates that we allow trailing content.
+ */
+simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); }
+simdjson_inline simdjson_result<uint64_t> document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); }
+simdjson_inline simdjson_result<int64_t> document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); }
+simdjson_inline simdjson_result<int64_t> document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); }
+simdjson_inline simdjson_result<double> document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
+simdjson_inline simdjson_result<double> document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); }
+simdjson_inline simdjson_result<std::string_view> document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); }
+template <typename string_type>
+simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); }
+simdjson_inline simdjson_result<std::string_view> document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); }
+simdjson_inline simdjson_result<raw_json_string> document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); }
+simdjson_inline simdjson_result<bool> document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); }
+simdjson_inline simdjson_result<value> document_reference::get_value() noexcept { return doc->get_value(); }
+simdjson_inline simdjson_result<bool> document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); }
+template<> simdjson_inline simdjson_result<array> document_reference::get() & noexcept { return get_array(); }
+template<> simdjson_inline simdjson_result<object> document_reference::get() & noexcept { return get_object(); }
+template<> simdjson_inline simdjson_result<raw_json_string> document_reference::get() & noexcept { return get_raw_json_string(); }
+template<> simdjson_inline simdjson_result<std::string_view> document_reference::get() & noexcept { return get_string(false); }
+template<> simdjson_inline simdjson_result<double> document_reference::get() & noexcept { return get_double(); }
+template<> simdjson_inline simdjson_result<uint64_t> document_reference::get() & noexcept { return get_uint64(); }
+template<> simdjson_inline simdjson_result<int64_t> document_reference::get() & noexcept { return get_int64(); }
+template<> simdjson_inline simdjson_result<bool> document_reference::get() & noexcept { return get_bool(); }
+template<> simdjson_inline simdjson_result<value> document_reference::get() & noexcept { return get_value(); }
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+simdjson_inline document_reference::operator T() noexcept(false) { return get<T>(); }
+simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); }
+simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); }
+simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); }
+simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); }
+simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); }
+simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); }
+simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); }
+simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); }
+simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); }
+#endif
+simdjson_inline simdjson_result<size_t> document_reference::count_elements() & noexcept { return doc->count_elements(); }
+simdjson_inline simdjson_result<size_t> document_reference::count_fields() & noexcept { return doc->count_fields(); }
+simdjson_inline simdjson_result<value> document_reference::at(size_t index) & noexcept { return doc->at(index); }
+simdjson_inline simdjson_result<array_iterator> document_reference::begin() & noexcept { return doc->begin(); }
+simdjson_inline simdjson_result<array_iterator> document_reference::end() & noexcept { return doc->end(); }
+simdjson_inline simdjson_result<value> document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); }
+simdjson_inline simdjson_result<value> document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); }
+simdjson_inline simdjson_result<value> document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; }
+simdjson_inline simdjson_result<value> document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; }
+simdjson_inline simdjson_result<value> document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); }
+simdjson_inline simdjson_result<value> document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); }
+simdjson_inline simdjson_result<json_type> document_reference::type() noexcept { return doc->type(); }
+simdjson_inline simdjson_result<bool> document_reference::is_scalar() noexcept { return doc->is_scalar(); }
+simdjson_inline simdjson_result<bool> document_reference::is_string() noexcept { return doc->is_string(); }
+simdjson_inline simdjson_result<const char *> document_reference::current_location() noexcept { return doc->current_location(); }
+simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); }
+simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); }
+simdjson_inline simdjson_result<bool> document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); }
+simdjson_inline simdjson_result<number_type> document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); }
+simdjson_inline simdjson_result<number> document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); }
+simdjson_inline simdjson_result<std::string_view> document_reference::raw_json_token() noexcept { return doc->raw_json_token(); }
+simdjson_inline simdjson_result<value> document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); }
+simdjson_inline simdjson_result<value> document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); }
+simdjson_inline simdjson_result<std::string_view> document_reference::raw_json() noexcept { return doc->raw_json();}
+simdjson_inline document_reference::operator document&() const noexcept { return *doc; }
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+
+
+namespace simdjson {
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_reference value, error_code error)
+ noexcept : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>(value), error) {}
+
+
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::count_elements() & noexcept {
+ if (error()) { return error(); }
+ return first.count_elements();
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::count_fields() & noexcept {
+ if (error()) { return error(); }
+ return first.count_fields();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::at(size_t index) & noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::rewind() noexcept {
+ if (error()) { return error(); }
+ first.rewind();
+ return SUCCESS;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::begin() & noexcept {
+ if (error()) { return error(); }
+ return first.begin();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::end() & noexcept {
+ return {};
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field_unordered(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field_unordered(const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator[](std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator[](const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::find_field(const char *key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_array() & noexcept {
+ if (error()) { return error(); }
+ return first.get_array();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_object() & noexcept {
+ if (error()) { return error(); }
+ return first.get_object();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_uint64() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_uint64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64_in_string();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int64() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_int64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64_in_string();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double() noexcept {
+ if (error()) { return error(); }
+ return first.get_double();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_double_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_double_in_string();
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_string(bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(allow_replacement);
+}
+template <typename string_type>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(receiver, allow_replacement);
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_wobbly_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_wobbly_string();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_raw_json_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_raw_json_string();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_bool() noexcept {
+ if (error()) { return error(); }
+ return first.get_bool();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_value() noexcept {
+ if (error()) { return error(); }
+ return first.get_value();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_null() noexcept {
+ if (error()) { return error(); }
+ return first.is_null();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::type() noexcept {
+ if (error()) { return error(); }
+ return first.type();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_scalar() noexcept {
+ if (error()) { return error(); }
+ return first.is_scalar();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_string() noexcept {
+ if (error()) { return error(); }
+ return first.is_string();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_negative() noexcept {
+ if (error()) { return error(); }
+ return first.is_negative();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::is_integer() noexcept {
+ if (error()) { return error(); }
+ return first.is_integer();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_number_type() noexcept {
+ if (error()) { return error(); }
+ return first.get_number_type();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::get_number() noexcept {
+ if (error()) { return error(); }
+ return first.get_number();
+}
+#if SIMDJSON_EXCEPTIONS
+template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::value == false>::type>
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator T() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator uint64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator int64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator double() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator std::string_view() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator bool() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+#endif
+
+simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::current_location() noexcept {
+ if (error()) { return error(); }
+ return first.current_location();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::raw_json_token() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json_token();
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::at_pointer(std::string_view json_pointer) noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::at_path(std::string_view json_path) noexcept {
+ if (error()) {
+ return error();
+ }
+ return first.at_path(json_path);
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h
new file mode 100644
index 0000000000..390180e6f4
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document.h
@@ -0,0 +1,914 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A JSON document. It holds a json_iterator instance.
+ *
+ * Used by tokens to get text, and string buffer location.
+ *
+ * You must keep the document around during iteration.
+ */
+class document {
+public:
+ /**
+ * Create a new invalid document.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline document() noexcept = default;
+ simdjson_inline document(const document &other) noexcept = delete; // pass your documents by reference, not by copy
+ simdjson_inline document(document &&other) noexcept = default;
+ simdjson_inline document &operator=(const document &other) noexcept = delete;
+ simdjson_inline document &operator=(document &&other) noexcept = default;
+
+ /**
+ * Cast this JSON value to an array.
+ *
+ * @returns An object that can be used to iterate the array.
+ * @returns INCORRECT_TYPE If the JSON value is not an array.
+ */
+ simdjson_inline simdjson_result<array> get_array() & noexcept;
+ /**
+ * Cast this JSON value to an object.
+ *
+ * @returns An object that can be used to look up or iterate fields.
+ * @returns INCORRECT_TYPE If the JSON value is not an object.
+ */
+ simdjson_inline simdjson_result<object> get_object() & noexcept;
+ /**
+ * Cast this JSON value to an unsigned integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ /**
+ * Cast this JSON value (inside string) to an unsigned integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ /**
+ * Cast this JSON value to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ /**
+ * Cast this JSON value (inside string) to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ /**
+ * Cast this JSON value to a double.
+ *
+ * @returns A double.
+ * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+
+ /**
+ * Cast this JSON value (inside string) to a double.
+ *
+ * @returns A double.
+ * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ /**
+ * Cast this JSON value to a string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * Important: Calling get_string() twice on the same document is an error.
+ *
+ * @param Whether to allow a replacement character for unmatched surrogate pairs.
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+ /**
+ * Attempts to fill the provided std::string reference with the parsed value of the current string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * Important: a value should be consumed once. Calling get_string() twice on the same value
+ * is an error.
+ *
+ * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
+ * We recommend you avoid allocating an std::string unless you need to.
+ *
+ * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
+ */
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+ /**
+ * Cast this JSON value to a string.
+ *
+ * The string is not guaranteed to be valid UTF-8. See https://simonsapin.github.io/wtf-8/
+ *
+ * Important: Calling get_wobbly_string() twice on the same document is an error.
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ /**
+ * Cast this JSON value to a raw_json_string.
+ *
+ * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
+ *
+ * @returns A pointer to the raw JSON for the given string.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
+ /**
+ * Cast this JSON value to a bool.
+ *
+ * @returns A bool value.
+ * @returns INCORRECT_TYPE if the JSON value is not true or false.
+ */
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ /**
+ * Cast this JSON value to a value when the document is an object or an array.
+ *
+ * You must not have begun iterating through the object or array. When
+ * SIMDJSON_DEVELOPMENT_CHECKS is set to 1 (which is the case when building in Debug mode
+ * by default), and you have already begun iterating,
+ * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
+ * rewind() to reset the document to its initial state before calling this method.
+ *
+ * @returns A value if a JSON array or object cannot be found.
+ * @returns SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
+ */
+ simdjson_inline simdjson_result<value> get_value() noexcept;
+
+ /**
+ * Checks if this JSON value is null. If and only if the value is
+ * null, then it is consumed (we advance). If we find a token that
+ * begins with 'n' but is not 'null', then an error is returned.
+ *
+ * @returns Whether the value is null.
+ * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
+ */
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+
+ /**
+ * Get this value as the given type.
+ *
+ * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
+ *
+ * You may use get_double(), get_bool(), get_uint64(), get_int64(),
+ * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
+ *
+ * @returns A value of the given type, parsed from the JSON.
+ * @returns INCORRECT_TYPE If the JSON value is not the given type.
+ */
+ template<typename T> simdjson_inline simdjson_result<T> get() & noexcept {
+ // Unless the simdjson library or the user provides an inline implementation, calling this method should
+ // immediately fail.
+ static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
+ "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
+ "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
+ " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
+ " You may also add support for custom types, see our documentation.");
+ }
+ /** @overload template<typename T> simdjson_result<T> get() & noexcept */
+ template<typename T> simdjson_deprecated simdjson_inline simdjson_result<T> get() && noexcept {
+ // Unless the simdjson library or the user provides an inline implementation, calling this method should
+ // immediately fail.
+ static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
+ "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
+ "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
+ " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
+ " You may also add support for custom types, see our documentation.");
+ }
+
+ /**
+ * Get this value as the given type.
+ *
+ * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value
+ *
+ * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances.
+ *
+ * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
+ * @returns INCORRECT_TYPE If the JSON value is not an object.
+ * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
+ */
+ template<typename T> simdjson_inline error_code get(T &out) & noexcept;
+ /** @overload template<typename T> error_code get(T &out) & noexcept */
+ template<typename T> simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ /**
+ * Cast this JSON value to an instance of type T. The programmer is responsible for
+ * providing an implementation of get<T> for the type T, if T is not one of the types
+ * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.)
+ *
+ * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
+ *
+ * @returns An instance of type T
+ */
+ template <class T>
+ explicit simdjson_inline operator T() & noexcept(false);
+ template <class T>
+ explicit simdjson_deprecated simdjson_inline operator T() && noexcept(false);
+
+ /**
+ * Cast this JSON value to an array.
+ *
+ * @returns An object that can be used to iterate the array.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
+ */
+ simdjson_inline operator array() & noexcept(false);
+ /**
+ * Cast this JSON value to an object.
+ *
+ * @returns An object that can be used to look up or iterate fields.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
+ */
+ simdjson_inline operator object() & noexcept(false);
+ /**
+ * Cast this JSON value to an unsigned integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline operator uint64_t() noexcept(false);
+ /**
+ * Cast this JSON value to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline operator int64_t() noexcept(false);
+ /**
+ * Cast this JSON value to a double.
+ *
+ * @returns A double.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline operator double() noexcept(false);
+ /**
+ * Cast this JSON value to a string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
+ */
+ simdjson_inline operator std::string_view() noexcept(false);
+ /**
+ * Cast this JSON value to a raw_json_string.
+ *
+ * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
+ *
+ * @returns A pointer to the raw JSON for the given string.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
+ */
+ simdjson_inline operator raw_json_string() noexcept(false);
+ /**
+ * Cast this JSON value to a bool.
+ *
+ * @returns A bool value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
+ */
+ simdjson_inline operator bool() noexcept(false);
+ /**
+ * Cast this JSON value to a value when the document is an object or an array.
+ *
+ * You must not have begun iterating through the object or array. When
+ * SIMDJSON_DEVELOPMENT_CHECKS is defined, and you have already begun iterating,
+ * you will get an OUT_OF_ORDER_ITERATION error. If you have begun iterating, you can use
+ * rewind() to reset the document to its initial state before calling this method.
+ *
+ * @returns A value value if a JSON array or object cannot be found.
+ * @exception SCALAR_DOCUMENT_AS_VALUE error is the document is a scalar (see is_scalar() function).
+ */
+ simdjson_inline operator value() noexcept(false);
+#endif
+ /**
+ * This method scans the array and counts the number of elements.
+ * The count_elements method should always be called before you have begun
+ * iterating through the array: it is expected that you are pointing at
+ * the beginning of the array.
+ * The runtime complexity is linear in the size of the array. After
+ * calling this function, if successful, the array is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ */
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ /**
+ * This method scans the object and counts the number of key-value pairs.
+ * The count_fields method should always be called before you have begun
+ * iterating through the object: it is expected that you are pointing at
+ * the beginning of the object.
+ * The runtime complexity is linear in the size of the object. After
+ * calling this function, if successful, the object is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ *
+ * To check that an object is empty, it is more performant to use
+ * the is_empty() method.
+ */
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ /**
+ * Get the value at the given index in the array. This function has linear-time complexity.
+ * This function should only be called once on an array instance since the array iterator is not reset between each call.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
+ /**
+ * Begin array iteration.
+ *
+ * Part of the std::iterable interface.
+ */
+ simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
+ /**
+ * Sentinel representing the end of the array.
+ *
+ * Part of the std::iterable interface.
+ */
+ simdjson_inline simdjson_result<array_iterator> end() & noexcept;
+
+ /**
+ * Look up a field by name on an object (order-sensitive).
+ *
+ * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
+ * JSON `{ "x": 1, "y": 2, "z": 3 }`:
+ *
+ * ```c++
+ * simdjson::ondemand::parser parser;
+ * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
+ * double z = obj.find_field("z");
+ * double y = obj.find_field("y");
+ * double x = obj.find_field("x");
+ * ```
+ *
+ * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
+ * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
+ *
+ *
+ * You must consume the fields on an object one at a time. A request for a new key
+ * invalidates previous field values: it makes them unsafe. E.g., the array
+ * given by content["bids"].get_array() should not be accessed after you have called
+ * content["asks"].get_array(). You can detect such mistakes by first compiling and running
+ * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
+ * OUT_OF_ORDER_ITERATION error is generated.
+ *
+ * You are expected to access keys only once. You should access the value corresponding to
+ * a key a single time. Doing object["mykey"].to_string()and then again object["mykey"].to_string()
+ * is an error.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
+
+ /**
+ * Look up a field by name on an object, without regard to key order.
+ *
+ * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
+ * and often appears negligible. It starts out normally, starting out at the last field; but if
+ * the field is not found, it scans from the beginning of the object to see if it missed it. That
+ * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
+ * in question is large. The fact that the extra code is there also bumps the executable size.
+ *
+ * It is the default, however, because it would be highly surprising (and hard to debug) if the
+ * default behavior failed to look up a field just because it was in the wrong order--and many
+ * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
+ *
+ * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
+ * field was not there when they are not in order).
+ *
+ * You must consume the fields on an object one at a time. A request for a new key
+ * invalidates previous field values: it makes them unsafe. E.g., the array
+ * given by content["bids"].get_array() should not be accessed after you have called
+ * content["asks"].get_array(). You can detect such mistakes by first compiling and running
+ * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
+ * OUT_OF_ORDER_ITERATION error is generated.
+ *
+ * You are expected to access keys only once. You should access the value corresponding to a key
+ * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
+ * is an error.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
+
+ /**
+ * Get the type of this JSON value. It does not validate or consume the value.
+ * E.g., you must still call "is_null()" to check that a value is null even if
+ * "type()" returns json_type::null.
+ *
+ * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
+ * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
+ * let it throw an exception).
+ *
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<json_type> type() noexcept;
+
+ /**
+ * Checks whether the document is a scalar (string, number, null, Boolean).
+ * Returns false when there it is an array or object.
+ *
+ * @returns true if the type is string, number, null, Boolean
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+
+ /**
+ * Checks whether the document is a string.
+ *
+ * @returns true if the type is string
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+
+ /**
+ * Checks whether the document is a negative number.
+ *
+ * @returns true if the number if negative.
+ */
+ simdjson_inline bool is_negative() noexcept;
+ /**
+ * Checks whether the document is an integer number. Note that
+ * this requires to partially parse the number string. If
+ * the value is determined to be an integer, it may still
+ * not parse properly as an integer in subsequent steps
+ * (e.g., it might overflow).
+ *
+ * @returns true if the number if negative.
+ */
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ /**
+ * Determine the number type (integer or floating-point number) as quickly
+ * as possible. This function does not fully validate the input. It is
+ * useful when you only need to classify the numbers, without parsing them.
+ *
+ * If you are planning to retrieve the value or you need full validation,
+ * consider using the get_number() method instead: it will fully parse
+ * and validate the input, and give you access to the type:
+ * get_number().get_number_type().
+ *
+ * get_number_type() is number_type::unsigned_integer if we have
+ * an integer greater or equal to 9223372036854775808 and no larger than 18446744073709551615.
+ * get_number_type() is number_type::signed_integer if we have an
+ * integer that is less than 9223372036854775808 and greater or equal to -9223372036854775808.
+ * get_number_type() is number_type::big_integer if we have an integer outside
+ * of those ranges (either larger than 18446744073709551615 or smaller than -9223372036854775808).
+ * Otherwise, get_number_type() has value number_type::floating_point_number
+ *
+ * This function requires processing the number string, but it is expected
+ * to be faster than get_number().get_number_type() because it is does not
+ * parse the number value.
+ *
+ * @returns the type of the number
+ */
+ simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
+
+ /**
+ * Attempt to parse an ondemand::number. An ondemand::number may
+ * contain an integer value or a floating-point value, the simdjson
+ * library will autodetect the type. Thus it is a dynamically typed
+ * number. Before accessing the value, you must determine the detected
+ * type.
+ *
+ * number.get_number_type() is number_type::signed_integer if we have
+ * an integer in [-9223372036854775808,9223372036854775808)
+ * You can recover the value by calling number.get_int64() and you
+ * have that number.is_int64() is true.
+ *
+ * number.get_number_type() is number_type::unsigned_integer if we have
+ * an integer in [9223372036854775808,18446744073709551616)
+ * You can recover the value by calling number.get_uint64() and you
+ * have that number.is_uint64() is true.
+ *
+ * Otherwise, number.get_number_type() has value number_type::floating_point_number
+ * and we have a binary64 number.
+ * You can recover the value by calling number.get_double() and you
+ * have that number.is_double() is true.
+ *
+ * You must check the type before accessing the value: it is an error
+ * to call "get_int64()" when number.get_number_type() is not
+ * number_type::signed_integer and when number.is_int64() is false.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
+
+ /**
+ * Get the raw JSON for this token.
+ *
+ * The string_view will always point into the input buffer.
+ *
+ * The string_view will start at the beginning of the token, and include the entire token
+ * *as well as all spaces until the next token (or EOF).* This means, for example, that a
+ * string token always begins with a " and is always terminated by the final ", possibly
+ * followed by a number of spaces.
+ *
+ * The string_view is *not* null-terminated. If this is a scalar (string, number,
+ * boolean, or null), the character after the end of the string_view may be the padded buffer.
+ *
+ * Tokens include:
+ * - {
+ * - [
+ * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
+ * - -1.2e-100
+ * - true
+ * - false
+ * - null
+ */
+ simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
+
+ /**
+ * Reset the iterator inside the document instance so we are pointing back at the
+ * beginning of the document, as if it had just been created. It invalidates all
+ * values, objects and arrays that you have created so far (including unescaped strings).
+ */
+ inline void rewind() noexcept;
+ /**
+ * Returns debugging information.
+ */
+ inline std::string to_debug_string() noexcept;
+ /**
+ * Some unrecoverable error conditions may render the document instance unusable.
+ * The is_alive() method returns true when the document is still suitable.
+ */
+ inline bool is_alive() noexcept;
+
+ /**
+ * Returns the current location in the document if in bounds.
+ */
+ inline simdjson_result<const char *> current_location() const noexcept;
+
+ /**
+ * Returns true if this document has been fully parsed.
+ * If you have consumed the whole document and at_end() returns
+ * false, then there may be trailing content.
+ */
+ inline bool at_end() const noexcept;
+
+ /**
+ * Returns the current depth in the document if in bounds.
+ *
+ * E.g.,
+ * 0 = finished with document
+ * 1 = document root value (could be [ or {, not yet known)
+ * 2 = , or } inside root array/object
+ * 3 = key or value inside root array/object.
+ */
+ simdjson_inline int32_t current_depth() const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard.
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("/foo/a/1") == 20
+ *
+ * It is allowed for a key to be the empty string:
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("//a/1") == 20
+ *
+ * Key values are matched exactly, without unescaping or Unicode normalization.
+ * We do a byte-by-byte comparison. E.g.
+ *
+ * const padded_string json = "{\"\\u00E9\":123}"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("/\\u00E9") == 123
+ * doc.at_pointer((const char*)u8"/\u00E9") returns an error (NO_SUCH_FIELD)
+ *
+ * Note that at_pointer() automatically calls rewind between each call. Thus
+ * all values, objects and arrays that you have created so far (including unescaped strings)
+ * are invalidated. After calling at_pointer, you need to consume the result: string values
+ * should be stored in your own variables, arrays should be decoded and stored in your own array-like
+ * structures and so forth.
+ *
+ * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ * - SCALAR_DOCUMENT_AS_VALUE if the json_pointer is empty and the document is not a scalar (see is_scalar() function).
+ */
+ simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
+
+ /**
+ * Get the value associated with the given JSONPath expression. We only support
+ * JSONPath queries that trivially convertible to JSON Pointer queries: key
+ * names and array indices.
+ *
+ * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00
+ *
+ * Key values are matched exactly, without unescaping or Unicode normalization.
+ * We do a byte-by-byte comparison. E.g.
+ *
+ * const padded_string json = "{\"\\u00E9\":123}"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_path(".\\u00E9") == 123
+ * doc.at_path((const char*)u8".\u00E9") returns an error (NO_SUCH_FIELD)
+ *
+ * @return The value associated with the given JSONPath expression, or:
+ * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ */
+ simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
+
+ /**
+ * Consumes the document and returns a string_view instance corresponding to the
+ * document as represented in JSON. It points inside the original byte array containing
+ * the JSON document.
+ */
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+protected:
+ /**
+ * Consumes the document.
+ */
+ simdjson_inline error_code consume() noexcept;
+
+ simdjson_inline document(ondemand::json_iterator &&iter) noexcept;
+ simdjson_inline const uint8_t *text(uint32_t idx) const noexcept;
+
+ simdjson_inline value_iterator resume_value_iterator() noexcept;
+ simdjson_inline value_iterator get_root_value_iterator() noexcept;
+ simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
+ static simdjson_inline document start(ondemand::json_iterator &&iter) noexcept;
+
+ //
+ // Fields
+ //
+ json_iterator iter{}; ///< Current position in the document
+ static constexpr depth_t DOCUMENT_DEPTH = 0; ///< document depth is always 0
+
+ friend class array_iterator;
+ friend class value;
+ friend class ondemand::parser;
+ friend class object;
+ friend class array;
+ friend class field;
+ friend class token;
+ friend class document_stream;
+ friend class document_reference;
+};
+
+
+/**
+ * A document_reference is a thin wrapper around a document reference instance.
+ */
+class document_reference {
+public:
+ simdjson_inline document_reference() noexcept;
+ simdjson_inline document_reference(document &d) noexcept;
+ simdjson_inline document_reference(const document_reference &other) noexcept = default;
+ simdjson_inline document_reference& operator=(const document_reference &other) noexcept = default;
+ simdjson_inline void rewind() noexcept;
+ simdjson_inline simdjson_result<array> get_array() & noexcept;
+ simdjson_inline simdjson_result<object> get_object() & noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ simdjson_inline simdjson_result<value> get_value() noexcept;
+
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+ template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+ simdjson_inline operator document&() const noexcept;
+#if SIMDJSON_EXCEPTIONS
+ template <class T>
+ explicit simdjson_inline operator T() noexcept(false);
+ simdjson_inline operator array() & noexcept(false);
+ simdjson_inline operator object() & noexcept(false);
+ simdjson_inline operator uint64_t() noexcept(false);
+ simdjson_inline operator int64_t() noexcept(false);
+ simdjson_inline operator double() noexcept(false);
+ simdjson_inline operator std::string_view() noexcept(false);
+ simdjson_inline operator raw_json_string() noexcept(false);
+ simdjson_inline operator bool() noexcept(false);
+ simdjson_inline operator value() noexcept(false);
+#endif
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ simdjson_inline simdjson_result<value> at(size_t index) & noexcept;
+ simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
+ simdjson_inline simdjson_result<array_iterator> end() & noexcept;
+ simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<value> find_field(const char *key) & noexcept;
+ simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<value> operator[](const char *key) & noexcept;
+ simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<value> find_field_unordered(const char *key) & noexcept;
+
+ simdjson_inline simdjson_result<json_type> type() noexcept;
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+
+ simdjson_inline simdjson_result<const char *> current_location() noexcept;
+ simdjson_inline int32_t current_depth() const noexcept;
+ simdjson_inline bool is_negative() noexcept;
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
+ simdjson_inline simdjson_result<number> get_number() noexcept;
+ simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
+ simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
+
+private:
+ document *doc{nullptr};
+};
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+ simdjson_inline error_code rewind() noexcept;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+
+ template<typename T> simdjson_inline simdjson_result<T> get() & noexcept;
+ template<typename T> simdjson_deprecated simdjson_inline simdjson_result<T> get() && noexcept;
+
+ template<typename T> simdjson_inline error_code get(T &out) & noexcept;
+ template<typename T> simdjson_inline error_code get(T &out) && noexcept;
+#if SIMDJSON_EXCEPTIONS
+ template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document>::value == false>::type>
+ explicit simdjson_inline operator T() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
+ simdjson_inline operator uint64_t() noexcept(false);
+ simdjson_inline operator int64_t() noexcept(false);
+ simdjson_inline operator double() noexcept(false);
+ simdjson_inline operator std::string_view() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
+ simdjson_inline operator bool() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
+#endif
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+ simdjson_inline simdjson_result<const char *> current_location() noexcept;
+ simdjson_inline int32_t current_depth() const noexcept;
+ simdjson_inline bool at_end() const noexcept;
+ simdjson_inline bool is_negative() noexcept;
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> get_number_type() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
+ /** @copydoc simdjson_inline std::string_view document::raw_json_token() const noexcept */
+ simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_path(std::string_view json_path) noexcept;
+};
+
+
+} // namespace simdjson
+
+
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_reference value, error_code error) noexcept;
+ simdjson_inline simdjson_result() noexcept = default;
+ simdjson_inline error_code rewind() noexcept;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() & noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> get_value() noexcept;
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+#if SIMDJSON_EXCEPTIONS
+ template <class T, typename std::enable_if<std::is_same<T, SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::value == false>::type>
+ explicit simdjson_inline operator T() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
+ simdjson_inline operator uint64_t() noexcept(false);
+ simdjson_inline operator int64_t() noexcept(false);
+ simdjson_inline operator double() noexcept(false);
+ simdjson_inline operator std::string_view() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
+ simdjson_inline operator bool() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
+#endif
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+ simdjson_inline simdjson_result<const char *> current_location() noexcept;
+ simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
+ simdjson_inline simdjson_result<bool> is_negative() noexcept;
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> get_number_type() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
+ /** @copydoc simdjson_inline std::string_view document_reference::raw_json_token() const noexcept */
+ simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_path(std::string_view json_path) noexcept;
+};
+
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h
new file mode 100644
index 0000000000..059ad0ec5f
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream-inl.h
@@ -0,0 +1,433 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/document_stream.h"
+#include "simdjson/generic/ondemand/document-inl.h"
+#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#include <algorithm>
+#include <stdexcept>
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+#ifdef SIMDJSON_THREADS_ENABLED
+
+inline void stage1_worker::finish() {
+ // After calling "run" someone would call finish() to wait
+ // for the end of the processing.
+ // This function will wait until either the thread has done
+ // the processing or, else, the destructor has been called.
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ cond_var.wait(lock, [this]{return has_work == false;});
+}
+
+inline stage1_worker::~stage1_worker() {
+ // The thread may never outlive the stage1_worker instance
+ // and will always be stopped/joined before the stage1_worker
+ // instance is gone.
+ stop_thread();
+}
+
+inline void stage1_worker::start_thread() {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ if(thread.joinable()) {
+ return; // This should never happen but we never want to create more than one thread.
+ }
+ thread = std::thread([this]{
+ while(true) {
+ std::unique_lock<std::mutex> thread_lock(locking_mutex);
+ // We wait for either "run" or "stop_thread" to be called.
+ cond_var.wait(thread_lock, [this]{return has_work || !can_work;});
+ // If, for some reason, the stop_thread() method was called (i.e., the
+ // destructor of stage1_worker is called, then we want to immediately destroy
+ // the thread (and not do any more processing).
+ if(!can_work) {
+ break;
+ }
+ this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser,
+ this->_next_batch_start);
+ this->has_work = false;
+ // The condition variable call should be moved after thread_lock.unlock() for performance
+ // reasons but thread sanitizers may report it as a data race if we do.
+ // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
+ cond_var.notify_one(); // will notify "finish"
+ thread_lock.unlock();
+ }
+ }
+ );
+}
+
+
+inline void stage1_worker::stop_thread() {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ // We have to make sure that all locks can be released.
+ can_work = false;
+ has_work = false;
+ cond_var.notify_all();
+ lock.unlock();
+ if(thread.joinable()) {
+ thread.join();
+ }
+}
+
+inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) {
+ std::unique_lock<std::mutex> lock(locking_mutex);
+ owner = ds;
+ _next_batch_start = next_batch_start;
+ stage1_thread_parser = stage1;
+ has_work = true;
+ // The condition variable call should be moved after thread_lock.unlock() for performance
+ // reasons but thread sanitizers may report it as a data race if we do.
+ // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock
+ cond_var.notify_one(); // will notify the thread lock that we have work
+ lock.unlock();
+}
+
+#endif // SIMDJSON_THREADS_ENABLED
+
+simdjson_inline document_stream::document_stream(
+ ondemand::parser &_parser,
+ const uint8_t *_buf,
+ size_t _len,
+ size_t _batch_size,
+ bool _allow_comma_separated
+) noexcept
+ : parser{&_parser},
+ buf{_buf},
+ len{_len},
+ batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size},
+ allow_comma_separated{_allow_comma_separated},
+ error{SUCCESS}
+ #ifdef SIMDJSON_THREADS_ENABLED
+ , use_thread(_parser.threaded) // we need to make a copy because _parser.threaded can change
+ #endif
+{
+#ifdef SIMDJSON_THREADS_ENABLED
+ if(worker.get() == nullptr) {
+ error = MEMALLOC;
+ }
+#endif
+}
+
+simdjson_inline document_stream::document_stream() noexcept
+ : parser{nullptr},
+ buf{nullptr},
+ len{0},
+ batch_size{0},
+ allow_comma_separated{false},
+ error{UNINITIALIZED}
+ #ifdef SIMDJSON_THREADS_ENABLED
+ , use_thread(false)
+ #endif
+{
+}
+
+simdjson_inline document_stream::~document_stream() noexcept
+{
+ #ifdef SIMDJSON_THREADS_ENABLED
+ worker.reset();
+ #endif
+}
+
+inline size_t document_stream::size_in_bytes() const noexcept {
+ return len;
+}
+
+inline size_t document_stream::truncated_bytes() const noexcept {
+ if(error == CAPACITY) { return len - batch_start; }
+ return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1];
+}
+
+simdjson_inline document_stream::iterator::iterator() noexcept
+ : stream{nullptr}, finished{true} {
+}
+
+simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept
+ : stream{_stream}, finished{is_end} {
+}
+
+simdjson_inline simdjson_result<ondemand::document_reference> document_stream::iterator::operator*() noexcept {
+ //if(stream->error) { return stream->error; }
+ return simdjson_result<ondemand::document_reference>(stream->doc, stream->error);
+}
+
+simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept {
+ // If there is an error, then we want the iterator
+ // to be finished, no matter what. (E.g., we do not
+ // keep generating documents with errors, or go beyond
+ // a document with errors.)
+ //
+ // Users do not have to call "operator*()" when they use operator++,
+ // so we need to end the stream in the operator++ function.
+ //
+ // Note that setting finished = true is essential otherwise
+ // we would enter an infinite loop.
+ if (stream->error) { finished = true; }
+ // Note that stream->error() is guarded against error conditions
+ // (it will immediately return if stream->error casts to false).
+ // In effect, this next function does nothing when (stream->error)
+ // is true (hence the risk of an infinite loop).
+ stream->next();
+ // If that was the last document, we're finished.
+ // It is the only type of error we do not want to appear
+ // in operator*.
+ if (stream->error == EMPTY) { finished = true; }
+ // If we had any other kind of error (not EMPTY) then we want
+ // to pass it along to the operator* and we cannot mark the result
+ // as "finished" just yet.
+ return *this;
+}
+
+simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept {
+ return finished != other.finished;
+}
+
+simdjson_inline document_stream::iterator document_stream::begin() noexcept {
+ start();
+ // If there are no documents, we're finished.
+ return iterator(this, error == EMPTY);
+}
+
+simdjson_inline document_stream::iterator document_stream::end() noexcept {
+ return iterator(this, true);
+}
+
+inline void document_stream::start() noexcept {
+ if (error) { return; }
+ error = parser->allocate(batch_size);
+ if (error) { return; }
+ // Always run the first stage 1 parse immediately
+ batch_start = 0;
+ error = run_stage1(*parser, batch_start);
+ while(error == EMPTY) {
+ // In exceptional cases, we may start with an empty block
+ batch_start = next_batch_start();
+ if (batch_start >= len) { return; }
+ error = run_stage1(*parser, batch_start);
+ }
+ if (error) { return; }
+ doc_index = batch_start;
+ doc = document(json_iterator(&buf[batch_start], parser));
+ doc.iter._streaming = true;
+
+ #ifdef SIMDJSON_THREADS_ENABLED
+ if (use_thread && next_batch_start() < len) {
+ // Kick off the first thread on next batch if needed
+ error = stage1_thread_parser.allocate(batch_size);
+ if (error) { return; }
+ worker->start_thread();
+ start_stage1_thread();
+ if (error) { return; }
+ }
+ #endif // SIMDJSON_THREADS_ENABLED
+}
+
+inline void document_stream::next() noexcept {
+ // We always enter at once once in an error condition.
+ if (error) { return; }
+ next_document();
+ if (error) { return; }
+ auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get();
+ doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index];
+
+ // Check if at end of structural indexes (i.e. at end of batch)
+ if(cur_struct_index >= static_cast<int64_t>(parser->implementation->n_structural_indexes)) {
+ error = EMPTY;
+ // Load another batch (if available)
+ while (error == EMPTY) {
+ batch_start = next_batch_start();
+ if (batch_start >= len) { break; }
+ #ifdef SIMDJSON_THREADS_ENABLED
+ if(use_thread) {
+ load_from_stage1_thread();
+ } else {
+ error = run_stage1(*parser, batch_start);
+ }
+ #else
+ error = run_stage1(*parser, batch_start);
+ #endif
+ /**
+ * Whenever we move to another window, we need to update all pointers to make
+ * it appear as if the input buffer started at the beginning of the window.
+ *
+ * Take this input:
+ *
+ * {"z":5} {"1":1,"2":2,"4":4} [7, 10, 9] [15, 11, 12, 13] [154, 110, 112, 1311]
+ *
+ * Say you process the following window...
+ *
+ * '{"z":5} {"1":1,"2":2,"4":4} [7, 10, 9]'
+ *
+ * When you do so, the json_iterator has a pointer at the beginning of the memory region
+ * (pointing at the beginning of '{"z"...'.
+ *
+ * When you move to the window that starts at...
+ *
+ * '[7, 10, 9] [15, 11, 12, 13] ...
+ *
+ * then it is not sufficient to just run stage 1. You also need to re-anchor the
+ * json_iterator so that it believes we are starting at '[7, 10, 9]...'.
+ *
+ * Under the DOM front-end, this gets done automatically because the parser owns
+ * the pointer the data, and when you call stage1 and then stage2 on the same
+ * parser, then stage2 will run on the pointer acquired by stage1.
+ *
+ * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that
+ * we used. But json_iterator has no callback when stage1 is called on the parser.
+ * In fact, I think that the parser is unaware of json_iterator.
+ *
+ *
+ * So we need to re-anchor the json_iterator after each call to stage 1 so that
+ * all of the pointers are in sync.
+ */
+ doc.iter = json_iterator(&buf[batch_start], parser);
+ doc.iter._streaming = true;
+ /**
+ * End of resync.
+ */
+
+ if (error) { continue; } // If the error was EMPTY, we may want to load another batch.
+ doc_index = batch_start;
+ }
+ }
+}
+
+inline void document_stream::next_document() noexcept {
+ // Go to next place where depth=0 (document depth)
+ error = doc.iter.skip_child(0);
+ if (error) { return; }
+ // Always set depth=1 at the start of document
+ doc.iter._depth = 1;
+ // consume comma if comma separated is allowed
+ if (allow_comma_separated) { doc.iter.consume_character(','); }
+ // Resets the string buffer at the beginning, thus invalidating the strings.
+ doc.iter._string_buf_loc = parser->string_buf.get();
+ doc.iter._root = doc.iter.position();
+}
+
+inline size_t document_stream::next_batch_start() const noexcept {
+ return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
+}
+
+inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept {
+ // This code only updates the structural index in the parser, it does not update any json_iterator
+ // instance.
+ size_t remaining = len - _batch_start;
+ if (remaining <= batch_size) {
+ return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final);
+ } else {
+ return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial);
+ }
+}
+
+simdjson_inline size_t document_stream::iterator::current_index() const noexcept {
+ return stream->doc_index;
+}
+
+simdjson_inline std::string_view document_stream::iterator::source() const noexcept {
+ auto depth = stream->doc.iter.depth();
+ auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get();
+
+ // If at root, process the first token to determine if scalar value
+ if (stream->doc.iter.at_root()) {
+ switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
+ case '{': case '[': // Depth=1 already at start of document
+ break;
+ case '}': case ']':
+ depth--;
+ break;
+ default: // Scalar value document
+ // TODO: We could remove trailing whitespaces
+ // This returns a string spanning from start of value to the beginning of the next document (excluded)
+ {
+ auto next_index = stream->parser->implementation->structural_indexes[++cur_struct_index];
+ // normally the length would be next_index - current_index() - 1, except for the last document
+ size_t svlen = next_index - current_index();
+ const char *start = reinterpret_cast<const char*>(stream->buf) + current_index();
+ while(svlen > 1 && (std::isspace(start[svlen-1]) || start[svlen-1] == '\0')) {
+ svlen--;
+ }
+ return std::string_view(start, svlen);
+ }
+ }
+ cur_struct_index++;
+ }
+
+ while (cur_struct_index <= static_cast<int64_t>(stream->parser->implementation->n_structural_indexes)) {
+ switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) {
+ case '{': case '[':
+ depth++;
+ break;
+ case '}': case ']':
+ depth--;
+ break;
+ }
+ if (depth == 0) { break; }
+ cur_struct_index++;
+ }
+
+ return std::string_view(reinterpret_cast<const char*>(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);;
+}
+
+inline error_code document_stream::iterator::error() const noexcept {
+ return stream->error;
+}
+
+#ifdef SIMDJSON_THREADS_ENABLED
+
+inline void document_stream::load_from_stage1_thread() noexcept {
+ worker->finish();
+ // Swap to the parser that was loaded up in the thread. Make sure the parser has
+ // enough memory to swap to, as well.
+ std::swap(stage1_thread_parser,*parser);
+ error = stage1_thread_error;
+ if (error) { return; }
+
+ // If there's anything left, start the stage 1 thread!
+ if (next_batch_start() < len) {
+ start_stage1_thread();
+ }
+}
+
+inline void document_stream::start_stage1_thread() noexcept {
+ // we call the thread on a lambda that will update
+ // this->stage1_thread_error
+ // there is only one thread that may write to this value
+ // TODO this is NOT exception-safe.
+ this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error
+ size_t _next_batch_start = this->next_batch_start();
+
+ worker->run(this, & this->stage1_thread_parser, _next_batch_start);
+}
+
+#endif // SIMDJSON_THREADS_ENABLED
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_stream>::simdjson_result(
+ error_code error
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_stream>(error)
+{
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_stream>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::document_stream &&value
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_stream>(
+ std::forward<SIMDJSON_IMPLEMENTATION::ondemand::document_stream>(value)
+ )
+{
+}
+
+}
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream.h
new file mode 100644
index 0000000000..ef1265fb33
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/document_stream.h
@@ -0,0 +1,337 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/document.h"
+#include "simdjson/generic/ondemand/parser.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#ifdef SIMDJSON_THREADS_ENABLED
+#include <thread>
+#include <mutex>
+#include <condition_variable>
+#endif
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+#ifdef SIMDJSON_THREADS_ENABLED
+/** @private Custom worker class **/
+struct stage1_worker {
+ stage1_worker() noexcept = default;
+ stage1_worker(const stage1_worker&) = delete;
+ stage1_worker(stage1_worker&&) = delete;
+ stage1_worker operator=(const stage1_worker&) = delete;
+ ~stage1_worker();
+ /**
+ * We only start the thread when it is needed, not at object construction, this may throw.
+ * You should only call this once.
+ **/
+ void start_thread();
+ /**
+ * Start a stage 1 job. You should first call 'run', then 'finish'.
+ * You must call start_thread once before.
+ */
+ void run(document_stream * ds, parser * stage1, size_t next_batch_start);
+ /** Wait for the run to finish (blocking). You should first call 'run', then 'finish'. **/
+ void finish();
+
+private:
+
+ /**
+ * Normally, we would never stop the thread. But we do in the destructor.
+ * This function is only safe assuming that you are not waiting for results. You
+ * should have called run, then finish, and be done.
+ **/
+ void stop_thread();
+
+ std::thread thread{};
+ /** These three variables define the work done by the thread. **/
+ ondemand::parser * stage1_thread_parser{};
+ size_t _next_batch_start{};
+ document_stream * owner{};
+ /**
+ * We have two state variables. This could be streamlined to one variable in the future but
+ * we use two for clarity.
+ */
+ bool has_work{false};
+ bool can_work{true};
+
+ /**
+ * We lock using a mutex.
+ */
+ std::mutex locking_mutex{};
+ std::condition_variable cond_var{};
+
+ friend class document_stream;
+};
+#endif // SIMDJSON_THREADS_ENABLED
+
+/**
+ * A forward-only stream of documents.
+ *
+ * Produced by parser::iterate_many.
+ *
+ */
+class document_stream {
+public:
+ /**
+ * Construct an uninitialized document_stream.
+ *
+ * ```c++
+ * document_stream docs;
+ * auto error = parser.iterate_many(json).get(docs);
+ * ```
+ */
+ simdjson_inline document_stream() noexcept;
+ /** Move one document_stream to another. */
+ simdjson_inline document_stream(document_stream &&other) noexcept = default;
+ /** Move one document_stream to another. */
+ simdjson_inline document_stream &operator=(document_stream &&other) noexcept = default;
+
+ simdjson_inline ~document_stream() noexcept;
+
+ /**
+ * Returns the input size in bytes.
+ */
+ inline size_t size_in_bytes() const noexcept;
+
+ /**
+ * After iterating through the stream, this method
+ * returns the number of bytes that were not parsed at the end
+ * of the stream. If truncated_bytes() differs from zero,
+ * then the input was truncated maybe because incomplete JSON
+ * documents were found at the end of the stream. You
+ * may need to process the bytes in the interval [size_in_bytes()-truncated_bytes(), size_in_bytes()).
+ *
+ * You should only call truncated_bytes() after streaming through all
+ * documents, like so:
+ *
+ * document_stream stream = parser.iterate_many(json,window);
+ * for(auto & doc : stream) {
+ * // do something with doc
+ * }
+ * size_t truncated = stream.truncated_bytes();
+ *
+ */
+ inline size_t truncated_bytes() const noexcept;
+
+ class iterator {
+ public:
+ using value_type = simdjson_result<document>;
+ using reference = simdjson_result<ondemand::document_reference>;
+ using pointer = void;
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::input_iterator_tag;
+
+ /**
+ * Default constructor.
+ */
+ simdjson_inline iterator() noexcept;
+ /**
+ * Get the current document (or error).
+ */
+ simdjson_inline reference operator*() noexcept;
+ /**
+ * Advance to the next document (prefix).
+ */
+ inline iterator& operator++() noexcept;
+ /**
+ * Check if we're at the end yet.
+ * @param other the end iterator to compare to.
+ */
+ simdjson_inline bool operator!=(const iterator &other) const noexcept;
+ /**
+ * @private
+ *
+ * Gives the current index in the input document in bytes.
+ *
+ * document_stream stream = parser.parse_many(json,window);
+ * for(auto i = stream.begin(); i != stream.end(); ++i) {
+ * auto doc = *i;
+ * size_t index = i.current_index();
+ * }
+ *
+ * This function (current_index()) is experimental and the usage
+ * may change in future versions of simdjson: we find the API somewhat
+ * awkward and we would like to offer something friendlier.
+ */
+ simdjson_inline size_t current_index() const noexcept;
+
+ /**
+ * @private
+ *
+ * Gives a view of the current document at the current position.
+ *
+ * document_stream stream = parser.iterate_many(json,window);
+ * for(auto i = stream.begin(); i != stream.end(); ++i) {
+ * std::string_view v = i.source();
+ * }
+ *
+ * The returned string_view instance is simply a map to the (unparsed)
+ * source string: it may thus include white-space characters and all manner
+ * of padding.
+ *
+ * This function (source()) is experimental and the usage
+ * may change in future versions of simdjson: we find the API somewhat
+ * awkward and we would like to offer something friendlier.
+ *
+ */
+ simdjson_inline std::string_view source() const noexcept;
+
+ /**
+ * Returns error of the stream (if any).
+ */
+ inline error_code error() const noexcept;
+
+ private:
+ simdjson_inline iterator(document_stream *s, bool finished) noexcept;
+ /** The document_stream we're iterating through. */
+ document_stream* stream;
+ /** Whether we're finished or not. */
+ bool finished;
+
+ friend class document;
+ friend class document_stream;
+ friend class json_iterator;
+ };
+
+ /**
+ * Start iterating the documents in the stream.
+ */
+ simdjson_inline iterator begin() noexcept;
+ /**
+ * The end of the stream, for iterator comparison purposes.
+ */
+ simdjson_inline iterator end() noexcept;
+
+private:
+
+ document_stream &operator=(const document_stream &) = delete; // Disallow copying
+ document_stream(const document_stream &other) = delete; // Disallow copying
+
+ /**
+ * Construct a document_stream. Does not allocate or parse anything until the iterator is
+ * used.
+ *
+ * @param parser is a reference to the parser instance used to generate this document_stream
+ * @param buf is the raw byte buffer we need to process
+ * @param len is the length of the raw byte buffer in bytes
+ * @param batch_size is the size of the windows (must be strictly greater or equal to the largest JSON document)
+ */
+ simdjson_inline document_stream(
+ ondemand::parser &parser,
+ const uint8_t *buf,
+ size_t len,
+ size_t batch_size,
+ bool allow_comma_separated
+ ) noexcept;
+
+ /**
+ * Parse the first document in the buffer. Used by begin(), to handle allocation and
+ * initialization.
+ */
+ inline void start() noexcept;
+
+ /**
+ * Parse the next document found in the buffer previously given to document_stream.
+ *
+ * The content should be a valid JSON document encoded as UTF-8. If there is a
+ * UTF-8 BOM, the parser skips it.
+ *
+ * You do NOT need to pre-allocate a parser. This function takes care of
+ * pre-allocating a capacity defined by the batch_size defined when creating the
+ * document_stream object.
+ *
+ * The function returns simdjson::EMPTY if there is no more data to be parsed.
+ *
+ * The function returns simdjson::SUCCESS (as integer = 0) in case of success
+ * and indicates that the buffer has successfully been parsed to the end.
+ * Every document it contained has been parsed without error.
+ *
+ * The function returns an error code from simdjson/simdjson.h in case of failure
+ * such as simdjson::CAPACITY, simdjson::MEMALLOC, simdjson::DEPTH_ERROR and so forth;
+ * the simdjson::error_message function converts these error codes into a string).
+ *
+ * You can also check validity by calling parser.is_valid(). The same parser can
+ * and should be reused for the other documents in the buffer.
+ */
+ inline void next() noexcept;
+
+ /** Move the json_iterator of the document to the location of the next document in the stream. */
+ inline void next_document() noexcept;
+
+ /** Get the next document index. */
+ inline size_t next_batch_start() const noexcept;
+
+ /** Pass the next batch through stage 1 with the given parser. */
+ inline error_code run_stage1(ondemand::parser &p, size_t batch_start) noexcept;
+
+ // Fields
+ ondemand::parser *parser;
+ const uint8_t *buf;
+ size_t len;
+ size_t batch_size;
+ bool allow_comma_separated;
+ /**
+ * We are going to use just one document instance. The document owns
+ * the json_iterator. It implies that we only ever pass a reference
+ * to the document to the users.
+ */
+ document doc{};
+ /** The error (or lack thereof) from the current document. */
+ error_code error;
+ size_t batch_start{0};
+ size_t doc_index{};
+
+ #ifdef SIMDJSON_THREADS_ENABLED
+ /** Indicates whether we use threads. Note that this needs to be a constant during the execution of the parsing. */
+ bool use_thread;
+
+ inline void load_from_stage1_thread() noexcept;
+
+ /** Start a thread to run stage 1 on the next batch. */
+ inline void start_stage1_thread() noexcept;
+
+ /** Wait for the stage 1 thread to finish and capture the results. */
+ inline void finish_stage1_thread() noexcept;
+
+ /** The error returned from the stage 1 thread. */
+ error_code stage1_thread_error{UNINITIALIZED};
+ /** The thread used to run stage 1 against the next batch in the background. */
+ std::unique_ptr<stage1_worker> worker{new(std::nothrow) stage1_worker()};
+ /**
+ * The parser used to run stage 1 in the background. Will be swapped
+ * with the regular parser when finished.
+ */
+ ondemand::parser stage1_thread_parser{};
+
+ friend struct stage1_worker;
+ #endif // SIMDJSON_THREADS_ENABLED
+
+ friend class parser;
+ friend class document;
+ friend class json_iterator;
+ friend struct simdjson_result<ondemand::document_stream>;
+ friend struct simdjson::internal::simdjson_result_base<ondemand::document_stream>;
+}; // document_stream
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_stream> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::document_stream> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::document_stream &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/field-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/field-inl.h
new file mode 100644
index 0000000000..ae5189536f
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/field-inl.h
@@ -0,0 +1,129 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/field.h"
+#include "simdjson/generic/ondemand/value-inl.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+// clang 6 does not think the default constructor can be noexcept, so we make it explicit
+simdjson_inline field::field() noexcept : std::pair<raw_json_string, ondemand::value>() {}
+
+simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept
+ : std::pair<raw_json_string, ondemand::value>(key, std::forward<ondemand::value>(value))
+{
+}
+
+simdjson_inline simdjson_result<field> field::start(value_iterator &parent_iter) noexcept {
+ raw_json_string key;
+ SIMDJSON_TRY( parent_iter.field_key().get(key) );
+ SIMDJSON_TRY( parent_iter.field_value() );
+ return field::start(parent_iter, key);
+}
+
+simdjson_inline simdjson_result<field> field::start(const value_iterator &parent_iter, raw_json_string key) noexcept {
+ return field(key, parent_iter.child());
+}
+
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> field::unescaped_key(bool allow_replacement) noexcept {
+ SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us.
+ simdjson_result<std::string_view> answer = first.unescape(second.iter.json_iter(), allow_replacement);
+ first.consume();
+ return answer;
+}
+
+template <typename string_type>
+simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept {
+ std::string_view key;
+ SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) );
+ receiver = key;
+ return SUCCESS;
+}
+
+simdjson_inline raw_json_string field::key() const noexcept {
+ SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
+ return first;
+}
+
+
+simdjson_inline std::string_view field::key_raw_json_token() const noexcept {
+ SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
+ return std::string_view(reinterpret_cast<const char*>(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1);
+}
+
+simdjson_inline std::string_view field::escaped_key() const noexcept {
+ SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us.
+ auto end_quote = second.iter._json_iter->token.peek(-1);
+ while(*end_quote != '"') end_quote--;
+ return std::string_view(reinterpret_cast<const char*>(first.buf), end_quote - first.buf);
+}
+
+simdjson_inline value &field::value() & noexcept {
+ return second;
+}
+
+simdjson_inline value field::value() && noexcept {
+ return std::forward<field>(*this).second;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::field &&value
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::field>(
+ std::forward<SIMDJSON_IMPLEMENTATION::ondemand::field>(value)
+ )
+{
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::simdjson_result(
+ error_code error
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::field>(error)
+{
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::key() noexcept {
+ if (error()) { return error(); }
+ return first.key();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::key_raw_json_token() noexcept {
+ if (error()) { return error(); }
+ return first.key_raw_json_token();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::escaped_key() noexcept {
+ if (error()) { return error(); }
+ return first.escaped_key();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::unescaped_key(bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.unescaped_key(allow_replacement);
+}
+
+template<typename string_type>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::unescaped_key(string_type &receiver, bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.unescaped_key(receiver, allow_replacement);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field>::value() noexcept {
+ if (error()) { return error(); }
+ return std::move(first.value());
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/field.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/field.h
new file mode 100644
index 0000000000..71344362f9
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/field.h
@@ -0,0 +1,113 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_FIELD_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/value.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A JSON field (key/value pair) in an object.
+ *
+ * Returned from object iteration.
+ *
+ * Extends from std::pair<raw_json_string, value> so you can use C++ algorithms that rely on pairs.
+ */
+class field : public std::pair<raw_json_string, value> {
+public:
+ /**
+ * Create a new invalid field.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline field() noexcept;
+
+ /**
+ * Get the key as a string_view (for higher speed, consider raw_key).
+ * We deliberately use a more cumbersome name (unescaped_key) to force users
+ * to think twice about using it.
+ *
+ * This consumes the key: once you have called unescaped_key(), you cannot
+ * call it again nor can you call key().
+ */
+ simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
+ /**
+ * Get the key as a string_view (for higher speed, consider raw_key).
+ * We deliberately use a more cumbersome name (unescaped_key) to force users
+ * to think twice about using it. The content is stored in the receiver.
+ *
+ * This consumes the key: once you have called unescaped_key(), you cannot
+ * call it again nor can you call key().
+ */
+ template <typename string_type>
+ simdjson_inline simdjson_warn_unused error_code unescaped_key(string_type& receiver, bool allow_replacement = false) noexcept;
+ /**
+ * Get the key as a raw_json_string. Can be used for direct comparison with
+ * an unescaped C string: e.g., key() == "test". This does not count as
+ * consumption of the content: you can safely call it repeatedly.
+ * See escaped_key() for a similar function which returns
+ * a more convenient std::string_view result.
+ */
+ simdjson_inline raw_json_string key() const noexcept;
+ /**
+ * Get the unprocessed key as a string_view. This includes the quotes and may include
+ * some spaces after the last quote. This does not count as
+ * consumption of the content: you can safely call it repeatedly.
+ * See escaped_key().
+ */
+ simdjson_inline std::string_view key_raw_json_token() const noexcept;
+ /**
+ * Get the key as a string_view. This does not include the quotes and
+ * the string is unprocessed key so it may contain escape characters
+ * (e.g., \uXXXX or \n). It does not count as a consumption of the content:
+ * you can safely call it repeatedly. Use unescaped_key() to get the unescaped key.
+ */
+ simdjson_inline std::string_view escaped_key() const noexcept;
+ /**
+ * Get the field value.
+ */
+ simdjson_inline ondemand::value &value() & noexcept;
+ /**
+ * @overload ondemand::value &ondemand::value() & noexcept
+ */
+ simdjson_inline ondemand::value value() && noexcept;
+
+protected:
+ simdjson_inline field(raw_json_string key, ondemand::value &&value) noexcept;
+ static simdjson_inline simdjson_result<field> start(value_iterator &parent_iter) noexcept;
+ static simdjson_inline simdjson_result<field> start(const value_iterator &parent_iter, raw_json_string key) noexcept;
+ friend struct simdjson_result<field>;
+ friend class object_iterator;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::field> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::field &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ simdjson_inline simdjson_result<std::string_view> unescaped_key(bool allow_replacement = false) noexcept;
+ template<typename string_type>
+ simdjson_inline error_code unescaped_key(string_type &receiver, bool allow_replacement = false) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> key() noexcept;
+ simdjson_inline simdjson_result<std::string_view> key_raw_json_token() noexcept;
+ simdjson_inline simdjson_result<std::string_view> escaped_key() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> value() noexcept;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator-inl.h
new file mode 100644
index 0000000000..6a054af813
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator-inl.h
@@ -0,0 +1,444 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H
+#include "simdjson/internal/dom_parser_implementation.h"
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/parser.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/logger-inl.h"
+#include "simdjson/generic/ondemand/parser-inl.h"
+#include "simdjson/generic/ondemand/token_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept
+ : token(std::forward<token_iterator>(other.token)),
+ parser{other.parser},
+ _string_buf_loc{other._string_buf_loc},
+ error{other.error},
+ _depth{other._depth},
+ _root{other._root},
+ _streaming{other._streaming}
+{
+ other.parser = nullptr;
+}
+simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept {
+ token = other.token;
+ parser = other.parser;
+ _string_buf_loc = other._string_buf_loc;
+ error = other.error;
+ _depth = other._depth;
+ _root = other._root;
+ _streaming = other._streaming;
+ other.parser = nullptr;
+ return *this;
+}
+
+simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept
+ : token(buf, &_parser->implementation->structural_indexes[0]),
+ parser{_parser},
+ _string_buf_loc{parser->string_buf.get()},
+ _depth{1},
+ _root{parser->implementation->structural_indexes.get()},
+ _streaming{false}
+
+{
+ logger::log_headers();
+#if SIMDJSON_CHECK_EOF
+ assert_more_tokens();
+#endif
+}
+
+#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser, bool streaming) noexcept
+ : token(buf, &_parser->implementation->structural_indexes[0]),
+ parser{_parser},
+ _string_buf_loc{parser->string_buf.get()},
+ _depth{1},
+ _root{parser->implementation->structural_indexes.get()},
+ _streaming{streaming}
+
+{
+ logger::log_headers();
+#if SIMDJSON_CHECK_EOF
+ assert_more_tokens();
+#endif
+}
+#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+
+inline void json_iterator::rewind() noexcept {
+ token.set_position( root_position() );
+ logger::log_headers(); // We start again
+ _string_buf_loc = parser->string_buf.get();
+ _depth = 1;
+}
+
+inline bool json_iterator::balanced() const noexcept {
+ token_iterator ti(token);
+ int32_t count{0};
+ ti.set_position( root_position() );
+ while(ti.peek() <= peek_last()) {
+ switch (*ti.return_current_and_advance())
+ {
+ case '[': case '{':
+ count++;
+ break;
+ case ']': case '}':
+ count--;
+ break;
+ default:
+ break;
+ }
+ }
+ return count == 0;
+}
+
+
+// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
+// relating depth and parent_depth, which is a desired effect. The warning does not show up if the
+// skip_child() function is not marked inline).
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept {
+ if (depth() <= parent_depth) { return SUCCESS; }
+ switch (*return_current_and_advance()) {
+ // TODO consider whether matching braces is a requirement: if non-matching braces indicates
+ // *missing* braces, then future lookups are not in the object/arrays they think they are,
+ // violating the rule "validate enough structure that the user can be confident they are
+ // looking at the right values."
+ // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
+
+ // For the first open array/object in a value, we've already incremented depth, so keep it the same
+ // We never stop at colon, but if we did, it wouldn't affect depth
+ case '[': case '{': case ':':
+ logger::log_start_value(*this, "skip");
+ break;
+ // If there is a comma, we have just finished a value in an array/object, and need to get back in
+ case ',':
+ logger::log_value(*this, "skip");
+ break;
+ // ] or } means we just finished a value and need to jump out of the array/object
+ case ']': case '}':
+ logger::log_end_value(*this, "skip");
+ _depth--;
+ if (depth() <= parent_depth) { return SUCCESS; }
+#if SIMDJSON_CHECK_EOF
+ // If there are no more tokens, the parent is incomplete.
+ if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); }
+#endif // SIMDJSON_CHECK_EOF
+ break;
+ case '"':
+ if(*peek() == ':') {
+ // We are at a key!!!
+ // This might happen if you just started an object and you skip it immediately.
+ // Performance note: it would be nice to get rid of this check as it is somewhat
+ // expensive.
+ // https://github.com/simdjson/simdjson/issues/1742
+ logger::log_value(*this, "key");
+ return_current_and_advance(); // eat up the ':'
+ break; // important!!!
+ }
+ simdjson_fallthrough;
+ // Anything else must be a scalar value
+ default:
+ // For the first scalar, we will have incremented depth already, so we decrement it here.
+ logger::log_value(*this, "skip");
+ _depth--;
+ if (depth() <= parent_depth) { return SUCCESS; }
+ break;
+ }
+
+ // Now that we've considered the first value, we only increment/decrement for arrays/objects
+ while (position() < end_position()) {
+ switch (*return_current_and_advance()) {
+ case '[': case '{':
+ logger::log_start_value(*this, "skip");
+ _depth++;
+ break;
+ // TODO consider whether matching braces is a requirement: if non-matching braces indicates
+ // *missing* braces, then future lookups are not in the object/arrays they think they are,
+ // violating the rule "validate enough structure that the user can be confident they are
+ // looking at the right values."
+ // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth
+ case ']': case '}':
+ logger::log_end_value(*this, "skip");
+ _depth--;
+ if (depth() <= parent_depth) { return SUCCESS; }
+ break;
+ default:
+ logger::log_value(*this, "skip", "");
+ break;
+ }
+ }
+
+ return report_error(TAPE_ERROR, "not enough close braces");
+}
+
+SIMDJSON_POP_DISABLE_WARNINGS
+
+simdjson_inline bool json_iterator::at_root() const noexcept {
+ return position() == root_position();
+}
+
+simdjson_inline bool json_iterator::is_single_token() const noexcept {
+ return parser->implementation->n_structural_indexes == 1;
+}
+
+simdjson_inline bool json_iterator::streaming() const noexcept {
+ return _streaming;
+}
+
+simdjson_inline token_position json_iterator::root_position() const noexcept {
+ return _root;
+}
+
+simdjson_inline void json_iterator::assert_at_document_depth() const noexcept {
+ SIMDJSON_ASSUME( _depth == 1 );
+}
+
+simdjson_inline void json_iterator::assert_at_root() const noexcept {
+ SIMDJSON_ASSUME( _depth == 1 );
+#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
+ // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument
+ // has side effects that will be discarded.
+ SIMDJSON_ASSUME( token.position() == _root );
+#endif
+}
+
+simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept {
+ assert_valid_position(token._position + required_tokens - 1);
+}
+
+simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept {
+#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
+ SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] );
+ SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] );
+#endif
+}
+
+simdjson_inline bool json_iterator::at_end() const noexcept {
+ return position() == end_position();
+}
+simdjson_inline token_position json_iterator::end_position() const noexcept {
+ uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
+ return &parser->implementation->structural_indexes[n_structural_indexes];
+}
+
+inline std::string json_iterator::to_string() const noexcept {
+ if( !is_alive() ) { return "dead json_iterator instance"; }
+ const char * current_structural = reinterpret_cast<const char *>(token.peek());
+ return std::string("json_iterator [ depth : ") + std::to_string(_depth)
+ + std::string(", structural : '") + std::string(current_structural,1)
+ + std::string("', offset : ") + std::to_string(token.current_offset())
+ + std::string("', error : ") + error_message(error)
+ + std::string(" ]");
+}
+
+inline simdjson_result<const char *> json_iterator::current_location() const noexcept {
+ if (!is_alive()) { // Unrecoverable error
+ if (!at_root()) {
+ return reinterpret_cast<const char *>(token.peek(-1));
+ } else {
+ return reinterpret_cast<const char *>(token.peek());
+ }
+ }
+ if (at_end()) {
+ return OUT_OF_BOUNDS;
+ }
+ return reinterpret_cast<const char *>(token.peek());
+}
+
+simdjson_inline bool json_iterator::is_alive() const noexcept {
+ return parser;
+}
+
+simdjson_inline void json_iterator::abandon() noexcept {
+ parser = nullptr;
+ _depth = 0;
+}
+
+simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept {
+#if SIMDJSON_CHECK_EOF
+ assert_more_tokens();
+#endif // SIMDJSON_CHECK_EOF
+ return token.return_current_and_advance();
+}
+
+simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept {
+ // deliberately done without safety guard:
+ return token.peek();
+}
+
+simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept {
+#if SIMDJSON_CHECK_EOF
+ assert_more_tokens(delta+1);
+#endif // SIMDJSON_CHECK_EOF
+ return token.peek(delta);
+}
+
+simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept {
+#if SIMDJSON_CHECK_EOF
+ assert_more_tokens(delta+1);
+#endif // #if SIMDJSON_CHECK_EOF
+ return token.peek_length(delta);
+}
+
+simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept {
+ // todo: currently we require end-of-string buffering, but the following
+ // assert_valid_position should be turned on if/when we lift that condition.
+ // assert_valid_position(position);
+ // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF
+ // is ON by default, we have no choice but to disable it for real with a comment.
+ return token.peek(position);
+}
+
+simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept {
+#if SIMDJSON_CHECK_EOF
+ assert_valid_position(position);
+#endif // SIMDJSON_CHECK_EOF
+ return token.peek_length(position);
+}
+simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept {
+#if SIMDJSON_CHECK_EOF
+ assert_valid_position(position);
+#endif // SIMDJSON_CHECK_EOF
+ return token.peek_root_length(position);
+}
+
+simdjson_inline token_position json_iterator::last_position() const noexcept {
+ // The following line fails under some compilers...
+ // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0);
+ // since it has side-effects.
+ uint32_t n_structural_indexes{parser->implementation->n_structural_indexes};
+ SIMDJSON_ASSUME(n_structural_indexes > 0);
+ return &parser->implementation->structural_indexes[n_structural_indexes - 1];
+}
+simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept {
+ return token.peek(last_position());
+}
+
+simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept {
+ SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1);
+ SIMDJSON_ASSUME(_depth == parent_depth + 1);
+ _depth = parent_depth;
+}
+
+simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept {
+ SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
+ SIMDJSON_ASSUME(_depth == child_depth - 1);
+ _depth = child_depth;
+}
+
+simdjson_inline depth_t json_iterator::depth() const noexcept {
+ return _depth;
+}
+
+simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept {
+ return _string_buf_loc;
+}
+
+simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept {
+ SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD);
+ logger::log_error(*this, message);
+ error = _error;
+ return error;
+}
+
+simdjson_inline token_position json_iterator::position() const noexcept {
+ return token.position();
+}
+
+simdjson_inline simdjson_result<std::string_view> json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ auto result = parser->unescape(in, _string_buf_loc, allow_replacement);
+ SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc));
+ return result;
+#else
+ return parser->unescape(in, _string_buf_loc, allow_replacement);
+#endif
+}
+
+simdjson_inline simdjson_result<std::string_view> json_iterator::unescape_wobbly(raw_json_string in) noexcept {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ auto result = parser->unescape_wobbly(in, _string_buf_loc);
+ SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc));
+ return result;
+#else
+ return parser->unescape_wobbly(in, _string_buf_loc);
+#endif
+}
+
+simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept {
+ SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX);
+ SIMDJSON_ASSUME(_depth == child_depth - 1);
+#if SIMDJSON_DEVELOPMENT_CHECKS
+#ifndef SIMDJSON_CLANG_VISUAL_STUDIO
+ SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth());
+ SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]);
+#endif
+#endif
+ token.set_position(position);
+ _depth = child_depth;
+}
+
+simdjson_inline error_code json_iterator::consume_character(char c) noexcept {
+ if (*peek() == c) {
+ return_current_and_advance();
+ return SUCCESS;
+ }
+ return TAPE_ERROR;
+}
+
+#if SIMDJSON_DEVELOPMENT_CHECKS
+
+simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept {
+ SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
+ return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0;
+}
+
+simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept {
+ SIMDJSON_ASSUME(size_t(depth) < parser->max_depth());
+ if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; }
+}
+
+#endif
+
+
+simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept {
+ SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD);
+ logger::log_error(*this, message);
+ return _error;
+}
+
+
+simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept {
+ // This function is not expected to be called in performance-sensitive settings.
+ // Let us guard against silly cases:
+ if((N < max_len) || (N == 0)) { return false; }
+ // Copy to the buffer.
+ std::memcpy(tmpbuf, json, max_len);
+ if(N > max_len) { // We pad whatever remains with ' '.
+ std::memset(tmpbuf + max_len, ' ', N - max_len);
+ }
+ return true;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator>(error) {}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator.h
new file mode 100644
index 0000000000..ee9872cb6c
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_iterator.h
@@ -0,0 +1,338 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/token_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * Iterates through JSON tokens, keeping track of depth and string buffer.
+ *
+ * @private This is not intended for external use.
+ */
+class json_iterator {
+protected:
+ token_iterator token{};
+ ondemand::parser *parser{};
+ /**
+ * Next free location in the string buffer.
+ *
+ * Used by raw_json_string::unescape() to have a place to unescape strings to.
+ */
+ uint8_t *_string_buf_loc{};
+ /**
+ * JSON error, if there is one.
+ *
+ * INCORRECT_TYPE and NO_SUCH_FIELD are *not* stored here, ever.
+ *
+ * PERF NOTE: we *hope* this will be elided into control flow, as it is only used (a) in the first
+ * iteration of the loop, or (b) for the final iteration after a missing comma is found in ++. If
+ * this is not elided, we should make sure it's at least not using up a register. Failing that,
+ * we should store it in document so there's only one of them.
+ */
+ error_code error{SUCCESS};
+ /**
+ * Depth of the current token in the JSON.
+ *
+ * - 0 = finished with document
+ * - 1 = document root value (could be [ or {, not yet known)
+ * - 2 = , or } inside root array/object
+ * - 3 = key or value inside root array/object.
+ */
+ depth_t _depth{};
+ /**
+ * Beginning of the document indexes.
+ * Normally we have root == parser->implementation->structural_indexes.get()
+ * but this may differ, especially in streaming mode (where we have several
+ * documents);
+ */
+ token_position _root{};
+ /**
+ * Normally, a json_iterator operates over a single document, but in
+ * some cases, we may have a stream of documents. This attribute is meant
+ * as meta-data: the json_iterator works the same irrespective of the
+ * value of this attribute.
+ */
+ bool _streaming{false};
+
+public:
+ simdjson_inline json_iterator() noexcept = default;
+ simdjson_inline json_iterator(json_iterator &&other) noexcept;
+ simdjson_inline json_iterator &operator=(json_iterator &&other) noexcept;
+ simdjson_inline explicit json_iterator(const json_iterator &other) noexcept = default;
+ simdjson_inline json_iterator &operator=(const json_iterator &other) noexcept = default;
+ /**
+ * Skips a JSON value, whether it is a scalar, array or object.
+ */
+ simdjson_warn_unused simdjson_inline error_code skip_child(depth_t parent_depth) noexcept;
+
+ /**
+ * Tell whether the iterator is still at the start
+ */
+ simdjson_inline bool at_root() const noexcept;
+
+ /**
+ * Tell whether we should be expected to run in streaming
+ * mode (iterating over many documents). It is pure metadata
+ * that does not affect how the iterator works. It is used by
+ * start_root_array() and start_root_object().
+ */
+ simdjson_inline bool streaming() const noexcept;
+
+ /**
+ * Get the root value iterator
+ */
+ simdjson_inline token_position root_position() const noexcept;
+ /**
+ * Assert that we are at the document depth (== 1)
+ */
+ simdjson_inline void assert_at_document_depth() const noexcept;
+ /**
+ * Assert that we are at the root of the document
+ */
+ simdjson_inline void assert_at_root() const noexcept;
+
+ /**
+ * Tell whether the iterator is at the EOF mark
+ */
+ simdjson_inline bool at_end() const noexcept;
+
+ /**
+ * Tell whether the iterator is live (has not been moved).
+ */
+ simdjson_inline bool is_alive() const noexcept;
+
+ /**
+ * Abandon this iterator, setting depth to 0 (as if the document is finished).
+ */
+ simdjson_inline void abandon() noexcept;
+
+ /**
+ * Advance the current token without modifying depth.
+ */
+ simdjson_inline const uint8_t *return_current_and_advance() noexcept;
+
+ /**
+ * Returns true if there is a single token in the index (i.e., it is
+ * a JSON with a scalar value such as a single number).
+ *
+ * @return whether there is a single token
+ */
+ simdjson_inline bool is_single_token() const noexcept;
+
+ /**
+ * Assert that there are at least the given number of tokens left.
+ *
+ * Has no effect in release builds.
+ */
+ simdjson_inline void assert_more_tokens(uint32_t required_tokens=1) const noexcept;
+ /**
+ * Assert that the given position addresses an actual token (is within bounds).
+ *
+ * Has no effect in release builds.
+ */
+ simdjson_inline void assert_valid_position(token_position position) const noexcept;
+ /**
+ * Get the JSON text for a given token (relative).
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
+ *
+ * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
+ * it is not used ...
+ */
+ simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for the current token (or relative).
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param delta The relative position of the token to retrieve. e.g. 0 = next token, -1 = prev token.
+ */
+ simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
+ /**
+ * Get a pointer to the current location in the input buffer.
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * You may be pointing outside of the input buffer: it is not generally
+ * safe to dereference this pointer.
+ */
+ simdjson_inline const uint8_t *unsafe_pointer() const noexcept;
+ /**
+ * Get the JSON text for a given token.
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param position The position of the token to retrieve.
+ *
+ * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
+ * it is not used ...
+ */
+ simdjson_inline const uint8_t *peek(token_position position) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for the current token (or relative).
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param position The position of the token to retrieve.
+ */
+ simdjson_inline uint32_t peek_length(token_position position) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for the current root token.
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param position The position of the token to retrieve.
+ */
+ simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
+ /**
+ * Get the JSON text for the last token in the document.
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
+ * it is not used ...
+ */
+ simdjson_inline const uint8_t *peek_last() const noexcept;
+
+ /**
+ * Ascend one level.
+ *
+ * Validates that the depth - 1 == parent_depth.
+ *
+ * @param parent_depth the expected parent depth.
+ */
+ simdjson_inline void ascend_to(depth_t parent_depth) noexcept;
+
+ /**
+ * Descend one level.
+ *
+ * Validates that the new depth == child_depth.
+ *
+ * @param child_depth the expected child depth.
+ */
+ simdjson_inline void descend_to(depth_t child_depth) noexcept;
+ simdjson_inline void descend_to(depth_t child_depth, int32_t delta) noexcept;
+
+ /**
+ * Get current depth.
+ */
+ simdjson_inline depth_t depth() const noexcept;
+
+ /**
+ * Get current (writeable) location in the string buffer.
+ */
+ simdjson_inline uint8_t *&string_buf_loc() noexcept;
+
+ /**
+ * Report an unrecoverable error, preventing further iteration.
+ *
+ * @param error The error to report. Must not be SUCCESS, UNINITIALIZED, INCORRECT_TYPE, or NO_SUCH_FIELD.
+ * @param message An error message to report with the error.
+ */
+ simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
+
+ /**
+ * Log error, but don't stop iteration.
+ * @param error The error to report. Must be INCORRECT_TYPE, or NO_SUCH_FIELD.
+ * @param message An error message to report with the error.
+ */
+ simdjson_inline error_code optional_error(error_code error, const char *message) noexcept;
+
+ /**
+ * Take an input in json containing max_len characters and attempt to copy it over to tmpbuf, a buffer with
+ * N bytes of capacity. It will return false if N is too small (smaller than max_len) of if it is zero.
+ * The buffer (tmpbuf) is padded with space characters.
+ */
+ simdjson_warn_unused simdjson_inline bool copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept;
+
+ simdjson_inline token_position position() const noexcept;
+ /**
+ * Write the raw_json_string to the string buffer and return a string_view.
+ * Each raw_json_string should be unescaped once, or else the string buffer might
+ * overflow.
+ */
+ simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, bool allow_replacement) noexcept;
+ simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in) noexcept;
+
+ simdjson_inline void reenter_child(token_position position, depth_t child_depth) noexcept;
+
+ simdjson_inline error_code consume_character(char c) noexcept;
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ simdjson_inline token_position start_position(depth_t depth) const noexcept;
+ simdjson_inline void set_start_position(depth_t depth, token_position position) noexcept;
+#endif
+
+ /* Useful for debugging and logging purposes. */
+ inline std::string to_string() const noexcept;
+
+ /**
+ * Returns the current location in the document if in bounds.
+ */
+ inline simdjson_result<const char *> current_location() const noexcept;
+
+ /**
+ * Updates this json iterator so that it is back at the beginning of the document,
+ * as if it had just been created.
+ */
+ inline void rewind() noexcept;
+ /**
+ * This checks whether the {,},[,] are balanced so that the document
+ * ends with proper zero depth. This requires scanning the whole document
+ * and it may be expensive. It is expected that it will be rarely called.
+ * It does not attempt to match { with } and [ with ].
+ */
+ inline bool balanced() const noexcept;
+protected:
+ simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;
+#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+ simdjson_inline json_iterator(const uint8_t *buf, ondemand::parser *parser, bool streaming) noexcept;
+#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+ /// The last token before the end
+ simdjson_inline token_position last_position() const noexcept;
+ /// The token *at* the end. This points at gibberish and should only be used for comparison.
+ simdjson_inline token_position end_position() const noexcept;
+ /// The end of the buffer.
+ simdjson_inline token_position end() const noexcept;
+
+ friend class document;
+ friend class document_stream;
+ friend class object;
+ friend class array;
+ friend class value;
+ friend class raw_json_string;
+ friend class parser;
+ friend class value_iterator;
+ friend class field;
+ template <typename... Args>
+ friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
+ template <typename... Args>
+ friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
+}; // json_iterator
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_iterator> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+
+ simdjson_inline simdjson_result() noexcept = default;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type-inl.h
new file mode 100644
index 0000000000..7fa5eeb30f
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type-inl.h
@@ -0,0 +1,117 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/json_type.h"
+#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept {
+ switch (type) {
+ case json_type::array: out << "array"; break;
+ case json_type::object: out << "object"; break;
+ case json_type::number: out << "number"; break;
+ case json_type::string: out << "string"; break;
+ case json_type::boolean: out << "boolean"; break;
+ case json_type::null: out << "null"; break;
+ default: SIMDJSON_UNREACHABLE();
+ }
+ return out;
+}
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false) {
+ return out << type.value();
+}
+#endif
+
+
+
+simdjson_inline number_type number::get_number_type() const noexcept {
+ return type;
+}
+
+simdjson_inline bool number::is_uint64() const noexcept {
+ return get_number_type() == number_type::unsigned_integer;
+}
+
+simdjson_inline uint64_t number::get_uint64() const noexcept {
+ return payload.unsigned_integer;
+}
+
+simdjson_inline number::operator uint64_t() const noexcept {
+ return get_uint64();
+}
+
+simdjson_inline bool number::is_int64() const noexcept {
+ return get_number_type() == number_type::signed_integer;
+}
+
+simdjson_inline int64_t number::get_int64() const noexcept {
+ return payload.signed_integer;
+}
+
+simdjson_inline number::operator int64_t() const noexcept {
+ return get_int64();
+}
+
+simdjson_inline bool number::is_double() const noexcept {
+ return get_number_type() == number_type::floating_point_number;
+}
+
+simdjson_inline double number::get_double() const noexcept {
+ return payload.floating_point_number;
+}
+
+simdjson_inline number::operator double() const noexcept {
+ return get_double();
+}
+
+simdjson_inline double number::as_double() const noexcept {
+ if(is_double()) {
+ return payload.floating_point_number;
+ }
+ if(is_int64()) {
+ return double(payload.signed_integer);
+ }
+ return double(payload.unsigned_integer);
+}
+
+simdjson_inline void number::append_s64(int64_t value) noexcept {
+ payload.signed_integer = value;
+ type = number_type::signed_integer;
+}
+
+simdjson_inline void number::append_u64(uint64_t value) noexcept {
+ payload.unsigned_integer = value;
+ type = number_type::unsigned_integer;
+}
+
+simdjson_inline void number::append_double(double value) noexcept {
+ payload.floating_point_number = value;
+ type = number_type::floating_point_number;
+}
+
+simdjson_inline void number::skip_double() noexcept {
+ type = number_type::floating_point_number;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::json_type &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_type>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::json_type>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_type>(error) {}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type.h
new file mode 100644
index 0000000000..b5a970433e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/json_type.h
@@ -0,0 +1,160 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/numberparsing.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * The type of a JSON value.
+ */
+enum class json_type {
+ // Start at 1 to catch uninitialized / default values more easily
+ array=1, ///< A JSON array ( [ 1, 2, 3 ... ] )
+ object, ///< A JSON object ( { "a": 1, "b" 2, ... } )
+ number, ///< A JSON number ( 1 or -2.3 or 4.5e6 ...)
+ string, ///< A JSON string ( "a" or "hello world\n" ...)
+ boolean, ///< A JSON boolean (true or false)
+ null ///< A JSON null (null)
+};
+
+/**
+ * A type representing a JSON number.
+ * The design of the struct is deliberately straight-forward. All
+ * functions return standard values with no error check.
+ */
+struct number {
+
+ /**
+ * return the automatically determined type of
+ * the number: number_type::floating_point_number,
+ * number_type::signed_integer or number_type::unsigned_integer.
+ *
+ * enum class number_type {
+ * floating_point_number=1, /// a binary64 number
+ * signed_integer, /// a signed integer that fits in a 64-bit word using two's complement
+ * unsigned_integer /// a positive integer larger or equal to 1<<63
+ * };
+ */
+ simdjson_inline ondemand::number_type get_number_type() const noexcept;
+ /**
+ * return true if the automatically determined type of
+ * the number is number_type::unsigned_integer.
+ */
+ simdjson_inline bool is_uint64() const noexcept;
+ /**
+ * return the value as a uint64_t, only valid if is_uint64() is true.
+ */
+ simdjson_inline uint64_t get_uint64() const noexcept;
+ simdjson_inline operator uint64_t() const noexcept;
+
+ /**
+ * return true if the automatically determined type of
+ * the number is number_type::signed_integer.
+ */
+ simdjson_inline bool is_int64() const noexcept;
+ /**
+ * return the value as a int64_t, only valid if is_int64() is true.
+ */
+ simdjson_inline int64_t get_int64() const noexcept;
+ simdjson_inline operator int64_t() const noexcept;
+
+
+ /**
+ * return true if the automatically determined type of
+ * the number is number_type::floating_point_number.
+ */
+ simdjson_inline bool is_double() const noexcept;
+ /**
+ * return the value as a double, only valid if is_double() is true.
+ */
+ simdjson_inline double get_double() const noexcept;
+ simdjson_inline operator double() const noexcept;
+
+ /**
+ * Convert the number to a double. Though it always succeed, the conversion
+ * may be lossy if the number cannot be represented exactly.
+ */
+ simdjson_inline double as_double() const noexcept;
+
+
+protected:
+ /**
+ * The next block of declaration is designed so that we can call the number parsing
+ * functions on a number type. They are protected and should never be used outside
+ * of the core simdjson library.
+ */
+ friend class value_iterator;
+ template<typename W>
+ friend error_code numberparsing::write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, size_t digit_count, int64_t exponent, W &writer);
+ template<typename W>
+ friend error_code numberparsing::parse_number(const uint8_t *const src, W &writer);
+ /** Store a signed 64-bit value to the number. */
+ simdjson_inline void append_s64(int64_t value) noexcept;
+ /** Store an unsigned 64-bit value to the number. */
+ simdjson_inline void append_u64(uint64_t value) noexcept;
+ /** Store a double value to the number. */
+ simdjson_inline void append_double(double value) noexcept;
+ /** Specifies that the value is a double, but leave it undefined. */
+ simdjson_inline void skip_double() noexcept;
+ /**
+ * End of friend declarations.
+ */
+
+ /**
+ * Our attributes are a union type (size = 64 bits)
+ * followed by a type indicator.
+ */
+ union {
+ double floating_point_number;
+ int64_t signed_integer;
+ uint64_t unsigned_integer;
+ } payload{0};
+ number_type type{number_type::signed_integer};
+};
+
+/**
+ * Write the JSON type to the output stream
+ *
+ * @param out The output stream.
+ * @param type The json_type.
+ */
+inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+/**
+ * Send JSON type to an output stream.
+ *
+ * @param out The output stream.
+ * @param type The json_type.
+ * @throw simdjson_error if the result being printed has an error. If there is an error with the
+ * underlying output stream, that error will be propagated (simdjson_error will not be
+ * thrown).
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson_result<json_type> &type) noexcept(false);
+#endif
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::json_type> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::json_type &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+ simdjson_inline ~simdjson_result() noexcept = default; ///< @private
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger-inl.h
new file mode 100644
index 0000000000..268fb2d1be
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger-inl.h
@@ -0,0 +1,225 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/logger.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#include <memory>
+#include <cstring>
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+namespace logger {
+
+static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------";
+static constexpr const int LOG_EVENT_LEN = 20;
+static constexpr const int LOG_BUFFER_LEN = 30;
+static constexpr const int LOG_SMALL_BUFFER_LEN = 10;
+static int log_depth = 0; // Not threadsafe. Log only.
+
+// Helper to turn unprintable or newline characters into spaces
+static inline char printable_char(char c) {
+ if (c >= 0x20) {
+ return c;
+ } else {
+ return ' ';
+ }
+}
+
+template<typename... Args>
+static inline std::string string_format(const std::string& format, const Args&... args)
+{
+ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
+ int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
+ auto size = static_cast<size_t>(size_s);
+ if (size <= 0) return std::string();
+ std::unique_ptr<char[]> buf(new char[size]);
+ std::snprintf(buf.get(), size, format.c_str(), args...);
+ SIMDJSON_POP_DISABLE_WARNINGS
+ return std::string(buf.get(), buf.get() + size - 1);
+}
+
+static inline log_level get_log_level_from_env()
+{
+ SIMDJSON_PUSH_DISABLE_WARNINGS
+ SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
+ char *lvl = getenv("SIMDJSON_LOG_LEVEL");
+ SIMDJSON_POP_DISABLE_WARNINGS
+ if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; }
+ return log_level::info;
+}
+
+static inline log_level log_threshold()
+{
+ static log_level threshold = get_log_level_from_env();
+ return threshold;
+}
+
+static inline bool should_log(log_level level)
+{
+ return level >= log_threshold();
+}
+
+inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
+ log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
+}
+
+inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
+ log_line(iter, index, depth, "", type, detail, log_level::info);
+}
+inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
+ log_line(iter, "", type, detail, delta, depth_delta, log_level::info);
+}
+
+inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept {
+ log_line(iter, index, depth, "+", type, detail, log_level::info);
+ if (LOG_ENABLED) { log_depth++; }
+}
+inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
+ log_line(iter, "+", type, "", delta, depth_delta, log_level::info);
+ if (LOG_ENABLED) { log_depth++; }
+}
+
+inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
+ if (LOG_ENABLED) { log_depth--; }
+ log_line(iter, "-", type, "", delta, depth_delta, log_level::info);
+}
+
+inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
+ log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error);
+}
+inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept {
+ log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error);
+}
+
+inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
+ log_event(iter.json_iter(), type, detail, delta, depth_delta);
+}
+
+inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept {
+ log_value(iter.json_iter(), type, detail, delta, depth_delta);
+}
+
+inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
+ log_start_value(iter.json_iter(), type, delta, depth_delta);
+}
+
+inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept {
+ log_end_value(iter.json_iter(), type, delta, depth_delta);
+}
+
+inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept {
+ log_error(iter.json_iter(), error, detail, delta, depth_delta);
+}
+
+inline void log_headers() noexcept {
+ if (LOG_ENABLED) {
+ if (simdjson_unlikely(should_log(log_level::info))) {
+ // Technically a static variable is not thread-safe, but if you are using threads and logging... well...
+ static bool displayed_hint{false};
+ log_depth = 0;
+ printf("\n");
+ if (!displayed_hint) {
+ // We only print this helpful header once.
+ printf("# Logging provides the depth and position of the iterator user-visible steps:\n");
+ printf("# +array says 'this is where we were when we discovered the start array'\n");
+ printf(
+ "# -array says 'this is where we were when we ended the array'\n");
+ printf("# skip says 'this is a structural or value I am skipping'\n");
+ printf("# +/-skip says 'this is a start/end array or object I am skipping'\n");
+ printf("#\n");
+ printf("# The indentation of the terms (array, string,...) indicates the depth,\n");
+ printf("# in addition to the depth being displayed.\n");
+ printf("#\n");
+ printf("# Every token in the document has a single depth determined by the tokens before it,\n");
+ printf("# and is not affected by what the token actually is.\n");
+ printf("#\n");
+ printf("# Not all structural elements are presented as tokens in the logs.\n");
+ printf("#\n");
+ printf("# We never give control to the user within an empty array or an empty object.\n");
+ printf("#\n");
+ printf("# Inside an array, having a depth greater than the array's depth means that\n");
+ printf("# we are pointing inside a value.\n");
+ printf("# Having a depth equal to the array means that we are pointing right before a value.\n");
+ printf("# Having a depth smaller than the array means that we have moved beyond the array.\n");
+ displayed_hint = true;
+ }
+ printf("\n");
+ printf("| %-*s ", LOG_EVENT_LEN, "Event");
+ printf("| %-*s ", LOG_BUFFER_LEN, "Buffer");
+ printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next");
+ // printf("| %-*s ", 5, "Next#");
+ printf("| %-*s ", 5, "Depth");
+ printf("| Detail ");
+ printf("|\n");
+
+ printf("|%.*s", LOG_EVENT_LEN + 2, DASHES);
+ printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES);
+ printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES);
+ // printf("|%.*s", 5+2, DASHES);
+ printf("|%.*s", 5 + 2, DASHES);
+ printf("|--------");
+ printf("|\n");
+ fflush(stdout);
+ }
+ }
+}
+
+template <typename... Args>
+inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept {
+ log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward<Args>(args)...);
+}
+
+template <typename... Args>
+inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept {
+ if (LOG_ENABLED) {
+ if (simdjson_unlikely(should_log(level))) {
+ const int indent = depth * 2;
+ const auto buf = iter.token.buf;
+ auto msg = string_format(title, std::forward<Args>(args)...);
+ printf("| %*s%s%-*s ", indent, "", title_prefix,
+ LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str());
+ {
+ // Print the current structural.
+ printf("| ");
+ // Before we begin, the index might point right before the document.
+ // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938
+ if (index < iter._root) {
+ printf("%*s", LOG_BUFFER_LEN, "");
+ } else {
+ auto current_structural = &buf[*index];
+ for (int i = 0; i < LOG_BUFFER_LEN; i++) {
+ printf("%c", printable_char(current_structural[i]));
+ }
+ }
+ printf(" ");
+ }
+ {
+ // Print the next structural.
+ printf("| ");
+ auto next_structural = &buf[*(index + 1)];
+ for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) {
+ printf("%c", printable_char(next_structural[i]));
+ }
+ printf(" ");
+ }
+ // printf("| %5u ", *(index+1));
+ printf("| %5i ", depth);
+ printf("| %6.*s ", int(detail.size()), detail.data());
+ printf("|\n");
+ fflush(stdout);
+ }
+ }
+}
+
+} // namespace logger
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger.h
new file mode 100644
index 0000000000..7696600f98
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/logger.h
@@ -0,0 +1,58 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_LOGGER_H
+#include "simdjson/generic/ondemand/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+// Logging should be free unless SIMDJSON_VERBOSE_LOGGING is set. Importantly, it is critical
+// that the call to the log functions be side-effect free. Thus, for example, you should not
+// create temporary std::string instances.
+namespace logger {
+
+enum class log_level : int32_t {
+ info = 0,
+ error = 1
+};
+
+#if SIMDJSON_VERBOSE_LOGGING
+ static constexpr const bool LOG_ENABLED = true;
+#else
+ static constexpr const bool LOG_ENABLED = false;
+#endif
+
+// We do not want these functions to be 'really inlined' since real inlining is
+// for performance purposes and if you are using the loggers, you do not care about
+// performance (or should not).
+static inline void log_headers() noexcept;
+// If args are provided, title will be treated as format string
+template <typename... Args>
+static inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
+template <typename... Args>
+static inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
+static inline void log_event(const json_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
+static inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
+static inline void log_value(const json_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
+static inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail="") noexcept;
+static inline void log_start_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
+static inline void log_end_value(const json_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
+
+static inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail="") noexcept;
+static inline void log_error(const json_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
+
+static inline void log_event(const value_iterator &iter, const char *type, std::string_view detail="", int delta=0, int depth_delta=0) noexcept;
+static inline void log_value(const value_iterator &iter, const char *type, std::string_view detail="", int delta=-1, int depth_delta=0) noexcept;
+static inline void log_start_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
+static inline void log_end_value(const value_iterator &iter, const char *type, int delta=-1, int depth_delta=0) noexcept;
+static inline void log_error(const value_iterator &iter, const char *error, const char *detail="", int delta=-1, int depth_delta=0) noexcept;
+
+} // namespace logger
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/object-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object-inl.h
new file mode 100644
index 0000000000..624d668383
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object-inl.h
@@ -0,0 +1,276 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/field.h"
+#include "simdjson/generic/ondemand/object.h"
+#include "simdjson/generic/ondemand/object_iterator.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/value-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) & noexcept {
+ bool has_value;
+ SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
+ if (!has_value) {
+ logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
+ return NO_SUCH_FIELD;
+ }
+ return value(iter.child());
+}
+simdjson_inline simdjson_result<value> object::find_field_unordered(const std::string_view key) && noexcept {
+ bool has_value;
+ SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) );
+ if (!has_value) {
+ logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
+ return NO_SUCH_FIELD;
+ }
+ return value(iter.child());
+}
+simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) & noexcept {
+ return find_field_unordered(key);
+}
+simdjson_inline simdjson_result<value> object::operator[](const std::string_view key) && noexcept {
+ return std::forward<object>(*this).find_field_unordered(key);
+}
+simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) & noexcept {
+ bool has_value;
+ SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
+ if (!has_value) {
+ logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
+ return NO_SUCH_FIELD;
+ }
+ return value(iter.child());
+}
+simdjson_inline simdjson_result<value> object::find_field(const std::string_view key) && noexcept {
+ bool has_value;
+ SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) );
+ if (!has_value) {
+ logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast<int>(key.size()), key.data());
+ return NO_SUCH_FIELD;
+ }
+ return value(iter.child());
+}
+
+simdjson_inline simdjson_result<object> object::start(value_iterator &iter) noexcept {
+ SIMDJSON_TRY( iter.start_object().error() );
+ return object(iter);
+}
+simdjson_inline simdjson_result<object> object::start_root(value_iterator &iter) noexcept {
+ SIMDJSON_TRY( iter.start_root_object().error() );
+ return object(iter);
+}
+simdjson_inline error_code object::consume() noexcept {
+ if(iter.is_at_key()) {
+ /**
+ * whenever you are pointing at a key, calling skip_child() is
+ * unsafe because you will hit a string and you will assume that
+ * it is string value, and this mistake will lead you to make bad
+ * depth computation.
+ */
+ /**
+ * We want to 'consume' the key. We could really
+ * just do _json_iter->return_current_and_advance(); at this
+ * point, but, for clarity, we will use the high-level API to
+ * eat the key. We assume that the compiler optimizes away
+ * most of the work.
+ */
+ simdjson_unused raw_json_string actual_key;
+ auto error = iter.field_key().get(actual_key);
+ if (error) { iter.abandon(); return error; };
+ // Let us move to the value while we are at it.
+ if ((error = iter.field_value())) { iter.abandon(); return error; }
+ }
+ auto error_skip = iter.json_iter().skip_child(iter.depth()-1);
+ if(error_skip) { iter.abandon(); }
+ return error_skip;
+}
+
+simdjson_inline simdjson_result<std::string_view> object::raw_json() noexcept {
+ const uint8_t * starting_point{iter.peek_start()};
+ auto error = consume();
+ if(error) { return error; }
+ const uint8_t * final_point{iter._json_iter->peek()};
+ return std::string_view(reinterpret_cast<const char*>(starting_point), size_t(final_point - starting_point));
+}
+
+simdjson_inline simdjson_result<object> object::started(value_iterator &iter) noexcept {
+ SIMDJSON_TRY( iter.started_object().error() );
+ return object(iter);
+}
+
+simdjson_inline object object::resume(const value_iterator &iter) noexcept {
+ return iter;
+}
+
+simdjson_inline object::object(const value_iterator &_iter) noexcept
+ : iter{_iter}
+{
+}
+
+simdjson_inline simdjson_result<object_iterator> object::begin() noexcept {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ return object_iterator(iter);
+}
+simdjson_inline simdjson_result<object_iterator> object::end() noexcept {
+ return object_iterator(iter);
+}
+
+inline simdjson_result<value> object::at_pointer(std::string_view json_pointer) noexcept {
+ if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; }
+ json_pointer = json_pointer.substr(1);
+ size_t slash = json_pointer.find('/');
+ std::string_view key = json_pointer.substr(0, slash);
+ // Grab the child with the given key
+ simdjson_result<value> child;
+
+ // If there is an escape character in the key, unescape it and then get the child.
+ size_t escape = key.find('~');
+ if (escape != std::string_view::npos) {
+ // Unescape the key
+ std::string unescaped(key);
+ do {
+ switch (unescaped[escape+1]) {
+ case '0':
+ unescaped.replace(escape, 2, "~");
+ break;
+ case '1':
+ unescaped.replace(escape, 2, "/");
+ break;
+ default:
+ return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer");
+ }
+ escape = unescaped.find('~', escape+1);
+ } while (escape != std::string::npos);
+ child = find_field(unescaped); // Take note find_field does not unescape keys when matching
+ } else {
+ child = find_field(key);
+ }
+ if(child.error()) {
+ return child; // we do not continue if there was an error
+ }
+ // If there is a /, we have to recurse and look up more of the path
+ if (slash != std::string_view::npos) {
+ child = child.at_pointer(json_pointer.substr(slash));
+ }
+ return child;
+}
+
+inline simdjson_result<value> object::at_path(std::string_view json_path) noexcept {
+ auto json_pointer = json_path_to_pointer_conversion(json_path);
+ if (json_pointer == "-1") {
+ return INVALID_JSON_POINTER;
+ }
+ return at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<size_t> object::count_fields() & noexcept {
+ size_t count{0};
+ // Important: we do not consume any of the values.
+ for(simdjson_unused auto v : *this) { count++; }
+ // The above loop will always succeed, but we want to report errors.
+ if(iter.error()) { return iter.error(); }
+ // We need to move back at the start because we expect users to iterate through
+ // the object after counting the number of elements.
+ iter.reset_object();
+ return count;
+}
+
+simdjson_inline simdjson_result<bool> object::is_empty() & noexcept {
+ bool is_not_empty;
+ auto error = iter.reset_object().get(is_not_empty);
+ if(error) { return error; }
+ return !is_not_empty;
+}
+
+simdjson_inline simdjson_result<bool> object::reset() & noexcept {
+ return iter.reset_object();
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::object &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object>(error) {}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::begin() noexcept {
+ if (error()) { return error(); }
+ return first.begin();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::end() noexcept {
+ if (error()) { return error(); }
+ return first.end();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field_unordered(std::string_view key) && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::operator[](std::string_view key) && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first)[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) & noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::find_field(std::string_view key) && noexcept {
+ if (error()) { return error(); }
+ return std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object>(first).find_field(key);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::at_pointer(std::string_view json_pointer) noexcept {
+ if (error()) { return error(); }
+ return first.at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::at_path(
+ std::string_view json_path) noexcept {
+ if (error()) {
+ return error();
+ }
+ return first.at_path(json_path);
+}
+
+inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::reset() noexcept {
+ if (error()) { return error(); }
+ return first.reset();
+}
+
+inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::is_empty() noexcept {
+ if (error()) { return error(); }
+ return first.is_empty();
+}
+
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::count_fields() & noexcept {
+ if (error()) { return error(); }
+ return first.count_fields();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object>::raw_json() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json();
+}
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/object.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object.h
new file mode 100644
index 0000000000..8e3ed9af39
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object.h
@@ -0,0 +1,258 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A forward-only JSON object field iterator.
+ */
+class object {
+public:
+ /**
+ * Create a new invalid object.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline object() noexcept = default;
+
+ simdjson_inline simdjson_result<object_iterator> begin() noexcept;
+ simdjson_inline simdjson_result<object_iterator> end() noexcept;
+ /**
+ * Look up a field by name on an object (order-sensitive).
+ *
+ * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
+ * JSON `{ "x": 1, "y": 2, "z": 3 }`:
+ *
+ * ```c++
+ * simdjson::ondemand::parser parser;
+ * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
+ * double z = obj.find_field("z");
+ * double y = obj.find_field("y");
+ * double x = obj.find_field("x");
+ * ```
+ * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
+ * that only one field is returned.
+ *
+ * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
+ * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
+ *
+ * You must consume the fields on an object one at a time. A request for a new key
+ * invalidates previous field values: it makes them unsafe. The value instance you get
+ * from `content["bids"]` becomes invalid when you call `content["asks"]`. The array
+ * given by content["bids"].get_array() should not be accessed after you have called
+ * content["asks"].get_array(). You can detect such mistakes by first compiling and running
+ * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
+ * OUT_OF_ORDER_ITERATION error is generated.
+ *
+ * You are expected to access keys only once. You should access the value corresponding to a
+ * key a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string()
+ * is an error.
+ *
+ * If you expect to have keys with escape characters, please review our documentation.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> find_field(std::string_view key) && noexcept;
+
+ /**
+ * Look up a field by name on an object, without regard to key order.
+ *
+ * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
+ * and often appears negligible. It starts out normally, starting out at the last field; but if
+ * the field is not found, it scans from the beginning of the object to see if it missed it. That
+ * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
+ * in question is large. The fact that the extra code is there also bumps the executable size.
+ *
+ * It is the default, however, because it would be highly surprising (and hard to debug) if the
+ * default behavior failed to look up a field just because it was in the wrong order--and many
+ * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
+ *
+ * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
+ * field was not there when they are not in order).
+ *
+ * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
+ * that only one field is returned.
+ *
+ * You must consume the fields on an object one at a time. A request for a new key
+ * invalidates previous field values: it makes them unsafe. The value instance you get
+ * from `content["bids"]` becomes invalid when you call `content["asks"]`. The array
+ * given by content["bids"].get_array() should not be accessed after you have called
+ * content["asks"].get_array(). You can detect such mistakes by first compiling and running
+ * the code in Debug mode (or with the macro `SIMDJSON_DEVELOPMENT_CHECKS` set to 1): an
+ * OUT_OF_ORDER_ITERATION error is generated.
+ *
+ * You are expected to access keys only once. You should access the value corresponding to a key
+ * a single time. Doing object["mykey"].to_string() and then again object["mykey"].to_string() is an error.
+ *
+ * If you expect to have keys with escape characters, please review our documentation.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) && noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> operator[](std::string_view key) & noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) & noexcept; */
+ simdjson_inline simdjson_result<value> operator[](std::string_view key) && noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard, interpreting the current node
+ * as the root of its own JSON document.
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("/foo/a/1") == 20
+ *
+ * It is allowed for a key to be the empty string:
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("//a/1") == 20
+ *
+ * Note that at_pointer() called on the document automatically calls the document's rewind
+ * method between each call. It invalidates all previously accessed arrays, objects and values
+ * that have not been consumed. Yet it is not the case when calling at_pointer on an object
+ * instance: there is no rewind and no invalidation.
+ *
+ * You may call at_pointer more than once on an object, but each time the pointer is advanced
+ * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
+ * key (as well as the current key) can no longer be used with following JSON pointer calls.
+ *
+ * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching.
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
+
+ /**
+ * Get the value associated with the given JSONPath expression. We only support
+ * JSONPath queries that trivially convertible to JSON Pointer queries: key
+ * names and array indices.
+ *
+ * @return The value associated with the given JSONPath expression, or:
+ * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ */
+ inline simdjson_result<value> at_path(std::string_view json_path) noexcept;
+
+ /**
+ * Reset the iterator so that we are pointing back at the
+ * beginning of the object. You should still consume values only once even if you
+ * can iterate through the object more than once. If you unescape a string or a key
+ * within the object more than once, you have unsafe code. Note that rewinding an object
+ * means that you may need to reparse it anew: it is not a free operation.
+ *
+ * @returns true if the object contains some elements (not empty)
+ */
+ inline simdjson_result<bool> reset() & noexcept;
+ /**
+ * This method scans the beginning of the object and checks whether the
+ * object is empty.
+ * The runtime complexity is constant time. After
+ * calling this function, if successful, the object is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ */
+ inline simdjson_result<bool> is_empty() & noexcept;
+ /**
+ * This method scans the object and counts the number of key-value pairs.
+ * The count_fields method should always be called before you have begun
+ * iterating through the object: it is expected that you are pointing at
+ * the beginning of the object.
+ * The runtime complexity is linear in the size of the object. After
+ * calling this function, if successful, the object is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ *
+ * To check that an object is empty, it is more performant to use
+ * the is_empty() method.
+ *
+ * Performance hint: You should only call count_fields() as a last
+ * resort as it may require scanning the document twice or more.
+ */
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ /**
+ * Consumes the object and returns a string_view instance corresponding to the
+ * object as represented in JSON. It points inside the original byte array containing
+ * the JSON document.
+ */
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+
+protected:
+ /**
+ * Go to the end of the object, no matter where you are right now.
+ */
+ simdjson_inline error_code consume() noexcept;
+ static simdjson_inline simdjson_result<object> start(value_iterator &iter) noexcept;
+ static simdjson_inline simdjson_result<object> start_root(value_iterator &iter) noexcept;
+ static simdjson_inline simdjson_result<object> started(value_iterator &iter) noexcept;
+ static simdjson_inline object resume(const value_iterator &iter) noexcept;
+ simdjson_inline object(const value_iterator &iter) noexcept;
+
+ simdjson_warn_unused simdjson_inline error_code find_field_raw(const std::string_view key) noexcept;
+
+ value_iterator iter{};
+
+ friend class value;
+ friend class document;
+ friend struct simdjson_result<object>;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::object &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> begin() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> end() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) && noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) && noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) && noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_path(std::string_view json_path) noexcept;
+
+ inline simdjson_result<bool> reset() noexcept;
+ inline simdjson_result<bool> is_empty() noexcept;
+ inline simdjson_result<size_t> count_fields() & noexcept;
+ inline simdjson_result<std::string_view> raw_json() noexcept;
+
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator-inl.h
new file mode 100644
index 0000000000..36294ce718
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator-inl.h
@@ -0,0 +1,138 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/object_iterator.h"
+#include "simdjson/generic/ondemand/field-inl.h"
+#include "simdjson/generic/ondemand/value_iterator-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+//
+// object_iterator
+//
+
+simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept
+ : iter{_iter}
+{}
+
+simdjson_inline simdjson_result<field> object_iterator::operator*() noexcept {
+ error_code error = iter.error();
+ if (error) { iter.abandon(); return error; }
+ auto result = field::start(iter);
+ // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
+ // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
+ if (result.error()) { iter.abandon(); }
+ return result;
+}
+simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept {
+ return !(*this != other);
+}
+simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept {
+ return iter.is_open();
+}
+
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+simdjson_inline object_iterator &object_iterator::operator++() noexcept {
+ // TODO this is a safety rail ... users should exit loops as soon as they receive an error.
+ // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free.
+ if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error
+
+ simdjson_unused error_code error;
+ if ((error = iter.skip_child() )) { return *this; }
+
+ simdjson_unused bool has_value;
+ if ((error = iter.has_next_field().get(has_value) )) { return *this; };
+ return *this;
+}
+SIMDJSON_POP_DISABLE_WARNINGS
+
+//
+// ### Live States
+//
+// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is
+// always SUCCESS:
+//
+// - Start: This is the state when the object is first found and the iterator is just past the {.
+// In this state, at_start == true.
+// - Next: After we hand a scalar value to the user, or an array/object which they then fully
+// iterate over, the iterator is at the , or } before the next value. In this state,
+// depth == iter.depth, at_start == false, and error == SUCCESS.
+// - Unfinished Business: When we hand an array/object to the user which they do not fully
+// iterate over, we need to finish that iteration by skipping child values until we reach the
+// Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS.
+//
+// ## Error States
+//
+// In error states, we will yield exactly one more value before stopping. iter.depth == depth
+// and at_start is always false. We decrement after yielding the error, moving to the Finished
+// state.
+//
+// - Chained Error: When the object iterator is part of an error chain--for example, in
+// `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an
+// object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and
+// iter.depth == depth, and at_start == false. We decrement depth when we yield the error.
+// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields,
+// we flag that as an error and treat it exactly the same as a Chained Error. In this state,
+// error == TAPE_ERROR, iter.depth == depth, and at_start == false.
+//
+// Errors that occur while reading a field to give to the user (such as when the key is not a
+// string or the field is missing a colon) are yielded immediately. Depth is then decremented,
+// moving to the Finished state without transitioning through an Error state at all.
+//
+// ## Terminal State
+//
+// The terminal state has iter.depth < depth. at_start is always false.
+//
+// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth.
+// In this state, iter.depth < depth, at_start == false, and error == SUCCESS.
+//
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::object_iterator &&value
+) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>(value))
+{
+ first.iter.assert_is_valid();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>({}, error)
+{
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator*() noexcept {
+ if (error()) { return error(); }
+ return *first;
+}
+// If we're iterating and there is an error, return the error once.
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
+ if (!first.iter.is_valid()) { return !error(); }
+ return first == other.first;
+}
+// If we're iterating and there is an error, return the error once.
+simdjson_inline bool simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &other) const noexcept {
+ if (!first.iter.is_valid()) { return error(); }
+ return first != other.first;
+}
+// Checks for ']' and ','
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator>::operator++() noexcept {
+ // Clear the error if there is one, so we don't yield it twice
+ if (error()) { second = SUCCESS; return *this; }
+ ++first;
+ return *this;
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator.h
new file mode 100644
index 0000000000..1cdc3f43b3
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/object_iterator.h
@@ -0,0 +1,80 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+class object_iterator {
+public:
+ /**
+ * Create a new invalid object_iterator.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline object_iterator() noexcept = default;
+
+ //
+ // Iterator interface
+ //
+
+ // Reads key and value, yielding them to the user.
+ // MUST ONLY BE CALLED ONCE PER ITERATION.
+ simdjson_inline simdjson_result<field> operator*() noexcept;
+ // Assumes it's being compared with the end. true if depth < iter->depth.
+ simdjson_inline bool operator==(const object_iterator &) const noexcept;
+ // Assumes it's being compared with the end. true if depth >= iter->depth.
+ simdjson_inline bool operator!=(const object_iterator &) const noexcept;
+ // Checks for ']' and ','
+ simdjson_inline object_iterator &operator++() noexcept;
+
+private:
+ /**
+ * The underlying JSON iterator.
+ *
+ * PERF NOTE: expected to be elided in favor of the parent document: this is set when the object
+ * is first used, and never changes afterwards.
+ */
+ value_iterator iter{};
+
+ simdjson_inline object_iterator(const value_iterator &iter) noexcept;
+ friend struct simdjson_result<object_iterator>;
+ friend class object;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::object_iterator &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ //
+ // Iterator interface
+ //
+
+ // Reads key and value, yielding them to the user.
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::field> operator*() noexcept; // MUST ONLY BE CALLED ONCE PER ITERATION.
+ // Assumes it's being compared with the end. true if depth < iter->depth.
+ simdjson_inline bool operator==(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &) const noexcept;
+ // Assumes it's being compared with the end. true if depth >= iter->depth.
+ simdjson_inline bool operator!=(const simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &) const noexcept;
+ // Checks for ']' and ','
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object_iterator> &operator++() noexcept;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser-inl.h
new file mode 100644
index 0000000000..8350fe7383
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser-inl.h
@@ -0,0 +1,205 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H
+#include "simdjson/padded_string.h"
+#include "simdjson/padded_string_view.h"
+#include "simdjson/implementation.h"
+#include "simdjson/internal/dom_parser_implementation.h"
+#include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/document_stream.h"
+#include "simdjson/generic/ondemand/parser.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline parser::parser(size_t max_capacity) noexcept
+ : _max_capacity{max_capacity} {
+}
+
+simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept {
+ if (new_capacity > max_capacity()) { return CAPACITY; }
+ if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; }
+
+ // string_capacity copied from document::allocate
+ _capacity = 0;
+ size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64);
+ string_buf.reset(new (std::nothrow) uint8_t[string_capacity]);
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ start_positions.reset(new (std::nothrow) token_position[new_max_depth]);
+#endif
+ if (implementation) {
+ SIMDJSON_TRY( implementation->set_capacity(new_capacity) );
+ SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) );
+ } else {
+ SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) );
+ }
+ _capacity = new_capacity;
+ _max_depth = new_max_depth;
+ return SUCCESS;
+}
+#if SIMDJSON_DEVELOPMENT_CHECKS
+simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept {
+ return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity());
+}
+#endif
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(padded_string_view json) & noexcept {
+ if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
+
+ json.remove_utf8_bom();
+
+ // Allocate if needed
+ if (capacity() < json.length() || !string_buf) {
+ SIMDJSON_TRY( allocate(json.length(), max_depth()) );
+ }
+
+ // Run stage 1.
+ SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
+ return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this });
+}
+
+#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate_allow_incomplete_json(padded_string_view json) & noexcept {
+ if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
+
+ json.remove_utf8_bom();
+
+ // Allocate if needed
+ if (capacity() < json.length() || !string_buf) {
+ SIMDJSON_TRY( allocate(json.length(), max_depth()) );
+ }
+
+ // Run stage 1.
+ const simdjson::error_code err = implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular);
+ if (err) {
+ if (err != UNCLOSED_STRING)
+ return err;
+ }
+ return document::start({ reinterpret_cast<const uint8_t *>(json.data()), this, true });
+}
+#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const char *json, size_t len, size_t allocated) & noexcept {
+ return iterate(padded_string_view(json, len, allocated));
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept {
+ return iterate(padded_string_view(json, len, allocated));
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string_view json, size_t allocated) & noexcept {
+ return iterate(padded_string_view(json, allocated));
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(std::string &json) & noexcept {
+ if(json.capacity() - json.size() < SIMDJSON_PADDING) {
+ json.reserve(json.size() + SIMDJSON_PADDING);
+ }
+ return iterate(padded_string_view(json));
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const std::string &json) & noexcept {
+ return iterate(padded_string_view(json));
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string_view> &result) & noexcept {
+ // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
+ SIMDJSON_TRY( result.error() );
+ padded_string_view json = result.value_unsafe();
+ return iterate(json);
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<document> parser::iterate(const simdjson_result<padded_string> &result) & noexcept {
+ // We don't presently have a way to temporarily get a const T& from a simdjson_result<T> without throwing an exception
+ SIMDJSON_TRY( result.error() );
+ const padded_string &json = result.value_unsafe();
+ return iterate(json);
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<json_iterator> parser::iterate_raw(padded_string_view json) & noexcept {
+ if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; }
+
+ json.remove_utf8_bom();
+
+ // Allocate if needed
+ if (capacity() < json.length()) {
+ SIMDJSON_TRY( allocate(json.length(), max_depth()) );
+ }
+
+ // Run stage 1.
+ SIMDJSON_TRY( implementation->stage1(reinterpret_cast<const uint8_t *>(json.data()), json.length(), stage1_mode::regular) );
+ return json_iterator(reinterpret_cast<const uint8_t *>(json.data()), this);
+}
+
+inline simdjson_result<document_stream> parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
+ if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; }
+ if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) {
+ buf += 3;
+ len -= 3;
+ }
+ if(allow_comma_separated && batch_size < len) { batch_size = len; }
+ return document_stream(*this, buf, len, batch_size, allow_comma_separated);
+}
+inline simdjson_result<document_stream> parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept {
+ return iterate_many(reinterpret_cast<const uint8_t *>(buf), len, batch_size, allow_comma_separated);
+}
+inline simdjson_result<document_stream> parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept {
+ return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
+}
+inline simdjson_result<document_stream> parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept {
+ return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated);
+}
+
+simdjson_pure simdjson_inline size_t parser::capacity() const noexcept {
+ return _capacity;
+}
+simdjson_pure simdjson_inline size_t parser::max_capacity() const noexcept {
+ return _max_capacity;
+}
+simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept {
+ return _max_depth;
+}
+
+simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept {
+ if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) {
+ _max_capacity = max_capacity;
+ } else {
+ _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY;
+ }
+}
+
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept {
+ uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement);
+ if (!end) { return STRING_ERROR; }
+ std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
+ dst = end;
+ return result;
+}
+
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept {
+ uint8_t *end = implementation->parse_wobbly_string(in.buf, dst);
+ if (!end) { return STRING_ERROR; }
+ std::string_view result(reinterpret_cast<const char *>(dst), end-dst);
+ dst = end;
+ return result;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::parser>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::parser &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::parser>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::parser>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::parser>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::parser>(error) {}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h
new file mode 100644
index 0000000000..f1f86d4843
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/parser.h
@@ -0,0 +1,372 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_PARSER_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#include <memory>
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * The default batch size for document_stream instances for this On-Demand kernel.
+ * Note that different On-Demand kernel may use a different DEFAULT_BATCH_SIZE value
+ * in the future.
+ */
+static constexpr size_t DEFAULT_BATCH_SIZE = 1000000;
+/**
+ * Some adversary might try to set the batch size to 0 or 1, which might cause problems.
+ * We set a minimum of 32B since anything else is highly likely to be an error. In practice,
+ * most users will want a much larger batch size.
+ *
+ * All non-negative MINIMAL_BATCH_SIZE values should be 'safe' except that, obviously, no JSON
+ * document can ever span 0 or 1 byte and that very large values would create memory allocation issues.
+ */
+static constexpr size_t MINIMAL_BATCH_SIZE = 32;
+
+/**
+ * A JSON fragment iterator.
+ *
+ * This holds the actual iterator as well as the buffer for writing strings.
+ */
+class parser {
+public:
+ /**
+ * Create a JSON parser.
+ *
+ * The new parser will have zero capacity.
+ */
+ inline explicit parser(size_t max_capacity = SIMDJSON_MAXSIZE_BYTES) noexcept;
+
+ inline parser(parser &&other) noexcept = default;
+ simdjson_inline parser(const parser &other) = delete;
+ simdjson_inline parser &operator=(const parser &other) = delete;
+ simdjson_inline parser &operator=(parser &&other) noexcept = default;
+
+ /** Deallocate the JSON parser. */
+ inline ~parser() noexcept = default;
+
+ /**
+ * Start iterating an on-demand JSON document.
+ *
+ * ondemand::parser parser;
+ * document doc = parser.iterate(json);
+ *
+ * It is expected that the content is a valid UTF-8 file, containing a valid JSON document.
+ * Otherwise the iterate method may return an error. In particular, the whole input should be
+ * valid: we do not attempt to tolerate incorrect content either before or after a JSON
+ * document. If there is a UTF-8 BOM, the parser skips it.
+ *
+ * ### IMPORTANT: Validate what you use
+ *
+ * Calling iterate on an invalid JSON document may not immediately trigger an error. The call to
+ * iterate does not parse and validate the whole document.
+ *
+ * ### IMPORTANT: Buffer Lifetime
+ *
+ * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
+ * long as the document iteration.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
+ * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
+ * you call parse() again or destroy the parser.
+ *
+ * ### REQUIRED: Buffer Padding
+ *
+ * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
+ * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
+ * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
+ * SIMDJSON_PADDING bytes to avoid runtime warnings.
+ *
+ * @param json The JSON to parse.
+ * @param len The length of the JSON.
+ * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING).
+ *
+ * @return The document, or an error:
+ * - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
+ * - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
+ * allocation fails.
+ * - EMPTY if the document is all whitespace.
+ * - UTF8_ERROR if the document is not valid UTF-8.
+ * - UNESCAPED_CHARS if a string contains control characters that must be escaped
+ * - UNCLOSED_STRING if there is an unclosed string in the document.
+ */
+ simdjson_warn_unused simdjson_result<document> iterate(padded_string_view json) & noexcept;
+#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+ simdjson_warn_unused simdjson_result<document> iterate_allow_incomplete_json(padded_string_view json) & noexcept;
+#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(const char *json, size_t len, size_t capacity) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(const uint8_t *json, size_t len, size_t capacity) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(std::string_view json, size_t capacity) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(const std::string &json) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(std::string &json) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string> &json) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(const simdjson_result<padded_string_view> &json) & noexcept;
+ /** @overload simdjson_result<document> iterate(padded_string_view json) & noexcept */
+ simdjson_warn_unused simdjson_result<document> iterate(padded_string &&json) & noexcept = delete;
+
+ /**
+ * @private
+ *
+ * Start iterating an on-demand JSON document.
+ *
+ * ondemand::parser parser;
+ * json_iterator doc = parser.iterate(json);
+ *
+ * ### IMPORTANT: Buffer Lifetime
+ *
+ * Because parsing is done while you iterate, you *must* keep the JSON buffer around at least as
+ * long as the document iteration.
+ *
+ * ### IMPORTANT: Document Lifetime
+ *
+ * Only one iteration at a time can happen per parser, and the parser *must* be kept alive during
+ * iteration to ensure intermediate buffers can be accessed. Any document must be destroyed before
+ * you call parse() again or destroy the parser.
+ *
+ * The ondemand::document instance holds the iterator. The document must remain in scope
+ * while you are accessing instances of ondemand::value, ondemand::object, ondemand::array.
+ *
+ * ### REQUIRED: Buffer Padding
+ *
+ * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
+ * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
+ * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
+ * SIMDJSON_PADDING bytes to avoid runtime warnings.
+ *
+ * @param json The JSON to parse.
+ *
+ * @return The iterator, or an error:
+ * - INSUFFICIENT_PADDING if the input has less than SIMDJSON_PADDING extra bytes.
+ * - MEMALLOC if realloc_if_needed the parser does not have enough capacity, and memory
+ * allocation fails.
+ * - EMPTY if the document is all whitespace.
+ * - UTF8_ERROR if the document is not valid UTF-8.
+ * - UNESCAPED_CHARS if a string contains control characters that must be escaped
+ * - UNCLOSED_STRING if there is an unclosed string in the document.
+ */
+ simdjson_warn_unused simdjson_result<json_iterator> iterate_raw(padded_string_view json) & noexcept;
+
+
+ /**
+ * Parse a buffer containing many JSON documents.
+ *
+ * auto json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"_padded;
+ * ondemand::parser parser;
+ * ondemand::document_stream docs = parser.iterate_many(json);
+ * for (auto & doc : docs) {
+ * std::cout << doc["foo"] << std::endl;
+ * }
+ * // Prints 1 2 3
+ *
+ * No copy of the input buffer is made.
+ *
+ * The function is lazy: it may be that no more than one JSON document at a time is parsed.
+ *
+ * The caller is responsabile to ensure that the input string data remains unchanged and is
+ * not deleted during the loop.
+ *
+ * ### Format
+ *
+ * The buffer must contain a series of one or more JSON documents, concatenated into a single
+ * buffer, separated by ASCII whitespace. It effectively parses until it has a fully valid document,
+ * then starts parsing the next document at that point. (It does this with more parallelism and
+ * lookahead than you might think, though.)
+ *
+ * documents that consist of an object or array may omit the whitespace between them, concatenating
+ * with no separator. Documents that consist of a single primitive (i.e. documents that are not
+ * arrays or objects) MUST be separated with ASCII whitespace.
+ *
+ * The characters inside a JSON document, and between JSON documents, must be valid Unicode (UTF-8).
+ * If there is a UTF-8 BOM, the parser skips it.
+ *
+ * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse.
+ * Setting batch_size to excessively large or excessively small values may impact negatively the
+ * performance.
+ *
+ * ### REQUIRED: Buffer Padding
+ *
+ * The buffer must have at least SIMDJSON_PADDING extra allocated bytes. It does not matter what
+ * those bytes are initialized to, as long as they are allocated. These bytes will be read: if you
+ * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the
+ * SIMDJSON_PADDING bytes to avoid runtime warnings.
+ *
+ * ### Threads
+ *
+ * When compiled with SIMDJSON_THREADS_ENABLED, this method will use a single thread under the
+ * hood to do some lookahead.
+ *
+ * ### Parser Capacity
+ *
+ * If the parser's current capacity is less than batch_size, it will allocate enough capacity
+ * to handle it (up to max_capacity).
+ *
+ * @param buf The concatenated JSON to parse.
+ * @param len The length of the concatenated JSON.
+ * @param batch_size The batch size to use. MUST be larger than the largest document. The sweet
+ * spot is cache-related: small enough to fit in cache, yet big enough to
+ * parse as many documents as possible in one tight loop.
+ * Defaults to 10MB, which has been a reasonable sweet spot in our tests.
+ * @param allow_comma_separated (defaults on false) This allows a mode where the documents are
+ * separated by commas instead of whitespace. It comes with a performance
+ * penalty because the entire document is indexed at once (and the document must be
+ * less than 4 GB), and there is no multithreading. In this mode, the batch_size parameter
+ * is effectively ignored, as it is set to at least the document size.
+ * @return The stream, or an error. An empty input will yield 0 documents rather than an EMPTY error. Errors:
+ * - MEMALLOC if the parser does not have enough capacity and memory allocation fails
+ * - CAPACITY if the parser does not have enough capacity and batch_size > max_capacity.
+ * - other json errors if parsing fails. You should not rely on these errors to always the same for the
+ * same document: they may vary under runtime dispatch (so they may vary depending on your system and hardware).
+ */
+ inline simdjson_result<document_stream> iterate_many(const uint8_t *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> iterate_many(const char *buf, size_t len, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> iterate_many(const std::string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
+ inline simdjson_result<document_stream> iterate_many(const std::string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
+ /** @overload parse_many(const uint8_t *buf, size_t len, size_t batch_size) */
+ inline simdjson_result<document_stream> iterate_many(const padded_string &s, size_t batch_size = DEFAULT_BATCH_SIZE, bool allow_comma_separated = false) noexcept;
+ inline simdjson_result<document_stream> iterate_many(const padded_string &&s, size_t batch_size, bool allow_comma_separated = false) = delete;// unsafe
+
+ /** @private We do not want to allow implicit conversion from C string to std::string. */
+ simdjson_result<document_stream> iterate_many(const char *buf, size_t batch_size = DEFAULT_BATCH_SIZE) noexcept = delete;
+
+ /** The capacity of this parser (the largest document it can process). */
+ simdjson_pure simdjson_inline size_t capacity() const noexcept;
+ /** The maximum capacity of this parser (the largest document it is allowed to process). */
+ simdjson_pure simdjson_inline size_t max_capacity() const noexcept;
+ simdjson_inline void set_max_capacity(size_t max_capacity) noexcept;
+ /**
+ * The maximum depth of this parser (the most deeply nested objects and arrays it can process).
+ * This parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
+ * The document's instance current_depth() method should be used to monitor the parsing
+ * depth and limit it if desired.
+ */
+ simdjson_pure simdjson_inline size_t max_depth() const noexcept;
+
+ /**
+ * Ensure this parser has enough memory to process JSON documents up to `capacity` bytes in length
+ * and `max_depth` depth.
+ *
+ * The max_depth parameter is only relevant when the macro SIMDJSON_DEVELOPMENT_CHECKS is set to true.
+ * The document's instance current_depth() method should be used to monitor the parsing
+ * depth and limit it if desired.
+ *
+ * @param capacity The new capacity.
+ * @param max_depth The new max_depth. Defaults to DEFAULT_MAX_DEPTH.
+ * @return The error, if there is one.
+ */
+ simdjson_warn_unused error_code allocate(size_t capacity, size_t max_depth=DEFAULT_MAX_DEPTH) noexcept;
+
+ #ifdef SIMDJSON_THREADS_ENABLED
+ /**
+ * The parser instance can use threads when they are available to speed up some
+ * operations. It is enabled by default. Changing this attribute will change the
+ * behavior of the parser for future operations.
+ */
+ bool threaded{true};
+ #endif
+
+ /**
+ * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
+ * The result must be valid UTF-8.
+ * The provided pointer is advanced to the end of the string by reference, and a string_view instance
+ * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
+ * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
+ *
+ * This unescape function is a low-level function. If you want a more user-friendly approach, you should
+ * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
+ * instead of get_raw_json_string()).
+ *
+ * ## IMPORTANT: string_view lifetime
+ *
+ * The string_view is only valid as long as the bytes in dst.
+ *
+ * @param raw_json_string input
+ * @param dst A pointer to a buffer at least large enough to write this string as well as
+ * an additional SIMDJSON_PADDING bytes.
+ * @param allow_replacement Whether we allow a replacement if the input string contains unmatched surrogate pairs.
+ * @return A string_view pointing at the unescaped string in dst
+ * @error STRING_ERROR if escapes are incorrect.
+ */
+ simdjson_inline simdjson_result<std::string_view> unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement = false) const noexcept;
+
+ /**
+ * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer.
+ * The result may not be valid UTF-8. See https://simonsapin.github.io/wtf-8/
+ * The provided pointer is advanced to the end of the string by reference, and a string_view instance
+ * is returned. You can ensure that your buffer is large enough by allocating a block of memory at least
+ * as large as the input JSON plus SIMDJSON_PADDING and then unescape all strings to this one buffer.
+ *
+ * This unescape function is a low-level function. If you want a more user-friendly approach, you should
+ * avoid raw_json_string instances (e.g., by calling unescaped_key() instead of key() or get_string()
+ * instead of get_raw_json_string()).
+ *
+ * ## IMPORTANT: string_view lifetime
+ *
+ * The string_view is only valid as long as the bytes in dst.
+ *
+ * @param raw_json_string input
+ * @param dst A pointer to a buffer at least large enough to write this string as well as
+ * an additional SIMDJSON_PADDING bytes.
+ * @return A string_view pointing at the unescaped string in dst
+ * @error STRING_ERROR if escapes are incorrect.
+ */
+ simdjson_inline simdjson_result<std::string_view> unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept;
+
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ /**
+ * Returns true if string_buf_loc is outside of the allocated range for the
+ * the string buffer. When true, it indicates that the string buffer has overflowed.
+ * This is a development-time check that is not needed in production. It can be
+ * used to detect buffer overflows in the string buffer and usafe usage of the
+ * string buffer.
+ */
+ bool string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept;
+#endif
+
+private:
+ /** @private [for benchmarking access] The implementation to use */
+ std::unique_ptr<simdjson::internal::dom_parser_implementation> implementation{};
+ size_t _capacity{0};
+ size_t _max_capacity;
+ size_t _max_depth{DEFAULT_MAX_DEPTH};
+ std::unique_ptr<uint8_t[]> string_buf{};
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ std::unique_ptr<token_position[]> start_positions{};
+#endif
+
+ friend class json_iterator;
+ friend class document_stream;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::parser> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::parser> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::parser &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string-inl.h
new file mode 100644
index 0000000000..5b814dd801
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string-inl.h
@@ -0,0 +1,203 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/json_iterator-inl.h"
+#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {}
+
+simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast<const char *>(buf); }
+
+
+simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept {
+ size_t pos{0};
+ // if the content has no escape character, just scan through it quickly!
+ for(;pos < target.size() && target[pos] != '\\';pos++) {}
+ // slow path may begin.
+ bool escaping{false};
+ for(;pos < target.size();pos++) {
+ if((target[pos] == '"') && !escaping) {
+ return false;
+ } else if(target[pos] == '\\') {
+ escaping = !escaping;
+ } else {
+ escaping = false;
+ }
+ }
+ return true;
+}
+
+simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept {
+ size_t pos{0};
+ // if the content has no escape character, just scan through it quickly!
+ for(;target[pos] && target[pos] != '\\';pos++) {}
+ // slow path may begin.
+ bool escaping{false};
+ for(;target[pos];pos++) {
+ if((target[pos] == '"') && !escaping) {
+ return false;
+ } else if(target[pos] == '\\') {
+ escaping = !escaping;
+ } else {
+ escaping = false;
+ }
+ }
+ return true;
+}
+
+
+simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept {
+ // If we are going to call memcmp, then we must know something about the length of the raw_json_string.
+ return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
+}
+
+simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept {
+ // Assumptions: does not contain unescaped quote characters, and
+ // the raw content is quote terminated within a valid JSON string.
+ if(target.size() <= SIMDJSON_PADDING) {
+ return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size());
+ }
+ const char * r{raw()};
+ size_t pos{0};
+ for(;pos < target.size();pos++) {
+ if(r[pos] != target[pos]) { return false; }
+ }
+ if(r[pos] != '"') { return false; }
+ return true;
+}
+
+simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept {
+ const char * r{raw()};
+ size_t pos{0};
+ bool escaping{false};
+ for(;pos < target.size();pos++) {
+ if(r[pos] != target[pos]) { return false; }
+ // if target is a compile-time constant and it is free from
+ // quotes, then the next part could get optimized away through
+ // inlining.
+ if((target[pos] == '"') && !escaping) {
+ // We have reached the end of the raw_json_string but
+ // the target is not done.
+ return false;
+ } else if(target[pos] == '\\') {
+ escaping = !escaping;
+ } else {
+ escaping = false;
+ }
+ }
+ if(r[pos] != '"') { return false; }
+ return true;
+}
+
+
+simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept {
+ // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and
+ // the raw content is quote terminated within a valid JSON string.
+ const char * r{raw()};
+ size_t pos{0};
+ for(;target[pos];pos++) {
+ if(r[pos] != target[pos]) { return false; }
+ }
+ if(r[pos] != '"') { return false; }
+ return true;
+}
+
+simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept {
+ // Assumptions: does not contain unescaped quote characters, and
+ // the raw content is quote terminated within a valid JSON string.
+ const char * r{raw()};
+ size_t pos{0};
+ bool escaping{false};
+ for(;target[pos];pos++) {
+ if(r[pos] != target[pos]) { return false; }
+ // if target is a compile-time constant and it is free from
+ // quotes, then the next part could get optimized away through
+ // inlining.
+ if((target[pos] == '"') && !escaping) {
+ // We have reached the end of the raw_json_string but
+ // the target is not done.
+ return false;
+ } else if(target[pos] == '\\') {
+ escaping = !escaping;
+ } else {
+ escaping = false;
+ }
+ }
+ if(r[pos] != '"') { return false; }
+ return true;
+}
+
+simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept {
+ return a.unsafe_is_equal(c);
+}
+
+simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept {
+ return a == c;
+}
+
+simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept {
+ return !(a == c);
+}
+
+simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept {
+ return !(a == c);
+}
+
+
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept {
+ return iter.unescape(*this, allow_replacement);
+}
+
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept {
+ return iter.unescape_wobbly(*this);
+}
+
+simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept {
+ bool in_escape = false;
+ const char *s = str.raw();
+ while (true) {
+ switch (*s) {
+ case '\\': in_escape = !in_escape; break;
+ case '"': if (in_escape) { in_escape = false; } else { return out; } break;
+ default: if (in_escape) { in_escape = false; }
+ }
+ out << *s;
+ s++;
+ }
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>(error) {}
+
+simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::raw() const noexcept {
+ if (error()) { return error(); }
+ return first.raw();
+}
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::unescape(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter, bool allow_replacement) const noexcept {
+ if (error()) { return error(); }
+ return first.unescape(iter, allow_replacement);
+}
+simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string>::unescape_wobbly(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter) const noexcept {
+ if (error()) { return error(); }
+ return first.unescape_wobbly(iter);
+}
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string.h
new file mode 100644
index 0000000000..be50a402d3
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/raw_json_string.h
@@ -0,0 +1,206 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * A string escaped per JSON rules, terminated with quote ("). They are used to represent
+ * unescaped keys inside JSON documents.
+ *
+ * (In other words, a pointer to the beginning of a string, just after the start quote, inside a
+ * JSON file.)
+ *
+ * This class is deliberately simplistic and has little functionality. You can
+ * compare a raw_json_string instance with an unescaped C string, but
+ * that is nearly all you can do.
+ *
+ * The raw_json_string is unescaped. If you wish to write an unescaped version of it to your own
+ * buffer, you may do so using the parser.unescape(string, buff) method, using an ondemand::parser
+ * instance. Doing so requires you to have a sufficiently large buffer.
+ *
+ * The raw_json_string instances originate typically from field instance which in turn represent
+ * key-value pairs from object instances. From a field instance, you get the raw_json_string
+ * instance by calling key(). You can, if you want a more usable string_view instance, call
+ * the unescaped_key() method on the field instance. You may also create a raw_json_string from
+ * any other string value, with the value.get_raw_json_string() method. Again, you can get
+ * a more usable string_view instance by calling get_string().
+ *
+ */
+class raw_json_string {
+public:
+ /**
+ * Create a new invalid raw_json_string.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline raw_json_string() noexcept = default;
+
+ /**
+ * Create a new invalid raw_json_string pointed at the given location in the JSON.
+ *
+ * The given location must be just *after* the beginning quote (") in the JSON file.
+ *
+ * It *must* be terminated by a ", and be a valid JSON string.
+ */
+ simdjson_inline raw_json_string(const uint8_t * _buf) noexcept;
+ /**
+ * Get the raw pointer to the beginning of the string in the JSON (just after the ").
+ *
+ * It is possible for this function to return a null pointer if the instance
+ * has outlived its existence.
+ */
+ simdjson_inline const char * raw() const noexcept;
+
+ /**
+ * This compares the current instance to the std::string_view target: returns true if
+ * they are byte-by-byte equal (no escaping is done) on target.size() characters,
+ * and if the raw_json_string instance has a quote character at byte index target.size().
+ * We never read more than length + 1 bytes in the raw_json_string instance.
+ * If length is smaller than target.size(), this will return false.
+ *
+ * The std::string_view instance may contain any characters. However, the caller
+ * is responsible for setting length so that length bytes may be read in the
+ * raw_json_string.
+ *
+ * Performance: the comparison may be done using memcmp which may be efficient
+ * for long strings.
+ */
+ simdjson_inline bool unsafe_is_equal(size_t length, std::string_view target) const noexcept;
+
+ /**
+ * This compares the current instance to the std::string_view target: returns true if
+ * they are byte-by-byte equal (no escaping is done).
+ * The std::string_view instance should not contain unescaped quote characters:
+ * the caller is responsible for this check. See is_free_from_unescaped_quote.
+ *
+ * Performance: the comparison is done byte-by-byte which might be inefficient for
+ * long strings.
+ *
+ * If target is a compile-time constant, and your compiler likes you,
+ * you should be able to do the following without performance penalty...
+ *
+ * static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
+ * s.unsafe_is_equal(target);
+ */
+ simdjson_inline bool unsafe_is_equal(std::string_view target) const noexcept;
+
+ /**
+ * This compares the current instance to the C string target: returns true if
+ * they are byte-by-byte equal (no escaping is done).
+ * The provided C string should not contain an unescaped quote character:
+ * the caller is responsible for this check. See is_free_from_unescaped_quote.
+ *
+ * If target is a compile-time constant, and your compiler likes you,
+ * you should be able to do the following without performance penalty...
+ *
+ * static_assert(raw_json_string::is_free_from_unescaped_quote(target), "");
+ * s.unsafe_is_equal(target);
+ */
+ simdjson_inline bool unsafe_is_equal(const char* target) const noexcept;
+
+ /**
+ * This compares the current instance to the std::string_view target: returns true if
+ * they are byte-by-byte equal (no escaping is done).
+ */
+ simdjson_inline bool is_equal(std::string_view target) const noexcept;
+
+ /**
+ * This compares the current instance to the C string target: returns true if
+ * they are byte-by-byte equal (no escaping is done).
+ */
+ simdjson_inline bool is_equal(const char* target) const noexcept;
+
+ /**
+ * Returns true if target is free from unescaped quote. If target is known at
+ * compile-time, we might expect the computation to happen at compile time with
+ * many compilers (not all!).
+ */
+ static simdjson_inline bool is_free_from_unescaped_quote(std::string_view target) noexcept;
+ static simdjson_inline bool is_free_from_unescaped_quote(const char* target) noexcept;
+
+private:
+
+
+ /**
+ * This will set the inner pointer to zero, effectively making
+ * this instance unusable.
+ */
+ simdjson_inline void consume() noexcept { buf = nullptr; }
+
+ /**
+ * Checks whether the inner pointer is non-null and thus usable.
+ */
+ simdjson_inline simdjson_warn_unused bool alive() const noexcept { return buf != nullptr; }
+
+ /**
+ * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
+ * The result will be a valid UTF-8.
+ *
+ * ## IMPORTANT: string_view lifetime
+ *
+ * The string_view is only valid until the next parse() call on the parser.
+ *
+ * @param iter A json_iterator, which contains a buffer where the string will be written.
+ * @param allow_replacement Whether we allow replacement of invalid surrogate pairs.
+ */
+ simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(json_iterator &iter, bool allow_replacement) const noexcept;
+
+ /**
+ * Unescape this JSON string, replacing \\ with \, \n with newline, etc.
+ * The result may not be a valid UTF-8. https://simonsapin.github.io/wtf-8/
+ *
+ * ## IMPORTANT: string_view lifetime
+ *
+ * The string_view is only valid until the next parse() call on the parser.
+ *
+ * @param iter A json_iterator, which contains a buffer where the string will be written.
+ */
+ simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(json_iterator &iter) const noexcept;
+ const uint8_t * buf{};
+ friend class object;
+ friend class field;
+ friend class parser;
+ friend struct simdjson_result<raw_json_string>;
+};
+
+simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &, const raw_json_string &) noexcept;
+
+/**
+ * Comparisons between raw_json_string and std::string_view instances are potentially unsafe: the user is responsible
+ * for providing a string with no unescaped quote. Note that unescaped quotes cannot be present in valid JSON strings.
+ */
+simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept;
+simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept;
+simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept;
+simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept;
+
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+ simdjson_inline ~simdjson_result() noexcept = default; ///< @private
+
+ simdjson_inline simdjson_result<const char *> raw() const noexcept;
+ simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter, bool allow_replacement) const noexcept;
+ simdjson_inline simdjson_warn_unused simdjson_result<std::string_view> unescape_wobbly(SIMDJSON_IMPLEMENTATION::ondemand::json_iterator &iter) const noexcept;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization-inl.h
new file mode 100644
index 0000000000..77be39a11c
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization-inl.h
@@ -0,0 +1,233 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/array.h"
+#include "simdjson/generic/ondemand/document-inl.h"
+#include "simdjson/generic/ondemand/json_type.h"
+#include "simdjson/generic/ondemand/object.h"
+#include "simdjson/generic/ondemand/serialization.h"
+#include "simdjson/generic/ondemand/value.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+
+inline std::string_view trim(const std::string_view str) noexcept {
+ // We can almost surely do better by rolling our own find_first_not_of function.
+ size_t first = str.find_first_not_of(" \t\n\r");
+ // If we have the empty string (just white space), then no trimming is possible, and
+ // we return the empty string_view.
+ if (std::string_view::npos == first) { return std::string_view(); }
+ size_t last = str.find_last_not_of(" \t\n\r");
+ return str.substr(first, (last - first + 1));
+}
+
+
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document& x) noexcept {
+ std::string_view v;
+ auto error = x.raw_json().get(v);
+ if(error) {return error; }
+ return trim(v);
+}
+
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document_reference& x) noexcept {
+ std::string_view v;
+ auto error = x.raw_json().get(v);
+ if(error) {return error; }
+ return trim(v);
+}
+
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::value& x) noexcept {
+ /**
+ * If we somehow receive a value that has already been consumed,
+ * then the following code could be in trouble. E.g., we create
+ * an array as needed, but if an array was already created, then
+ * it could be bad.
+ */
+ using namespace SIMDJSON_IMPLEMENTATION::ondemand;
+ SIMDJSON_IMPLEMENTATION::ondemand::json_type t;
+ auto error = x.type().get(t);
+ if(error != SUCCESS) { return error; }
+ switch (t)
+ {
+ case json_type::array:
+ {
+ SIMDJSON_IMPLEMENTATION::ondemand::array array;
+ error = x.get_array().get(array);
+ if(error) { return error; }
+ return to_json_string(array);
+ }
+ case json_type::object:
+ {
+ SIMDJSON_IMPLEMENTATION::ondemand::object object;
+ error = x.get_object().get(object);
+ if(error) { return error; }
+ return to_json_string(object);
+ }
+ default:
+ return trim(x.raw_json_token());
+ }
+}
+
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::object& x) noexcept {
+ std::string_view v;
+ auto error = x.raw_json().get(v);
+ if(error) {return error; }
+ return trim(v);
+}
+
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::array& x) noexcept {
+ std::string_view v;
+ auto error = x.raw_json().get(v);
+ if(error) {return error; }
+ return trim(v);
+}
+
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> x) {
+ if (x.error()) { return x.error(); }
+ return to_json_string(x.value_unsafe());
+}
+
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference> x) {
+ if (x.error()) { return x.error(); }
+ return to_json_string(x.value_unsafe());
+}
+
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> x) {
+ if (x.error()) { return x.error(); }
+ return to_json_string(x.value_unsafe());
+}
+
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> x) {
+ if (x.error()) { return x.error(); }
+ return to_json_string(x.value_unsafe());
+}
+
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> x) {
+ if (x.error()) { return x.error(); }
+ return to_json_string(x.value_unsafe());
+}
+} // namespace simdjson
+
+namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand {
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value x) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(x).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ throw simdjson::simdjson_error(error);
+ }
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#else
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value x) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(x).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ return (out << error);
+ }
+}
+#endif
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ throw simdjson::simdjson_error(error);
+ }
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#else
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ return (out << error);
+ }
+}
+#endif
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document& value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ throw simdjson::simdjson_error(error);
+ }
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference& value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ throw simdjson::simdjson_error(error);
+ }
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document>&& x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference>&& x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#else
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document& value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ return (out << error);
+ }
+}
+#endif
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::object value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ throw simdjson::simdjson_error(error);
+ }
+}
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::object> x) {
+ if (x.error()) { throw simdjson::simdjson_error(x.error()); }
+ return (out << x.value());
+}
+#else
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::object value) {
+ std::string_view v;
+ auto error = simdjson::to_json_string(value).get(v);
+ if(error == simdjson::SUCCESS) {
+ return (out << v);
+ } else {
+ return (out << error);
+ }
+}
+#endif
+}}} // namespace simdjson::SIMDJSON_IMPLEMENTATION::ondemand
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization.h
new file mode 100644
index 0000000000..048c73cda8
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/serialization.h
@@ -0,0 +1,103 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H
+#include "simdjson/generic/ondemand/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+/**
+ * Create a string-view instance out of a document instance. The string-view instance
+ * contains JSON text that is suitable to be parsed as JSON again. It does not
+ * validate the content.
+ */
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document& x) noexcept;
+/**
+ * Create a string-view instance out of a value instance. The string-view instance
+ * contains JSON text that is suitable to be parsed as JSON again. The value must
+ * not have been accessed previously. It does not
+ * validate the content.
+ */
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::value& x) noexcept;
+/**
+ * Create a string-view instance out of an object instance. The string-view instance
+ * contains JSON text that is suitable to be parsed as JSON again. It does not
+ * validate the content.
+ */
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::object& x) noexcept;
+/**
+ * Create a string-view instance out of an array instance. The string-view instance
+ * contains JSON text that is suitable to be parsed as JSON again. It does not
+ * validate the content.
+ */
+inline simdjson_result<std::string_view> to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::array& x) noexcept;
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document> x);
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> x);
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> x);
+inline simdjson_result<std::string_view> to_json_string(simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> x);
+} // namespace simdjson
+
+/**
+ * We want to support argument-dependent lookup (ADL).
+ * Hence we should define operator<< in the namespace
+ * where the argument (here value, object, etc.) resides.
+ * Credit: @madhur4127
+ * See https://github.com/simdjson/simdjson/issues/1768
+ */
+namespace simdjson { namespace SIMDJSON_IMPLEMENTATION { namespace ondemand {
+
+/**
+ * Print JSON to an output stream. It does not
+ * validate the content.
+ *
+ * @param out The output stream.
+ * @param value The element.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value x);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::value> x);
+#endif
+/**
+ * Print JSON to an output stream. It does not
+ * validate the content.
+ *
+ * @param out The output stream.
+ * @param value The array.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::array> x);
+#endif
+/**
+ * Print JSON to an output stream. It does not
+ * validate the content.
+ *
+ * @param out The output stream.
+ * @param value The array.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document& value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document>&& x);
+#endif
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference& value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::document_reference>&& x);
+#endif
+/**
+ * Print JSON to an output stream. It does not
+ * validate the content.
+ *
+ * @param out The output stream.
+ * @param value The object.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson::SIMDJSON_IMPLEMENTATION::ondemand::object value);
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result<simdjson::SIMDJSON_IMPLEMENTATION::ondemand::object> x);
+#endif
+}}} // namespace simdjson::SIMDJSON_IMPLEMENTATION::ondemand
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator-inl.h
new file mode 100644
index 0000000000..c93a10d829
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator-inl.h
@@ -0,0 +1,94 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/token_iterator.h"
+#include "simdjson/generic/implementation_simdjson_result_base-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline token_iterator::token_iterator(
+ const uint8_t *_buf,
+ token_position position
+) noexcept : buf{_buf}, _position{position}
+{
+}
+
+simdjson_inline uint32_t token_iterator::current_offset() const noexcept {
+ return *(_position);
+}
+
+
+simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept {
+ return &buf[*(_position++)];
+}
+
+simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept {
+ return &buf[*position];
+}
+simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept {
+ return *position;
+}
+simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept {
+ return *(position+1) - *position;
+}
+
+simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept {
+ return *(position+2) - *(position) > *(position+1) - *(position) ?
+ *(position+1) - *(position)
+ : *(position+2) - *(position);
+}
+simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept {
+ return &buf[*(_position+delta)];
+}
+simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept {
+ return *(_position+delta);
+}
+simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept {
+ return *(_position+delta+1) - *(_position+delta);
+}
+
+simdjson_inline token_position token_iterator::position() const noexcept {
+ return _position;
+}
+simdjson_inline void token_iterator::set_position(token_position target_position) noexcept {
+ _position = target_position;
+}
+
+simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept {
+ return _position == other._position;
+}
+simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept {
+ return _position != other._position;
+}
+simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept {
+ return _position > other._position;
+}
+simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept {
+ return _position >= other._position;
+}
+simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept {
+ return _position < other._position;
+}
+simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept {
+ return _position <= other._position;
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::token_iterator &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator>(error) {}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator.h
new file mode 100644
index 0000000000..dc1b4fac4c
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/token_iterator.h
@@ -0,0 +1,158 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/logger.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * Iterates through JSON tokens (`{` `}` `[` `]` `,` `:` `"<string>"` `123` `true` `false` `null`)
+ * detected by stage 1.
+ *
+ * @private This is not intended for external use.
+ */
+class token_iterator {
+public:
+ /**
+ * Create a new invalid token_iterator.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline token_iterator() noexcept = default;
+ simdjson_inline token_iterator(token_iterator &&other) noexcept = default;
+ simdjson_inline token_iterator &operator=(token_iterator &&other) noexcept = default;
+ simdjson_inline token_iterator(const token_iterator &other) noexcept = default;
+ simdjson_inline token_iterator &operator=(const token_iterator &other) noexcept = default;
+
+ /**
+ * Advance to the next token (returning the current one).
+ */
+ simdjson_inline const uint8_t *return_current_and_advance() noexcept;
+ /**
+ * Reports the current offset in bytes from the start of the underlying buffer.
+ */
+ simdjson_inline uint32_t current_offset() const noexcept;
+ /**
+ * Get the JSON text for a given token (relative).
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
+ * 1 = next token, -1 = prev token.
+ *
+ * TODO consider a string_view, assuming the length will get stripped out by the optimizer when
+ * it is not used...
+ */
+ simdjson_inline const uint8_t *peek(int32_t delta=0) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for a given token.
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
+ * 1 = next token, -1 = prev token.
+ */
+ simdjson_inline uint32_t peek_length(int32_t delta=0) const noexcept;
+
+ /**
+ * Get the JSON text for a given token.
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param position The position of the token.
+ *
+ */
+ simdjson_inline const uint8_t *peek(token_position position) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for a given token.
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param position The position of the token.
+ */
+ simdjson_inline uint32_t peek_length(token_position position) const noexcept;
+ /**
+ * Get the maximum length of the JSON text for a root token.
+ *
+ * The length will include any whitespace at the end of the token.
+ *
+ * @param position The position of the token (start of the document).
+ */
+ simdjson_inline uint32_t peek_root_length(token_position position) const noexcept;
+ /**
+ * Return the current index.
+ */
+ simdjson_inline token_position position() const noexcept;
+ /**
+ * Reset to a previously saved index.
+ */
+ simdjson_inline void set_position(token_position target_position) noexcept;
+
+ // NOTE: we don't support a full C++ iterator interface, because we expect people to make
+ // different calls to advance the iterator based on *their own* state.
+
+ simdjson_inline bool operator==(const token_iterator &other) const noexcept;
+ simdjson_inline bool operator!=(const token_iterator &other) const noexcept;
+ simdjson_inline bool operator>(const token_iterator &other) const noexcept;
+ simdjson_inline bool operator>=(const token_iterator &other) const noexcept;
+ simdjson_inline bool operator<(const token_iterator &other) const noexcept;
+ simdjson_inline bool operator<=(const token_iterator &other) const noexcept;
+
+protected:
+ simdjson_inline token_iterator(const uint8_t *buf, token_position position) noexcept;
+
+ /**
+ * Get the index of the JSON text for a given token (relative).
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param delta The relative position of the token to retrieve. e.g. 0 = current token,
+ * 1 = next token, -1 = prev token.
+ */
+ simdjson_inline uint32_t peek_index(int32_t delta=0) const noexcept;
+ /**
+ * Get the index of the JSON text for a given token.
+ *
+ * This is not null-terminated; it is a view into the JSON.
+ *
+ * @param position The position of the token.
+ *
+ */
+ simdjson_inline uint32_t peek_index(token_position position) const noexcept;
+
+ const uint8_t *buf{};
+ token_position _position{};
+
+ friend class json_iterator;
+ friend class value_iterator;
+ friend class object;
+ template <typename... Args>
+ friend simdjson_inline void logger::log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, logger::log_level level, Args&&... args) noexcept;
+ template <typename... Args>
+ friend simdjson_inline void logger::log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, logger::log_level level, Args&&... args) noexcept;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::token_iterator> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::token_iterator &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+ simdjson_inline ~simdjson_result() noexcept = default; ///< @private
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h
new file mode 100644
index 0000000000..886bb9d050
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value-inl.h
@@ -0,0 +1,542 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/ondemand/array.h"
+#include "simdjson/generic/ondemand/array_iterator.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/json_type.h"
+#include "simdjson/generic/ondemand/object.h"
+#include "simdjson/generic/ondemand/raw_json_string.h"
+#include "simdjson/generic/ondemand/value.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline value::value(const value_iterator &_iter) noexcept
+ : iter{_iter}
+{
+}
+simdjson_inline value value::start(const value_iterator &iter) noexcept {
+ return iter;
+}
+simdjson_inline value value::resume(const value_iterator &iter) noexcept {
+ return iter;
+}
+
+simdjson_inline simdjson_result<array> value::get_array() noexcept {
+ return array::start(iter);
+}
+simdjson_inline simdjson_result<object> value::get_object() noexcept {
+ return object::start(iter);
+}
+simdjson_inline simdjson_result<object> value::start_or_resume_object() noexcept {
+ if (iter.at_start()) {
+ return get_object();
+ } else {
+ return object::resume(iter);
+ }
+}
+
+simdjson_inline simdjson_result<raw_json_string> value::get_raw_json_string() noexcept {
+ return iter.get_raw_json_string();
+}
+simdjson_inline simdjson_result<std::string_view> value::get_string(bool allow_replacement) noexcept {
+ return iter.get_string(allow_replacement);
+}
+template <typename string_type>
+simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ return iter.get_string(receiver, allow_replacement);
+}
+simdjson_inline simdjson_result<std::string_view> value::get_wobbly_string() noexcept {
+ return iter.get_wobbly_string();
+}
+simdjson_inline simdjson_result<double> value::get_double() noexcept {
+ return iter.get_double();
+}
+simdjson_inline simdjson_result<double> value::get_double_in_string() noexcept {
+ return iter.get_double_in_string();
+}
+simdjson_inline simdjson_result<uint64_t> value::get_uint64() noexcept {
+ return iter.get_uint64();
+}
+simdjson_inline simdjson_result<uint64_t> value::get_uint64_in_string() noexcept {
+ return iter.get_uint64_in_string();
+}
+simdjson_inline simdjson_result<int64_t> value::get_int64() noexcept {
+ return iter.get_int64();
+}
+simdjson_inline simdjson_result<int64_t> value::get_int64_in_string() noexcept {
+ return iter.get_int64_in_string();
+}
+simdjson_inline simdjson_result<bool> value::get_bool() noexcept {
+ return iter.get_bool();
+}
+simdjson_inline simdjson_result<bool> value::is_null() noexcept {
+ return iter.is_null();
+}
+template<> simdjson_inline simdjson_result<array> value::get() noexcept { return get_array(); }
+template<> simdjson_inline simdjson_result<object> value::get() noexcept { return get_object(); }
+template<> simdjson_inline simdjson_result<raw_json_string> value::get() noexcept { return get_raw_json_string(); }
+template<> simdjson_inline simdjson_result<std::string_view> value::get() noexcept { return get_string(false); }
+template<> simdjson_inline simdjson_result<number> value::get() noexcept { return get_number(); }
+template<> simdjson_inline simdjson_result<double> value::get() noexcept { return get_double(); }
+template<> simdjson_inline simdjson_result<uint64_t> value::get() noexcept { return get_uint64(); }
+template<> simdjson_inline simdjson_result<int64_t> value::get() noexcept { return get_int64(); }
+template<> simdjson_inline simdjson_result<bool> value::get() noexcept { return get_bool(); }
+
+template<typename T> simdjson_inline error_code value::get(T &out) noexcept {
+ return get<T>().get(out);
+}
+
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+simdjson_inline value::operator T() noexcept(false) {
+ return get<T>();
+}
+simdjson_inline value::operator array() noexcept(false) {
+ return get_array();
+}
+simdjson_inline value::operator object() noexcept(false) {
+ return get_object();
+}
+simdjson_inline value::operator uint64_t() noexcept(false) {
+ return get_uint64();
+}
+simdjson_inline value::operator int64_t() noexcept(false) {
+ return get_int64();
+}
+simdjson_inline value::operator double() noexcept(false) {
+ return get_double();
+}
+simdjson_inline value::operator std::string_view() noexcept(false) {
+ return get_string(false);
+}
+simdjson_inline value::operator raw_json_string() noexcept(false) {
+ return get_raw_json_string();
+}
+simdjson_inline value::operator bool() noexcept(false) {
+ return get_bool();
+}
+#endif
+
+simdjson_inline simdjson_result<array_iterator> value::begin() & noexcept {
+ return get_array().begin();
+}
+simdjson_inline simdjson_result<array_iterator> value::end() & noexcept {
+ return {};
+}
+simdjson_inline simdjson_result<size_t> value::count_elements() & noexcept {
+ simdjson_result<size_t> answer;
+ auto a = get_array();
+ answer = a.count_elements();
+ // count_elements leaves you pointing inside the array, at the first element.
+ // We need to move back so that the user can create a new array (which requires that
+ // we point at '[').
+ iter.move_at_start();
+ return answer;
+}
+simdjson_inline simdjson_result<size_t> value::count_fields() & noexcept {
+ simdjson_result<size_t> answer;
+ auto a = get_object();
+ answer = a.count_fields();
+ iter.move_at_start();
+ return answer;
+}
+simdjson_inline simdjson_result<value> value::at(size_t index) noexcept {
+ auto a = get_array();
+ return a.at(index);
+}
+
+simdjson_inline simdjson_result<value> value::find_field(std::string_view key) noexcept {
+ return start_or_resume_object().find_field(key);
+}
+simdjson_inline simdjson_result<value> value::find_field(const char *key) noexcept {
+ return start_or_resume_object().find_field(key);
+}
+
+simdjson_inline simdjson_result<value> value::find_field_unordered(std::string_view key) noexcept {
+ return start_or_resume_object().find_field_unordered(key);
+}
+simdjson_inline simdjson_result<value> value::find_field_unordered(const char *key) noexcept {
+ return start_or_resume_object().find_field_unordered(key);
+}
+
+simdjson_inline simdjson_result<value> value::operator[](std::string_view key) noexcept {
+ return start_or_resume_object()[key];
+}
+simdjson_inline simdjson_result<value> value::operator[](const char *key) noexcept {
+ return start_or_resume_object()[key];
+}
+
+simdjson_inline simdjson_result<json_type> value::type() noexcept {
+ return iter.type();
+}
+
+simdjson_inline simdjson_result<bool> value::is_scalar() noexcept {
+ json_type this_type;
+ auto error = type().get(this_type);
+ if(error) { return error; }
+ return ! ((this_type == json_type::array) || (this_type == json_type::object));
+}
+
+simdjson_inline simdjson_result<bool> value::is_string() noexcept {
+ json_type this_type;
+ auto error = type().get(this_type);
+ if(error) { return error; }
+ return (this_type == json_type::string);
+}
+
+
+simdjson_inline bool value::is_negative() noexcept {
+ return iter.is_negative();
+}
+
+simdjson_inline simdjson_result<bool> value::is_integer() noexcept {
+ return iter.is_integer();
+}
+simdjson_warn_unused simdjson_inline simdjson_result<number_type> value::get_number_type() noexcept {
+ return iter.get_number_type();
+}
+simdjson_warn_unused simdjson_inline simdjson_result<number> value::get_number() noexcept {
+ return iter.get_number();
+}
+
+simdjson_inline std::string_view value::raw_json_token() noexcept {
+ return std::string_view(reinterpret_cast<const char*>(iter.peek_start()), iter.peek_start_length());
+}
+
+simdjson_inline simdjson_result<std::string_view> value::raw_json() noexcept {
+ json_type t;
+ SIMDJSON_TRY(type().get(t));
+ switch (t)
+ {
+ case json_type::array: {
+ ondemand::array array;
+ SIMDJSON_TRY(get_array().get(array));
+ return array.raw_json();
+ }
+ case json_type::object: {
+ ondemand::object object;
+ SIMDJSON_TRY(get_object().get(object));
+ return object.raw_json();
+ }
+ default:
+ return raw_json_token();
+ }
+}
+
+simdjson_inline simdjson_result<const char *> value::current_location() noexcept {
+ return iter.json_iter().current_location();
+}
+
+simdjson_inline int32_t value::current_depth() const noexcept{
+ return iter.json_iter().depth();
+}
+
+inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept {
+ if (simdjson_unlikely(json_pointer.empty())) { // can't be
+ return false;
+ }
+ if (simdjson_unlikely(json_pointer[0] != '/')) {
+ return false;
+ }
+ size_t escape = json_pointer.find('~');
+ if (escape == std::string_view::npos) {
+ return true;
+ }
+ if (escape == json_pointer.size() - 1) {
+ return false;
+ }
+ if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') {
+ return false;
+ }
+ return true;
+}
+
+simdjson_inline simdjson_result<value> value::at_pointer(std::string_view json_pointer) noexcept {
+ json_type t;
+ SIMDJSON_TRY(type().get(t));
+ switch (t)
+ {
+ case json_type::array:
+ return (*this).get_array().at_pointer(json_pointer);
+ case json_type::object:
+ return (*this).get_object().at_pointer(json_pointer);
+ default:
+ // a non-empty string can be invalid, or accessing a primitive (issue 2154)
+ if (is_pointer_well_formed(json_pointer)) {
+ return NO_SUCH_FIELD;
+ }
+ return INVALID_JSON_POINTER;
+ }
+}
+
+simdjson_inline simdjson_result<value> value::at_path(std::string_view json_path) noexcept {
+ json_type t;
+ SIMDJSON_TRY(type().get(t));
+ switch (t) {
+ case json_type::array:
+ return (*this).get_array().at_path(json_path);
+ case json_type::object:
+ return (*this).get_object().at_path(json_path);
+ default:
+ return INVALID_JSON_POINTER;
+ }
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::simdjson_result(
+ SIMDJSON_IMPLEMENTATION::ondemand::value &&value
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value>(
+ std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value>(value)
+ )
+{
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::simdjson_result(
+ error_code error
+) noexcept :
+ implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value>(error)
+{
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::count_elements() & noexcept {
+ if (error()) { return error(); }
+ return first.count_elements();
+}
+simdjson_inline simdjson_result<size_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::count_fields() & noexcept {
+ if (error()) { return error(); }
+ return first.count_fields();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::at(size_t index) noexcept {
+ if (error()) { return error(); }
+ return first.at(index);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::begin() & noexcept {
+ if (error()) { return error(); }
+ return first.begin();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::end() & noexcept {
+ if (error()) { return error(); }
+ return {};
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(std::string_view key) noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field(const char *key) noexcept {
+ if (error()) { return error(); }
+ return first.find_field(key);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(std::string_view key) noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::find_field_unordered(const char *key) noexcept {
+ if (error()) { return error(); }
+ return first.find_field_unordered(key);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](std::string_view key) noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator[](const char *key) noexcept {
+ if (error()) { return error(); }
+ return first[key];
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_array() noexcept {
+ if (error()) { return error(); }
+ return first.get_array();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_object() noexcept {
+ if (error()) { return error(); }
+ return first.get_object();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_uint64() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64();
+}
+simdjson_inline simdjson_result<uint64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_uint64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_uint64_in_string();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_int64() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64();
+}
+simdjson_inline simdjson_result<int64_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_int64_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_int64_in_string();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_double() noexcept {
+ if (error()) { return error(); }
+ return first.get_double();
+}
+simdjson_inline simdjson_result<double> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_double_in_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_double_in_string();
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_string(bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(allow_replacement);
+}
+template <typename string_type>
+simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ if (error()) { return error(); }
+ return first.get_string(receiver, allow_replacement);
+}
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_wobbly_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_wobbly_string();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_raw_json_string() noexcept {
+ if (error()) { return error(); }
+ return first.get_raw_json_string();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_bool() noexcept {
+ if (error()) { return error(); }
+ return first.get_bool();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_null() noexcept {
+ if (error()) { return error(); }
+ return first.is_null();
+}
+
+template<typename T> simdjson_inline simdjson_result<T> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get() noexcept {
+ if (error()) { return error(); }
+ return first.get<T>();
+}
+template<typename T> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get(T &out) noexcept {
+ if (error()) { return error(); }
+ return first.get<T>(out);
+}
+
+template<> simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>() noexcept {
+ if (error()) { return error(); }
+ return std::move(first);
+}
+template<> simdjson_inline error_code simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get<SIMDJSON_IMPLEMENTATION::ondemand::value>(SIMDJSON_IMPLEMENTATION::ondemand::value &out) noexcept {
+ if (error()) { return error(); }
+ out = first;
+ return SUCCESS;
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::type() noexcept {
+ if (error()) { return error(); }
+ return first.type();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_scalar() noexcept {
+ if (error()) { return error(); }
+ return first.is_scalar();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_string() noexcept {
+ if (error()) { return error(); }
+ return first.is_string();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_negative() noexcept {
+ if (error()) { return error(); }
+ return first.is_negative();
+}
+simdjson_inline simdjson_result<bool> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::is_integer() noexcept {
+ if (error()) { return error(); }
+ return first.is_integer();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_number_type() noexcept {
+ if (error()) { return error(); }
+ return first.get_number_type();
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::get_number() noexcept {
+ if (error()) { return error(); }
+ return first.get_number();
+}
+#if SIMDJSON_EXCEPTIONS
+template <class T>
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator T() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return static_cast<T>(first);
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator uint64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator int64_t() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator double() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator std::string_view() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::operator bool() noexcept(false) {
+ if (error()) { throw simdjson_error(error()); }
+ return first;
+}
+#endif
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::raw_json_token() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json_token();
+}
+
+simdjson_inline simdjson_result<std::string_view> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::raw_json() noexcept {
+ if (error()) { return error(); }
+ return first.raw_json();
+}
+
+simdjson_inline simdjson_result<const char *> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_location() noexcept {
+ if (error()) { return error(); }
+ return first.current_location();
+}
+
+simdjson_inline simdjson_result<int32_t> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::current_depth() const noexcept {
+ if (error()) { return error(); }
+ return first.current_depth();
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::at_pointer(
+ std::string_view json_pointer) noexcept {
+ if (error()) {
+ return error();
+ }
+ return first.at_pointer(json_pointer);
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value>::at_path(
+ std::string_view json_path) noexcept {
+ if (error()) {
+ return error();
+ }
+ return first.at_path(json_path);
+}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h
new file mode 100644
index 0000000000..bd6b74ed32
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value.h
@@ -0,0 +1,781 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_VALUE_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * An ephemeral JSON value returned during iteration. It is only valid for as long as you do
+ * not access more data in the JSON document.
+ */
+class value {
+public:
+ /**
+ * Create a new invalid value.
+ *
+ * Exists so you can declare a variable and later assign to it before use.
+ */
+ simdjson_inline value() noexcept = default;
+
+ /**
+ * Get this value as the given type.
+ *
+ * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
+ *
+ * You may use get_double(), get_bool(), get_uint64(), get_int64(),
+ * get_object(), get_array(), get_raw_json_string(), or get_string() instead.
+ *
+ * @returns A value of the given type, parsed from the JSON.
+ * @returns INCORRECT_TYPE If the JSON value is not the given type.
+ */
+ template<typename T> simdjson_inline simdjson_result<T> get() noexcept {
+ // Unless the simdjson library or the user provides an inline implementation, calling this method should
+ // immediately fail.
+ static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. "
+ "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, "
+ "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), "
+ " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template."
+ " You may also add support for custom types, see our documentation.");
+ }
+
+ /**
+ * Get this value as the given type.
+ *
+ * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool
+ *
+ * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized.
+ * @returns INCORRECT_TYPE If the JSON value is not an object.
+ * @returns SUCCESS If the parse succeeded and the out parameter was set to the value.
+ */
+ template<typename T> simdjson_inline error_code get(T &out) noexcept;
+
+ /**
+ * Cast this JSON value to an array.
+ *
+ * @returns An object that can be used to iterate the array.
+ * @returns INCORRECT_TYPE If the JSON value is not an array.
+ */
+ simdjson_inline simdjson_result<array> get_array() noexcept;
+
+ /**
+ * Cast this JSON value to an object.
+ *
+ * @returns An object that can be used to look up or iterate fields.
+ * @returns INCORRECT_TYPE If the JSON value is not an object.
+ */
+ simdjson_inline simdjson_result<object> get_object() noexcept;
+
+ /**
+ * Cast this JSON value to an unsigned integer.
+ *
+ * @returns A unsigned 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+
+ /**
+ * Cast this JSON value (inside string) to a unsigned integer.
+ *
+ * @returns A unsigned 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+
+ /**
+ * Cast this JSON value to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+
+ /**
+ * Cast this JSON value (inside string) to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @returns INCORRECT_TYPE If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+
+ /**
+ * Cast this JSON value to a double.
+ *
+ * @returns A double.
+ * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+
+ /**
+ * Cast this JSON value (inside string) to a double
+ *
+ * @returns A double.
+ * @returns INCORRECT_TYPE If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+
+ /**
+ * Cast this JSON value to a string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * Equivalent to get<std::string_view>().
+ *
+ * Important: a value should be consumed once. Calling get_string() twice on the same value
+ * is an error.
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+
+ /**
+ * Attempts to fill the provided std::string reference with the parsed value of the current string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * Important: a value should be consumed once. Calling get_string() twice on the same value
+ * is an error.
+ *
+ * Performance: This method may be slower than get_string() or get_string(bool) because it may need to allocate memory.
+ * We recommend you avoid allocating an std::string unless you need to.
+ *
+ * @returns INCORRECT_TYPE if the JSON value is not a string. Otherwise, we return SUCCESS.
+ */
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+
+ /**
+ * Cast this JSON value to a "wobbly" string.
+ *
+ * The string is may not be a valid UTF-8 string.
+ * See https://simonsapin.github.io/wtf-8/
+ *
+ * Important: a value should be consumed once. Calling get_wobbly_string() twice on the same value
+ * is an error.
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ /**
+ * Cast this JSON value to a raw_json_string.
+ *
+ * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
+ *
+ * @returns A pointer to the raw JSON for the given string.
+ * @returns INCORRECT_TYPE if the JSON value is not a string.
+ */
+ simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
+
+ /**
+ * Cast this JSON value to a bool.
+ *
+ * @returns A bool value.
+ * @returns INCORRECT_TYPE if the JSON value is not true or false.
+ */
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+
+ /**
+ * Checks if this JSON value is null. If and only if the value is
+ * null, then it is consumed (we advance). If we find a token that
+ * begins with 'n' but is not 'null', then an error is returned.
+ *
+ * @returns Whether the value is null.
+ * @returns INCORRECT_TYPE If the JSON value begins with 'n' and is not 'null'.
+ */
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ /**
+ * Cast this JSON value to an instance of type T. The programmer is responsible for
+ * providing an implementation of get<T> for the type T, if T is not one of the types
+ * supported by the library (object, array, raw_json_string, string_view, uint64_t, etc.).
+ *
+ * See https://github.com/simdjson/simdjson/blob/master/doc/basics.md#adding-support-for-custom-types
+ *
+ * @returns An instance of type T
+ */
+ template <class T>
+ explicit simdjson_inline operator T() noexcept(false);
+ /**
+ * Cast this JSON value to an array.
+ *
+ * @returns An object that can be used to iterate the array.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an array.
+ */
+ simdjson_inline operator array() noexcept(false);
+ /**
+ * Cast this JSON value to an object.
+ *
+ * @returns An object that can be used to look up or iterate fields.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not an object.
+ */
+ simdjson_inline operator object() noexcept(false);
+ /**
+ * Cast this JSON value to an unsigned integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
+ */
+ simdjson_inline operator uint64_t() noexcept(false);
+ /**
+ * Cast this JSON value to a signed integer.
+ *
+ * @returns A signed 64-bit integer.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
+ */
+ simdjson_inline operator int64_t() noexcept(false);
+ /**
+ * Cast this JSON value to a double.
+ *
+ * @returns A double.
+ * @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
+ */
+ simdjson_inline operator double() noexcept(false);
+ /**
+ * Cast this JSON value to a string.
+ *
+ * The string is guaranteed to be valid UTF-8.
+ *
+ * Equivalent to get<std::string_view>().
+ *
+ * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next
+ * time it parses a document or when it is destroyed.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
+ */
+ simdjson_inline operator std::string_view() noexcept(false);
+ /**
+ * Cast this JSON value to a raw_json_string.
+ *
+ * The string is guaranteed to be valid UTF-8, and may have escapes in it (e.g. \\ or \n).
+ *
+ * @returns A pointer to the raw JSON for the given string.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
+ */
+ simdjson_inline operator raw_json_string() noexcept(false);
+ /**
+ * Cast this JSON value to a bool.
+ *
+ * @returns A bool value.
+ * @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
+ */
+ simdjson_inline operator bool() noexcept(false);
+#endif
+
+ /**
+ * Begin array iteration.
+ *
+ * Part of the std::iterable interface.
+ *
+ * @returns INCORRECT_TYPE If the JSON value is not an array.
+ */
+ simdjson_inline simdjson_result<array_iterator> begin() & noexcept;
+ /**
+ * Sentinel representing the end of the array.
+ *
+ * Part of the std::iterable interface.
+ */
+ simdjson_inline simdjson_result<array_iterator> end() & noexcept;
+ /**
+ * This method scans the array and counts the number of elements.
+ * The count_elements method should always be called before you have begun
+ * iterating through the array: it is expected that you are pointing at
+ * the beginning of the array.
+ * The runtime complexity is linear in the size of the array. After
+ * calling this function, if successful, the array is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ *
+ * Performance hint: You should only call count_elements() as a last
+ * resort as it may require scanning the document twice or more.
+ */
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ /**
+ * This method scans the object and counts the number of key-value pairs.
+ * The count_fields method should always be called before you have begun
+ * iterating through the object: it is expected that you are pointing at
+ * the beginning of the object.
+ * The runtime complexity is linear in the size of the object. After
+ * calling this function, if successful, the object is 'rewinded' at its
+ * beginning as if it had never been accessed. If the JSON is malformed (e.g.,
+ * there is a missing comma), then an error is returned and it is no longer
+ * safe to continue.
+ *
+ * To check that an object is empty, it is more performant to use
+ * the is_empty() method on the object instance.
+ *
+ * Performance hint: You should only call count_fields() as a last
+ * resort as it may require scanning the document twice or more.
+ */
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ /**
+ * Get the value at the given index in the array. This function has linear-time complexity.
+ * This function should only be called once on an array instance since the array iterator is not reset between each call.
+ *
+ * @return The value at the given index, or:
+ * - INDEX_OUT_OF_BOUNDS if the array index is larger than an array length
+ */
+ simdjson_inline simdjson_result<value> at(size_t index) noexcept;
+ /**
+ * Look up a field by name on an object (order-sensitive).
+ *
+ * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
+ * JSON `{ "x": 1, "y": 2, "z": 3 }`:
+ *
+ * ```c++
+ * simdjson::ondemand::parser parser;
+ * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
+ * double z = obj.find_field("z");
+ * double y = obj.find_field("y");
+ * double x = obj.find_field("x");
+ * ```
+ * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
+ * that only one field is returned.
+
+ * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
+ * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<value> find_field(const char *key) noexcept;
+
+ /**
+ * Look up a field by name on an object, without regard to key order.
+ *
+ * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
+ * and often appears negligible. It starts out normally, starting out at the last field; but if
+ * the field is not found, it scans from the beginning of the object to see if it missed it. That
+ * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
+ * in question is large. The fact that the extra code is there also bumps the executable size.
+ *
+ * It is the default, however, because it would be highly surprising (and hard to debug) if the
+ * default behavior failed to look up a field just because it was in the wrong order--and many
+ * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
+ *
+ * If you have multiple fields with a matching key ({"x": 1, "x": 1}) be mindful
+ * that only one field is returned.
+ *
+ * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
+ * field as not there when they are not in order).
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<value> find_field_unordered(const char *key) noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<value> operator[](std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<value> operator[](const char *key) noexcept;
+
+ /**
+ * Get the type of this JSON value. It does not validate or consume the value.
+ * E.g., you must still call "is_null()" to check that a value is null even if
+ * "type()" returns json_type::null.
+ *
+ * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
+ * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
+ * let it throw an exception).
+ *
+ * @return The type of JSON value (json_type::array, json_type::object, json_type::string,
+ * json_type::number, json_type::boolean, or json_type::null).
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<json_type> type() noexcept;
+
+ /**
+ * Checks whether the value is a scalar (string, number, null, Boolean).
+ * Returns false when there it is an array or object.
+ *
+ * @returns true if the type is string, number, null, Boolean
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+ /**
+ * Checks whether the value is a string.
+ *
+ * @returns true if the type is string
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+
+ /**
+ * Checks whether the value is a negative number.
+ *
+ * @returns true if the number if negative.
+ */
+ simdjson_inline bool is_negative() noexcept;
+ /**
+ * Checks whether the value is an integer number. Note that
+ * this requires to partially parse the number string. If
+ * the value is determined to be an integer, it may still
+ * not parse properly as an integer in subsequent steps
+ * (e.g., it might overflow).
+ *
+ * Performance note: if you call this function systematically
+ * before parsing a number, you may have fallen for a performance
+ * anti-pattern.
+ *
+ * @returns true if the number if negative.
+ */
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ /**
+ * Determine the number type (integer or floating-point number) as quickly
+ * as possible. This function does not fully validate the input. It is
+ * useful when you only need to classify the numbers, without parsing them.
+ *
+ * If you are planning to retrieve the value or you need full validation,
+ * consider using the get_number() method instead: it will fully parse
+ * and validate the input, and give you access to the type:
+ * get_number().get_number_type().
+ *
+ * get_number_type() is number_type::unsigned_integer if we have
+ * an integer greater or equal to 9223372036854775808.
+ * get_number_type() is number_type::signed_integer if we have an
+ * integer that is less than 9223372036854775808.
+ * get_number_type() is number_type::big_integer for integers that do not fit in 64 bits,
+ * in which case the digit_count is set to the length of the big integer string.
+ * Otherwise, get_number_type() has value number_type::floating_point_number.
+ *
+ * This function requires processing the number string, but it is expected
+ * to be faster than get_number().get_number_type() because it is does not
+ * parse the number value.
+ *
+ * @returns the type of the number
+ */
+ simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
+
+ /**
+ * Attempt to parse an ondemand::number. An ondemand::number may
+ * contain an integer value or a floating-point value, the simdjson
+ * library will autodetect the type. Thus it is a dynamically typed
+ * number. Before accessing the value, you must determine the detected
+ * type.
+ *
+ * number.get_number_type() is number_type::signed_integer if we have
+ * an integer in [-9223372036854775808,9223372036854775808)
+ * You can recover the value by calling number.get_int64() and you
+ * have that number.is_int64() is true.
+ *
+ * number.get_number_type() is number_type::unsigned_integer if we have
+ * an integer in [9223372036854775808,18446744073709551616)
+ * You can recover the value by calling number.get_uint64() and you
+ * have that number.is_uint64() is true.
+ *
+ * For integers that do not fit in 64 bits, the function returns BIGINT_ERROR error code.
+ *
+ * Otherwise, number.get_number_type() has value number_type::floating_point_number
+ * and we have a binary64 number.
+ * You can recover the value by calling number.get_double() and you
+ * have that number.is_double() is true.
+ *
+ * You must check the type before accessing the value: it is an error
+ * to call "get_int64()" when number.get_number_type() is not
+ * number_type::signed_integer and when number.is_int64() is false.
+ *
+ * Performance note: this is designed with performance in mind. When
+ * calling 'get_number()', you scan the number string only once, determining
+ * efficiently the type and storing it in an efficient manner.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
+
+ /**
+ * Get the raw JSON for this token.
+ *
+ * The string_view will always point into the input buffer.
+ *
+ * The string_view will start at the beginning of the token, and include the entire token
+ * *as well as all spaces until the next token (or EOF).* This means, for example, that a
+ * string token always begins with a " and is always terminated by the final ", possibly
+ * followed by a number of spaces.
+ *
+ * The string_view is *not* null-terminated. However, if this is a scalar (string, number,
+ * boolean, or null), the character after the end of the string_view is guaranteed to be
+ * a non-space token.
+ *
+ * Tokens include:
+ * - {
+ * - [
+ * - "a string (possibly with UTF-8 or backslashed characters like \\\")".
+ * - -1.2e-100
+ * - true
+ * - false
+ * - null
+ *
+ * See also value::raw_json().
+ */
+ simdjson_inline std::string_view raw_json_token() noexcept;
+
+ /**
+ * Get a string_view pointing at this value in the JSON document.
+ * If this element is an array or an object, it consumes the array or the object
+ * and returns a string_view instance corresponding to the
+ * array as represented in JSON. It points inside the original document.
+ * If this element is a scalar (string, number, Boolean, null), it returns what
+ * raw_json_token() would return.
+ */
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+
+ /**
+ * Returns the current location in the document if in bounds.
+ */
+ simdjson_inline simdjson_result<const char *> current_location() noexcept;
+
+ /**
+ * Returns the current depth in the document if in bounds.
+ *
+ * E.g.,
+ * 0 = finished with document
+ * 1 = document root value (could be [ or {, not yet known)
+ * 2 = , or } inside root array/object
+ * 3 = key or value inside root array/object.
+ */
+ simdjson_inline int32_t current_depth() const noexcept;
+
+ /**
+ * Get the value associated with the given JSON pointer. We use the RFC 6901
+ * https://tools.ietf.org/html/rfc6901 standard.
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "foo": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("/foo/a/1") == 20
+ *
+ * It is allowed for a key to be the empty string:
+ *
+ * ondemand::parser parser;
+ * auto json = R"({ "": { "a": [ 10, 20, 30 ] }})"_padded;
+ * auto doc = parser.iterate(json);
+ * doc.at_pointer("//a/1") == 20
+ *
+ * Note that at_pointer() called on the document automatically calls the document's rewind
+ * method between each call. It invalidates all previously accessed arrays, objects and values
+ * that have not been consumed.
+ *
+ * Calling at_pointer() on non-document instances (e.g., arrays and objects) is not
+ * standardized (by RFC 6901). We provide some experimental support for JSON pointers
+ * on non-document instances. Yet it is not the case when calling at_pointer on an array
+ * or an object instance: there is no rewind and no invalidation.
+ *
+ * You may only call at_pointer on an array after it has been created, but before it has
+ * been first accessed. When calling at_pointer on an array, the pointer is advanced to
+ * the location indicated by the JSON pointer (in case of success). It is no longer possible
+ * to call at_pointer on the same array.
+ *
+ * You may call at_pointer more than once on an object, but each time the pointer is advanced
+ * to be within the value matched by the key indicated by the JSON pointer query. Thus any preceding
+ * key (as well as the current key) can no longer be used with following JSON pointer calls.
+ *
+ * Also note that at_pointer() relies on find_field() which implies that we do not unescape keys when matching
+ *
+ * @return The value associated with the given JSON pointer, or:
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ * - INVALID_JSON_POINTER if the JSON pointer is invalid and cannot be parsed
+ */
+ simdjson_inline simdjson_result<value> at_pointer(std::string_view json_pointer) noexcept;
+
+ /**
+ * Get the value associated with the given JSONPath expression. We only support
+ * JSONPath queries that trivially convertible to JSON Pointer queries: key
+ * names and array indices.
+ *
+ * @return The value associated with the given JSONPath expression, or:
+ * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails
+ * - NO_SUCH_FIELD if a field does not exist in an object
+ * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length
+ * - INCORRECT_TYPE if a non-integer is used to access an array
+ */
+ simdjson_inline simdjson_result<value> at_path(std::string_view at_path) noexcept;
+
+
+protected:
+ /**
+ * Create a value.
+ */
+ simdjson_inline value(const value_iterator &iter) noexcept;
+
+ /**
+ * Skip this value, allowing iteration to continue.
+ */
+ simdjson_inline void skip() noexcept;
+
+ /**
+ * Start a value at the current position.
+ *
+ * (It should already be started; this is just a self-documentation method.)
+ */
+ static simdjson_inline value start(const value_iterator &iter) noexcept;
+
+ /**
+ * Resume a value.
+ */
+ static simdjson_inline value resume(const value_iterator &iter) noexcept;
+
+ /**
+ * Get the object, starting or resuming it as necessary
+ */
+ simdjson_inline simdjson_result<object> start_or_resume_object() noexcept;
+
+ // simdjson_inline void log_value(const char *type) const noexcept;
+ // simdjson_inline void log_error(const char *message) const noexcept;
+
+ value_iterator iter{};
+
+ friend class document;
+ friend class array_iterator;
+ friend class field;
+ friend class object;
+ friend struct simdjson_result<value>;
+ friend struct simdjson_result<field>;
+ friend class field;
+};
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array> get_array() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::object> get_object() noexcept;
+
+ simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ simdjson_inline simdjson_result<double> get_double() noexcept;
+ simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement = false) noexcept;
+ template <typename string_type>
+ simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement = false) noexcept;
+ simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string> get_raw_json_string() noexcept;
+ simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ simdjson_inline simdjson_result<bool> is_null() noexcept;
+
+ template<typename T> simdjson_inline simdjson_result<T> get() noexcept;
+
+ template<typename T> simdjson_inline error_code get(T &out) noexcept;
+
+#if SIMDJSON_EXCEPTIONS
+ template <class T>
+ explicit simdjson_inline operator T() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() noexcept(false);
+ simdjson_inline operator uint64_t() noexcept(false);
+ simdjson_inline operator int64_t() noexcept(false);
+ simdjson_inline operator double() noexcept(false);
+ simdjson_inline operator std::string_view() noexcept(false);
+ simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
+ simdjson_inline operator bool() noexcept(false);
+#endif
+ simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
+ simdjson_inline simdjson_result<size_t> count_fields() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at(size_t index) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> begin() & noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::array_iterator> end() & noexcept;
+
+ /**
+ * Look up a field by name on an object (order-sensitive).
+ *
+ * The following code reads z, then y, then x, and thus will not retrieve x or y if fed the
+ * JSON `{ "x": 1, "y": 2, "z": 3 }`:
+ *
+ * ```c++
+ * simdjson::ondemand::parser parser;
+ * auto obj = parser.parse(R"( { "x": 1, "y": 2, "z": 3 } )"_padded);
+ * double z = obj.find_field("z");
+ * double y = obj.find_field("y");
+ * double x = obj.find_field("x");
+ * ```
+ *
+ * **Raw Keys:** The lookup will be done against the *raw* key, and will not unescape keys.
+ * e.g. `object["a"]` will match `{ "a": 1 }`, but will *not* match `{ "\u0061": 1 }`.
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field(const char *key) noexcept;
+
+ /**
+ * Look up a field by name on an object, without regard to key order.
+ *
+ * **Performance Notes:** This is a bit less performant than find_field(), though its effect varies
+ * and often appears negligible. It starts out normally, starting out at the last field; but if
+ * the field is not found, it scans from the beginning of the object to see if it missed it. That
+ * missing case has a non-cache-friendly bump and lots of extra scanning, especially if the object
+ * in question is large. The fact that the extra code is there also bumps the executable size.
+ *
+ * It is the default, however, because it would be highly surprising (and hard to debug) if the
+ * default behavior failed to look up a field just because it was in the wrong order--and many
+ * APIs assume this. Therefore, you must be explicit if you want to treat objects as out of order.
+ *
+ * Use find_field() if you are sure fields will be in order (or are willing to treat it as if the
+ * field as not there when they are not in order).
+ *
+ * @param key The key to look up.
+ * @returns The value of the field, or NO_SUCH_FIELD if the field is not in the object.
+ */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(const char *key) noexcept;
+ /** @overload simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](std::string_view key) noexcept;
+ /** @overload simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> find_field_unordered(std::string_view key) noexcept; */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> operator[](const char *key) noexcept;
+
+ /**
+ * Get the type of this JSON value.
+ *
+ * NOTE: If you're only expecting a value to be one type (a typical case), it's generally
+ * better to just call .get_double, .get_string, etc. and check for INCORRECT_TYPE (or just
+ * let it throw an exception).
+ */
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::json_type> type() noexcept;
+ simdjson_inline simdjson_result<bool> is_scalar() noexcept;
+ simdjson_inline simdjson_result<bool> is_string() noexcept;
+ simdjson_inline simdjson_result<bool> is_negative() noexcept;
+ simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> get_number_type() noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::number> get_number() noexcept;
+
+ /** @copydoc simdjson_inline std::string_view value::raw_json_token() const noexcept */
+ simdjson_inline simdjson_result<std::string_view> raw_json_token() noexcept;
+ simdjson_inline simdjson_result<std::string_view> raw_json() noexcept;
+
+ /** @copydoc simdjson_inline simdjson_result<const char *> current_location() noexcept */
+ simdjson_inline simdjson_result<const char *> current_location() noexcept;
+ /** @copydoc simdjson_inline int32_t current_depth() const noexcept */
+ simdjson_inline simdjson_result<int32_t> current_depth() const noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_pointer(std::string_view json_pointer) noexcept;
+ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value> at_path(std::string_view json_path) noexcept;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_H
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h
new file mode 100644
index 0000000000..e67bddaeb1
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator-inl.h
@@ -0,0 +1,1091 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/atomparsing.h"
+#include "simdjson/generic/numberparsing.h"
+#include "simdjson/generic/ondemand/json_iterator.h"
+#include "simdjson/generic/ondemand/value_iterator.h"
+#include "simdjson/generic/ondemand/json_type-inl.h"
+#include "simdjson/generic/ondemand/raw_json_string-inl.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+simdjson_inline value_iterator::value_iterator(
+ json_iterator *json_iter,
+ depth_t depth,
+ token_position start_position
+) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position}
+{
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_object() noexcept {
+ SIMDJSON_TRY( start_container('{', "Not an object", "object") );
+ return started_object();
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_object() noexcept {
+ SIMDJSON_TRY( start_container('{', "Not an object", "object") );
+ return started_root_object();
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_object() noexcept {
+ assert_at_container_start();
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ _json_iter->set_start_position(_depth, start_position());
+#endif
+ if (*_json_iter->peek() == '}') {
+ logger::log_value(*_json_iter, "empty object");
+ _json_iter->return_current_and_advance();
+ end_container();
+ return false;
+ }
+ return true;
+}
+
+simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept {
+ // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
+ // current document. It only works in the normal mode where we have indexed a single document.
+ // Note that adding a check for 'streaming' is not expensive since we only have at most
+ // one root element.
+ if ( ! _json_iter->streaming() ) {
+ // The following lines do not fully protect against garbage content within the
+ // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should
+ // call `at_end()` on the document instance at the end of the processing to
+ // ensure that the processing has finished at the end.
+ //
+ if (*_json_iter->peek_last() != '}') {
+ _json_iter->abandon();
+ return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end");
+ }
+ // If the last character is } *and* the first gibberish character is also '}'
+ // then on-demand could accidentally go over. So we need additional checks.
+ // https://github.com/simdjson/simdjson/issues/1834
+ // Checking that the document is balanced requires a full scan which is potentially
+ // expensive, but it only happens in edge cases where the first padding character is
+ // a closing bracket.
+ if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) {
+ _json_iter->abandon();
+ // The exact error would require more work. It will typically be an unclosed object.
+ return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
+ }
+ }
+ return SUCCESS;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_object() noexcept {
+ auto error = check_root_object();
+ if(error) { return error; }
+ return started_object();
+}
+
+simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept {
+#if SIMDJSON_CHECK_EOF
+ if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); }
+ // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); }
+#endif // SIMDJSON_CHECK_EOF
+ _json_iter->ascend_to(depth()-1);
+ return SUCCESS;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_field() noexcept {
+ assert_at_next();
+
+ // It's illegal to call this unless there are more tokens: anything that ends in } or ] is
+ // obligated to verify there are more tokens if they are not the top level.
+ switch (*_json_iter->return_current_and_advance()) {
+ case '}':
+ logger::log_end_value(*_json_iter, "object");
+ SIMDJSON_TRY( end_container() );
+ return false;
+ case ',':
+ return true;
+ default:
+ return report_error(TAPE_ERROR, "Missing comma between object fields");
+ }
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_raw(const std::string_view key) noexcept {
+ error_code error;
+ bool has_value;
+ //
+ // Initially, the object can be in one of a few different places:
+ //
+ // 1. The start of the object, at the first field:
+ //
+ // ```
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 2, index 1)
+ // ```
+ if (at_first_field()) {
+ has_value = true;
+
+ //
+ // 2. When a previous search did not yield a value or the object is empty:
+ //
+ // ```
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 0)
+ // { }
+ // ^ (depth 0, index 2)
+ // ```
+ //
+ } else if (!is_open()) {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ // If we're past the end of the object, we're being iterated out of order.
+ // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
+ // this object iterator will blithely scan that object for fields.
+ if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ return false;
+
+ // 3. When a previous search found a field or an iterator yielded a value:
+ //
+ // ```
+ // // When a field was not fully consumed (or not even touched at all)
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 2)
+ // // When a field was fully consumed
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // // When the last field was fully consumed
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // ```
+ //
+ } else {
+ if ((error = skip_child() )) { abandon(); return error; }
+ if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ }
+ while (has_value) {
+ // Get the key and colon, stopping at the value.
+ raw_json_string actual_key;
+ // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
+ // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
+ // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
+ // The depth is left unchanged by field_key().
+ if ((error = field_key().get(actual_key) )) { abandon(); return error; };
+ // field_value() will advance and check that we find a ':' separating the
+ // key and the value. It will also increment the depth by one.
+ if ((error = field_value() )) { abandon(); return error; }
+ // If it matches, stop and return
+ // We could do it this way if we wanted to allow arbitrary
+ // key content (including escaped quotes).
+ //if (actual_key.unsafe_is_equal(max_key_length, key)) {
+ // Instead we do the following which may trigger buffer overruns if the
+ // user provides an adversarial key (containing a well placed unescaped quote
+ // character and being longer than the number of bytes remaining in the JSON
+ // input).
+ if (actual_key.unsafe_is_equal(key)) {
+ logger::log_event(*this, "match", key, -2);
+ // If we return here, then we return while pointing at the ':' that we just checked.
+ return true;
+ }
+
+ // No match: skip the value and see if , or } is next
+ logger::log_event(*this, "no match", key, -2);
+ // The call to skip_child is meant to skip over the value corresponding to the key.
+ // After skip_child(), we are right before the next comma (',') or the final brace ('}').
+ SIMDJSON_TRY( skip_child() ); // Skip the value entirely
+ // The has_next_field() advances the pointer and check that either ',' or '}' is found.
+ // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
+ // then we are in error and we abort.
+ if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
+ }
+
+ // If the loop ended, we're out of fields to look at.
+ return false;
+}
+
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::find_field_unordered_raw(const std::string_view key) noexcept {
+ /**
+ * When find_field_unordered_raw is called, we can either be pointing at the
+ * first key, pointing outside (at the closing brace) or if a key was matched
+ * we can be either pointing right afterthe ':' right before the value (that we need skip),
+ * or we may have consumed the value and we might be at a comma or at the
+ * final brace (ready for a call to has_next_field()).
+ */
+ error_code error;
+ bool has_value;
+
+ // First, we scan from that point to the end.
+ // If we don't find a match, we may loop back around, and scan from the beginning to that point.
+ token_position search_start = _json_iter->position();
+
+ // We want to know whether we need to go back to the beginning.
+ bool at_first = at_first_field();
+ ///////////////
+ // Initially, the object can be in one of a few different places:
+ //
+ // 1. At the first key:
+ //
+ // ```
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 2, index 1)
+ // ```
+ //
+ if (at_first) {
+ has_value = true;
+
+ // 2. When a previous search did not yield a value or the object is empty:
+ //
+ // ```
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 0)
+ // { }
+ // ^ (depth 0, index 2)
+ // ```
+ //
+ } else if (!is_open()) {
+
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ // If we're past the end of the object, we're being iterated out of order.
+ // Note: this is not perfect detection. It's possible the user is inside some other object; if so,
+ // this object iterator will blithely scan that object for fields.
+ if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ SIMDJSON_TRY(reset_object().get(has_value));
+ at_first = true;
+ // 3. When a previous search found a field or an iterator yielded a value:
+ //
+ // ```
+ // // When a field was not fully consumed (or not even touched at all)
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 2)
+ // // When a field was fully consumed
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // // When the last field was fully consumed
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // ```
+ //
+ } else {
+ // If someone queried a key but they not did access the value, then we are left pointing
+ // at the ':' and we need to move forward through the value... If the value was
+ // processed then skip_child() does not move the iterator (but may adjust the depth).
+ if ((error = skip_child() )) { abandon(); return error; }
+ search_start = _json_iter->position();
+ if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ }
+
+ // After initial processing, we will be in one of two states:
+ //
+ // ```
+ // // At the beginning of a field
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 1)
+ // // At the end of the object
+ // { "a": [ 1, 2 ], "b": [ 3, 4 ] }
+ // ^ (depth 0)
+ // ```
+ //
+ // Next, we find a match starting from the current position.
+ while (has_value) {
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
+
+ // Get the key and colon, stopping at the value.
+ raw_json_string actual_key;
+ // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
+ // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
+ // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
+ // The depth is left unchanged by field_key().
+ if ((error = field_key().get(actual_key) )) { abandon(); return error; };
+ // field_value() will advance and check that we find a ':' separating the
+ // key and the value. It will also increment the depth by one.
+ if ((error = field_value() )) { abandon(); return error; }
+
+ // If it matches, stop and return
+ // We could do it this way if we wanted to allow arbitrary
+ // key content (including escaped quotes).
+ // if (actual_key.unsafe_is_equal(max_key_length, key)) {
+ // Instead we do the following which may trigger buffer overruns if the
+ // user provides an adversarial key (containing a well placed unescaped quote
+ // character and being longer than the number of bytes remaining in the JSON
+ // input).
+ if (actual_key.unsafe_is_equal(key)) {
+ logger::log_event(*this, "match", key, -2);
+ // If we return here, then we return while pointing at the ':' that we just checked.
+ return true;
+ }
+
+ // No match: skip the value and see if , or } is next
+ logger::log_event(*this, "no match", key, -2);
+ // The call to skip_child is meant to skip over the value corresponding to the key.
+ // After skip_child(), we are right before the next comma (',') or the final brace ('}').
+ SIMDJSON_TRY( skip_child() );
+ // The has_next_field() advances the pointer and check that either ',' or '}' is found.
+ // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
+ // then we are in error and we abort.
+ if ((error = has_next_field().get(has_value) )) { abandon(); return error; }
+ }
+ // Performance note: it maybe wasteful to rewind to the beginning when there might be
+ // no other query following. Indeed, it would require reskipping the whole object.
+ // Instead, you can just stay where you are. If there is a new query, there is always time
+ // to rewind.
+ if(at_first) { return false; }
+
+ // If we reach the end without finding a match, search the rest of the fields starting at the
+ // beginning of the object.
+ // (We have already run through the object before, so we've already validated its structure. We
+ // don't check errors in this bit.)
+ SIMDJSON_TRY(reset_object().get(has_value));
+ while (true) {
+ SIMDJSON_ASSUME(has_value); // we should reach search_start before ever reaching the end of the object
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth ); // We must be at the start of a field
+
+ // Get the key and colon, stopping at the value.
+ raw_json_string actual_key;
+ // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes
+ // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2.
+ // field_key() advances the pointer and checks that '"' is found (corresponding to a key).
+ // The depth is left unchanged by field_key().
+ error = field_key().get(actual_key); SIMDJSON_ASSUME(!error);
+ // field_value() will advance and check that we find a ':' separating the
+ // key and the value. It will also increment the depth by one.
+ error = field_value(); SIMDJSON_ASSUME(!error);
+
+ // If it matches, stop and return
+ // We could do it this way if we wanted to allow arbitrary
+ // key content (including escaped quotes).
+ // if (actual_key.unsafe_is_equal(max_key_length, key)) {
+ // Instead we do the following which may trigger buffer overruns if the
+ // user provides an adversarial key (containing a well placed unescaped quote
+ // character and being longer than the number of bytes remaining in the JSON
+ // input).
+ if (actual_key.unsafe_is_equal(key)) {
+ logger::log_event(*this, "match", key, -2);
+ // If we return here, then we return while pointing at the ':' that we just checked.
+ return true;
+ }
+
+ // No match: skip the value and see if , or } is next
+ logger::log_event(*this, "no match", key, -2);
+ // The call to skip_child is meant to skip over the value corresponding to the key.
+ // After skip_child(), we are right before the next comma (',') or the final brace ('}').
+ SIMDJSON_TRY( skip_child() );
+ // If we reached the end of the key-value pair we started from, then we know
+ // that the key is not there so we return false. We are either right before
+ // the next comma or the final brace.
+ if(_json_iter->position() == search_start) { return false; }
+ // The has_next_field() advances the pointer and check that either ',' or '}' is found.
+ // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
+ // then we are in error and we abort.
+ error = has_next_field().get(has_value); SIMDJSON_ASSUME(!error);
+ // If we make the mistake of exiting here, then we could be left pointing at a key
+ // in the middle of an object. That's not an allowable state.
+ }
+ // If the loop ended, we're out of fields to look at. The program should
+ // never reach this point.
+ return false;
+}
+SIMDJSON_POP_DISABLE_WARNINGS
+
+simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::field_key() noexcept {
+ assert_at_next();
+
+ const uint8_t *key = _json_iter->return_current_and_advance();
+ if (*(key++) != '"') { return report_error(TAPE_ERROR, "Object key is not a string"); }
+ return raw_json_string(key);
+}
+
+simdjson_warn_unused simdjson_inline error_code value_iterator::field_value() noexcept {
+ assert_at_next();
+
+ if (*_json_iter->return_current_and_advance() != ':') { return report_error(TAPE_ERROR, "Missing colon in object field"); }
+ _json_iter->descend_to(depth()+1);
+ return SUCCESS;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_array() noexcept {
+ SIMDJSON_TRY( start_container('[', "Not an array", "array") );
+ return started_array();
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::start_root_array() noexcept {
+ SIMDJSON_TRY( start_container('[', "Not an array", "array") );
+ return started_root_array();
+}
+
+inline std::string value_iterator::to_string() const noexcept {
+ auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
+ if(_json_iter != nullptr) { answer += _json_iter->to_string(); }
+ answer += std::string(" ]");
+ return answer;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_array() noexcept {
+ assert_at_container_start();
+ if (*_json_iter->peek() == ']') {
+ logger::log_value(*_json_iter, "empty array");
+ _json_iter->return_current_and_advance();
+ SIMDJSON_TRY( end_container() );
+ return false;
+ }
+ _json_iter->descend_to(depth()+1);
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ _json_iter->set_start_position(_depth, start_position());
+#endif
+ return true;
+}
+
+simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_array() noexcept {
+ // When in streaming mode, we cannot expect peek_last() to be the last structural element of the
+ // current document. It only works in the normal mode where we have indexed a single document.
+ // Note that adding a check for 'streaming' is not expensive since we only have at most
+ // one root element.
+ if ( ! _json_iter->streaming() ) {
+ // The following lines do not fully protect against garbage content within the
+ // array: e.g., `[1, 2] foo]`. Users concerned with garbage content should
+ // also call `at_end()` on the document instance at the end of the processing to
+ // ensure that the processing has finished at the end.
+ //
+ if (*_json_iter->peek_last() != ']') {
+ _json_iter->abandon();
+ return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing ] at end");
+ }
+ // If the last character is ] *and* the first gibberish character is also ']'
+ // then on-demand could accidentally go over. So we need additional checks.
+ // https://github.com/simdjson/simdjson/issues/1834
+ // Checking that the document is balanced requires a full scan which is potentially
+ // expensive, but it only happens in edge cases where the first padding character is
+ // a closing bracket.
+ if ((*_json_iter->peek(_json_iter->end_position()) == ']') && (!_json_iter->balanced())) {
+ _json_iter->abandon();
+ // The exact error would require more work. It will typically be an unclosed array.
+ return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced");
+ }
+ }
+ return SUCCESS;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::started_root_array() noexcept {
+ auto error = check_root_array();
+ if (error) { return error; }
+ return started_array();
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::has_next_element() noexcept {
+ assert_at_next();
+
+ logger::log_event(*this, "has_next_element");
+ switch (*_json_iter->return_current_and_advance()) {
+ case ']':
+ logger::log_end_value(*_json_iter, "array");
+ SIMDJSON_TRY( end_container() );
+ return false;
+ case ',':
+ _json_iter->descend_to(depth()+1);
+ return true;
+ default:
+ return report_error(TAPE_ERROR, "Missing comma between array elements");
+ }
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_bool(const uint8_t *json) const noexcept {
+ auto not_true = atomparsing::str4ncmp(json, "true");
+ auto not_false = atomparsing::str4ncmp(json, "fals") | (json[4] ^ 'e');
+ bool error = (not_true && not_false) || jsoncharutils::is_not_structural_or_whitespace(json[not_true ? 5 : 4]);
+ if (error) { return incorrect_type_error("Not a boolean"); }
+ return simdjson_result<bool>(!not_true);
+}
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::parse_null(const uint8_t *json) const noexcept {
+ bool is_null_string = !atomparsing::str4ncmp(json, "null") && jsoncharutils::is_structural_or_whitespace(json[4]);
+ // if we start with 'n', we must be a null
+ if(!is_null_string && json[0]=='n') { return incorrect_type_error("Not a null but starts with n"); }
+ return is_null_string;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_string(bool allow_replacement) noexcept {
+ return get_raw_json_string().unescape(json_iter(), allow_replacement);
+}
+template <typename string_type>
+simdjson_warn_unused simdjson_inline error_code value_iterator::get_string(string_type& receiver, bool allow_replacement) noexcept {
+ std::string_view content;
+ auto err = get_string(allow_replacement).get(content);
+ if (err) { return err; }
+ receiver = content;
+ return SUCCESS;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_wobbly_string() noexcept {
+ return get_raw_json_string().unescape_wobbly(json_iter());
+}
+simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_raw_json_string() noexcept {
+ auto json = peek_scalar("string");
+ if (*json != '"') { return incorrect_type_error("Not a string"); }
+ advance_scalar("string");
+ return raw_json_string(json+1);
+}
+simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64() noexcept {
+ auto result = numberparsing::parse_unsigned(peek_non_root_scalar("uint64"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_uint64_in_string() noexcept {
+ auto result = numberparsing::parse_unsigned_in_string(peek_non_root_scalar("uint64"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("uint64"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64() noexcept {
+ auto result = numberparsing::parse_integer(peek_non_root_scalar("int64"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_int64_in_string() noexcept {
+ auto result = numberparsing::parse_integer_in_string(peek_non_root_scalar("int64"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("int64"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double() noexcept {
+ auto result = numberparsing::parse_double(peek_non_root_scalar("double"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_double_in_string() noexcept {
+ auto result = numberparsing::parse_double_in_string(peek_non_root_scalar("double"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("double"); }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_bool() noexcept {
+ auto result = parse_bool(peek_non_root_scalar("bool"));
+ if(result.error() == SUCCESS) { advance_non_root_scalar("bool"); }
+ return result;
+}
+simdjson_inline simdjson_result<bool> value_iterator::is_null() noexcept {
+ bool is_null_value;
+ SIMDJSON_TRY(parse_null(peek_non_root_scalar("null")).get(is_null_value));
+ if(is_null_value) { advance_non_root_scalar("null"); }
+ return is_null_value;
+}
+simdjson_inline bool value_iterator::is_negative() noexcept {
+ return numberparsing::is_negative(peek_non_root_scalar("numbersign"));
+}
+simdjson_inline bool value_iterator::is_root_negative() noexcept {
+ return numberparsing::is_negative(peek_root_scalar("numbersign"));
+}
+simdjson_inline simdjson_result<bool> value_iterator::is_integer() noexcept {
+ return numberparsing::is_integer(peek_non_root_scalar("integer"));
+}
+simdjson_inline simdjson_result<number_type> value_iterator::get_number_type() noexcept {
+ return numberparsing::get_number_type(peek_non_root_scalar("integer"));
+}
+simdjson_inline simdjson_result<number> value_iterator::get_number() noexcept {
+ number num;
+ error_code error = numberparsing::parse_number(peek_non_root_scalar("number"), num);
+ if(error) { return error; }
+ return num;
+}
+
+simdjson_inline simdjson_result<bool> value_iterator::is_root_integer(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("is_root_integer");
+ uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
+ tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
+ return false; // if there are more than 20 characters, it cannot be represented as an integer.
+ }
+ auto answer = numberparsing::is_integer(tmpbuf);
+ // If the parsing was a success, we must still check that it is
+ // a single scalar. Note that we parse first because of cases like '[]' where
+ // getting TRAILING_CONTENT is wrong.
+ if(check_trailing && (answer.error() == SUCCESS) && (!_json_iter->is_single_token())) { return TRAILING_CONTENT; }
+ return answer;
+}
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::number_type> value_iterator::get_root_number_type(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("number");
+ // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
+ // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
+ // number: -0.<fraction>e-308.
+ uint8_t tmpbuf[1074+8+1+1];
+ tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
+ if(numberparsing::check_if_integer(json, max_len)) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
+ return number_type::big_integer;
+ }
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
+ return NUMBER_ERROR;
+ }
+ auto answer = numberparsing::get_number_type(tmpbuf);
+ if (check_trailing && (answer.error() == SUCCESS) && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ return answer;
+}
+simdjson_inline simdjson_result<number> value_iterator::get_root_number(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("number");
+ // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
+ // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
+ // number: -0.<fraction>e-308.
+ // NOTE: the current approach doesn't work for very big integer numbers containing more than 1074 digits.
+ uint8_t tmpbuf[1074+8+1+1];
+ tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
+ if(numberparsing::check_if_integer(json, max_len)) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ logger::log_error(*_json_iter, start_position(), depth(), "Found big integer");
+ return BIGINT_ERROR;
+ }
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters and not a big integer");
+ return NUMBER_ERROR;
+ }
+ number num;
+ error_code error = numberparsing::parse_number(tmpbuf, num);
+ if(error) { return error; }
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("number");
+ return num;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_string(bool check_trailing, bool allow_replacement) noexcept {
+ return get_root_raw_json_string(check_trailing).unescape(json_iter(), allow_replacement);
+}
+template <typename string_type>
+simdjson_warn_unused simdjson_inline error_code value_iterator::get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept {
+ std::string_view content;
+ auto err = get_root_string(check_trailing, allow_replacement).get(content);
+ if (err) { return err; }
+ receiver = content;
+ return SUCCESS;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> value_iterator::get_root_wobbly_string(bool check_trailing) noexcept {
+ return get_root_raw_json_string(check_trailing).unescape_wobbly(json_iter());
+}
+simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> value_iterator::get_root_raw_json_string(bool check_trailing) noexcept {
+ auto json = peek_scalar("string");
+ if (*json != '"') { return incorrect_type_error("Not a string"); }
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_scalar("string");
+ return raw_json_string(json+1);
+}
+simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("uint64");
+ uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
+ tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
+ return NUMBER_ERROR;
+ }
+ auto result = numberparsing::parse_unsigned(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("uint64");
+ }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> value_iterator::get_root_uint64_in_string(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("uint64");
+ uint8_t tmpbuf[20+1+1]{}; // <20 digits> is the longest possible unsigned integer
+ tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
+ return NUMBER_ERROR;
+ }
+ auto result = numberparsing::parse_unsigned_in_string(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("uint64");
+ }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("int64");
+ uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
+ tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
+ return NUMBER_ERROR;
+ }
+
+ auto result = numberparsing::parse_integer(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("int64");
+ }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<int64_t> value_iterator::get_root_int64_in_string(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("int64");
+ uint8_t tmpbuf[20+1+1]; // -<19 digits> is the longest possible integer
+ tmpbuf[20+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 20+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 20 characters");
+ return NUMBER_ERROR;
+ }
+
+ auto result = numberparsing::parse_integer_in_string(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("int64");
+ }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("double");
+ // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
+ // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
+ // number: -0.<fraction>e-308.
+ uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
+ tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
+ return NUMBER_ERROR;
+ }
+ auto result = numberparsing::parse_double(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("double");
+ }
+ return result;
+}
+
+simdjson_warn_unused simdjson_inline simdjson_result<double> value_iterator::get_root_double_in_string(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("double");
+ // Per https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/,
+ // 1074 is the maximum number of significant fractional digits. Add 8 more digits for the biggest
+ // number: -0.<fraction>e-308.
+ uint8_t tmpbuf[1074+8+1+1]; // +1 for null termination.
+ tmpbuf[1074+8+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 1074+8+1)) {
+ logger::log_error(*_json_iter, start_position(), depth(), "Root number more than 1082 characters");
+ return NUMBER_ERROR;
+ }
+ auto result = numberparsing::parse_double_in_string(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("double");
+ }
+ return result;
+}
+simdjson_warn_unused simdjson_inline simdjson_result<bool> value_iterator::get_root_bool(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("bool");
+ uint8_t tmpbuf[5+1+1]; // +1 for null termination
+ tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated.
+ if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); }
+ auto result = parse_bool(tmpbuf);
+ if(result.error() == SUCCESS) {
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("bool");
+ }
+ return result;
+}
+simdjson_inline simdjson_result<bool> value_iterator::is_root_null(bool check_trailing) noexcept {
+ auto max_len = peek_root_length();
+ auto json = peek_root_scalar("null");
+ bool result = (max_len >= 4 && !atomparsing::str4ncmp(json, "null") &&
+ (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4])));
+ if(result) { // we have something that looks like a null.
+ if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; }
+ advance_root_scalar("null");
+ }
+ return result;
+}
+
+simdjson_warn_unused simdjson_inline error_code value_iterator::skip_child() noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
+ SIMDJSON_ASSUME( _json_iter->_depth >= _depth );
+
+ return _json_iter->skip_child(depth());
+}
+
+simdjson_inline value_iterator value_iterator::child() const noexcept {
+ assert_at_child();
+ return { _json_iter, depth()+1, _json_iter->token.position() };
+}
+
+// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller
+// relating depth and iterator depth, which is a desired effect. It does not happen if is_open is
+// marked non-inline.
+SIMDJSON_PUSH_DISABLE_WARNINGS
+SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING
+simdjson_inline bool value_iterator::is_open() const noexcept {
+ return _json_iter->depth() >= depth();
+}
+SIMDJSON_POP_DISABLE_WARNINGS
+
+simdjson_inline bool value_iterator::at_end() const noexcept {
+ return _json_iter->at_end();
+}
+
+simdjson_inline bool value_iterator::at_start() const noexcept {
+ return _json_iter->token.position() == start_position();
+}
+
+simdjson_inline bool value_iterator::at_first_field() const noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
+ return _json_iter->token.position() == start_position() + 1;
+}
+
+simdjson_inline void value_iterator::abandon() noexcept {
+ _json_iter->abandon();
+}
+
+simdjson_warn_unused simdjson_inline depth_t value_iterator::depth() const noexcept {
+ return _depth;
+}
+simdjson_warn_unused simdjson_inline error_code value_iterator::error() const noexcept {
+ return _json_iter->error;
+}
+simdjson_warn_unused simdjson_inline uint8_t *&value_iterator::string_buf_loc() noexcept {
+ return _json_iter->string_buf_loc();
+}
+simdjson_warn_unused simdjson_inline const json_iterator &value_iterator::json_iter() const noexcept {
+ return *_json_iter;
+}
+simdjson_warn_unused simdjson_inline json_iterator &value_iterator::json_iter() noexcept {
+ return *_json_iter;
+}
+
+simdjson_inline const uint8_t *value_iterator::peek_start() const noexcept {
+ return _json_iter->peek(start_position());
+}
+simdjson_inline uint32_t value_iterator::peek_start_length() const noexcept {
+ return _json_iter->peek_length(start_position());
+}
+simdjson_inline uint32_t value_iterator::peek_root_length() const noexcept {
+ return _json_iter->peek_root_length(start_position());
+}
+
+simdjson_inline const uint8_t *value_iterator::peek_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ // If we're not at the position anymore, we don't want to advance the cursor.
+ if (!is_at_start()) { return peek_start(); }
+
+ // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
+ assert_at_start();
+ return _json_iter->peek();
+}
+
+simdjson_inline void value_iterator::advance_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ // If we're not at the position anymore, we don't want to advance the cursor.
+ if (!is_at_start()) { return; }
+
+ // Get the JSON and advance the cursor, decreasing depth to signify that we have retrieved the value.
+ assert_at_start();
+ _json_iter->return_current_and_advance();
+ _json_iter->ascend_to(depth()-1);
+}
+
+simdjson_inline error_code value_iterator::start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept {
+ logger::log_start_value(*_json_iter, start_position(), depth(), type);
+ // If we're not at the position anymore, we don't want to advance the cursor.
+ const uint8_t *json;
+ if (!is_at_start()) {
+#if SIMDJSON_DEVELOPMENT_CHECKS
+ if (!is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; }
+#endif
+ json = peek_start();
+ if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
+ } else {
+ assert_at_start();
+ /**
+ * We should be prudent. Let us peek. If it is not the right type, we
+ * return an error. Only once we have determined that we have the right
+ * type are we allowed to advance!
+ */
+ json = _json_iter->peek();
+ if (*json != start_char) { return incorrect_type_error(incorrect_type_message); }
+ _json_iter->return_current_and_advance();
+ }
+
+
+ return SUCCESS;
+}
+
+
+simdjson_inline const uint8_t *value_iterator::peek_root_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ if (!is_at_start()) { return peek_start(); }
+
+ assert_at_root();
+ return _json_iter->peek();
+}
+simdjson_inline const uint8_t *value_iterator::peek_non_root_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ if (!is_at_start()) { return peek_start(); }
+
+ assert_at_non_root_start();
+ return _json_iter->peek();
+}
+
+simdjson_inline void value_iterator::advance_root_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ if (!is_at_start()) { return; }
+
+ assert_at_root();
+ _json_iter->return_current_and_advance();
+ _json_iter->ascend_to(depth()-1);
+}
+simdjson_inline void value_iterator::advance_non_root_scalar(const char *type) noexcept {
+ logger::log_value(*_json_iter, start_position(), depth(), type);
+ if (!is_at_start()) { return; }
+
+ assert_at_non_root_start();
+ _json_iter->return_current_and_advance();
+ _json_iter->ascend_to(depth()-1);
+}
+
+simdjson_inline error_code value_iterator::incorrect_type_error(const char *message) const noexcept {
+ logger::log_error(*_json_iter, start_position(), depth(), message);
+ return INCORRECT_TYPE;
+}
+
+simdjson_inline bool value_iterator::is_at_start() const noexcept {
+ return position() == start_position();
+}
+
+simdjson_inline bool value_iterator::is_at_key() const noexcept {
+ // Keys are at the same depth as the object.
+ // Note here that we could be safer and check that we are within an object,
+ // but we do not.
+ return _depth == _json_iter->_depth && *_json_iter->peek() == '"';
+}
+
+simdjson_inline bool value_iterator::is_at_iterator_start() const noexcept {
+ // We can legitimately be either at the first value ([1]), or after the array if it's empty ([]).
+ auto delta = position() - start_position();
+ return delta == 1 || delta == 2;
+}
+
+inline void value_iterator::assert_at_start() const noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position == _start_position );
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth );
+ SIMDJSON_ASSUME( _depth > 0 );
+}
+
+inline void value_iterator::assert_at_container_start() const noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position == _start_position + 1 );
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth );
+ SIMDJSON_ASSUME( _depth > 0 );
+}
+
+inline void value_iterator::assert_at_next() const noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth );
+ SIMDJSON_ASSUME( _depth > 0 );
+}
+
+simdjson_inline void value_iterator::move_at_start() noexcept {
+ _json_iter->_depth = _depth;
+ _json_iter->token.set_position(_start_position);
+}
+
+simdjson_inline void value_iterator::move_at_container_start() noexcept {
+ _json_iter->_depth = _depth;
+ _json_iter->token.set_position(_start_position + 1);
+}
+
+simdjson_inline simdjson_result<bool> value_iterator::reset_array() noexcept {
+ if(error()) { return error(); }
+ move_at_container_start();
+ return started_array();
+}
+
+simdjson_inline simdjson_result<bool> value_iterator::reset_object() noexcept {
+ if(error()) { return error(); }
+ move_at_container_start();
+ return started_object();
+}
+
+inline void value_iterator::assert_at_child() const noexcept {
+ SIMDJSON_ASSUME( _json_iter->token._position > _start_position );
+ SIMDJSON_ASSUME( _json_iter->_depth == _depth + 1 );
+ SIMDJSON_ASSUME( _depth > 0 );
+}
+
+inline void value_iterator::assert_at_root() const noexcept {
+ assert_at_start();
+ SIMDJSON_ASSUME( _depth == 1 );
+}
+
+inline void value_iterator::assert_at_non_root_start() const noexcept {
+ assert_at_start();
+ SIMDJSON_ASSUME( _depth > 1 );
+}
+
+inline void value_iterator::assert_is_valid() const noexcept {
+ SIMDJSON_ASSUME( _json_iter != nullptr );
+}
+
+simdjson_inline bool value_iterator::is_valid() const noexcept {
+ return _json_iter != nullptr;
+}
+
+simdjson_inline simdjson_result<json_type> value_iterator::type() const noexcept {
+ switch (*peek_start()) {
+ case '{':
+ return json_type::object;
+ case '[':
+ return json_type::array;
+ case '"':
+ return json_type::string;
+ case 'n':
+ return json_type::null;
+ case 't': case 'f':
+ return json_type::boolean;
+ case '-':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ return json_type::number;
+ default:
+ return TAPE_ERROR;
+ }
+}
+
+simdjson_inline token_position value_iterator::start_position() const noexcept {
+ return _start_position;
+}
+
+simdjson_inline token_position value_iterator::position() const noexcept {
+ return _json_iter->position();
+}
+
+simdjson_inline token_position value_iterator::end_position() const noexcept {
+ return _json_iter->end_position();
+}
+
+simdjson_inline token_position value_iterator::last_position() const noexcept {
+ return _json_iter->last_position();
+}
+
+simdjson_inline error_code value_iterator::report_error(error_code error, const char *message) noexcept {
+ return _json_iter->report_error(error, message);
+}
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(std::forward<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(value)) {}
+simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>::simdjson_result(error_code error) noexcept
+ : implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator>(error) {}
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator.h b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator.h
new file mode 100644
index 0000000000..a01a8fb09e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/generic/ondemand/value_iterator.h
@@ -0,0 +1,492 @@
+#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H
+#include "simdjson/generic/ondemand/base.h"
+#include "simdjson/generic/implementation_simdjson_result_base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace SIMDJSON_IMPLEMENTATION {
+namespace ondemand {
+
+/**
+ * Iterates through a single JSON value at a particular depth.
+ *
+ * Does not keep track of the type of value: provides methods for objects, arrays and scalars and expects
+ * the caller to call the right ones.
+ *
+ * @private This is not intended for external use.
+ */
+class value_iterator {
+protected:
+ /** The underlying JSON iterator */
+ json_iterator *_json_iter{};
+ /** The depth of this value */
+ depth_t _depth{};
+ /**
+ * The starting token index for this value
+ */
+ token_position _start_position{};
+
+public:
+ simdjson_inline value_iterator() noexcept = default;
+
+ /**
+ * Denote that we're starting a document.
+ */
+ simdjson_inline void start_document() noexcept;
+
+ /**
+ * Skips a non-iterated or partially-iterated JSON value, whether it is a scalar, array or object.
+ *
+ * Optimized for scalars.
+ */
+ simdjson_warn_unused simdjson_inline error_code skip_child() noexcept;
+
+ /**
+ * Tell whether the iterator is at the EOF mark
+ */
+ simdjson_inline bool at_end() const noexcept;
+
+ /**
+ * Tell whether the iterator is at the start of the value
+ */
+ simdjson_inline bool at_start() const noexcept;
+
+ /**
+ * Tell whether the value is open--if the value has not been used, or the array/object is still open.
+ */
+ simdjson_inline bool is_open() const noexcept;
+
+ /**
+ * Tell whether the value is at an object's first field (just after the {).
+ */
+ simdjson_inline bool at_first_field() const noexcept;
+
+ /**
+ * Abandon all iteration.
+ */
+ simdjson_inline void abandon() noexcept;
+
+ /**
+ * Get the child value as a value_iterator.
+ */
+ simdjson_inline value_iterator child_value() const noexcept;
+
+ /**
+ * Get the depth of this value.
+ */
+ simdjson_inline int32_t depth() const noexcept;
+
+ /**
+ * Get the JSON type of this value.
+ *
+ * @error TAPE_ERROR when the JSON value is a bad token like "}" "," or "alse".
+ */
+ simdjson_inline simdjson_result<json_type> type() const noexcept;
+
+ /**
+ * @addtogroup object Object iteration
+ *
+ * Methods to iterate and find object fields. These methods generally *assume* the value is
+ * actually an object; the caller is responsible for keeping track of that fact.
+ *
+ * @{
+ */
+
+ /**
+ * Start an object iteration.
+ *
+ * @returns Whether the object had any fields (returns false for empty).
+ * @error INCORRECT_TYPE if there is no opening {
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> start_object() noexcept;
+ /**
+ * Start an object iteration from the root.
+ *
+ * @returns Whether the object had any fields (returns false for empty).
+ * @error INCORRECT_TYPE if there is no opening {
+ * @error TAPE_ERROR if there is no matching } at end of document
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_object() noexcept;
+ /**
+ * Checks whether an object could be started from the root. May be called by start_root_object.
+ *
+ * @returns SUCCESS if it is possible to safely start an object from the root (document level).
+ * @error INCORRECT_TYPE if there is no opening {
+ * @error TAPE_ERROR if there is no matching } at end of document
+ */
+ simdjson_warn_unused simdjson_inline error_code check_root_object() noexcept;
+ /**
+ * Start an object iteration after the user has already checked and moved past the {.
+ *
+ * Does not move the iterator unless the object is empty ({}).
+ *
+ * @returns Whether the object had any fields (returns false for empty).
+ * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
+ * array or object is incomplete).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> started_object() noexcept;
+ /**
+ * Start an object iteration from the root, after the user has already checked and moved past the {.
+ *
+ * Does not move the iterator unless the object is empty ({}).
+ *
+ * @returns Whether the object had any fields (returns false for empty).
+ * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
+ * array or object is incomplete).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_object() noexcept;
+
+ /**
+ * Moves to the next field in an object.
+ *
+ * Looks for , and }. If } is found, the object is finished and the iterator advances past it.
+ * Otherwise, it advances to the next value.
+ *
+ * @return whether there is another field in the object.
+ * @error TAPE_ERROR If there is a comma missing between fields.
+ * @error TAPE_ERROR If there is a comma, but not enough tokens remaining to have a key, :, and value.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_field() noexcept;
+
+ /**
+ * Get the current field's key.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> field_key() noexcept;
+
+ /**
+ * Pass the : in the field and move to its value.
+ */
+ simdjson_warn_unused simdjson_inline error_code field_value() noexcept;
+
+ /**
+ * Find the next field with the given key.
+ *
+ * Assumes you have called next_field() or otherwise matched the previous value.
+ *
+ * This means the iterator must be sitting at the next key:
+ *
+ * ```
+ * { "a": 1, "b": 2 }
+ * ^
+ * ```
+ *
+ * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
+ * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
+ * fail to match some keys with escapes (\u, \n, etc.).
+ */
+ simdjson_warn_unused simdjson_inline error_code find_field(const std::string_view key) noexcept;
+
+ /**
+ * Find the next field with the given key, *without* unescaping. This assumes object order: it
+ * will not find the field if it was already passed when looking for some *other* field.
+ *
+ * Assumes you have called next_field() or otherwise matched the previous value.
+ *
+ * This means the iterator must be sitting at the next key:
+ *
+ * ```
+ * { "a": 1, "b": 2 }
+ * ^
+ * ```
+ *
+ * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
+ * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
+ * fail to match some keys with escapes (\u, \n, etc.).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_raw(const std::string_view key) noexcept;
+
+ /**
+ * Find the field with the given key without regard to order, and *without* unescaping.
+ *
+ * This is an unordered object lookup: if the field is not found initially, it will cycle around and scan from the beginning.
+ *
+ * Assumes you have called next_field() or otherwise matched the previous value.
+ *
+ * This means the iterator must be sitting at the next key:
+ *
+ * ```
+ * { "a": 1, "b": 2 }
+ * ^
+ * ```
+ *
+ * Key is *raw JSON,* meaning it will be matched against the verbatim JSON without attempting to
+ * unescape it. This works well for typical ASCII and UTF-8 keys (almost all of them), but may
+ * fail to match some keys with escapes (\u, \n, etc.).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> find_field_unordered_raw(const std::string_view key) noexcept;
+
+ /** @} */
+
+ /**
+ * @addtogroup array Array iteration
+ * Methods to iterate over array elements. These methods generally *assume* the value is actually
+ * an object; the caller is responsible for keeping track of that fact.
+ * @{
+ */
+
+ /**
+ * Check for an opening [ and start an array iteration.
+ *
+ * @returns Whether the array had any elements (returns false for empty).
+ * @error INCORRECT_TYPE If there is no [.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> start_array() noexcept;
+ /**
+ * Check for an opening [ and start an array iteration while at the root.
+ *
+ * @returns Whether the array had any elements (returns false for empty).
+ * @error INCORRECT_TYPE If there is no [.
+ * @error TAPE_ERROR if there is no matching ] at end of document
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> start_root_array() noexcept;
+ /**
+ * Checks whether an array could be started from the root. May be called by start_root_array.
+ *
+ * @returns SUCCESS if it is possible to safely start an array from the root (document level).
+ * @error INCORRECT_TYPE If there is no [.
+ * @error TAPE_ERROR if there is no matching ] at end of document
+ */
+ simdjson_warn_unused simdjson_inline error_code check_root_array() noexcept;
+ /**
+ * Start an array iteration, after the user has already checked and moved past the [.
+ *
+ * Does not move the iterator unless the array is empty ([]).
+ *
+ * @returns Whether the array had any elements (returns false for empty).
+ * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
+ * array or object is incomplete).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> started_array() noexcept;
+ /**
+ * Start an array iteration from the root, after the user has already checked and moved past the [.
+ *
+ * Does not move the iterator unless the array is empty ([]).
+ *
+ * @returns Whether the array had any elements (returns false for empty).
+ * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent*
+ * array or object is incomplete).
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> started_root_array() noexcept;
+
+ /**
+ * Moves to the next element in an array.
+ *
+ * Looks for , and ]. If ] is found, the array is finished and the iterator advances past it.
+ * Otherwise, it advances to the next value.
+ *
+ * @return Whether there is another element in the array.
+ * @error TAPE_ERROR If there is a comma missing between elements.
+ */
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> has_next_element() noexcept;
+
+ /**
+ * Get a child value iterator.
+ */
+ simdjson_warn_unused simdjson_inline value_iterator child() const noexcept;
+
+ /** @} */
+
+ /**
+ * @defgroup scalar Scalar values
+ * @addtogroup scalar
+ * @{
+ */
+
+ simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_string(bool allow_replacement) noexcept;
+ template <typename string_type>
+ simdjson_warn_unused simdjson_inline error_code get_string(string_type& receiver, bool allow_replacement) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_wobbly_string() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_raw_json_string() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_uint64_in_string() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_int64_in_string() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<double> get_double() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<double> get_double_in_string() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> get_bool() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> is_null() noexcept;
+ simdjson_warn_unused simdjson_inline bool is_negative() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> is_integer() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_number_type() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<number> get_number() noexcept;
+
+ simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_string(bool check_trailing, bool allow_replacement) noexcept;
+ template <typename string_type>
+ simdjson_warn_unused simdjson_inline error_code get_root_string(string_type& receiver, bool check_trailing, bool allow_replacement) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<std::string_view> get_root_wobbly_string(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<raw_json_string> get_root_raw_json_string(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<uint64_t> get_root_uint64_in_string(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<int64_t> get_root_int64_in_string(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<double> get_root_double_in_string(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> get_root_bool(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline bool is_root_negative() noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_integer(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<number_type> get_root_number_type(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<number> get_root_number(bool check_trailing) noexcept;
+ simdjson_warn_unused simdjson_inline simdjson_result<bool> is_root_null(bool check_trailing) noexcept;
+
+ simdjson_inline error_code error() const noexcept;
+ simdjson_inline uint8_t *&string_buf_loc() noexcept;
+ simdjson_inline const json_iterator &json_iter() const noexcept;
+ simdjson_inline json_iterator &json_iter() noexcept;
+
+ simdjson_inline void assert_is_valid() const noexcept;
+ simdjson_inline bool is_valid() const noexcept;
+
+ /** @} */
+protected:
+ /**
+ * Restarts an array iteration.
+ * @returns Whether the array has any elements (returns false for empty).
+ */
+ simdjson_inline simdjson_result<bool> reset_array() noexcept;
+ /**
+ * Restarts an object iteration.
+ * @returns Whether the object has any fields (returns false for empty).
+ */
+ simdjson_inline simdjson_result<bool> reset_object() noexcept;
+ /**
+ * move_at_start(): moves us so that we are pointing at the beginning of
+ * the container. It updates the index so that at_start() is true and it
+ * syncs the depth. The user can then create a new container instance.
+ *
+ * Usage: used with value::count_elements().
+ **/
+ simdjson_inline void move_at_start() noexcept;
+
+ /**
+ * move_at_container_start(): moves us so that we are pointing at the beginning of
+ * the container so that assert_at_container_start() passes.
+ *
+ * Usage: used with reset_array() and reset_object().
+ **/
+ simdjson_inline void move_at_container_start() noexcept;
+ /* Useful for debugging and logging purposes. */
+ inline std::string to_string() const noexcept;
+ simdjson_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
+
+ simdjson_inline simdjson_result<bool> parse_null(const uint8_t *json) const noexcept;
+ simdjson_inline simdjson_result<bool> parse_bool(const uint8_t *json) const noexcept;
+ simdjson_inline const uint8_t *peek_start() const noexcept;
+ simdjson_inline uint32_t peek_start_length() const noexcept;
+ simdjson_inline uint32_t peek_root_length() const noexcept;
+
+ /**
+ * The general idea of the advance_... methods and the peek_* methods
+ * is that you first peek and check that you have desired type. If you do,
+ * and only if you do, then you advance.
+ *
+ * We used to unconditionally advance. But this made reasoning about our
+ * current state difficult.
+ * Suppose you always advance. Look at the 'value' matching the key
+ * "shadowable" in the following example...
+ *
+ * ({"globals":{"a":{"shadowable":[}}}})
+ *
+ * If the user thinks it is a Boolean and asks for it, then we check the '[',
+ * decide it is not a Boolean, but still move into the next character ('}'). Now
+ * we are left pointing at '}' right after a '['. And we have not yet reported
+ * an error, only that we do not have a Boolean.
+ *
+ * If, instead, you just stand your ground until it is content that you know, then
+ * you will only even move beyond the '[' if the user tells you that you have an
+ * array. So you will be at the '}' character inside the array and, hopefully, you
+ * will then catch the error because an array cannot start with '}', but the code
+ * processing Boolean values does not know this.
+ *
+ * So the contract is: first call 'peek_...' and then call 'advance_...' only
+ * if you have determined that it is a type you can handle.
+ *
+ * Unfortunately, it makes the code more verbose, longer and maybe more error prone.
+ */
+
+ simdjson_inline void advance_scalar(const char *type) noexcept;
+ simdjson_inline void advance_root_scalar(const char *type) noexcept;
+ simdjson_inline void advance_non_root_scalar(const char *type) noexcept;
+
+ simdjson_inline const uint8_t *peek_scalar(const char *type) noexcept;
+ simdjson_inline const uint8_t *peek_root_scalar(const char *type) noexcept;
+ simdjson_inline const uint8_t *peek_non_root_scalar(const char *type) noexcept;
+
+
+ simdjson_inline error_code start_container(uint8_t start_char, const char *incorrect_type_message, const char *type) noexcept;
+ simdjson_inline error_code end_container() noexcept;
+
+ /**
+ * Advance to a place expecting a value (increasing depth).
+ *
+ * @return The current token (the one left behind).
+ * @error TAPE_ERROR If the document ended early.
+ */
+ simdjson_inline simdjson_result<const uint8_t *> advance_to_value() noexcept;
+
+ simdjson_inline error_code incorrect_type_error(const char *message) const noexcept;
+ simdjson_inline error_code error_unless_more_tokens(uint32_t tokens=1) const noexcept;
+
+ simdjson_inline bool is_at_start() const noexcept;
+ /**
+ * is_at_iterator_start() returns true on an array or object after it has just been
+ * created, whether the instance is empty or not.
+ *
+ * Usage: used by array::begin() in debug mode (SIMDJSON_DEVELOPMENT_CHECKS)
+ */
+ simdjson_inline bool is_at_iterator_start() const noexcept;
+
+ /**
+ * Assuming that we are within an object, this returns true if we
+ * are pointing at a key.
+ *
+ * Usage: the skip_child() method should never be used while we are pointing
+ * at a key inside an object.
+ */
+ simdjson_inline bool is_at_key() const noexcept;
+
+ inline void assert_at_start() const noexcept;
+ inline void assert_at_container_start() const noexcept;
+ inline void assert_at_root() const noexcept;
+ inline void assert_at_child() const noexcept;
+ inline void assert_at_next() const noexcept;
+ inline void assert_at_non_root_start() const noexcept;
+
+ /** Get the starting position of this value */
+ simdjson_inline token_position start_position() const noexcept;
+
+ /** @copydoc error_code json_iterator::position() const noexcept; */
+ simdjson_inline token_position position() const noexcept;
+ /** @copydoc error_code json_iterator::end_position() const noexcept; */
+ simdjson_inline token_position last_position() const noexcept;
+ /** @copydoc error_code json_iterator::end_position() const noexcept; */
+ simdjson_inline token_position end_position() const noexcept;
+ /** @copydoc error_code json_iterator::report_error(error_code error, const char *message) noexcept; */
+ simdjson_inline error_code report_error(error_code error, const char *message) noexcept;
+
+ friend class document;
+ friend class object;
+ friend class array;
+ friend class value;
+ friend class field;
+}; // value_iterator
+
+} // namespace ondemand
+} // namespace SIMDJSON_IMPLEMENTATION
+} // namespace simdjson
+
+namespace simdjson {
+
+template<>
+struct simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator> : public SIMDJSON_IMPLEMENTATION::implementation_simdjson_result_base<SIMDJSON_IMPLEMENTATION::ondemand::value_iterator> {
+public:
+ simdjson_inline simdjson_result(SIMDJSON_IMPLEMENTATION::ondemand::value_iterator &&value) noexcept; ///< @private
+ simdjson_inline simdjson_result(error_code error) noexcept; ///< @private
+ simdjson_inline simdjson_result() noexcept = default;
+};
+
+} // namespace simdjson
+
+#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/haswell/ondemand.h b/contrib/libs/simdjson/include/simdjson/haswell/ondemand.h
new file mode 100644
index 0000000000..b3aa993eff
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/haswell/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_HASWELL_ONDEMAND_H
+#define SIMDJSON_HASWELL_ONDEMAND_H
+
+#include "simdjson/haswell/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/haswell/end.h"
+
+#endif // SIMDJSON_HASWELL_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/icelake/ondemand.h b/contrib/libs/simdjson/include/simdjson/icelake/ondemand.h
new file mode 100644
index 0000000000..e2f13b4787
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/icelake/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_ICELAKE_ONDEMAND_H
+#define SIMDJSON_ICELAKE_ONDEMAND_H
+
+#include "simdjson/icelake/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/icelake/end.h"
+
+#endif // SIMDJSON_ICELAKE_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/internal/jsonformatutils.h b/contrib/libs/simdjson/include/simdjson/internal/jsonformatutils.h
new file mode 100644
index 0000000000..43000ab431
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/internal/jsonformatutils.h
@@ -0,0 +1,64 @@
+#ifndef SIMDJSON_INTERNAL_JSONFORMATUTILS_H
+#define SIMDJSON_INTERNAL_JSONFORMATUTILS_H
+
+#include "simdjson/base.h"
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+namespace simdjson {
+namespace internal {
+
+inline std::ostream& operator<<(std::ostream& out, const escape_json_string &str);
+
+class escape_json_string {
+public:
+ escape_json_string(std::string_view _str) noexcept : str{_str} {}
+ operator std::string() const noexcept { std::stringstream s; s << *this; return s.str(); }
+private:
+ std::string_view str;
+ friend std::ostream& operator<<(std::ostream& out, const escape_json_string &unescaped);
+};
+
+inline std::ostream& operator<<(std::ostream& out, const escape_json_string &unescaped) {
+ for (size_t i=0; i<unescaped.str.length(); i++) {
+ switch (unescaped.str[i]) {
+ case '\b':
+ out << "\\b";
+ break;
+ case '\f':
+ out << "\\f";
+ break;
+ case '\n':
+ out << "\\n";
+ break;
+ case '\r':
+ out << "\\r";
+ break;
+ case '\"':
+ out << "\\\"";
+ break;
+ case '\t':
+ out << "\\t";
+ break;
+ case '\\':
+ out << "\\\\";
+ break;
+ default:
+ if (static_cast<unsigned char>(unescaped.str[i]) <= 0x1F) {
+ // TODO can this be done once at the beginning, or will it mess up << char?
+ std::ios::fmtflags f(out.flags());
+ out << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(unescaped.str[i]);
+ out.flags(f);
+ } else {
+ out << unescaped.str[i];
+ }
+ }
+ }
+ return out;
+}
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_INTERNAL_JSONFORMATUTILS_H
diff --git a/contrib/libs/simdjson/include/simdjson/internal/tape_ref-inl.h b/contrib/libs/simdjson/include/simdjson/internal/tape_ref-inl.h
new file mode 100644
index 0000000000..a100d569e2
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/internal/tape_ref-inl.h
@@ -0,0 +1,118 @@
+#ifndef SIMDJSON_TAPE_REF_INL_H
+#define SIMDJSON_TAPE_REF_INL_H
+
+#include "simdjson/dom/document.h"
+#include "simdjson/internal/tape_ref.h"
+#include "simdjson/internal/tape_type.h"
+
+#include <cstring>
+
+namespace simdjson {
+namespace internal {
+
+constexpr const uint64_t JSON_VALUE_MASK = 0x00FFFFFFFFFFFFFF;
+constexpr const uint32_t JSON_COUNT_MASK = 0xFFFFFF;
+
+//
+// tape_ref inline implementation
+//
+simdjson_inline tape_ref::tape_ref() noexcept : doc{nullptr}, json_index{0} {}
+simdjson_inline tape_ref::tape_ref(const dom::document *_doc, size_t _json_index) noexcept : doc{_doc}, json_index{_json_index} {}
+
+
+simdjson_inline bool tape_ref::is_document_root() const noexcept {
+ return json_index == 1; // should we ever change the structure of the tape, this should get updated.
+}
+simdjson_inline bool tape_ref::usable() const noexcept {
+ return doc != nullptr; // when the document pointer is null, this tape_ref is uninitialized (should not be accessed).
+}
+// Some value types have a specific on-tape word value. It can be faster
+// to check the type by doing a word-to-word comparison instead of extracting the
+// most significant 8 bits.
+
+simdjson_inline bool tape_ref::is_double() const noexcept {
+ constexpr uint64_t tape_double = uint64_t(tape_type::DOUBLE)<<56;
+ return doc->tape[json_index] == tape_double;
+}
+simdjson_inline bool tape_ref::is_int64() const noexcept {
+ constexpr uint64_t tape_int64 = uint64_t(tape_type::INT64)<<56;
+ return doc->tape[json_index] == tape_int64;
+}
+simdjson_inline bool tape_ref::is_uint64() const noexcept {
+ constexpr uint64_t tape_uint64 = uint64_t(tape_type::UINT64)<<56;
+ return doc->tape[json_index] == tape_uint64;
+}
+simdjson_inline bool tape_ref::is_false() const noexcept {
+ constexpr uint64_t tape_false = uint64_t(tape_type::FALSE_VALUE)<<56;
+ return doc->tape[json_index] == tape_false;
+}
+simdjson_inline bool tape_ref::is_true() const noexcept {
+ constexpr uint64_t tape_true = uint64_t(tape_type::TRUE_VALUE)<<56;
+ return doc->tape[json_index] == tape_true;
+}
+simdjson_inline bool tape_ref::is_null_on_tape() const noexcept {
+ constexpr uint64_t tape_null = uint64_t(tape_type::NULL_VALUE)<<56;
+ return doc->tape[json_index] == tape_null;
+}
+
+inline size_t tape_ref::after_element() const noexcept {
+ switch (tape_ref_type()) {
+ case tape_type::START_ARRAY:
+ case tape_type::START_OBJECT:
+ return matching_brace_index();
+ case tape_type::UINT64:
+ case tape_type::INT64:
+ case tape_type::DOUBLE:
+ return json_index + 2;
+ default:
+ return json_index + 1;
+ }
+}
+simdjson_inline tape_type tape_ref::tape_ref_type() const noexcept {
+ return static_cast<tape_type>(doc->tape[json_index] >> 56);
+}
+simdjson_inline uint64_t internal::tape_ref::tape_value() const noexcept {
+ return doc->tape[json_index] & internal::JSON_VALUE_MASK;
+}
+simdjson_inline uint32_t internal::tape_ref::matching_brace_index() const noexcept {
+ return uint32_t(doc->tape[json_index]);
+}
+simdjson_inline uint32_t internal::tape_ref::scope_count() const noexcept {
+ return uint32_t((doc->tape[json_index] >> 32) & internal::JSON_COUNT_MASK);
+}
+
+template<typename T>
+simdjson_inline T tape_ref::next_tape_value() const noexcept {
+ static_assert(sizeof(T) == sizeof(uint64_t), "next_tape_value() template parameter must be 64-bit");
+ // Though the following is tempting...
+ // return *reinterpret_cast<const T*>(&doc->tape[json_index + 1]);
+ // It is not generally safe. It is safer, and often faster to rely
+ // on memcpy. Yes, it is uglier, but it is also encapsulated.
+ T x;
+ std::memcpy(&x,&doc->tape[json_index + 1],sizeof(uint64_t));
+ return x;
+}
+
+simdjson_inline uint32_t internal::tape_ref::get_string_length() const noexcept {
+ size_t string_buf_index = size_t(tape_value());
+ uint32_t len;
+ std::memcpy(&len, &doc->string_buf[string_buf_index], sizeof(len));
+ return len;
+}
+
+simdjson_inline const char * internal::tape_ref::get_c_str() const noexcept {
+ size_t string_buf_index = size_t(tape_value());
+ return reinterpret_cast<const char *>(&doc->string_buf[string_buf_index + sizeof(uint32_t)]);
+}
+
+inline std::string_view internal::tape_ref::get_string_view() const noexcept {
+ return std::string_view(
+ get_c_str(),
+ get_string_length()
+ );
+}
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_TAPE_REF_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/internal/tape_ref.h b/contrib/libs/simdjson/include/simdjson/internal/tape_ref.h
new file mode 100644
index 0000000000..922a057010
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/internal/tape_ref.h
@@ -0,0 +1,49 @@
+#ifndef SIMDJSON_INTERNAL_TAPE_REF_H
+#define SIMDJSON_INTERNAL_TAPE_REF_H
+
+#include "simdjson/base.h"
+
+namespace simdjson {
+namespace dom {
+class document;
+} // namespace dom
+
+namespace internal {
+
+/**
+ * A reference to an element on the tape. Internal only.
+ */
+class tape_ref {
+public:
+ simdjson_inline tape_ref() noexcept;
+ simdjson_inline tape_ref(const dom::document *doc, size_t json_index) noexcept;
+ inline size_t after_element() const noexcept;
+ simdjson_inline tape_type tape_ref_type() const noexcept;
+ simdjson_inline uint64_t tape_value() const noexcept;
+ simdjson_inline bool is_double() const noexcept;
+ simdjson_inline bool is_int64() const noexcept;
+ simdjson_inline bool is_uint64() const noexcept;
+ simdjson_inline bool is_false() const noexcept;
+ simdjson_inline bool is_true() const noexcept;
+ simdjson_inline bool is_null_on_tape() const noexcept;// different name to avoid clash with is_null.
+ simdjson_inline uint32_t matching_brace_index() const noexcept;
+ simdjson_inline uint32_t scope_count() const noexcept;
+ template<typename T>
+ simdjson_inline T next_tape_value() const noexcept;
+ simdjson_inline uint32_t get_string_length() const noexcept;
+ simdjson_inline const char * get_c_str() const noexcept;
+ inline std::string_view get_string_view() const noexcept;
+ simdjson_inline bool is_document_root() const noexcept;
+ simdjson_inline bool usable() const noexcept;
+
+ /** The document this element references. */
+ const dom::document *doc;
+
+ /** The index of this element on `doc.tape[]` */
+ size_t json_index;
+};
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_INTERNAL_TAPE_REF_H
diff --git a/contrib/libs/simdjson/include/simdjson/jsonioutil.h b/contrib/libs/simdjson/include/simdjson/jsonioutil.h
new file mode 100644
index 0000000000..cff25ab693
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/jsonioutil.h
@@ -0,0 +1,22 @@
+#ifndef SIMDJSON_JSONIOUTIL_H
+#define SIMDJSON_JSONIOUTIL_H
+
+#include "simdjson/base.h"
+#include "simdjson/padded_string.h"
+
+#include "simdjson/padded_string-inl.h"
+
+namespace simdjson {
+
+#if SIMDJSON_EXCEPTIONS
+#ifndef SIMDJSON_DISABLE_DEPRECATED_API
+[[deprecated("Use padded_string::load() instead")]]
+inline padded_string get_corpus(const char *path) {
+ return padded_string::load(path);
+}
+#endif // SIMDJSON_DISABLE_DEPRECATED_API
+#endif // SIMDJSON_EXCEPTIONS
+
+} // namespace simdjson
+
+#endif // SIMDJSON_JSONIOUTIL_H
diff --git a/contrib/libs/simdjson/include/simdjson/lasx.h b/contrib/libs/simdjson/include/simdjson/lasx.h
new file mode 100644
index 0000000000..37a20c8986
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lasx.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_LASX_H
+#define SIMDJSON_LASX_H
+
+#include "simdjson/lasx/begin.h"
+#include "simdjson/generic/amalgamated.h"
+#include "simdjson/lasx/end.h"
+
+#endif // SIMDJSON_LASX_H
diff --git a/contrib/libs/simdjson/include/simdjson/lasx/end.h b/contrib/libs/simdjson/include/simdjson/lasx/end.h
new file mode 100644
index 0000000000..2f5ec80790
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lasx/end.h
@@ -0,0 +1,6 @@
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#include "simdjson/lasx/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
+#undef SIMDJSON_IMPLEMENTATION
diff --git a/contrib/libs/simdjson/include/simdjson/lasx/ondemand.h b/contrib/libs/simdjson/include/simdjson/lasx/ondemand.h
new file mode 100644
index 0000000000..9f7ab96fa6
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lasx/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_LASX_ONDEMAND_H
+#define SIMDJSON_LASX_ONDEMAND_H
+
+#include "simdjson/lasx/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/lasx/end.h"
+
+#endif // SIMDJSON_LASX_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/lsx.h b/contrib/libs/simdjson/include/simdjson/lsx.h
new file mode 100644
index 0000000000..1496e9ceb6
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lsx.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_LSX_H
+#define SIMDJSON_LSX_H
+
+#include "simdjson/lsx/begin.h"
+#include "simdjson/generic/amalgamated.h"
+#include "simdjson/lsx/end.h"
+
+#endif // SIMDJSON_LSX_H
diff --git a/contrib/libs/simdjson/include/simdjson/lsx/end.h b/contrib/libs/simdjson/include/simdjson/lsx/end.h
new file mode 100644
index 0000000000..0ae4d37228
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lsx/end.h
@@ -0,0 +1,6 @@
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#include "simdjson/lsx/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
+#undef SIMDJSON_IMPLEMENTATION
diff --git a/contrib/libs/simdjson/include/simdjson/lsx/ondemand.h b/contrib/libs/simdjson/include/simdjson/lsx/ondemand.h
new file mode 100644
index 0000000000..b1b612e171
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/lsx/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_LSX_ONDEMAND_H
+#define SIMDJSON_LSX_ONDEMAND_H
+
+#include "simdjson/lsx/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/lsx/end.h"
+
+#endif // SIMDJSON_LSX_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/minify.h b/contrib/libs/simdjson/include/simdjson/minify.h
new file mode 100644
index 0000000000..8b8f217e4f
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/minify.h
@@ -0,0 +1,30 @@
+#ifndef SIMDJSON_MINIFY_H
+#define SIMDJSON_MINIFY_H
+
+#include "simdjson/base.h"
+#include "simdjson/padded_string.h"
+#include <string>
+#include <ostream>
+#include <sstream>
+
+namespace simdjson {
+
+/**
+ *
+ * Minify the input string assuming that it represents a JSON string, does not parse or validate.
+ * This function is much faster than parsing a JSON string and then writing a minified version of it.
+ * However, it does not validate the input. It will merely return an error in simple cases (e.g., if
+ * there is a string that was never terminated).
+ *
+ *
+ * @param buf the json document to minify.
+ * @param len the length of the json document.
+ * @param dst the buffer to write the minified document to. *MUST* be allocated up to len bytes.
+ * @param dst_len the number of bytes written. Output only.
+ * @return the error code, or SUCCESS if there was no error.
+ */
+simdjson_warn_unused error_code minify(const char *buf, size_t len, char *dst, size_t &dst_len) noexcept;
+
+} // namespace simdjson
+
+#endif // SIMDJSON_MINIFY_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/ondemand.h b/contrib/libs/simdjson/include/simdjson/ondemand.h
new file mode 100644
index 0000000000..d17615910d
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ondemand.h
@@ -0,0 +1,13 @@
+#ifndef SIMDJSON_ONDEMAND_H
+#define SIMDJSON_ONDEMAND_H
+
+#include "simdjson/builtin/ondemand.h"
+
+namespace simdjson {
+ /**
+ * @copydoc simdjson::builtin::ondemand
+ */
+ namespace ondemand = builtin::ondemand;
+} // namespace simdjson
+
+#endif // SIMDJSON_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/padded_string-inl.h b/contrib/libs/simdjson/include/simdjson/padded_string-inl.h
new file mode 100644
index 0000000000..abb566fa32
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/padded_string-inl.h
@@ -0,0 +1,190 @@
+#ifndef SIMDJSON_PADDED_STRING_INL_H
+#define SIMDJSON_PADDED_STRING_INL_H
+
+#include "simdjson/padded_string.h"
+#include "simdjson/padded_string_view.h"
+
+#include "simdjson/error-inl.h"
+#include "simdjson/padded_string_view-inl.h"
+
+#include <climits>
+
+namespace simdjson {
+namespace internal {
+
+// The allocate_padded_buffer function is a low-level function to allocate memory
+// with padding so we can read past the "length" bytes safely. It is used by
+// the padded_string class automatically. It returns nullptr in case
+// of error: the caller should check for a null pointer.
+// The length parameter is the maximum size in bytes of the string.
+// The caller is responsible to free the memory (e.g., delete[] (...)).
+inline char *allocate_padded_buffer(size_t length) noexcept {
+ const size_t totalpaddedlength = length + SIMDJSON_PADDING;
+ if(totalpaddedlength<length) {
+ // overflow
+ return nullptr;
+ }
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ // avoid getting out of memory
+ if (totalpaddedlength>(1UL<<20)) {
+ return nullptr;
+ }
+#endif
+
+ char *padded_buffer = new (std::nothrow) char[totalpaddedlength];
+ if (padded_buffer == nullptr) {
+ return nullptr;
+ }
+ // We write nulls in the padded region to avoid having uninitialized
+ // content which may trigger warning for some sanitizers
+ std::memset(padded_buffer + length, 0, totalpaddedlength - length);
+ return padded_buffer;
+} // allocate_padded_buffer()
+
+} // namespace internal
+
+
+inline padded_string::padded_string() noexcept = default;
+inline padded_string::padded_string(size_t length) noexcept
+ : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
+}
+inline padded_string::padded_string(const char *data, size_t length) noexcept
+ : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
+ if ((data != nullptr) && (data_ptr != nullptr)) {
+ std::memcpy(data_ptr, data, length);
+ }
+}
+#ifdef __cpp_char8_t
+inline padded_string::padded_string(const char8_t *data, size_t length) noexcept
+ : viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
+ if ((data != nullptr) && (data_ptr != nullptr)) {
+ std::memcpy(data_ptr, reinterpret_cast<const char *>(data), length);
+ }
+}
+#endif
+// note: do not pass std::string arguments by value
+inline padded_string::padded_string(const std::string & str_ ) noexcept
+ : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) {
+ if (data_ptr != nullptr) {
+ std::memcpy(data_ptr, str_.data(), str_.size());
+ }
+}
+// note: do pass std::string_view arguments by value
+inline padded_string::padded_string(std::string_view sv_) noexcept
+ : viable_size(sv_.size()), data_ptr(internal::allocate_padded_buffer(sv_.size())) {
+ if(simdjson_unlikely(!data_ptr)) {
+ //allocation failed or zero size
+ viable_size = 0;
+ return;
+ }
+ if (sv_.size()) {
+ std::memcpy(data_ptr, sv_.data(), sv_.size());
+ }
+}
+inline padded_string::padded_string(padded_string &&o) noexcept
+ : viable_size(o.viable_size), data_ptr(o.data_ptr) {
+ o.data_ptr = nullptr; // we take ownership
+ o.viable_size = 0;
+}
+
+inline padded_string &padded_string::operator=(padded_string &&o) noexcept {
+ delete[] data_ptr;
+ data_ptr = o.data_ptr;
+ viable_size = o.viable_size;
+ o.data_ptr = nullptr; // we take ownership
+ o.viable_size = 0;
+ return *this;
+}
+
+inline void padded_string::swap(padded_string &o) noexcept {
+ size_t tmp_viable_size = viable_size;
+ char *tmp_data_ptr = data_ptr;
+ viable_size = o.viable_size;
+ data_ptr = o.data_ptr;
+ o.data_ptr = tmp_data_ptr;
+ o.viable_size = tmp_viable_size;
+}
+
+inline padded_string::~padded_string() noexcept {
+ delete[] data_ptr;
+}
+
+inline size_t padded_string::size() const noexcept { return viable_size; }
+
+inline size_t padded_string::length() const noexcept { return viable_size; }
+
+inline const char *padded_string::data() const noexcept { return data_ptr; }
+
+inline char *padded_string::data() noexcept { return data_ptr; }
+
+inline padded_string::operator std::string_view() const { return std::string_view(data(), length()); }
+
+inline padded_string::operator padded_string_view() const noexcept {
+ return padded_string_view(data(), length(), length() + SIMDJSON_PADDING);
+}
+
+inline simdjson_result<padded_string> padded_string::load(std::string_view filename) noexcept {
+ // Open the file
+ SIMDJSON_PUSH_DISABLE_WARNINGS
+ SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe
+ std::FILE *fp = std::fopen(filename.data(), "rb");
+ SIMDJSON_POP_DISABLE_WARNINGS
+
+ if (fp == nullptr) {
+ return IO_ERROR;
+ }
+
+ // Get the file size
+ int ret;
+#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
+ ret = _fseeki64(fp, 0, SEEK_END);
+#else
+ ret = std::fseek(fp, 0, SEEK_END);
+#endif // _WIN64
+ if(ret < 0) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#if SIMDJSON_VISUAL_STUDIO && !SIMDJSON_IS_32BITS
+ __int64 llen = _ftelli64(fp);
+ if(llen == -1L) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#else
+ long llen = std::ftell(fp);
+ if((llen < 0) || (llen == LONG_MAX)) {
+ std::fclose(fp);
+ return IO_ERROR;
+ }
+#endif
+
+ // Allocate the padded_string
+ size_t len = static_cast<size_t>(llen);
+ padded_string s(len);
+ if (s.data() == nullptr) {
+ std::fclose(fp);
+ return MEMALLOC;
+ }
+
+ // Read the padded_string
+ std::rewind(fp);
+ size_t bytes_read = std::fread(s.data(), 1, len, fp);
+ if (std::fclose(fp) != 0 || bytes_read != len) {
+ return IO_ERROR;
+ }
+
+ return s;
+}
+
+} // namespace simdjson
+
+inline simdjson::padded_string operator "" _padded(const char *str, size_t len) {
+ return simdjson::padded_string(str, len);
+}
+#ifdef __cpp_char8_t
+inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len) {
+ return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len);
+}
+#endif
+#endif // SIMDJSON_PADDED_STRING_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/padded_string.h b/contrib/libs/simdjson/include/simdjson/padded_string.h
new file mode 100644
index 0000000000..536669b465
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/padded_string.h
@@ -0,0 +1,183 @@
+#ifndef SIMDJSON_PADDED_STRING_H
+#define SIMDJSON_PADDED_STRING_H
+
+#include "simdjson/base.h"
+#include "simdjson/error.h"
+
+#include "simdjson/error-inl.h"
+
+#include <cstring>
+#include <memory>
+#include <string>
+#include <ostream>
+
+namespace simdjson {
+
+class padded_string_view;
+
+/**
+ * String with extra allocation for ease of use with parser::parse()
+ *
+ * This is a move-only class, it cannot be copied.
+ */
+struct padded_string final {
+
+ /**
+ * Create a new, empty padded string.
+ */
+ explicit inline padded_string() noexcept;
+ /**
+ * Create a new padded string buffer.
+ *
+ * @param length the size of the string.
+ */
+ explicit inline padded_string(size_t length) noexcept;
+ /**
+ * Create a new padded string by copying the given input.
+ *
+ * @param data the buffer to copy
+ * @param length the number of bytes to copy
+ */
+ explicit inline padded_string(const char *data, size_t length) noexcept;
+#ifdef __cpp_char8_t
+ explicit inline padded_string(const char8_t *data, size_t length) noexcept;
+#endif
+ /**
+ * Create a new padded string by copying the given input.
+ *
+ * @param str_ the string to copy
+ */
+ inline padded_string(const std::string & str_ ) noexcept;
+ /**
+ * Create a new padded string by copying the given input.
+ *
+ * @param sv_ the string to copy
+ */
+ inline padded_string(std::string_view sv_) noexcept;
+ /**
+ * Move one padded string into another.
+ *
+ * The original padded string will be reduced to zero capacity.
+ *
+ * @param o the string to move.
+ */
+ inline padded_string(padded_string &&o) noexcept;
+ /**
+ * Move one padded string into another.
+ *
+ * The original padded string will be reduced to zero capacity.
+ *
+ * @param o the string to move.
+ */
+ inline padded_string &operator=(padded_string &&o) noexcept;
+ inline void swap(padded_string &o) noexcept;
+ ~padded_string() noexcept;
+
+ /**
+ * The length of the string.
+ *
+ * Does not include padding.
+ */
+ size_t size() const noexcept;
+
+ /**
+ * The length of the string.
+ *
+ * Does not include padding.
+ */
+ size_t length() const noexcept;
+
+ /**
+ * The string data.
+ **/
+ const char *data() const noexcept;
+ const uint8_t *u8data() const noexcept { return static_cast<const uint8_t*>(static_cast<const void*>(data_ptr));}
+
+ /**
+ * The string data.
+ **/
+ char *data() noexcept;
+
+ /**
+ * Create a std::string_view with the same content.
+ */
+ operator std::string_view() const;
+
+ /**
+ * Create a padded_string_view with the same content.
+ */
+ operator padded_string_view() const noexcept;
+
+ /**
+ * Load this padded string from a file.
+ *
+ * ## Windows and Unicode
+ *
+ * Windows users who need to read files with non-ANSI characters in the
+ * name should set their code page to UTF-8 (65001) before calling this
+ * function. This should be the default with Windows 11 and better.
+ * Further, they may use the AreFileApisANSI function to determine whether
+ * the filename is interpreted using the ANSI or the system default OEM
+ * codepage, and they may call SetFileApisToOEM accordingly.
+ *
+ * @return IO_ERROR on error. Be mindful that on some 32-bit systems,
+ * the file size might be limited to 2 GB.
+ *
+ * @param path the path to the file.
+ **/
+ inline static simdjson_result<padded_string> load(std::string_view path) noexcept;
+
+private:
+ padded_string &operator=(const padded_string &o) = delete;
+ padded_string(const padded_string &o) = delete;
+
+ size_t viable_size{0};
+ char *data_ptr{nullptr};
+
+}; // padded_string
+
+/**
+ * Send padded_string instance to an output stream.
+ *
+ * @param out The output stream.
+ * @param s The padded_string instance.
+ * @throw if there is an error with the underlying output stream. simdjson itself will not throw.
+ */
+inline std::ostream& operator<<(std::ostream& out, const padded_string& s) { return out << s.data(); }
+
+#if SIMDJSON_EXCEPTIONS
+/**
+ * Send padded_string instance to an output stream.
+ *
+ * @param out The output stream.
+ * @param s The padded_string instance.
+ * @throw simdjson_error if the result being printed has an error. If there is an error with the
+ * underlying output stream, that error will be propagated (simdjson_error will not be
+ * thrown).
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string> &s) noexcept(false) { return out << s.value(); }
+#endif
+
+} // namespace simdjson
+
+// This is deliberately outside of simdjson so that people get it without having to use the namespace
+inline simdjson::padded_string operator "" _padded(const char *str, size_t len);
+#ifdef __cpp_char8_t
+inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len);
+#endif
+
+namespace simdjson {
+namespace internal {
+
+// The allocate_padded_buffer function is a low-level function to allocate memory
+// with padding so we can read past the "length" bytes safely. It is used by
+// the padded_string class automatically. It returns nullptr in case
+// of error: the caller should check for a null pointer.
+// The length parameter is the maximum size in bytes of the string.
+// The caller is responsible to free the memory (e.g., delete[] (...)).
+inline char *allocate_padded_buffer(size_t length) noexcept;
+
+} // namespace internal
+} // namespace simdjson
+
+#endif // SIMDJSON_PADDED_STRING_H
diff --git a/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h b/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h
new file mode 100644
index 0000000000..1c1811de4c
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/padded_string_view-inl.h
@@ -0,0 +1,59 @@
+#ifndef SIMDJSON_PADDED_STRING_VIEW_INL_H
+#define SIMDJSON_PADDED_STRING_VIEW_INL_H
+
+#include "simdjson/padded_string_view.h"
+#include "simdjson/error-inl.h"
+
+#include <cstring> /* memcmp */
+
+namespace simdjson {
+
+inline padded_string_view::padded_string_view(const char* s, size_t len, size_t capacity) noexcept
+ : std::string_view(s, len), _capacity(capacity)
+{
+ if(_capacity < len) { _capacity = len; }
+}
+
+inline padded_string_view::padded_string_view(const uint8_t* s, size_t len, size_t capacity) noexcept
+ : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
+{
+}
+#ifdef __cpp_char8_t
+inline padded_string_view::padded_string_view(const char8_t* s, size_t len, size_t capacity) noexcept
+ : padded_string_view(reinterpret_cast<const char*>(s), len, capacity)
+{
+}
+#endif
+inline padded_string_view::padded_string_view(const std::string &s) noexcept
+ : std::string_view(s), _capacity(s.capacity())
+{
+}
+
+inline padded_string_view::padded_string_view(std::string_view s, size_t capacity) noexcept
+ : std::string_view(s), _capacity(capacity)
+{
+ if(_capacity < s.length()) { _capacity = s.length(); }
+}
+
+inline size_t padded_string_view::capacity() const noexcept { return _capacity; }
+
+inline size_t padded_string_view::padding() const noexcept { return capacity() - length(); }
+
+inline bool padded_string_view::remove_utf8_bom() noexcept {
+ if(length() < 3) { return false; }
+ if (std::memcmp(data(), "\xEF\xBB\xBF", 3) == 0) {
+ remove_prefix(3);
+ _capacity -= 3;
+ return true;
+ }
+ return false;
+}
+
+#if SIMDJSON_EXCEPTIONS
+inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false) { return out << s.value(); }
+#endif
+
+} // namespace simdjson
+
+
+#endif // SIMDJSON_PADDED_STRING_VIEW_INL_H
diff --git a/contrib/libs/simdjson/include/simdjson/padded_string_view.h b/contrib/libs/simdjson/include/simdjson/padded_string_view.h
new file mode 100644
index 0000000000..f8dc59a79c
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/padded_string_view.h
@@ -0,0 +1,88 @@
+#ifndef SIMDJSON_PADDED_STRING_VIEW_H
+#define SIMDJSON_PADDED_STRING_VIEW_H
+
+#include "simdjson/portability.h"
+#include "simdjson/base.h" // for SIMDJSON_PADDING
+#include "simdjson/error.h"
+
+#include <cstring>
+#include <memory>
+#include <string>
+#include <ostream>
+
+namespace simdjson {
+
+/**
+ * User-provided string that promises it has extra padded bytes at the end for use with parser::parse().
+ */
+class padded_string_view : public std::string_view {
+private:
+ size_t _capacity;
+
+public:
+ /** Create an empty padded_string_view. */
+ inline padded_string_view() noexcept = default;
+
+ /**
+ * Promise the given buffer has at least SIMDJSON_PADDING extra bytes allocated to it.
+ *
+ * @param s The string.
+ * @param len The length of the string (not including padding).
+ * @param capacity The allocated length of the string, including padding. If the capacity is less
+ * than the length, the capacity will be set to the length.
+ */
+ explicit inline padded_string_view(const char* s, size_t len, size_t capacity) noexcept;
+ /** overload explicit inline padded_string_view(const char* s, size_t len) noexcept */
+ explicit inline padded_string_view(const uint8_t* s, size_t len, size_t capacity) noexcept;
+#ifdef __cpp_char8_t
+ explicit inline padded_string_view(const char8_t* s, size_t len, size_t capacity) noexcept;
+#endif
+ /**
+ * Promise the given string has at least SIMDJSON_PADDING extra bytes allocated to it.
+ *
+ * The capacity of the string will be used to determine its padding.
+ *
+ * @param s The string.
+ */
+ explicit inline padded_string_view(const std::string &s) noexcept;
+
+ /**
+ * Promise the given string_view has at least SIMDJSON_PADDING extra bytes allocated to it.
+ *
+ * @param s The string.
+ * @param capacity The allocated length of the string, including padding. If the capacity is less
+ * than the length, the capacity will be set to the length.
+ */
+ explicit inline padded_string_view(std::string_view s, size_t capacity) noexcept;
+
+ /** The number of allocated bytes. */
+ inline size_t capacity() const noexcept;
+
+ /**
+ * Remove the UTF-8 Byte Order Mark (BOM) if it exists.
+ *
+ * @return whether a BOM was found and removed
+ */
+ inline bool remove_utf8_bom() noexcept;
+
+ /** The amount of padding on the string (capacity() - length()) */
+ inline size_t padding() const noexcept;
+
+}; // padded_string_view
+
+#if SIMDJSON_EXCEPTIONS
+/**
+ * Send padded_string instance to an output stream.
+ *
+ * @param out The output stream.
+ * @param s The padded_string_view.
+ * @throw simdjson_error if the result being printed has an error. If there is an error with the
+ * underlying output stream, that error will be propagated (simdjson_error will not be
+ * thrown).
+ */
+inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string_view> &s) noexcept(false);
+#endif
+
+} // namespace simdjson
+
+#endif // SIMDJSON_PADDED_STRING_VIEW_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64.h b/contrib/libs/simdjson/include/simdjson/ppc64.h
new file mode 100644
index 0000000000..8f563cf8d8
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_PPC64_H
+#define SIMDJSON_PPC64_H
+
+#error #include "simdjson/ppc64/begin.h"
+#include "simdjson/generic/amalgamated.h"
+#error #include "simdjson/ppc64/end.h"
+
+#endif // SIMDJSON_PPC64_H \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/base.h b/contrib/libs/simdjson/include/simdjson/ppc64/base.h
new file mode 100644
index 0000000000..6e460dfb8e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/base.h
@@ -0,0 +1,26 @@
+#ifndef SIMDJSON_PPC64_BASE_H
+#define SIMDJSON_PPC64_BASE_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#include "simdjson/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+/**
+ * Implementation for ALTIVEC (PPC64).
+ */
+namespace ppc64 {
+
+class implementation;
+
+namespace {
+namespace simd {
+template <typename T> struct simd8;
+template <typename T> struct simd8x64;
+} // namespace simd
+} // unnamed namespace
+
+} // namespace ppc64
+} // namespace simdjson
+
+#endif // SIMDJSON_PPC64_BASE_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/begin.h b/contrib/libs/simdjson/include/simdjson/ppc64/begin.h
new file mode 100644
index 0000000000..36a8d42996
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/begin.h
@@ -0,0 +1,10 @@
+#define SIMDJSON_IMPLEMENTATION ppc64
+#error #include "simdjson/ppc64/base.h"
+#error #include "simdjson/ppc64/intrinsics.h"
+#error #include "simdjson/ppc64/bitmanipulation.h"
+#error #include "simdjson/ppc64/bitmask.h"
+#error #include "simdjson/ppc64/numberparsing_defs.h"
+#error #include "simdjson/ppc64/simd.h"
+#error #include "simdjson/ppc64/stringparsing_defs.h"
+
+#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1 \ No newline at end of file
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/bitmanipulation.h b/contrib/libs/simdjson/include/simdjson/ppc64/bitmanipulation.h
new file mode 100644
index 0000000000..b2dda09cea
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/bitmanipulation.h
@@ -0,0 +1,78 @@
+#ifndef SIMDJSON_PPC64_BITMANIPULATION_H
+#define SIMDJSON_PPC64_BITMANIPULATION_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace ppc64 {
+namespace {
+
+// We sometimes call trailing_zero on inputs that are zero,
+// but the algorithms do not end up using the returned value.
+// Sadly, sanitizers are not smart enough to figure it out.
+SIMDJSON_NO_SANITIZE_UNDEFINED
+// This function can be used safely even if not all bytes have been
+// initialized.
+// See issue https://github.com/simdjson/simdjson/issues/1965
+SIMDJSON_NO_SANITIZE_MEMORY
+simdjson_inline int trailing_zeroes(uint64_t input_num) {
+#if SIMDJSON_REGULAR_VISUAL_STUDIO
+ unsigned long ret;
+ // Search the mask data from least significant bit (LSB)
+ // to the most significant bit (MSB) for a set bit (1).
+ _BitScanForward64(&ret, input_num);
+ return (int)ret;
+#else // SIMDJSON_REGULAR_VISUAL_STUDIO
+ return __builtin_ctzll(input_num);
+#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
+}
+
+/* result might be undefined when input_num is zero */
+simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
+ return input_num & (input_num - 1);
+}
+
+/* result might be undefined when input_num is zero */
+simdjson_inline int leading_zeroes(uint64_t input_num) {
+#if SIMDJSON_REGULAR_VISUAL_STUDIO
+ unsigned long leading_zero = 0;
+ // Search the mask data from most significant bit (MSB)
+ // to least significant bit (LSB) for a set bit (1).
+ if (_BitScanReverse64(&leading_zero, input_num))
+ return (int)(63 - leading_zero);
+ else
+ return 64;
+#else
+ return __builtin_clzll(input_num);
+#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
+}
+
+#if SIMDJSON_REGULAR_VISUAL_STUDIO
+simdjson_inline int count_ones(uint64_t input_num) {
+ // note: we do not support legacy 32-bit Windows in this kernel
+ return __popcnt64(input_num); // Visual Studio wants two underscores
+}
+#else
+simdjson_inline int count_ones(uint64_t input_num) {
+ return __builtin_popcountll(input_num);
+}
+#endif
+
+simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
+ uint64_t *result) {
+#if SIMDJSON_REGULAR_VISUAL_STUDIO
+ *result = value1 + value2;
+ return *result < value1;
+#else
+ return __builtin_uaddll_overflow(value1, value2,
+ reinterpret_cast<unsigned long long *>(result));
+#endif
+}
+
+} // unnamed namespace
+} // namespace ppc64
+} // namespace simdjson
+
+#endif // SIMDJSON_PPC64_BITMANIPULATION_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/bitmask.h b/contrib/libs/simdjson/include/simdjson/ppc64/bitmask.h
new file mode 100644
index 0000000000..25714ae133
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/bitmask.h
@@ -0,0 +1,46 @@
+#ifndef SIMDJSON_PPC64_BITMASK_H
+#define SIMDJSON_PPC64_BITMASK_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace ppc64 {
+namespace {
+
+//
+// Perform a "cumulative bitwise xor," flipping bits each time a 1 is
+// encountered.
+//
+// For example, prefix_xor(00100100) == 00011100
+//
+simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
+ // You can use the version below, however gcc sometimes miscompiles
+ // vec_pmsum_be, it happens somewhere around between 8 and 9th version.
+ // The performance boost was not noticeable, falling back to a usual
+ // implementation.
+ // __vector unsigned long long all_ones = {~0ull, ~0ull};
+ // __vector unsigned long long mask = {bitmask, 0};
+ // // Clang and GCC return different values for pmsum for ull so cast it to one.
+ // // Generally it is not specified by ALTIVEC ISA what is returned by
+ // // vec_pmsum_be.
+ // #if defined(__LITTLE_ENDIAN__)
+ // return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[0]);
+ // #else
+ // return (uint64_t)(((__vector unsigned long long)vec_pmsum_be(all_ones, mask))[1]);
+ // #endif
+ bitmask ^= bitmask << 1;
+ bitmask ^= bitmask << 2;
+ bitmask ^= bitmask << 4;
+ bitmask ^= bitmask << 8;
+ bitmask ^= bitmask << 16;
+ bitmask ^= bitmask << 32;
+ return bitmask;
+}
+
+} // unnamed namespace
+} // namespace ppc64
+} // namespace simdjson
+
+#endif
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/end.h b/contrib/libs/simdjson/include/simdjson/ppc64/end.h
new file mode 100644
index 0000000000..701538b651
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/end.h
@@ -0,0 +1,6 @@
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
+#undef SIMDJSON_IMPLEMENTATION
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/implementation.h b/contrib/libs/simdjson/include/simdjson/ppc64/implementation.h
new file mode 100644
index 0000000000..505581f0cd
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/implementation.h
@@ -0,0 +1,40 @@
+#ifndef SIMDJSON_PPC64_IMPLEMENTATION_H
+#define SIMDJSON_PPC64_IMPLEMENTATION_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#include "simdjson/implementation.h"
+#include "simdjson/internal/instruction_set.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+
+/**
+ * Implementation for ALTIVEC (PPC64).
+ */
+namespace ppc64 {
+
+/**
+ * @private
+ */
+class implementation final : public simdjson::implementation {
+public:
+ simdjson_inline implementation()
+ : simdjson::implementation("ppc64", "PPC64 ALTIVEC",
+ internal::instruction_set::ALTIVEC) {}
+
+ simdjson_warn_unused error_code create_dom_parser_implementation(
+ size_t capacity, size_t max_length,
+ std::unique_ptr<internal::dom_parser_implementation> &dst)
+ const noexcept final;
+ simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len,
+ uint8_t *dst,
+ size_t &dst_len) const noexcept final;
+ simdjson_warn_unused bool validate_utf8(const char *buf,
+ size_t len) const noexcept final;
+};
+
+} // namespace ppc64
+} // namespace simdjson
+
+#endif // SIMDJSON_PPC64_IMPLEMENTATION_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/intrinsics.h b/contrib/libs/simdjson/include/simdjson/ppc64/intrinsics.h
new file mode 100644
index 0000000000..96d90eaae3
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/intrinsics.h
@@ -0,0 +1,23 @@
+#ifndef SIMDJSON_PPC64_INTRINSICS_H
+#define SIMDJSON_PPC64_INTRINSICS_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+// This should be the correct header whether
+// you use visual studio or other compilers.
+#include <altivec.h>
+
+// These are defined by altivec.h in GCC toolchain, it is safe to undef them.
+#ifdef bool
+#undef bool
+#endif
+
+#ifdef vector
+#undef vector
+#endif
+
+static_assert(sizeof(__vector unsigned char) <= simdjson::SIMDJSON_PADDING, "insufficient padding for ppc64");
+
+#endif // SIMDJSON_PPC64_INTRINSICS_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h b/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h
new file mode 100644
index 0000000000..5ec2f60a6e
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/numberparsing_defs.h
@@ -0,0 +1,65 @@
+#ifndef SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
+#define SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#error #include "simdjson/ppc64/intrinsics.h"
+#include "simdjson/internal/numberparsing_tables.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#include <cstring>
+
+#if defined(__linux__)
+#include <byteswap.h>
+#elif defined(__FreeBSD__)
+#include <sys/endian.h>
+#endif
+
+namespace simdjson {
+namespace ppc64 {
+namespace numberparsing {
+
+// we don't have appropriate instructions, so let us use a scalar function
+// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
+/** @private */
+static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
+ uint64_t val;
+ std::memcpy(&val, chars, sizeof(uint64_t));
+#ifdef __BIG_ENDIAN__
+#if defined(__linux__)
+ val = bswap_64(val);
+#elif defined(__FreeBSD__)
+ val = bswap64(val);
+#endif
+#endif
+ val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
+ val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
+ return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
+}
+
+/** @private */
+simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
+ internal::value128 answer;
+#if SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
+#if SIMDJSON_IS_ARM64
+ // ARM64 has native support for 64-bit multiplications, no need to emultate
+ answer.high = __umulh(value1, value2);
+ answer.low = value1 * value2;
+#else
+ answer.low = _umul128(value1, value2, &answer.high); // _umul128 not available on ARM64
+#endif // SIMDJSON_IS_ARM64
+#else // SIMDJSON_REGULAR_VISUAL_STUDIO || SIMDJSON_IS_32BITS
+ __uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
+ answer.low = uint64_t(r);
+ answer.high = uint64_t(r >> 64);
+#endif
+ return answer;
+}
+
+} // namespace numberparsing
+} // namespace ppc64
+} // namespace simdjson
+
+#define SIMDJSON_SWAR_NUMBER_PARSING 1
+
+#endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/ondemand.h b/contrib/libs/simdjson/include/simdjson/ppc64/ondemand.h
new file mode 100644
index 0000000000..a9df4b5971
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_PPC64_ONDEMAND_H
+#define SIMDJSON_PPC64_ONDEMAND_H
+
+#error #include "simdjson/ppc64/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#error #include "simdjson/ppc64/end.h"
+
+#endif // SIMDJSON_PPC64_ONDEMAND_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/simd.h b/contrib/libs/simdjson/include/simdjson/ppc64/simd.h
new file mode 100644
index 0000000000..d20fe9c6f3
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/simd.h
@@ -0,0 +1,472 @@
+#ifndef SIMDJSON_PPC64_SIMD_H
+#define SIMDJSON_PPC64_SIMD_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#error #include "simdjson/ppc64/bitmanipulation.h"
+#include "simdjson/internal/simdprune_tables.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+#include <type_traits>
+
+namespace simdjson {
+namespace ppc64 {
+namespace {
+namespace simd {
+
+using __m128i = __vector unsigned char;
+
+template <typename Child> struct base {
+ __m128i value;
+
+ // Zero constructor
+ simdjson_inline base() : value{__m128i()} {}
+
+ // Conversion from SIMD register
+ simdjson_inline base(const __m128i _value) : value(_value) {}
+
+ // Conversion to SIMD register
+ simdjson_inline operator const __m128i &() const {
+ return this->value;
+ }
+ simdjson_inline operator __m128i &() { return this->value; }
+
+ // Bit operations
+ simdjson_inline Child operator|(const Child other) const {
+ return vec_or(this->value, (__m128i)other);
+ }
+ simdjson_inline Child operator&(const Child other) const {
+ return vec_and(this->value, (__m128i)other);
+ }
+ simdjson_inline Child operator^(const Child other) const {
+ return vec_xor(this->value, (__m128i)other);
+ }
+ simdjson_inline Child bit_andnot(const Child other) const {
+ return vec_andc(this->value, (__m128i)other);
+ }
+ simdjson_inline Child &operator|=(const Child other) {
+ auto this_cast = static_cast<Child*>(this);
+ *this_cast = *this_cast | other;
+ return *this_cast;
+ }
+ simdjson_inline Child &operator&=(const Child other) {
+ auto this_cast = static_cast<Child*>(this);
+ *this_cast = *this_cast & other;
+ return *this_cast;
+ }
+ simdjson_inline Child &operator^=(const Child other) {
+ auto this_cast = static_cast<Child*>(this);
+ *this_cast = *this_cast ^ other;
+ return *this_cast;
+ }
+};
+
+template <typename T, typename Mask = simd8<bool>>
+struct base8 : base<simd8<T>> {
+ typedef uint16_t bitmask_t;
+ typedef uint32_t bitmask2_t;
+
+ simdjson_inline base8() : base<simd8<T>>() {}
+ simdjson_inline base8(const __m128i _value) : base<simd8<T>>(_value) {}
+
+ friend simdjson_inline Mask operator==(const simd8<T> lhs, const simd8<T> rhs) {
+ return (__m128i)vec_cmpeq(lhs.value, (__m128i)rhs);
+ }
+
+ static const int SIZE = sizeof(base<simd8<T>>::value);
+
+ template <int N = 1>
+ simdjson_inline simd8<T> prev(simd8<T> prev_chunk) const {
+ __m128i chunk = this->value;
+#ifdef __LITTLE_ENDIAN__
+ chunk = (__m128i)vec_reve(this->value);
+ prev_chunk = (__m128i)vec_reve((__m128i)prev_chunk);
+#endif
+ chunk = (__m128i)vec_sld((__m128i)prev_chunk, (__m128i)chunk, 16 - N);
+#ifdef __LITTLE_ENDIAN__
+ chunk = (__m128i)vec_reve((__m128i)chunk);
+#endif
+ return chunk;
+ }
+};
+
+// SIMD byte mask type (returned by things like eq and gt)
+template <> struct simd8<bool> : base8<bool> {
+ static simdjson_inline simd8<bool> splat(bool _value) {
+ return (__m128i)vec_splats((unsigned char)(-(!!_value)));
+ }
+
+ simdjson_inline simd8() : base8<bool>() {}
+ simdjson_inline simd8(const __m128i _value)
+ : base8<bool>(_value) {}
+ // Splat constructor
+ simdjson_inline simd8(bool _value)
+ : base8<bool>(splat(_value)) {}
+
+ simdjson_inline int to_bitmask() const {
+ __vector unsigned long long result;
+ const __m128i perm_mask = {0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40,
+ 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x00};
+
+ result = ((__vector unsigned long long)vec_vbpermq((__m128i)this->value,
+ (__m128i)perm_mask));
+#ifdef __LITTLE_ENDIAN__
+ return static_cast<int>(result[1]);
+#else
+ return static_cast<int>(result[0]);
+#endif
+ }
+ simdjson_inline bool any() const {
+ return !vec_all_eq(this->value, (__m128i)vec_splats(0));
+ }
+ simdjson_inline simd8<bool> operator~() const {
+ return this->value ^ (__m128i)splat(true);
+ }
+};
+
+template <typename T> struct base8_numeric : base8<T> {
+ static simdjson_inline simd8<T> splat(T value) {
+ (void)value;
+ return (__m128i)vec_splats(value);
+ }
+ static simdjson_inline simd8<T> zero() { return splat(0); }
+ static simdjson_inline simd8<T> load(const T values[16]) {
+ return (__m128i)(vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(values)));
+ }
+ // Repeat 16 values as many times as necessary (usually for lookup tables)
+ static simdjson_inline simd8<T> repeat_16(T v0, T v1, T v2, T v3, T v4,
+ T v5, T v6, T v7, T v8, T v9,
+ T v10, T v11, T v12, T v13,
+ T v14, T v15) {
+ return simd8<T>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+ v14, v15);
+ }
+
+ simdjson_inline base8_numeric() : base8<T>() {}
+ simdjson_inline base8_numeric(const __m128i _value)
+ : base8<T>(_value) {}
+
+ // Store to array
+ simdjson_inline void store(T dst[16]) const {
+ vec_vsx_st(this->value, 0, reinterpret_cast<__m128i *>(dst));
+ }
+
+ // Override to distinguish from bool version
+ simdjson_inline simd8<T> operator~() const { return *this ^ 0xFFu; }
+
+ // Addition/subtraction are the same for signed and unsigned
+ simdjson_inline simd8<T> operator+(const simd8<T> other) const {
+ return (__m128i)((__m128i)this->value + (__m128i)other);
+ }
+ simdjson_inline simd8<T> operator-(const simd8<T> other) const {
+ return (__m128i)((__m128i)this->value - (__m128i)other);
+ }
+ simdjson_inline simd8<T> &operator+=(const simd8<T> other) {
+ *this = *this + other;
+ return *static_cast<simd8<T> *>(this);
+ }
+ simdjson_inline simd8<T> &operator-=(const simd8<T> other) {
+ *this = *this - other;
+ return *static_cast<simd8<T> *>(this);
+ }
+
+ // Perform a lookup assuming the value is between 0 and 16 (undefined behavior
+ // for out of range values)
+ template <typename L>
+ simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
+ return (__m128i)vec_perm((__m128i)lookup_table, (__m128i)lookup_table, this->value);
+ }
+
+ // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted
+ // as a bitset). Passing a 0 value for mask would be equivalent to writing out
+ // every byte to output. Only the first 16 - count_ones(mask) bytes of the
+ // result are significant but 16 bytes get written. Design consideration: it
+ // seems like a function with the signature simd8<L> compress(uint32_t mask)
+ // would be sensible, but the AVX ISA makes this kind of approach difficult.
+ template <typename L>
+ simdjson_inline void compress(uint16_t mask, L *output) const {
+ using internal::BitsSetTable256mul2;
+ using internal::pshufb_combine_table;
+ using internal::thintable_epi8;
+ // this particular implementation was inspired by work done by @animetosho
+ // we do it in two steps, first 8 bytes and then second 8 bytes
+ uint8_t mask1 = uint8_t(mask); // least significant 8 bits
+ uint8_t mask2 = uint8_t(mask >> 8); // most significant 8 bits
+ // next line just loads the 64-bit values thintable_epi8[mask1] and
+ // thintable_epi8[mask2] into a 128-bit register, using only
+ // two instructions on most compilers.
+#ifdef __LITTLE_ENDIAN__
+ __m128i shufmask = (__m128i)(__vector unsigned long long){
+ thintable_epi8[mask1], thintable_epi8[mask2]};
+#else
+ __m128i shufmask = (__m128i)(__vector unsigned long long){
+ thintable_epi8[mask2], thintable_epi8[mask1]};
+ shufmask = (__m128i)vec_reve((__m128i)shufmask);
+#endif
+ // we increment by 0x08 the second half of the mask
+ shufmask = ((__m128i)shufmask) +
+ ((__m128i)(__vector int){0, 0, 0x08080808, 0x08080808});
+
+ // this is the version "nearly pruned"
+ __m128i pruned = vec_perm(this->value, this->value, shufmask);
+ // we still need to put the two halves together.
+ // we compute the popcount of the first half:
+ int pop1 = BitsSetTable256mul2[mask1];
+ // then load the corresponding mask, what it does is to write
+ // only the first pop1 bytes from the first 8 bytes, and then
+ // it fills in with the bytes from the second 8 bytes + some filling
+ // at the end.
+ __m128i compactmask =
+ vec_vsx_ld(0, reinterpret_cast<const uint8_t *>(pshufb_combine_table + pop1 * 8));
+ __m128i answer = vec_perm(pruned, (__m128i)vec_splats(0), compactmask);
+ vec_vsx_st(answer, 0, reinterpret_cast<__m128i *>(output));
+ }
+
+ template <typename L>
+ simdjson_inline simd8<L>
+ lookup_16(L replace0, L replace1, L replace2, L replace3, L replace4,
+ L replace5, L replace6, L replace7, L replace8, L replace9,
+ L replace10, L replace11, L replace12, L replace13, L replace14,
+ L replace15) const {
+ return lookup_16(simd8<L>::repeat_16(
+ replace0, replace1, replace2, replace3, replace4, replace5, replace6,
+ replace7, replace8, replace9, replace10, replace11, replace12,
+ replace13, replace14, replace15));
+ }
+};
+
+// Signed bytes
+template <> struct simd8<int8_t> : base8_numeric<int8_t> {
+ simdjson_inline simd8() : base8_numeric<int8_t>() {}
+ simdjson_inline simd8(const __m128i _value)
+ : base8_numeric<int8_t>(_value) {}
+ // Splat constructor
+ simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
+ // Array constructor
+ simdjson_inline simd8(const int8_t *values) : simd8(load(values)) {}
+ // Member-by-member initialization
+ simdjson_inline simd8(int8_t v0, int8_t v1, int8_t v2, int8_t v3,
+ int8_t v4, int8_t v5, int8_t v6, int8_t v7,
+ int8_t v8, int8_t v9, int8_t v10, int8_t v11,
+ int8_t v12, int8_t v13, int8_t v14, int8_t v15)
+ : simd8((__m128i)(__vector signed char){v0, v1, v2, v3, v4, v5, v6, v7,
+ v8, v9, v10, v11, v12, v13, v14,
+ v15}) {}
+ // Repeat 16 values as many times as necessary (usually for lookup tables)
+ simdjson_inline static simd8<int8_t>
+ repeat_16(int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5,
+ int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11,
+ int8_t v12, int8_t v13, int8_t v14, int8_t v15) {
+ return simd8<int8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15);
+ }
+
+ // Order-sensitive comparisons
+ simdjson_inline simd8<int8_t>
+ max_val(const simd8<int8_t> other) const {
+ return (__m128i)vec_max((__vector signed char)this->value,
+ (__vector signed char)(__m128i)other);
+ }
+ simdjson_inline simd8<int8_t>
+ min_val(const simd8<int8_t> other) const {
+ return (__m128i)vec_min((__vector signed char)this->value,
+ (__vector signed char)(__m128i)other);
+ }
+ simdjson_inline simd8<bool>
+ operator>(const simd8<int8_t> other) const {
+ return (__m128i)vec_cmpgt((__vector signed char)this->value,
+ (__vector signed char)(__m128i)other);
+ }
+ simdjson_inline simd8<bool>
+ operator<(const simd8<int8_t> other) const {
+ return (__m128i)vec_cmplt((__vector signed char)this->value,
+ (__vector signed char)(__m128i)other);
+ }
+};
+
+// Unsigned bytes
+template <> struct simd8<uint8_t> : base8_numeric<uint8_t> {
+ simdjson_inline simd8() : base8_numeric<uint8_t>() {}
+ simdjson_inline simd8(const __m128i _value)
+ : base8_numeric<uint8_t>(_value) {}
+ // Splat constructor
+ simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
+ // Array constructor
+ simdjson_inline simd8(const uint8_t *values) : simd8(load(values)) {}
+ // Member-by-member initialization
+ simdjson_inline
+ simd8(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5,
+ uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10,
+ uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15)
+ : simd8((__m128i){v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15}) {}
+ // Repeat 16 values as many times as necessary (usually for lookup tables)
+ simdjson_inline static simd8<uint8_t>
+ repeat_16(uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4,
+ uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9,
+ uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14,
+ uint8_t v15) {
+ return simd8<uint8_t>(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+ v13, v14, v15);
+ }
+
+ // Saturated math
+ simdjson_inline simd8<uint8_t>
+ saturating_add(const simd8<uint8_t> other) const {
+ return (__m128i)vec_adds(this->value, (__m128i)other);
+ }
+ simdjson_inline simd8<uint8_t>
+ saturating_sub(const simd8<uint8_t> other) const {
+ return (__m128i)vec_subs(this->value, (__m128i)other);
+ }
+
+ // Order-specific operations
+ simdjson_inline simd8<uint8_t>
+ max_val(const simd8<uint8_t> other) const {
+ return (__m128i)vec_max(this->value, (__m128i)other);
+ }
+ simdjson_inline simd8<uint8_t>
+ min_val(const simd8<uint8_t> other) const {
+ return (__m128i)vec_min(this->value, (__m128i)other);
+ }
+ // Same as >, but only guarantees true is nonzero (< guarantees true = -1)
+ simdjson_inline simd8<uint8_t>
+ gt_bits(const simd8<uint8_t> other) const {
+ return this->saturating_sub(other);
+ }
+ // Same as <, but only guarantees true is nonzero (< guarantees true = -1)
+ simdjson_inline simd8<uint8_t>
+ lt_bits(const simd8<uint8_t> other) const {
+ return other.saturating_sub(*this);
+ }
+ simdjson_inline simd8<bool>
+ operator<=(const simd8<uint8_t> other) const {
+ return other.max_val(*this) == other;
+ }
+ simdjson_inline simd8<bool>
+ operator>=(const simd8<uint8_t> other) const {
+ return other.min_val(*this) == other;
+ }
+ simdjson_inline simd8<bool>
+ operator>(const simd8<uint8_t> other) const {
+ return this->gt_bits(other).any_bits_set();
+ }
+ simdjson_inline simd8<bool>
+ operator<(const simd8<uint8_t> other) const {
+ return this->gt_bits(other).any_bits_set();
+ }
+
+ // Bit-specific operations
+ simdjson_inline simd8<bool> bits_not_set() const {
+ return (__m128i)vec_cmpeq(this->value, (__m128i)vec_splats(uint8_t(0)));
+ }
+ simdjson_inline simd8<bool> bits_not_set(simd8<uint8_t> bits) const {
+ return (*this & bits).bits_not_set();
+ }
+ simdjson_inline simd8<bool> any_bits_set() const {
+ return ~this->bits_not_set();
+ }
+ simdjson_inline simd8<bool> any_bits_set(simd8<uint8_t> bits) const {
+ return ~this->bits_not_set(bits);
+ }
+ simdjson_inline bool bits_not_set_anywhere() const {
+ return vec_all_eq(this->value, (__m128i)vec_splats(0));
+ }
+ simdjson_inline bool any_bits_set_anywhere() const {
+ return !bits_not_set_anywhere();
+ }
+ simdjson_inline bool bits_not_set_anywhere(simd8<uint8_t> bits) const {
+ return vec_all_eq(vec_and(this->value, (__m128i)bits),
+ (__m128i)vec_splats(0));
+ }
+ simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const {
+ return !bits_not_set_anywhere(bits);
+ }
+ template <int N> simdjson_inline simd8<uint8_t> shr() const {
+ return simd8<uint8_t>(
+ (__m128i)vec_sr(this->value, (__m128i)vec_splat_u8(N)));
+ }
+ template <int N> simdjson_inline simd8<uint8_t> shl() const {
+ return simd8<uint8_t>(
+ (__m128i)vec_sl(this->value, (__m128i)vec_splat_u8(N)));
+ }
+};
+
+template <typename T> struct simd8x64 {
+ static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
+ static_assert(NUM_CHUNKS == 4,
+ "PPC64 kernel should use four registers per 64-byte block.");
+ const simd8<T> chunks[NUM_CHUNKS];
+
+ simd8x64(const simd8x64<T> &o) = delete; // no copy allowed
+ simd8x64<T> &
+ operator=(const simd8<T>& other) = delete; // no assignment allowed
+ simd8x64() = delete; // no default constructor allowed
+
+ simdjson_inline simd8x64(const simd8<T> chunk0, const simd8<T> chunk1,
+ const simd8<T> chunk2, const simd8<T> chunk3)
+ : chunks{chunk0, chunk1, chunk2, chunk3} {}
+ simdjson_inline simd8x64(const T ptr[64])
+ : chunks{simd8<T>::load(ptr), simd8<T>::load(ptr + 16),
+ simd8<T>::load(ptr + 32), simd8<T>::load(ptr + 48)} {}
+
+ simdjson_inline void store(T ptr[64]) const {
+ this->chunks[0].store(ptr + sizeof(simd8<T>) * 0);
+ this->chunks[1].store(ptr + sizeof(simd8<T>) * 1);
+ this->chunks[2].store(ptr + sizeof(simd8<T>) * 2);
+ this->chunks[3].store(ptr + sizeof(simd8<T>) * 3);
+ }
+
+ simdjson_inline simd8<T> reduce_or() const {
+ return (this->chunks[0] | this->chunks[1]) |
+ (this->chunks[2] | this->chunks[3]);
+ }
+
+ simdjson_inline uint64_t compress(uint64_t mask, T *output) const {
+ this->chunks[0].compress(uint16_t(mask), output);
+ this->chunks[1].compress(uint16_t(mask >> 16),
+ output + 16 - count_ones(mask & 0xFFFF));
+ this->chunks[2].compress(uint16_t(mask >> 32),
+ output + 32 - count_ones(mask & 0xFFFFFFFF));
+ this->chunks[3].compress(uint16_t(mask >> 48),
+ output + 48 - count_ones(mask & 0xFFFFFFFFFFFF));
+ return 64 - count_ones(mask);
+ }
+
+ simdjson_inline uint64_t to_bitmask() const {
+ uint64_t r0 = uint32_t(this->chunks[0].to_bitmask());
+ uint64_t r1 = this->chunks[1].to_bitmask();
+ uint64_t r2 = this->chunks[2].to_bitmask();
+ uint64_t r3 = this->chunks[3].to_bitmask();
+ return r0 | (r1 << 16) | (r2 << 32) | (r3 << 48);
+ }
+
+ simdjson_inline uint64_t eq(const T m) const {
+ const simd8<T> mask = simd8<T>::splat(m);
+ return simd8x64<bool>(this->chunks[0] == mask, this->chunks[1] == mask,
+ this->chunks[2] == mask, this->chunks[3] == mask)
+ .to_bitmask();
+ }
+
+ simdjson_inline uint64_t eq(const simd8x64<uint8_t> &other) const {
+ return simd8x64<bool>(this->chunks[0] == other.chunks[0],
+ this->chunks[1] == other.chunks[1],
+ this->chunks[2] == other.chunks[2],
+ this->chunks[3] == other.chunks[3])
+ .to_bitmask();
+ }
+
+ simdjson_inline uint64_t lteq(const T m) const {
+ const simd8<T> mask = simd8<T>::splat(m);
+ return simd8x64<bool>(this->chunks[0] <= mask, this->chunks[1] <= mask,
+ this->chunks[2] <= mask, this->chunks[3] <= mask)
+ .to_bitmask();
+ }
+}; // struct simd8x64<T>
+
+} // namespace simd
+} // unnamed namespace
+} // namespace ppc64
+} // namespace simdjson
+
+#endif // SIMDJSON_PPC64_SIMD_INPUT_H
diff --git a/contrib/libs/simdjson/include/simdjson/ppc64/stringparsing_defs.h b/contrib/libs/simdjson/include/simdjson/ppc64/stringparsing_defs.h
new file mode 100644
index 0000000000..b1bd46e521
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/ppc64/stringparsing_defs.h
@@ -0,0 +1,65 @@
+#ifndef SIMDJSON_PPC64_STRINGPARSING_DEFS_H
+#define SIMDJSON_PPC64_STRINGPARSING_DEFS_H
+
+#ifndef SIMDJSON_CONDITIONAL_INCLUDE
+#error #include "simdjson/ppc64/base.h"
+#error #include "simdjson/ppc64/bitmanipulation.h"
+#error #include "simdjson/ppc64/simd.h"
+#endif // SIMDJSON_CONDITIONAL_INCLUDE
+
+namespace simdjson {
+namespace ppc64 {
+namespace {
+
+using namespace simd;
+
+// Holds backslashes and quotes locations.
+struct backslash_and_quote {
+public:
+ static constexpr uint32_t BYTES_PROCESSED = 32;
+ simdjson_inline static backslash_and_quote
+ copy_and_find(const uint8_t *src, uint8_t *dst);
+
+ simdjson_inline bool has_quote_first() {
+ return ((bs_bits - 1) & quote_bits) != 0;
+ }
+ simdjson_inline bool has_backslash() { return bs_bits != 0; }
+ simdjson_inline int quote_index() {
+ return trailing_zeroes(quote_bits);
+ }
+ simdjson_inline int backslash_index() {
+ return trailing_zeroes(bs_bits);
+ }
+
+ uint32_t bs_bits;
+ uint32_t quote_bits;
+}; // struct backslash_and_quote
+
+simdjson_inline backslash_and_quote
+backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
+ // this can read up to 31 bytes beyond the buffer size, but we require
+ // SIMDJSON_PADDING of padding
+ static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1),
+ "backslash and quote finder must process fewer than "
+ "SIMDJSON_PADDING bytes");
+ simd8<uint8_t> v0(src);
+ simd8<uint8_t> v1(src + sizeof(v0));
+ v0.store(dst);
+ v1.store(dst + sizeof(v0));
+
+ // Getting a 64-bit bitmask is much cheaper than multiple 16-bit bitmasks on
+ // PPC; therefore, we smash them together into a 64-byte mask and get the
+ // bitmask from there.
+ uint64_t bs_and_quote =
+ simd8x64<bool>(v0 == '\\', v1 == '\\', v0 == '"', v1 == '"').to_bitmask();
+ return {
+ uint32_t(bs_and_quote), // bs_bits
+ uint32_t(bs_and_quote >> 32) // quote_bits
+ };
+}
+
+} // unnamed namespace
+} // namespace ppc64
+} // namespace simdjson
+
+#endif // SIMDJSON_PPC64_STRINGPARSING_DEFS_H
diff --git a/contrib/libs/simdjson/include/simdjson/simdjson.h b/contrib/libs/simdjson/include/simdjson/simdjson.h
new file mode 100644
index 0000000000..551673aefb
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/simdjson.h
@@ -0,0 +1,11 @@
+/**
+ * @file
+ * @deprecated We will be removing this file so it is not confused with the top level simdjson.h
+ */
+#ifndef SIMDJSON_SIMDJSON_H
+#define SIMDJSON_SIMDJSON_H
+
+#include "simdjson/compiler_check.h"
+#include "simdjson/error.h"
+
+#endif // SIMDJSON_SIMDJSON_H
diff --git a/contrib/libs/simdjson/include/simdjson/simdjson_version.h b/contrib/libs/simdjson/include/simdjson/simdjson_version.h
new file mode 100644
index 0000000000..059bb9a501
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/simdjson_version.h
@@ -0,0 +1,26 @@
+// /include/simdjson/simdjson_version.h automatically generated by release.py,
+// do not change by hand
+#ifndef SIMDJSON_SIMDJSON_VERSION_H
+#define SIMDJSON_SIMDJSON_VERSION_H
+
+/** The version of simdjson being used (major.minor.revision) */
+#define SIMDJSON_VERSION "3.10.1"
+
+namespace simdjson {
+enum {
+ /**
+ * The major version (MAJOR.minor.revision) of simdjson being used.
+ */
+ SIMDJSON_VERSION_MAJOR = 3,
+ /**
+ * The minor version (major.MINOR.revision) of simdjson being used.
+ */
+ SIMDJSON_VERSION_MINOR = 10,
+ /**
+ * The revision (major.minor.REVISION) of simdjson being used.
+ */
+ SIMDJSON_VERSION_REVISION = 1
+};
+} // namespace simdjson
+
+#endif // SIMDJSON_SIMDJSON_VERSION_H
diff --git a/contrib/libs/simdjson/include/simdjson/westmere/ondemand.h b/contrib/libs/simdjson/include/simdjson/westmere/ondemand.h
new file mode 100644
index 0000000000..40d4ce2551
--- /dev/null
+++ b/contrib/libs/simdjson/include/simdjson/westmere/ondemand.h
@@ -0,0 +1,8 @@
+#ifndef SIMDJSON_WESTMERE_ONDEMAND_H
+#define SIMDJSON_WESTMERE_ONDEMAND_H
+
+#include "simdjson/westmere/begin.h"
+#include "simdjson/generic/ondemand/amalgamated.h"
+#include "simdjson/westmere/end.h"
+
+#endif // SIMDJSON_WESTMERE_IMPLEMENTATION_H