summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorEmanuel Sprung <emanuel.sprung@gmail.com>2020-03-31 20:44:34 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-01 22:12:19 +0200
commitb995a499d3ba75b0c3efb53abc429f1dfd4da06f (patch)
tree0913ddc284d89242597b3d6552e3320d1566c252 /AK
parentc27e8a258adbe0dd4bf31d06d0e1cdd589bd9d5c (diff)
downloadserenity-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.cpp40
-rw-r--r--AK/JsonValue.h2
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&);