mirror of
https://github.com/nlohmann/json.git
synced 2026-10-22 14:08:13 +00:00
Split a JSON pointer in one scan and construct the tokens in place
split() looked for the end of every reference token with find_first_of('/'),
for a '~' in it with a second find_first_of, and moved the token into the
vector. One loop over the characters now finds both, and a token without an
escape is constructed in the vector. Tokens with an escape are checked and
unescaped as before, so the exceptions are the same.
json_pointer(string) over the keys of citm_catalog (instructions on macOS, Linux
Ir GCC 13 / Clang 18): 42.3M -> 36.4M, 42.9M -> 35.1M / 41.2M -> 34.7M;
twitter 17.7M -> 16.2M, 18.5M -> 16.3M / 17.6M -> 16.0M.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+60
-54
No files matched your search
@@ -1198,33 +1198,32 @@ class json_pointer
|
||||
}
|
||||
result.reserve(token_count);
|
||||
|
||||
// extract the reference tokens:
|
||||
// - slash: position of the last read slash (or end of string)
|
||||
// - start: position after the previous slash
|
||||
for (
|
||||
// search for the first slash after the first character
|
||||
std::size_t slash = reference_string.find_first_of('/', 1),
|
||||
// set the beginning of the first reference token
|
||||
start = 1;
|
||||
// we can stop if start == 0 (if slash == string_t::npos)
|
||||
start != 0;
|
||||
// set the beginning of the next reference token
|
||||
// (will eventually be 0 if slash == string_t::npos)
|
||||
start = (slash == string_t::npos) ? 0 : slash + 1,
|
||||
// find next slash
|
||||
slash = reference_string.find_first_of('/', start))
|
||||
// extract the reference tokens: every one runs from after a slash to
|
||||
// the next slash or the end of the string; a token without a '~' (the
|
||||
// common case) is stored as it is, others are checked and unescaped
|
||||
const char* const data = reference_string.data();
|
||||
const char* const end = data + size;
|
||||
for (const char* start = data + 1;; ++start)
|
||||
{
|
||||
// use the text between the beginning of the reference token
|
||||
// (start) and the last slash (slash).
|
||||
const auto count = (slash == string_t::npos ? reference_string.size() : slash) - start;
|
||||
auto reference_token = string_t(reference_string.data() + start, count);
|
||||
|
||||
// check reference tokens are properly escaped; a token without
|
||||
// a '~' (the common case) needs neither check nor unescaping
|
||||
std::size_t pos = reference_token.find_first_of('~');
|
||||
if (pos != string_t::npos)
|
||||
const char* slash = start;
|
||||
bool escaped = false;
|
||||
while (slash != end && *slash != '/')
|
||||
{
|
||||
for (; pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
|
||||
escaped = escaped || *slash == '~';
|
||||
++slash;
|
||||
}
|
||||
|
||||
const auto count = static_cast<std::size_t>(slash - start);
|
||||
if (JSON_HEDLEY_LIKELY(!escaped))
|
||||
{
|
||||
result.emplace_back(start, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto reference_token = string_t(start, count);
|
||||
|
||||
// check reference tokens are properly escaped
|
||||
for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
|
||||
{
|
||||
JSON_ASSERT(reference_token[pos] == '~');
|
||||
|
||||
@@ -1238,10 +1237,14 @@ class json_pointer
|
||||
}
|
||||
|
||||
detail::unescape(reference_token);
|
||||
result.push_back(std::move(reference_token));
|
||||
}
|
||||
|
||||
// finally, store the reference token
|
||||
result.push_back(std::move(reference_token));
|
||||
if (slash == end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
start = slash;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Generated
+30
-27
@@ -23548,33 +23548,32 @@ class json_pointer
|
||||
}
|
||||
result.reserve(token_count);
|
||||
|
||||
// extract the reference tokens:
|
||||
// - slash: position of the last read slash (or end of string)
|
||||
// - start: position after the previous slash
|
||||
for (
|
||||
// search for the first slash after the first character
|
||||
std::size_t slash = reference_string.find_first_of('/', 1),
|
||||
// set the beginning of the first reference token
|
||||
start = 1;
|
||||
// we can stop if start == 0 (if slash == string_t::npos)
|
||||
start != 0;
|
||||
// set the beginning of the next reference token
|
||||
// (will eventually be 0 if slash == string_t::npos)
|
||||
start = (slash == string_t::npos) ? 0 : slash + 1,
|
||||
// find next slash
|
||||
slash = reference_string.find_first_of('/', start))
|
||||
// extract the reference tokens: every one runs from after a slash to
|
||||
// the next slash or the end of the string; a token without a '~' (the
|
||||
// common case) is stored as it is, others are checked and unescaped
|
||||
const char* const data = reference_string.data();
|
||||
const char* const end = data + size;
|
||||
for (const char* start = data + 1;; ++start)
|
||||
{
|
||||
// use the text between the beginning of the reference token
|
||||
// (start) and the last slash (slash).
|
||||
const auto count = (slash == string_t::npos ? reference_string.size() : slash) - start;
|
||||
auto reference_token = string_t(reference_string.data() + start, count);
|
||||
|
||||
// check reference tokens are properly escaped; a token without
|
||||
// a '~' (the common case) needs neither check nor unescaping
|
||||
std::size_t pos = reference_token.find_first_of('~');
|
||||
if (pos != string_t::npos)
|
||||
const char* slash = start;
|
||||
bool escaped = false;
|
||||
while (slash != end && *slash != '/')
|
||||
{
|
||||
for (; pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
|
||||
escaped = escaped || *slash == '~';
|
||||
++slash;
|
||||
}
|
||||
|
||||
const auto count = static_cast<std::size_t>(slash - start);
|
||||
if (JSON_HEDLEY_LIKELY(!escaped))
|
||||
{
|
||||
result.emplace_back(start, count);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto reference_token = string_t(start, count);
|
||||
|
||||
// check reference tokens are properly escaped
|
||||
for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
|
||||
{
|
||||
JSON_ASSERT(reference_token[pos] == '~');
|
||||
|
||||
@@ -23588,10 +23587,14 @@ class json_pointer
|
||||
}
|
||||
|
||||
detail::unescape(reference_token);
|
||||
result.push_back(std::move(reference_token));
|
||||
}
|
||||
|
||||
// finally, store the reference token
|
||||
result.push_back(std::move(reference_token));
|
||||
if (slash == end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
start = slash;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Reference in new issue
Block a user