All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Habkost <ehabkost@redhat.com>
To: Eric Blake <eblake@redhat.com>,
	qemu-devel@nongnu.org, Markus Armbruster <armbru@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	Marcel Apfelbaum <marcel@redhat.com>,
	Laine Stump <laine@redhat.com>
Subject: [Qemu-devel] [RFC v4 02/13] qapi: qobject_compare() helper
Date: Mon, 14 Aug 2017 18:57:37 -0300	[thread overview]
Message-ID: <20170814215748.5158-3-ehabkost@redhat.com> (raw)
In-Reply-To: <20170814215748.5158-1-ehabkost@redhat.com>

The helper function will be useful when writing support code to
deal with device slot information.

TODO: documentation is incomplete and unclear, needs to be
improved.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 include/qapi/util.h    | 39 +++++++++++++++++++++++++++++
 qapi/qapi-util.c       | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-qapi-util.c | 53 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 158 insertions(+)

diff --git a/include/qapi/util.h b/include/qapi/util.h
index 7436ed8..d4562c4 100644
--- a/include/qapi/util.h
+++ b/include/qapi/util.h
@@ -11,9 +11,48 @@
 #ifndef QAPI_UTIL_H
 #define QAPI_UTIL_H
 
+#include "qapi/qmp/qobject.h"
+#include "qapi-types.h"
+
 int qapi_enum_parse(const char * const lookup[], const char *buf,
                     int max, int def, Error **errp);
 
 int parse_qapi_name(const char *name, bool complete);
 
+/**
+ * qobject_compare:
+ *
+ * Compare the value of @a and @b.
+ *
+ * If @a and @b have the same type and the same value (see list
+ * of supported types below), return 0.
+ *
+ * If @a and @b are both strings, return strcmp(a, b).
+ *
+ * If @a and @b are numbers, return a negative value if a < b,
+ * and a positive value if a > b.
+ *
+ * Otherwise (if @a and @b are not the same, have different types,
+ * are of an unsupported type, or are different), return a non-zero value.
+ *
+ * Note that this function doesn't support some types, and may
+ * return false if the types are unsupported, or if the types don't
+ * match exactly.
+ *
+ * Supported types:
+ * - QTYPE_QNULL
+ * - QTYPE_QSTRING
+ * - QTYPE_QBOOL
+ * - QTYPE_QNUM (integers only)
+ * - QTYPE_QLIST
+ *
+ * Unsupported (always return false):
+ * - QTYPE_QNUM (non-integer values)
+ * - QTYPE_QDICT
+ *
+ * TODO: rewrite documentation to be clearer.
+ * TODO: support non-integer QTYPE_NUM values and QTYPE_QDICT.
+ */
+int qobject_compare(QObject *a, QObject *b);
+
 #endif
diff --git a/qapi/qapi-util.c b/qapi/qapi-util.c
index 46eda7d..67c5e82 100644
--- a/qapi/qapi-util.c
+++ b/qapi/qapi-util.c
@@ -13,6 +13,9 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qbool.h"
 #include "qapi/util.h"
 
 int qapi_enum_parse(const char * const lookup[], const char *buf,
@@ -80,3 +83,66 @@ int parse_qapi_name(const char *str, bool complete)
     }
     return p - str;
 }
+
+static int qnum_compare(QNum *a, QNum *b)
+{
+    int64_t ia, ib;
+    bool va = qnum_get_try_int(a, &ia);
+    bool vb = qnum_get_try_int(b, &ib);
+
+    if (va && vb) {
+        return (ia < ib) ? -1 : (ia > ib) ? 1 : 0;
+    }
+
+    /*TODO: uint, double */
+    return -1;
+}
+
+static int qlist_compare(QList *a, QList *b)
+{
+    const QListEntry *ea, *eb;
+
+    for (ea = qlist_first(a), eb = qlist_first(b);
+         ea && eb;
+         ea = qlist_next(ea), eb = qlist_next(eb)) {
+        QObject *va = qlist_entry_obj(ea);
+        QObject *vb = qlist_entry_obj(eb);
+        int c = qobject_compare(va, vb);
+        if (c) {
+            return c;
+        }
+    }
+
+    if (eb) {
+        return -1;
+    } else if (ea) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+int qobject_compare(QObject *a, QObject *b)
+{
+    QType ta = qobject_type(a);
+    QType tb = qobject_type(b);
+
+    if (ta != tb) {
+        return -1;
+    }
+
+    switch (ta) {
+    case QTYPE_QNULL:
+        return true;
+    case QTYPE_QNUM:
+        return qnum_compare(qobject_to_qnum(a), qobject_to_qnum(b));
+    case QTYPE_QSTRING:
+        return strcmp(qstring_get_str(qobject_to_qstring(a)), qstring_get_str(qobject_to_qstring(b)));
+    case QTYPE_QBOOL:
+        return (int)qbool_get_bool(qobject_to_qbool(a)) - (int)qbool_get_bool(qobject_to_qbool(b));
+    case QTYPE_QLIST:
+        return qlist_compare(qobject_to_qlist(a), qobject_to_qlist(b));
+    default:
+        return -1;
+    }
+}
diff --git a/tests/test-qapi-util.c b/tests/test-qapi-util.c
index e869757..c0cf46c 100644
--- a/tests/test-qapi-util.c
+++ b/tests/test-qapi-util.c
@@ -13,6 +13,10 @@
 #include "qemu/osdep.h"
 #include "qapi/error.h"
 #include "qapi/util.h"
+#include "qapi/qmp/qnum.h"
+#include "qapi/qmp/qstring.h"
+#include "qapi/qmp/qlist.h"
+#include "qapi/qmp/qjson.h"
 #include "test-qapi-types.h"
 
 static void test_qapi_enum_parse(void)
@@ -75,11 +79,60 @@ static void test_parse_qapi_name(void)
     g_assert(ret == -1);
 }
 
+static void test_qobject_compare(void)
+{
+    QString *a1 = qstring_from_str("abc");
+    QString *a2 = qstring_from_str("abc");
+    QString *b = qstring_from_str("bcd");
+    QNum *i1 = qnum_from_int(100);
+    QNum *i2 = qnum_from_int(100);
+    QNum *j = qnum_from_int(200);
+    QList *l1 = qlist_new();
+    QList *l2 = qlist_new();
+    QList *m = qlist_new();
+
+    qlist_append_int(l1, 100);
+    qlist_append_int(l1, 200);
+    qlist_append_int(l2, 100);
+    qlist_append_int(l2, 200);
+
+    qlist_append_int(m, 100);
+    qlist_append_int(m, 300);
+
+    g_assert_cmpint(qobject_compare(QOBJECT(a1), QOBJECT(a2)), ==, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(i1), QOBJECT(i2)), ==, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(l1), QOBJECT(l2)), ==, 0);
+
+    g_assert_cmpint(qobject_compare(QOBJECT(a1), QOBJECT(b)), <, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(b), QOBJECT(a1)), >, 0);
+
+    g_assert_cmpint(qobject_compare(QOBJECT(i1), QOBJECT(j)), <, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(j), QOBJECT(i1)), >, 0);
+
+    g_assert_cmpint(qobject_compare(QOBJECT(l1), QOBJECT(m)), <, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(m), QOBJECT(l1)), >, 0);
+
+    g_assert_cmpint(qobject_compare(QOBJECT(a1), QOBJECT(i1)), !=, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(a1), QOBJECT(l1)), !=, 0);
+    g_assert_cmpint(qobject_compare(QOBJECT(l1), QOBJECT(i1)), !=, 0);
+
+    QDECREF(a1);
+    QDECREF(a2);
+    QDECREF(b);
+    QDECREF(i1);
+    QDECREF(i2);
+    QDECREF(j);
+    QDECREF(l1);
+    QDECREF(l2);
+    QDECREF(m);
+}
+
 int main(int argc, char *argv[])
 {
     g_test_init(&argc, &argv, NULL);
     g_test_add_func("/qapi/util/qapi_enum_parse", test_qapi_enum_parse);
     g_test_add_func("/qapi/util/parse_qapi_name", test_parse_qapi_name);
+    g_test_add_func("/qapi/util/qobject_compare", test_qobject_compare);
     g_test_run();
     return 0;
 }
-- 
2.9.4

  parent reply	other threads:[~2017-08-14 21:58 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-14 21:57 [Qemu-devel] [RFC v4 00/13] qmp: query-device-slots command Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 01/13] qmp: Define " Eduardo Habkost
2017-08-14 21:57 ` Eduardo Habkost [this message]
2017-08-15 16:16   ` [Qemu-devel] [RFC v4 02/13] qapi: qobject_compare() helper Eric Blake
2017-08-15 17:59     ` Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 03/13] qdev: Add BusClass::device_type field Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 04/13] qdev: Slot info helpers Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 05/13] query-device-slots: Collapse similar entries Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 06/13] qdev core: generic enumerate_slots implementation Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 07/13] qdev: Enumerate CPU slots on query-device-slots Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 08/13] ide: enumerate_slots implementation Eduardo Habkost
2017-08-16 21:46   ` John Snow
2017-08-17  4:54     ` Markus Armbruster
2017-08-17 18:40       ` John Snow
2017-08-18 16:57     ` Eduardo Habkost
2017-08-21 21:46       ` John Snow
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 09/13] pci: pci_bus_has_pcie_upstream_port() function Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 10/13] pci: device-number & function properties Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 11/13] pci: enumerate_slots implementation Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 12/13] usb: " Eduardo Habkost
2017-08-21 11:44   ` Gerd Hoffmann
2017-08-23 17:17     ` Eduardo Habkost
2017-08-14 21:57 ` [Qemu-devel] [RFC v4 13/13] tests: Experimental query-device-slots test code Eduardo Habkost
2017-08-14 22:37 ` [Qemu-devel] [libvirt] [RFC v4 00/13] qmp: query-device-slots command no-reply
2017-08-15 18:57 ` [Qemu-devel] " Eric Blake
2017-08-15 19:44   ` Eduardo Habkost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170814215748.5158-3-ehabkost@redhat.com \
    --to=ehabkost@redhat.com \
    --cc=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=laine@redhat.com \
    --cc=marcel@redhat.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.