Skip the token copy for array indices and the prefix look-up for a first child 0 in unflatten()

Array elements are addressed by a plain index of up to 9 digits in nearly
all flattened documents. Parse it straight from the key instead of copying
the token into a string and converting that. A new container whose first
child has the token 0 is an array by definition, so the hash set of array
prefixes is only consulted for other first children.

unflatten() (instructions on macOS, Linux Ir GCC 13 / Clang 18): canada 188.4M ->
161.1M, 151.3M -> 128.1M / 162.3M -> 138.0M; citm_catalog 45.0M -> 43.3M, 40.3M
-> 38.9M / 41.1M -> 39.6M; twitter unchanged. Output and exceptions are
identical to develop over the differential check.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-22 09:29:46 +02:00
1 parent 38ba507196
commit f2c0e8b6f9
2 files changed
+46 -4

No files matched your search

+23 -2
View File
@@ -1595,8 +1595,28 @@ class json_pointer
{
end = key.size();
}
const std::size_t token_size = end - pos - 1;
// a token that is a plain index of up to 9 digits, which is
// the case for almost all array elements, is not copied
std::size_t index = 0;
bool plain_index = current->type() == detail::value_t::array && token_size != 0 && token_size <= 9 && (token_size == 1 || data[pos + 1] != '0');
for (std::size_t k = pos + 1; plain_index && k < end; ++k)
{
plain_index = data[k] >= '0' && data[k] <= '9';
index = (index * 10) + static_cast<std::size_t>(data[k] - '0');
}
if (plain_index)
{
current = &current->operator[](static_cast<typename BasicJsonType::size_type>(index));
values.push_back(current);
ends.push_back(end);
pos = end;
continue;
}
token.clear();
token.append(data + pos + 1, end - pos - 1);
token.append(data + pos + 1, token_size);
if (token.find_first_of('~') != string_t::npos)
{
detail::unescape(token);
@@ -1606,7 +1626,8 @@ class json_pointer
{
case detail::value_t::null:
{
if (arrays.contains(data, pos))
// a first child 0 makes the value an array without a look-up
if ((token_size == 1 && data[pos + 1] == '0') || arrays.contains(data, pos))
{
// some reference token below this position is 0, so the
// value is an array