]> git.proxmox.com Git - mirror_qemu.git/commitdiff
qapi: Add qobject_is_equal()
authorMax Reitz <mreitz@redhat.com>
Tue, 14 Nov 2017 18:01:25 +0000 (19:01 +0100)
committerMax Reitz <mreitz@redhat.com>
Fri, 17 Nov 2017 17:21:30 +0000 (18:21 +0100)
This generic function (along with its implementations for different
types) determines whether two QObjects are equal.

Signed-off-by: Max Reitz <mreitz@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Alberto Garcia <berto@igalia.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Message-id: 20171114180128.17076-4-mreitz@redhat.com
Signed-off-by: Max Reitz <mreitz@redhat.com>
14 files changed:
include/qapi/qmp/qbool.h
include/qapi/qmp/qdict.h
include/qapi/qmp/qlist.h
include/qapi/qmp/qnull.h
include/qapi/qmp/qnum.h
include/qapi/qmp/qobject.h
include/qapi/qmp/qstring.h
qobject/qbool.c
qobject/qdict.c
qobject/qlist.c
qobject/qnull.c
qobject/qnum.c
qobject/qobject.c
qobject/qstring.c

index a41111c3096f1df01eb6f0651c480ded2ab94aa1..f77ea86c4ecabbdb4cb976155a17d0fc20321a00 100644 (file)
@@ -24,6 +24,7 @@ typedef struct QBool {
 QBool *qbool_from_bool(bool value);
 bool qbool_get_bool(const QBool *qb);
 QBool *qobject_to_qbool(const QObject *obj);
+bool qbool_is_equal(const QObject *x, const QObject *y);
 void qbool_destroy_obj(QObject *obj);
 
 #endif /* QBOOL_H */
index 7ea5120c4a506c17f6782f8a8212233f09c1931c..fc218e7be61080edcd035502534db084a0761f49 100644 (file)
@@ -43,6 +43,7 @@ void qdict_del(QDict *qdict, const char *key);
 int qdict_haskey(const QDict *qdict, const char *key);
 QObject *qdict_get(const QDict *qdict, const char *key);
 QDict *qobject_to_qdict(const QObject *obj);
+bool qdict_is_equal(const QObject *x, const QObject *y);
 void qdict_iter(const QDict *qdict,
                 void (*iter)(const char *key, QObject *obj, void *opaque),
                 void *opaque);
index 59d209bbaea04a5060c2db28d790936a10e4fd5d..ec3fcc1a4c9f787072a0eab1944be39b40faa0f7 100644 (file)
@@ -61,6 +61,7 @@ QObject *qlist_peek(QList *qlist);
 int qlist_empty(const QList *qlist);
 size_t qlist_size(const QList *qlist);
 QList *qobject_to_qlist(const QObject *obj);
+bool qlist_is_equal(const QObject *x, const QObject *y);
 void qlist_destroy_obj(QObject *obj);
 
 static inline const QListEntry *qlist_first(const QList *qlist)
index d0755492834a931c01572220d7b307d56d6b5883..c992ee2ae1815011cafb8e630d15b0ca3ad35dac 100644 (file)
@@ -27,4 +27,6 @@ static inline QNull *qnull(void)
     return &qnull_;
 }
 
+bool qnull_is_equal(const QObject *x, const QObject *y);
+
 #endif /* QNULL_H */
index d6b07911398dbb6773c789aedc6a3a6d8209dc80..c3d86794bbb7fc79eb0cb2c4a7e69f773aae25a3 100644 (file)
@@ -69,6 +69,7 @@ double qnum_get_double(QNum *qn);
 char *qnum_to_string(QNum *qn);
 
 QNum *qobject_to_qnum(const QObject *obj);
+bool qnum_is_equal(const QObject *x, const QObject *y);
 void qnum_destroy_obj(QObject *obj);
 
 #endif /* QNUM_H */
index ef1d1a92374df78c017ad6e43e4211d2c1b20fdd..38ac68845cc9ebd8bbc7ef7f6138af083bb5a346 100644 (file)
@@ -67,6 +67,15 @@ static inline void qobject_incref(QObject *obj)
         obj->refcnt++;
 }
 
+/**
+ * qobject_is_equal(): Return whether the two objects are equal.
+ *
+ * Any of the pointers may be NULL; return true if both are.  Always
+ * return false if only one is (therefore a QNull object is not
+ * considered equal to a NULL pointer).
+ */
+bool qobject_is_equal(const QObject *x, const QObject *y);
+
 /**
  * qobject_destroy(): Free resources used by the object
  */
index 10076b7c8cd4df87ff58a1963e20ca7484ca3a2f..65c05a9be57809df6204d2ad1fd3ddf329d58d42 100644 (file)
@@ -31,6 +31,7 @@ void qstring_append_int(QString *qstring, int64_t value);
 void qstring_append(QString *qstring, const char *str);
 void qstring_append_chr(QString *qstring, int c);
 QString *qobject_to_qstring(const QObject *obj);
+bool qstring_is_equal(const QObject *x, const QObject *y);
 void qstring_destroy_obj(QObject *obj);
 
 #endif /* QSTRING_H */
index 0606bbd2a337e4b202669e02c7d0967b9d3f4f50..ac825fc5a2e65cffa19bdb7a9f525a21e4626d2c 100644 (file)
@@ -51,6 +51,14 @@ QBool *qobject_to_qbool(const QObject *obj)
     return container_of(obj, QBool, base);
 }
 
+/**
+ * qbool_is_equal(): Test whether the two QBools are equal
+ */
+bool qbool_is_equal(const QObject *x, const QObject *y)
+{
+    return qobject_to_qbool(x)->value == qobject_to_qbool(y)->value;
+}
+
 /**
  * qbool_destroy_obj(): Free all memory allocated by a
  * QBool object
index 576018e5314e74b184210c0d018baa2a8af9db12..e8f15f113244293e3a37c2530883c920865e8a45 100644 (file)
@@ -402,6 +402,35 @@ void qdict_del(QDict *qdict, const char *key)
     }
 }
 
+/**
+ * qdict_is_equal(): Test whether the two QDicts are equal
+ *
+ * Here, equality means whether they contain the same keys and whether
+ * the respective values are in turn equal (i.e. invoking
+ * qobject_is_equal() on them yields true).
+ */
+bool qdict_is_equal(const QObject *x, const QObject *y)
+{
+    const QDict *dict_x = qobject_to_qdict(x);
+    const QDict *dict_y = qobject_to_qdict(y);
+    const QDictEntry *e;
+
+    if (qdict_size(dict_x) != qdict_size(dict_y)) {
+        return false;
+    }
+
+    for (e = qdict_first(dict_x); e; e = qdict_next(dict_x, e)) {
+        const QObject *obj_x = qdict_entry_value(e);
+        const QObject *obj_y = qdict_get(dict_y, qdict_entry_key(e));
+
+        if (!qobject_is_equal(obj_x, obj_y)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 /**
  * qdict_destroy_obj(): Free all the memory allocated by a QDict
  */
index 86b60cb88ccbeff25d95b29d1c73c92ba9970985..3ef57d31d14ff844861f1d38a046965381d02dba 100644 (file)
@@ -139,6 +139,38 @@ QList *qobject_to_qlist(const QObject *obj)
     return container_of(obj, QList, base);
 }
 
+/**
+ * qlist_is_equal(): Test whether the two QLists are equal
+ *
+ * In order to be considered equal, the respective two objects at each
+ * index of the two lists have to compare equal (regarding
+ * qobject_is_equal()), and both lists have to have the same number of
+ * elements.
+ * That means both lists have to contain equal objects in equal order.
+ */
+bool qlist_is_equal(const QObject *x, const QObject *y)
+{
+    const QList *list_x = qobject_to_qlist(x);
+    const QList *list_y = qobject_to_qlist(y);
+    const QListEntry *entry_x, *entry_y;
+
+    entry_x = qlist_first(list_x);
+    entry_y = qlist_first(list_y);
+
+    while (entry_x && entry_y) {
+        if (!qobject_is_equal(qlist_entry_obj(entry_x),
+                              qlist_entry_obj(entry_y)))
+        {
+            return false;
+        }
+
+        entry_x = qlist_next(entry_x);
+        entry_y = qlist_next(entry_y);
+    }
+
+    return !entry_x && !entry_y;
+}
+
 /**
  * qlist_destroy_obj(): Free all the memory allocated by a QList
  */
index bc9fd3162616a65df79489e0cf393967a1f5e3c1..f6f55f11ea0b6f5aeed88b2d4aa35bd779123f2e 100644 (file)
@@ -20,3 +20,12 @@ QNull qnull_ = {
         .refcnt = 1,
     },
 };
+
+/**
+ * qnull_is_equal(): Always return true because any two QNull objects
+ * are equal.
+ */
+bool qnull_is_equal(const QObject *x, const QObject *y)
+{
+    return true;
+}
index 476e81c93b37f35c3ac131ba5c5396357826fc7e..410686a611ad6a8cf4903cd103ea193cd2eaf8bc 100644 (file)
@@ -212,6 +212,60 @@ QNum *qobject_to_qnum(const QObject *obj)
     return container_of(obj, QNum, base);
 }
 
+/**
+ * qnum_is_equal(): Test whether the two QNums are equal
+ *
+ * Negative integers are never considered equal to unsigned integers,
+ * but positive integers in the range [0, INT64_MAX] are considered
+ * equal independently of whether the QNum's kind is i64 or u64.
+ *
+ * Doubles are never considered equal to integers.
+ */
+bool qnum_is_equal(const QObject *x, const QObject *y)
+{
+    QNum *num_x = qobject_to_qnum(x);
+    QNum *num_y = qobject_to_qnum(y);
+
+    switch (num_x->kind) {
+    case QNUM_I64:
+        switch (num_y->kind) {
+        case QNUM_I64:
+            /* Comparison in native int64_t type */
+            return num_x->u.i64 == num_y->u.i64;
+        case QNUM_U64:
+            /* Implicit conversion of x to uin64_t, so we have to
+             * check its sign before */
+            return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64;
+        case QNUM_DOUBLE:
+            return false;
+        }
+        abort();
+    case QNUM_U64:
+        switch (num_y->kind) {
+        case QNUM_I64:
+            return qnum_is_equal(y, x);
+        case QNUM_U64:
+            /* Comparison in native uint64_t type */
+            return num_x->u.u64 == num_y->u.u64;
+        case QNUM_DOUBLE:
+            return false;
+        }
+        abort();
+    case QNUM_DOUBLE:
+        switch (num_y->kind) {
+        case QNUM_I64:
+        case QNUM_U64:
+            return false;
+        case QNUM_DOUBLE:
+            /* Comparison in native double type */
+            return num_x->u.dbl == num_y->u.dbl;
+        }
+        abort();
+    }
+
+    abort();
+}
+
 /**
  * qnum_destroy_obj(): Free all memory allocated by a
  * QNum object
index b0cafb66f1bf59e4ec2c96c5180204883ea38d42..b2a536041ddaf496e843b5bd56de0bd84f82b393 100644 (file)
@@ -27,3 +27,32 @@ void qobject_destroy(QObject *obj)
     assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX);
     qdestroy[obj->type](obj);
 }
+
+
+static bool (*qis_equal[QTYPE__MAX])(const QObject *, const QObject *) = {
+    [QTYPE_NONE] = NULL,               /* No such object exists */
+    [QTYPE_QNULL] = qnull_is_equal,
+    [QTYPE_QNUM] = qnum_is_equal,
+    [QTYPE_QSTRING] = qstring_is_equal,
+    [QTYPE_QDICT] = qdict_is_equal,
+    [QTYPE_QLIST] = qlist_is_equal,
+    [QTYPE_QBOOL] = qbool_is_equal,
+};
+
+bool qobject_is_equal(const QObject *x, const QObject *y)
+{
+    /* We cannot test x == y because an object does not need to be
+     * equal to itself (e.g. NaN floats are not). */
+
+    if (!x && !y) {
+        return true;
+    }
+
+    if (!x || !y || x->type != y->type) {
+        return false;
+    }
+
+    assert(QTYPE_NONE < x->type && x->type < QTYPE__MAX);
+
+    return qis_equal[x->type](x, y);
+}
index 5da7b5f37c3a1ef4ed077f0adc641a1090019724..74182a1c029a9fa8747366ec069fc76497392df2 100644 (file)
@@ -128,6 +128,15 @@ const char *qstring_get_str(const QString *qstring)
     return qstring->string;
 }
 
+/**
+ * qstring_is_equal(): Test whether the two QStrings are equal
+ */
+bool qstring_is_equal(const QObject *x, const QObject *y)
+{
+    return !strcmp(qobject_to_qstring(x)->string,
+                   qobject_to_qstring(y)->string);
+}
+
 /**
  * qstring_destroy_obj(): Free all memory allocated by a QString
  * object