diff options
author | Emanuel Sprung <emanuel.sprung@gmail.com> | 2020-03-31 20:44:34 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-04-01 22:12:19 +0200 |
commit | b995a499d3ba75b0c3efb53abc429f1dfd4da06f (patch) | |
tree | 0913ddc284d89242597b3d6552e3320d1566c252 /AK | |
parent | c27e8a258adbe0dd4bf31d06d0e1cdd589bd9d5c (diff) | |
download | serenity-b995a499d3ba75b0c3efb53abc429f1dfd4da06f.zip |
AK: Add equals method to JsonValue to semantically compare two values.
This patchsets adds the semantic check of two values. One first approach
was to compare the (generated) json strings of the two values. This works
out in the most cases, but not with numbers, where "1.0" and "1" in JSON
format are semantically the same. Therefore, this patch adds deep (recursive)
check of two JsonValues.
Diffstat (limited to 'AK')
-rw-r--r-- | AK/JsonValue.cpp | 40 | ||||
-rw-r--r-- | AK/JsonValue.h | 2 |
2 files changed, 42 insertions, 0 deletions
diff --git a/AK/JsonValue.cpp b/AK/JsonValue.cpp index c78c05c8d9..88b57c9879 100644 --- a/AK/JsonValue.cpp +++ b/AK/JsonValue.cpp @@ -89,6 +89,46 @@ JsonValue& JsonValue::operator=(JsonValue&& other) return *this; } +bool JsonValue::equals(const JsonValue& other) const +{ + if (is_null() && other.is_null()) + return true; + + if (is_bool() && other.is_bool() && as_bool() == other.as_bool()) + return true; + + if (is_string() && other.is_string() && as_string() == other.as_string()) + return true; + +#if !defined(KERNEL) && !defined(BOOTSTRAPPER) + if (is_number() && other.is_number() && to_number<double>() == other.to_number<double>()) { + return true; + } +#else + if (is_number() && other.is_number() && to_number<i64>() == other.to_number<i64>()) { + return true; + } +#endif + + if (is_array() && other.is_array() && as_array().size() == other.as_array().size()) { + bool result = true; + for (int i = 0; i < as_array().size(); ++i) { + result &= as_array().at(i).equals(other.as_array().at(i)); + } + return result; + } + + if (is_object() && other.is_object() && as_object().size() == other.as_object().size()) { + bool result = true; + as_object().for_each_member([&](auto& key, auto& value) { + result &= value.equals(other.as_object().get(key)); + }); + return result; + } + + return false; +} + JsonValue::JsonValue(i32 value) : m_type(Type::Int32) { diff --git a/AK/JsonValue.h b/AK/JsonValue.h index c0780e331c..681f1fdcc6 100644 --- a/AK/JsonValue.h +++ b/AK/JsonValue.h @@ -238,6 +238,8 @@ public: return default_value; } + bool equals(const JsonValue& other) const; + private: void clear(); void copy_from(const JsonValue&); |