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:
2 files changed
+46
-4
No files matched your search
@@ -1595,8 +1595,28 @@ class json_pointer
|
|||||||
{
|
{
|
||||||
end = key.size();
|
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 = ¤t->operator[](static_cast<typename BasicJsonType::size_type>(index));
|
||||||
|
values.push_back(current);
|
||||||
|
ends.push_back(end);
|
||||||
|
pos = end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
token.clear();
|
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)
|
if (token.find_first_of('~') != string_t::npos)
|
||||||
{
|
{
|
||||||
detail::unescape(token);
|
detail::unescape(token);
|
||||||
@@ -1606,7 +1626,8 @@ class json_pointer
|
|||||||
{
|
{
|
||||||
case detail::value_t::null:
|
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
|
// some reference token below this position is 0, so the
|
||||||
// value is an array
|
// value is an array
|
||||||
|
|||||||
Generated
+23
-2
@@ -23945,8 +23945,28 @@ class json_pointer
|
|||||||
{
|
{
|
||||||
end = key.size();
|
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 = ¤t->operator[](static_cast<typename BasicJsonType::size_type>(index));
|
||||||
|
values.push_back(current);
|
||||||
|
ends.push_back(end);
|
||||||
|
pos = end;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
token.clear();
|
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)
|
if (token.find_first_of('~') != string_t::npos)
|
||||||
{
|
{
|
||||||
detail::unescape(token);
|
detail::unescape(token);
|
||||||
@@ -23956,7 +23976,8 @@ class json_pointer
|
|||||||
{
|
{
|
||||||
case detail::value_t::null:
|
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
|
// some reference token below this position is 0, so the
|
||||||
// value is an array
|
// value is an array
|
||||||
|
|||||||
Reference in new issue
Block a user