diff --git a/docs/mkdocs/docs/home/architecture.md b/docs/mkdocs/docs/home/architecture.md index 76b3e1af1..1b0d84dd7 100644 --- a/docs/mkdocs/docs/home/architecture.md +++ b/docs/mkdocs/docs/home/architecture.md @@ -203,7 +203,7 @@ packet-beta | 2-3 | `extra` | `uint16_t` | numbers: the number of integer digits (low byte) and fraction digits (high byte), 255 for more; objects: the number of their key hash index (1-based), or 0; otherwise 0 | | 4-7 | `off` | `uint32_t` | where the value starts: the first byte after a string's opening quote (or its position in the buffer of decoded strings), the first byte of a number or literal, the bracket of an array or object | | 8-11 | `len` | `uint32_t` | strings: the length after decoding; floats and literals: the length of the token; arrays and objects: the number of elements | -| 12-15 | `next` | `uint32_t` | arrays and objects: the number of nodes of the subtree, including the node itself; strings with escapes: the position of the opening quote in the source plus one if the document was parsed with [`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md), else 0; otherwise 0 | +| 12-15 | `next` | `uint32_t` | arrays and objects: the number of nodes of the subtree, including the node itself; strings with escapes: the position of the opening quote in the source plus one if the document was parsed with [`JSON_DIAGNOSTIC_POSITIONS`](../api/macros/json_diagnostic_positions.md), or 0 if it was not; all other values: 0 |
Fields of a node, by their byte offset within the 16-byte node. Integers use bytes 8-15 differently, see below.
diff --git a/include/nlohmann/detail/view/materialize.hpp b/include/nlohmann/detail/view/materialize.hpp index 7bc9674f0..1dcd1940c 100644 --- a/include/nlohmann/detail/view/materialize.hpp +++ b/include/nlohmann/detail/view/materialize.hpp @@ -320,15 +320,13 @@ BasicJsonType materialize(const document_data& d, const node* n) const bool object = n->kind == node_kind::object; #if JSON_DIAGNOSTIC_POSITIONS // (moved containers are also new) - const std::size_t start = (n->flags & node_flags::is_new) == 0 && n->off < d.size ? std::size_t{n->off} : - std::string::npos; - if (start == std::string::npos) + if ((n->flags & node_flags::is_new) != 0 || n->off >= d.size) { positions.clear(); } else { - positions.set(start, start + 1); + positions.set(std::size_t{n->off}, std::size_t{n->off} + 1); } #endif if (object) @@ -351,7 +349,7 @@ BasicJsonType materialize(const document_data& d, const node* n) // own bracket is the last thing read) open[depth++] = frame{nav::first(d, n), nav::end(d, n), object #if JSON_DIAGNOSTIC_POSITIONS - , start, positions.end + , positions.start, positions.end #endif }; break; @@ -395,22 +393,28 @@ BasicJsonType materialize(const document_data& d, const node* n) if (f.pos == f.end) { #if JSON_DIAGNOSTIC_POSITIONS - const std::size_t end = f.start == std::string::npos || f.last_end == std::string::npos ? std::string::npos : - position_source::container_end(d.base[0], d.size, f.last_end); - if (end == std::string::npos) + if (f.start == std::string::npos || f.last_end == std::string::npos) { positions.clear(); } else { - // the closing bracket, as the lexer reports it (end_object() - // and end_array() only read its end; the start of the - // container was set when it was opened) - positions.set(end - 1, end); + const std::size_t end = position_source::container_end(d.base[0], d.size, f.last_end); + if (end == std::string::npos) + { + positions.clear(); + } + else + { + // the closing bracket, as the lexer reports it (end_object() + // and end_array() only read its end; the start of the + // container was set when it was opened) + positions.set(end - 1, end); + } } if (depth > 1) { - open[depth - 2].last_end = end; + open[depth - 2].last_end = positions.end; } #endif if (f.object) diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index 33f2dbd07..90593b2d1 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -6427,15 +6427,13 @@ BasicJsonType materialize(const document_data& d, const node* n) const bool object = n->kind == node_kind::object; #if JSON_DIAGNOSTIC_POSITIONS // (moved containers are also new) - const std::size_t start = (n->flags & node_flags::is_new) == 0 && n->off < d.size ? std::size_t{n->off} : - std::string::npos; - if (start == std::string::npos) + if ((n->flags & node_flags::is_new) != 0 || n->off >= d.size) { positions.clear(); } else { - positions.set(start, start + 1); + positions.set(std::size_t{n->off}, std::size_t{n->off} + 1); } #endif if (object) @@ -6458,7 +6456,7 @@ BasicJsonType materialize(const document_data& d, const node* n) // own bracket is the last thing read) open[depth++] = frame{nav::first(d, n), nav::end(d, n), object #if JSON_DIAGNOSTIC_POSITIONS - , start, positions.end + , positions.start, positions.end #endif }; break; @@ -6502,22 +6500,28 @@ BasicJsonType materialize(const document_data& d, const node* n) if (f.pos == f.end) { #if JSON_DIAGNOSTIC_POSITIONS - const std::size_t end = f.start == std::string::npos || f.last_end == std::string::npos ? std::string::npos : - position_source::container_end(d.base[0], d.size, f.last_end); - if (end == std::string::npos) + if (f.start == std::string::npos || f.last_end == std::string::npos) { positions.clear(); } else { - // the closing bracket, as the lexer reports it (end_object() - // and end_array() only read its end; the start of the - // container was set when it was opened) - positions.set(end - 1, end); + const std::size_t end = position_source::container_end(d.base[0], d.size, f.last_end); + if (end == std::string::npos) + { + positions.clear(); + } + else + { + // the closing bracket, as the lexer reports it (end_object() + // and end_array() only read its end; the start of the + // container was set when it was opened) + positions.set(end - 1, end); + } } if (depth > 1) { - open[depth - 2].last_end = end; + open[depth - 2].last_end = positions.end; } #endif if (f.object)