Keep the byte comparison helpers in compare.hpp

Address review comments: bytes_equal() and bytes_less() move from node.hpp
to compare.hpp, their only user; key_less() no longer splits the comment of
resolve_indices() from its function; and the loop counters of bytes_equal()
and all_digits() are scoped to their loops.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-23 06:47:22 +02:00
1 parent db5bd7fbcc
commit 55cdc93ff8
4 files changed
+152 -154

No files matched your search

-68
View File
@@ -120,74 +120,6 @@ NLOHMANN_VIEW_ALWAYS_INLINE std::uint32_t number_length(const node& n) noexcept
: (n.extra & 0xFFu) + (n.kind == static_cast<std::uint8_t>(value_t::number_integer) ? 1u : 0u);
}
/// whether n bytes are equal; the short texts of JSON (keys, numbers, most
/// strings) are compared by two overlapping loads instead of a library call
NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_equal(const char* x, const char* y, std::size_t n) noexcept
{
const auto load8 = [](const char* p)
{
std::uint64_t v = 0;
std::memcpy(&v, p, sizeof(v));
return v;
};
const auto load4 = [](const char* p)
{
std::uint32_t v = 0;
std::memcpy(&v, p, sizeof(v));
return v;
};
if (n >= 8)
{
std::size_t i = 0;
for (; i + 8 < n; i += 8)
{
if (load8(x + i) != load8(y + i))
{
return false;
}
}
return load8(x + n - 8) == load8(y + n - 8);
}
if (n >= 4)
{
return load4(x) == load4(y) && load4(x + n - 4) == load4(y + n - 4);
}
for (std::size_t i = 0; i < n; ++i)
{
if (x[i] != y[i])
{
return false;
}
}
return true;
}
/// whether the n1 bytes at x are before the n2 bytes at y (memcmp() order, then the shorter first);
/// the first difference is found eight bytes at a time
NLOHMANN_VIEW_ALWAYS_INLINE bool bytes_less(const char* x, std::size_t n1, const char* y, std::size_t n2) noexcept
{
const std::size_t n = n1 < n2 ? n1 : n2;
std::size_t i = 0;
for (; i + 8 <= n; i += 8)
{
const std::uint64_t u = read_eight_bytes(x + i);
const std::uint64_t v = read_eight_bytes(y + i);
if (u != v)
{
const auto shift = static_cast<unsigned>(count_trailing_zeros(u ^ v)) & ~7u; // (the first byte that differs)
return ((u >> shift) & 0xFFu) < ((v >> shift) & 0xFFu);
}
}
for (; i < n; ++i)
{
if (x[i] != y[i])
{
return static_cast<unsigned char>(x[i]) < static_cast<unsigned char>(y[i]);
}
}
return n1 < n2;
}
/// estimated number of nodes for an input of `size` bytes (one node per ~12
/// bytes covers typical documents without regrowth)
inline std::size_t estimate_nodes(std::size_t size) noexcept