mirror of
https://github.com/nlohmann/json.git
synced 2026-11-12 07:00:46 +00:00
Do not compare an edited NaN equal to itself in json_view (#6085)
Two views compared equal when the tokens of two floats were equal, and the same node was equal to itself. An edit writes a NaN as the token "nan", so a view of it (or of an array holding it) was equal to itself and to another NaN, while json(NaN) == json(NaN) and view == json are false. The token shortcut now excludes the edited "nan" token (found by the missing digit layout), dispatched on the document mode by a tag: a read-only document cannot hold a NaN, and its walk is unchanged (instruction count and cycles on canada, citm and twitter within noise). For editable documents the check costs about 2 % instructions on canada (cycles within noise). The same-node shortcut is kept for read-only documents and for editable ones that were never edited; a document with edits is walked, so comparing it with itself is linear instead of constant. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
9d35fe6d21
commit
02d57db31e
4 files changed
+87
-9
No files matched your search
@@ -206,6 +206,44 @@ TEST_CASE("json_view edits: views and values")
|
||||
CHECK(d.root().materialize().dump() == json::parse(R"([1.5, 100.0, 0.1, null, null, 18446744073709551615, -9223372036854775808])").dump());
|
||||
}
|
||||
|
||||
SECTION("a NaN written by an edit is not equal to itself")
|
||||
{
|
||||
// as for basic_json: NaN != NaN, so a view of it, of the array that holds it, and the same view twice agree
|
||||
json_editable_document d = json_editable_document::parse("[0, 0, 1.5]");
|
||||
d.set(d.root(), 0, std::numeric_limits<double>::quiet_NaN());
|
||||
d.set(d.root(), 1, std::numeric_limits<double>::quiet_NaN());
|
||||
json_editable_document other = json_editable_document::parse("[0, 0, 1.5]");
|
||||
other.set(other.root(), 0, std::numeric_limits<double>::quiet_NaN());
|
||||
other.set(other.root(), 1, std::numeric_limits<double>::quiet_NaN());
|
||||
const json value = d.root().materialize();
|
||||
|
||||
CHECK_FALSE(value == value);
|
||||
CHECK_FALSE(d.root()[0] == d.root()[0]);
|
||||
CHECK_FALSE(d.root()[0] == d.root()[1]);
|
||||
CHECK_FALSE(d.root() == d.root());
|
||||
CHECK_FALSE(d.root() == other.root());
|
||||
CHECK_FALSE(d.root()[0] == other.root()[0]);
|
||||
CHECK(d.root() != d.root());
|
||||
CHECK(d.root()[0] != d.root()[0]);
|
||||
CHECK_FALSE(d.root() == value);
|
||||
CHECK_FALSE(d.root()[0] == value[0]);
|
||||
// the other elements are equal as before
|
||||
CHECK(d.root()[2] == d.root()[2]);
|
||||
CHECK(d.root()[2] == other.root()[2]);
|
||||
// finite and infinite floats written by an edit stay equal to themselves
|
||||
d.set(d.root(), 0, 0.1);
|
||||
d.set(d.root(), 1, std::numeric_limits<double>::infinity());
|
||||
other.set(other.root(), 0, 0.1);
|
||||
other.set(other.root(), 1, std::numeric_limits<double>::infinity());
|
||||
CHECK(d.root() == d.root());
|
||||
CHECK(d.root() == other.root());
|
||||
CHECK(d.root()[1] == other.root()[1]);
|
||||
// a document that was never edited
|
||||
const json_editable_document untouched = json_editable_document::parse("[0.5, [1, 2]]");
|
||||
CHECK(untouched.root() == untouched.root());
|
||||
CHECK(untouched.root()[1] == untouched.root()[1]);
|
||||
}
|
||||
|
||||
SECTION("numbers of other float types")
|
||||
{
|
||||
// doubles have their own path to the output; other float types are
|
||||
|
||||
Reference in new issue
Block a user