// __ _____ _____ _____ // __| | __| | | | JSON for Modern C++ // | | |__ | | | | | | version 3.12.0 // |_____|_____|_____|_|___| https://github.com/nlohmann/json // // SPDX-FileCopyrightText: 2013-2026 Niels Lohmann // SPDX-License-Identifier: MIT #pragma once #include // int64_t, uint8_t #include // string #include // vector #include #include #include #include #include NLOHMANN_JSON_NAMESPACE_BEGIN namespace detail { namespace view { /*! @brief the basic_json value of the subtree at n The subtree is replayed into the SAX handler that parse() uses to build its values, so the result is the value parse() would produce: duplicate keys keep the last value, and with JSON_DIAGNOSTICS the parent pointers are set. It is iterative, so the nesting depth is limited by memory only, as for parse(). Without a lexer the handler records no source positions (JSON_DIAGNOSTIC_POSITIONS). */ template BasicJsonType materialize(const document_data& d, const node* n) { using string_t = typename BasicJsonType::string_t; using sax_t = json_sax_dom_parser>; using nav = navigation; struct frame { const node* pos; ///< next element, or key of the next member const node* end; bool object; }; BasicJsonType result; sax_t sax(result, true); const string_t no_token{}; std::vector open; for (;;) { // false positive: n comes from nav::value(), which never returns null for a valid index // @infer-ignore NULLPTR_DEREFERENCE switch (static_cast(n->kind)) { case value_t::object: case value_t::array: { const bool object = n->kind == static_cast(value_t::object); if (object) { sax.start_object(n->len); } else { sax.start_array(n->len); } open.push_back(frame{nav::first(d, n), nav::end(d, n), object}); break; } case value_t::string: { string_t s(d.str(*n), n->len); sax.string(s); break; } case value_t::number_integer: sax.number_integer(static_cast(static_cast(integer_bits(*n)))); break; case value_t::number_unsigned: sax.number_unsigned(static_cast(integer_bits(*n))); break; case value_t::number_float: sax.number_float(float_value(d, *n), no_token); break; case value_t::boolean: sax.boolean((n->flags & node_flags::is_true) != 0); break; case value_t::null: case value_t::binary: case value_t::discarded: default: sax.null(); break; } // the next value: close finished containers, then read the key for (;;) { if (open.empty()) { return result; } frame& f = open.back(); if (f.pos == f.end) { if (f.object) { sax.end_object(); } else { sax.end_array(); } open.pop_back(); continue; } const node* entry = f.pos; if (f.object) { string_t key(d.str(*entry), entry->len); sax.key(key); ++entry; } n = nav::value(entry); f.pos = document_data::after(entry); break; } } } } // namespace view } // namespace detail NLOHMANN_JSON_NAMESPACE_END