mirror of
https://github.com/nlohmann/json.git
synced 2026-10-23 06:18:56 +00:00
Fix the compiler and lint failures of the json_view comparison
- all_digits(): the lambda declares its constant itself; MSVC does not let a lambda without captures read a constexpr local of the function - equal(): the frame's "in document order" index is a namespace-scope constant (document_order); the local constexpr npos in the default member initializers of the local struct crashed GCC 9 and MinGW GCC and was not found by MSVC - keys_differ_early() keeps the first keys in std::arrays (cpplint: variable-length arrays; clang-tidy: C arrays), and the basic_json side's first_keys() is not noexcept (key() may throw) - the numbers of one type are compared in an if chain instead of a nested conditional operator - the dump test avoids C arrays and temporary string concatenations View comparison instructions are unchanged (Apple clang, twitter, citm, canada: -0.1 % to +0.1 %). Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
4 files changed
+88
-38
No files matched your search
@@ -479,7 +479,7 @@ class json_side
|
||||
}
|
||||
|
||||
/// the keys of the first n members of this object (n <= its size), in document order
|
||||
void first_keys(string_view_t* out, std::size_t n) const noexcept
|
||||
void first_keys(string_view_t* out, std::size_t n) const
|
||||
{
|
||||
auto it = m_json->cbegin();
|
||||
for (std::size_t i = 0; i < n; ++i, ++it)
|
||||
@@ -808,10 +808,10 @@ bool keys_differ_early(const SideA& a, const SideB& b)
|
||||
using string_view_t = typename SideA::string_view_t;
|
||||
constexpr std::size_t limit = 4;
|
||||
const std::size_t n = (std::min)((std::min)(a.size(), b.size()), limit);
|
||||
string_view_t ka[limit];
|
||||
string_view_t kb[limit];
|
||||
a.first_keys(ka, n);
|
||||
b.first_keys(kb, n);
|
||||
std::array<string_view_t, limit> ka{};
|
||||
std::array<string_view_t, limit> kb{};
|
||||
a.first_keys(ka.data(), n);
|
||||
b.first_keys(kb.data(), n);
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
{
|
||||
if (ka[i] != kb[i])
|
||||
@@ -834,6 +834,9 @@ inline bool is_number(value_t t) noexcept
|
||||
return t == value_t::number_integer || t == value_t::number_unsigned || t == value_t::number_float;
|
||||
}
|
||||
|
||||
/// the index_a/index_b of a frame of equal() whose members are compared in document order
|
||||
constexpr std::size_t document_order = static_cast<std::size_t>(-1);
|
||||
|
||||
/// whether two sides are equal; iterative, so that the nesting depth is
|
||||
/// limited by memory only
|
||||
template<typename BasicJsonType, typename A, typename B>
|
||||
@@ -842,7 +845,6 @@ bool equal(const A& a0, const B& b0)
|
||||
using string_view_t = typename A::string_view_t;
|
||||
const bool ordered = is_ordered_map<typename BasicJsonType::object_t>::value;
|
||||
|
||||
constexpr std::size_t npos = static_cast<std::size_t>(-1);
|
||||
struct frame
|
||||
{
|
||||
A array_a{};
|
||||
@@ -851,8 +853,8 @@ bool equal(const A& a0, const B& b0)
|
||||
typename B::cursor cursor_b{};
|
||||
std::size_t base_a = 0; ///< the members of an object: from this position in members_a
|
||||
std::size_t base_b = 0;
|
||||
std::size_t index_a = npos; ///< their order in the comparison: from this position in indices (npos: as they are)
|
||||
std::size_t index_b = npos;
|
||||
std::size_t index_a = document_order; ///< their order in the comparison: from this position in indices (document_order: as they are)
|
||||
std::size_t index_b = document_order;
|
||||
std::size_t index_mark = 0; ///< the size of indices before this frame
|
||||
bool object = false;
|
||||
std::size_t next = 0;
|
||||
@@ -983,9 +985,20 @@ bool equal(const A& a0, const B& b0)
|
||||
else if (numbers && ta == tb)
|
||||
{
|
||||
// numbers of one type: as basic_json compares them
|
||||
if (ta == value_t::number_integer ? a.integer() != b.integer()
|
||||
: ta == value_t::number_unsigned ? a.unsigned_integer() != b.unsigned_integer()
|
||||
: !floats_equal(a, b))
|
||||
bool differ = false;
|
||||
if (ta == value_t::number_integer)
|
||||
{
|
||||
differ = a.integer() != b.integer();
|
||||
}
|
||||
else if (ta == value_t::number_unsigned)
|
||||
{
|
||||
differ = a.unsigned_integer() != b.unsigned_integer();
|
||||
}
|
||||
else
|
||||
{
|
||||
differ = !floats_equal(a, b);
|
||||
}
|
||||
if (differ)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1018,8 +1031,8 @@ bool equal(const A& a0, const B& b0)
|
||||
}
|
||||
if (f.object)
|
||||
{
|
||||
const auto& member_a = members_a[f.base_a + (f.index_a == npos ? f.next : indices[f.index_a + f.next])];
|
||||
const auto& member_b = members_b[f.base_b + (f.index_b == npos ? f.next : indices[f.index_b + f.next])];
|
||||
const auto& member_a = members_a[f.base_a + (f.index_a == document_order ? f.next : indices[f.index_a + f.next])];
|
||||
const auto& member_b = members_b[f.base_b + (f.index_b == document_order ? f.next : indices[f.index_b + f.next])];
|
||||
if (!(member_a.first == member_b.first))
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -282,9 +282,9 @@ inline const unsigned char* digit_run(const unsigned char* p, const unsigned cha
|
||||
/// whether the n bytes at p are ASCII digits (n > 0)
|
||||
inline bool all_digits(const unsigned char* p, std::size_t n) noexcept
|
||||
{
|
||||
constexpr std::uint64_t ones = 0x0101010101010101ull;
|
||||
const auto digits = [](const unsigned char* q)
|
||||
{
|
||||
constexpr std::uint64_t ones = 0x0101010101010101ull;
|
||||
const std::uint64_t x = read_eight_bytes(q) ^ (ones * 0x30u);
|
||||
return (((x + (ones * 0x76u)) | x) & (ones * 0x80u)) == 0;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user