[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v4 02/13] qapi: qobject_compare() helper
From: |
Eduardo Habkost |
Subject: |
[Qemu-devel] [RFC v4 02/13] qapi: qobject_compare() helper |
Date: |
Mon, 14 Aug 2017 18:57:37 -0300 |
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 <address@hidden>
---
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
- [Qemu-devel] [RFC v4 00/13] qmp: query-device-slots command, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 01/13] qmp: Define query-device-slots command, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 02/13] qapi: qobject_compare() helper,
Eduardo Habkost <=
- [Qemu-devel] [RFC v4 03/13] qdev: Add BusClass::device_type field, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 04/13] qdev: Slot info helpers, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 05/13] query-device-slots: Collapse similar entries, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 06/13] qdev core: generic enumerate_slots implementation, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 07/13] qdev: Enumerate CPU slots on query-device-slots, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 09/13] pci: pci_bus_has_pcie_upstream_port() function, Eduardo Habkost, 2017/08/14
- [Qemu-devel] [RFC v4 08/13] ide: enumerate_slots implementation, Eduardo Habkost, 2017/08/14