Address the second review round of json_view element access

From gregmarr's review of #5622:

- begin()/end(): "a null value or a discarded view iterates as an empty
  range", singular like the primitive case before it.
- The class page's list of function groups has no trailing commas.
- document_data::key_equals() compares a key node with a string, for the
  key comparisons that were spelled out in each lookup.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-19 22:07:11 +02:00
1 parent 06147f8763
commit 63ca8e4c8b
5 files changed
+17 -12

No files matched your search

@@ -6,7 +6,7 @@ iterator begin() const noexcept;
Returns an iterator to the first element of an array, or the first member value of an object, in **document order** Returns an iterator to the first element of an array, or the first member value of an object, in **document order**
-- the order the values appear in the source text, not sorted by key. A primitive value iterates as a range of one -- the order the values appear in the source text, not sorted by key. A primitive value iterates as a range of one
element (itself); `#!json null` and a [discarded](is_discarded.md) view iterate as an empty range. element (itself), and a `#!json null` value or a [discarded](is_discarded.md) view iterates as an empty range.
## Return value ## Return value
+2 -3
View File
@@ -5,9 +5,8 @@ iterator end() const noexcept;
``` ```
Returns an iterator to one past the last element of an array, one past the last member value of an object, in Returns an iterator to one past the last element of an array, one past the last member value of an object, in
**document order** -- see [`begin()`](begin.md). A primitive value iterates as a range of one element (itself); **document order** -- see [`begin()`](begin.md). A primitive value iterates as a range of one element (itself), and a
`#!json null` and a [discarded](is_discarded.md) view iterate as an empty range, so `#!cpp begin() == end()` for `#!json null` value or a [discarded](is_discarded.md) view iterates as an empty range (`#!cpp begin() == end()`).
them.
## Return value ## Return value
@@ -22,12 +22,12 @@ Moving the document itself does not invalidate its views: the index is heap-allo
`basic_json_view` provides the read-only part of the `BasicJsonType` interface: `basic_json_view` provides the read-only part of the `BasicJsonType` interface:
- the type-inspection functions, - the type-inspection functions
- element access, - element access
- lookup, - lookup
- iteration, and - iteration
- conversion: [`get<T>()`](get.md), [`get_string()`](get_string.md), [`number_token()`](number_token.md), and - conversion: [`get<T>()`](get.md), [`get_string()`](get_string.md), [`number_token()`](number_token.md), and
[`materialize()`](materialize.md) to build the `BasicJsonType` value of a subtree on demand. [`materialize()`](materialize.md) to build the `BasicJsonType` value of a subtree on demand
[`operator[]`](operator%5B%5D.md), [`at`](at.md), [`contains`](contains.md), and [`value`](value.md) also accept a [`operator[]`](operator%5B%5D.md), [`at`](at.md), [`contains`](contains.md), and [`value`](value.md) also accept a
[`json_pointer`](../json_pointer/index.md). It does not (yet) provide `dump()` or comparison. Unlike `basic_json`, [`json_pointer`](../json_pointer/index.md). It does not (yet) provide `dump()` or comparison. Unlike `basic_json`,
@@ -10,7 +10,7 @@
#include <array> // array #include <array> // array
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstring> // memcpy #include <cstring> // memcmp, memcpy
#include <limits> // numeric_limits #include <limits> // numeric_limits
#include <new> // bad_alloc, operator new, placement new #include <new> // bad_alloc, operator new, placement new
#include <string> // string #include <string> // string
@@ -141,6 +141,12 @@ struct document_data
return base[n.flags & node_flags::storage] + n.off; return base[n.flags & node_flags::storage] + n.off;
} }
/// whether the string of node k (a key) is the n bytes at key
bool key_equals(const node& k, const char* key, std::size_t n) const noexcept
{
return k.len == n && (n == 0 || std::memcmp(str(k), key, n) == 0);
}
/// the node after n's subtree (containers span `next` nodes, scalars one) /// the node after n's subtree (containers span `next` nodes, scalars one)
static NLOHMANN_VIEW_ALWAYS_INLINE const node* after(const node* n) noexcept static NLOHMANN_VIEW_ALWAYS_INLINE const node* after(const node* n) noexcept
{ {
+2 -2
View File
@@ -105,7 +105,7 @@ inline const node* find_member(const document_data& d, const node* object, const
} }
for (const node* m = document_data::first_child(object); m != end; m = document_data::after(m + 1)) for (const node* m = document_data::first_child(object); m != end; m = document_data::after(m + 1))
{ {
if (m->len == n && std::memcmp(d.str(*m), key, n) == 0) if (d.key_equals(*m, key, n))
{ {
return m; return m;
} }
@@ -120,7 +120,7 @@ inline std::size_t count_members(const document_data& d, const node* object, con
const node* const end = document_data::child_end(object); const node* const end = document_data::child_end(object);
for (const node* m = document_data::first_child(object); m != end; m = document_data::after(m + 1)) for (const node* m = document_data::first_child(object); m != end; m = document_data::after(m + 1))
{ {
if (m->len == n && (n == 0 || std::memcmp(d.str(*m), key, n) == 0)) if (d.key_equals(*m, key, n))
{ {
++result; ++result;
} }