mirror of
https://github.com/nlohmann/json.git
synced 2026-10-18 20:18:12 +00:00
Address the review of the view builder and document
Changes promised in the replies to the review of #5620: - read() reuses the owned copy: a copied input (an rvalue byte container, a stream, FILE*, wide characters, an iterator range) is appended to the cleared owned buffer instead of a fresh std::string being move-assigned over it. A moved-in std::string still replaces it. - The error replay runs the library parser with a SAX handler that stores nothing and throws the reported exception, instead of BasicJsonType::parse(), which built a DOM up to the error. - Pointers to and arrays of wide characters, and FILE*, take the input adapter path (converted to UTF-8 into an owned buffer) instead of failing a static_assert. Wide pointers are NUL-terminated. - Streams are read in blocks through rdbuf() into the buffer, instead of character by character through the input adapter; eofbit is set at the end, as by the library's stream adapter. - tape/tape_size/tape_cap are now nodes/node_count/node_capacity. - The builder's members get descriptive, m_-prefixed names. - The shallow frame stack is a std::array (in a wrapper with a user-provided constructor: -Weffc++ wants the member initialized, and value-initializing the 64 frames costs up to 30 % on small documents). - The value dispatch macro has no NEXT parameter; the switch is left with break, and the macro is undefined after its last use. - literal() and digits_exceed() deduce the length from the string literal; each literal has one helper; the two `if (!is_float)` blocks are merged. - arena_ensure() sits right before the writes; the decode arena is a std::vector<char>. - The builder records the deepest nesting, and materialize() sizes its stack from it once (growing it only if a subtree is deeper). - Comment fixes (hex4, slow_string, the NUL rule, put_utf8, 0 - m, the arena resize, grow()) and formatting (macro backslashes, digit cases, one power of ten per line, value_t assertion next to is_container()). - build_with's template parameters follow the builder's order. Greg's idea of keeping the source offset in `off` and the arena offset in `next` for escaped strings was measured and not adopted: string access got 7-18 % slower with a select, and 3.5-18 % slower with a branch-free field pick (Apple M-series, clang -O3), parsing was unchanged. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
11 files changed
+1152
-478
No files matched your search
@@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm> // max
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // int64_t, uint8_t
|
||||
#include <string> // string
|
||||
#include <vector> // vector
|
||||
@@ -43,8 +45,15 @@ BasicJsonType materialize(const document_data& d, const node* n)
|
||||
BasicJsonType result;
|
||||
sax_t sax(result, true);
|
||||
const string_t no_token{};
|
||||
// the ends of the open containers, and whether they are objects
|
||||
std::vector<std::pair<const node*, bool>> open;
|
||||
// the ends of the open containers, and whether they are objects; sized
|
||||
// once from the document's deepest nesting (for a subtree an upper bound)
|
||||
struct open_container
|
||||
{
|
||||
const node* end;
|
||||
bool is_object;
|
||||
};
|
||||
std::vector<open_container> open((std::max)(d.max_depth, std::size_t{1}));
|
||||
std::size_t depth = 0;
|
||||
for (;;)
|
||||
{
|
||||
switch (static_cast<value_t>(n->kind))
|
||||
@@ -61,7 +70,11 @@ BasicJsonType materialize(const document_data& d, const node* n)
|
||||
{
|
||||
sax.start_array(n->len);
|
||||
}
|
||||
open.emplace_back(document_data::child_end(n), object);
|
||||
if (NLOHMANN_VIEW_UNLIKELY(depth == open.size()))
|
||||
{
|
||||
open.resize(depth * 2); // (deeper than the document's recorded nesting)
|
||||
}
|
||||
open[depth++] = open_container{document_data::child_end(n), object};
|
||||
n = document_data::first_child(n);
|
||||
break;
|
||||
}
|
||||
@@ -98,15 +111,15 @@ BasicJsonType materialize(const document_data& d, const node* n)
|
||||
}
|
||||
for (;;)
|
||||
{
|
||||
if (open.empty())
|
||||
if (depth == 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
if (n != open.back().first)
|
||||
if (n != open[depth - 1].end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (open.back().second)
|
||||
if (open[depth - 1].is_object)
|
||||
{
|
||||
sax.end_object();
|
||||
}
|
||||
@@ -114,9 +127,9 @@ BasicJsonType materialize(const document_data& d, const node* n)
|
||||
{
|
||||
sax.end_array();
|
||||
}
|
||||
open.pop_back();
|
||||
--depth;
|
||||
}
|
||||
if (open.back().second)
|
||||
if (open[depth - 1].is_object)
|
||||
{
|
||||
// the key of the next member
|
||||
string_t key(d.str(*n), n->len);
|
||||
|
||||
Reference in new issue
Block a user