json_view: accept() checks strings without decoding them

The builder that accept() runs stores no nodes, but still decoded every string
with escapes into the arena (slow_string(): memcpy of the runs between escapes
and the UTF-8 of every \u escape). It now calls check_string() instead, which
has the same checks and the same errors and error positions (control characters,
ill-formed UTF-8, bad escapes, bad hex digits, lone and unpaired surrogates, a
missing closing quote) and skips the text between them with scan_string_run(),
without writing anything. The builder that stores keeps slow_string().

The flag that passes the request from accept() to build() now sits next to
`discarded` in document_data, where it uses padding: no member of document_data
moves (the first version put it after `nodes`, which moved all members behind it
by eight bytes).

Tests: the new section of the accept test checks runs of text of every length from
0 to 40 between valid and invalid escapes, UTF-8 sequences and control characters,
in values and in keys, cut near the end of the text, against json::accept().
Checked against a checker that accepts a lone low surrogate.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-30 22:34:32 +01:00
1 parent dea2a4434a
commit 9ba25b1b66
4 files changed
+211 -4

No files matched your search

@@ -36,7 +36,6 @@ struct document_data
const char* src = nullptr;
std::size_t size = 0;
node* nodes = nullptr; ///< the node index (see node.hpp)
bool validate_only = false; ///< accept(): build() checks the text and stores no nodes
std::size_t node_count = 0;
std::size_t node_capacity = 0;
node* inline_nodes = nullptr; ///< node array allocated together with this header
@@ -59,6 +58,7 @@ struct document_data
std::vector<std::uint32_t> large_objects; ///< positions of the objects to index (noted while parsing)
std::array<const char*, 4> base = {{nullptr, nullptr, nullptr, nullptr}}; ///< string bases: source, arena, edit arena, unused (indexed by flags & node_flags::storage)
bool discarded = true;
bool validate_only = false; ///< accept(): build() checks the text and stores no nodes (next to `discarded`: no member moves)
/// The storage of edits (editable documents only; see edit_storage.hpp).
/// No edit moves or resizes the parsed index, and the nodes of values