qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

qapi: Add qobject_is_equal()

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>

+186
+1
include/qapi/qmp/qbool.h
··· 24 24 QBool *qbool_from_bool(bool value); 25 25 bool qbool_get_bool(const QBool *qb); 26 26 QBool *qobject_to_qbool(const QObject *obj); 27 + bool qbool_is_equal(const QObject *x, const QObject *y); 27 28 void qbool_destroy_obj(QObject *obj); 28 29 29 30 #endif /* QBOOL_H */
+1
include/qapi/qmp/qdict.h
··· 43 43 int qdict_haskey(const QDict *qdict, const char *key); 44 44 QObject *qdict_get(const QDict *qdict, const char *key); 45 45 QDict *qobject_to_qdict(const QObject *obj); 46 + bool qdict_is_equal(const QObject *x, const QObject *y); 46 47 void qdict_iter(const QDict *qdict, 47 48 void (*iter)(const char *key, QObject *obj, void *opaque), 48 49 void *opaque);
+1
include/qapi/qmp/qlist.h
··· 61 61 int qlist_empty(const QList *qlist); 62 62 size_t qlist_size(const QList *qlist); 63 63 QList *qobject_to_qlist(const QObject *obj); 64 + bool qlist_is_equal(const QObject *x, const QObject *y); 64 65 void qlist_destroy_obj(QObject *obj); 65 66 66 67 static inline const QListEntry *qlist_first(const QList *qlist)
+2
include/qapi/qmp/qnull.h
··· 27 27 return &qnull_; 28 28 } 29 29 30 + bool qnull_is_equal(const QObject *x, const QObject *y); 31 + 30 32 #endif /* QNULL_H */
+1
include/qapi/qmp/qnum.h
··· 69 69 char *qnum_to_string(QNum *qn); 70 70 71 71 QNum *qobject_to_qnum(const QObject *obj); 72 + bool qnum_is_equal(const QObject *x, const QObject *y); 72 73 void qnum_destroy_obj(QObject *obj); 73 74 74 75 #endif /* QNUM_H */
+9
include/qapi/qmp/qobject.h
··· 68 68 } 69 69 70 70 /** 71 + * qobject_is_equal(): Return whether the two objects are equal. 72 + * 73 + * Any of the pointers may be NULL; return true if both are. Always 74 + * return false if only one is (therefore a QNull object is not 75 + * considered equal to a NULL pointer). 76 + */ 77 + bool qobject_is_equal(const QObject *x, const QObject *y); 78 + 79 + /** 71 80 * qobject_destroy(): Free resources used by the object 72 81 */ 73 82 void qobject_destroy(QObject *obj);
+1
include/qapi/qmp/qstring.h
··· 31 31 void qstring_append(QString *qstring, const char *str); 32 32 void qstring_append_chr(QString *qstring, int c); 33 33 QString *qobject_to_qstring(const QObject *obj); 34 + bool qstring_is_equal(const QObject *x, const QObject *y); 34 35 void qstring_destroy_obj(QObject *obj); 35 36 36 37 #endif /* QSTRING_H */
+8
qobject/qbool.c
··· 52 52 } 53 53 54 54 /** 55 + * qbool_is_equal(): Test whether the two QBools are equal 56 + */ 57 + bool qbool_is_equal(const QObject *x, const QObject *y) 58 + { 59 + return qobject_to_qbool(x)->value == qobject_to_qbool(y)->value; 60 + } 61 + 62 + /** 55 63 * qbool_destroy_obj(): Free all memory allocated by a 56 64 * QBool object 57 65 */
+29
qobject/qdict.c
··· 403 403 } 404 404 405 405 /** 406 + * qdict_is_equal(): Test whether the two QDicts are equal 407 + * 408 + * Here, equality means whether they contain the same keys and whether 409 + * the respective values are in turn equal (i.e. invoking 410 + * qobject_is_equal() on them yields true). 411 + */ 412 + bool qdict_is_equal(const QObject *x, const QObject *y) 413 + { 414 + const QDict *dict_x = qobject_to_qdict(x); 415 + const QDict *dict_y = qobject_to_qdict(y); 416 + const QDictEntry *e; 417 + 418 + if (qdict_size(dict_x) != qdict_size(dict_y)) { 419 + return false; 420 + } 421 + 422 + for (e = qdict_first(dict_x); e; e = qdict_next(dict_x, e)) { 423 + const QObject *obj_x = qdict_entry_value(e); 424 + const QObject *obj_y = qdict_get(dict_y, qdict_entry_key(e)); 425 + 426 + if (!qobject_is_equal(obj_x, obj_y)) { 427 + return false; 428 + } 429 + } 430 + 431 + return true; 432 + } 433 + 434 + /** 406 435 * qdict_destroy_obj(): Free all the memory allocated by a QDict 407 436 */ 408 437 void qdict_destroy_obj(QObject *obj)
+32
qobject/qlist.c
··· 140 140 } 141 141 142 142 /** 143 + * qlist_is_equal(): Test whether the two QLists are equal 144 + * 145 + * In order to be considered equal, the respective two objects at each 146 + * index of the two lists have to compare equal (regarding 147 + * qobject_is_equal()), and both lists have to have the same number of 148 + * elements. 149 + * That means both lists have to contain equal objects in equal order. 150 + */ 151 + bool qlist_is_equal(const QObject *x, const QObject *y) 152 + { 153 + const QList *list_x = qobject_to_qlist(x); 154 + const QList *list_y = qobject_to_qlist(y); 155 + const QListEntry *entry_x, *entry_y; 156 + 157 + entry_x = qlist_first(list_x); 158 + entry_y = qlist_first(list_y); 159 + 160 + while (entry_x && entry_y) { 161 + if (!qobject_is_equal(qlist_entry_obj(entry_x), 162 + qlist_entry_obj(entry_y))) 163 + { 164 + return false; 165 + } 166 + 167 + entry_x = qlist_next(entry_x); 168 + entry_y = qlist_next(entry_y); 169 + } 170 + 171 + return !entry_x && !entry_y; 172 + } 173 + 174 + /** 143 175 * qlist_destroy_obj(): Free all the memory allocated by a QList 144 176 */ 145 177 void qlist_destroy_obj(QObject *obj)
+9
qobject/qnull.c
··· 20 20 .refcnt = 1, 21 21 }, 22 22 }; 23 + 24 + /** 25 + * qnull_is_equal(): Always return true because any two QNull objects 26 + * are equal. 27 + */ 28 + bool qnull_is_equal(const QObject *x, const QObject *y) 29 + { 30 + return true; 31 + }
+54
qobject/qnum.c
··· 213 213 } 214 214 215 215 /** 216 + * qnum_is_equal(): Test whether the two QNums are equal 217 + * 218 + * Negative integers are never considered equal to unsigned integers, 219 + * but positive integers in the range [0, INT64_MAX] are considered 220 + * equal independently of whether the QNum's kind is i64 or u64. 221 + * 222 + * Doubles are never considered equal to integers. 223 + */ 224 + bool qnum_is_equal(const QObject *x, const QObject *y) 225 + { 226 + QNum *num_x = qobject_to_qnum(x); 227 + QNum *num_y = qobject_to_qnum(y); 228 + 229 + switch (num_x->kind) { 230 + case QNUM_I64: 231 + switch (num_y->kind) { 232 + case QNUM_I64: 233 + /* Comparison in native int64_t type */ 234 + return num_x->u.i64 == num_y->u.i64; 235 + case QNUM_U64: 236 + /* Implicit conversion of x to uin64_t, so we have to 237 + * check its sign before */ 238 + return num_x->u.i64 >= 0 && num_x->u.i64 == num_y->u.u64; 239 + case QNUM_DOUBLE: 240 + return false; 241 + } 242 + abort(); 243 + case QNUM_U64: 244 + switch (num_y->kind) { 245 + case QNUM_I64: 246 + return qnum_is_equal(y, x); 247 + case QNUM_U64: 248 + /* Comparison in native uint64_t type */ 249 + return num_x->u.u64 == num_y->u.u64; 250 + case QNUM_DOUBLE: 251 + return false; 252 + } 253 + abort(); 254 + case QNUM_DOUBLE: 255 + switch (num_y->kind) { 256 + case QNUM_I64: 257 + case QNUM_U64: 258 + return false; 259 + case QNUM_DOUBLE: 260 + /* Comparison in native double type */ 261 + return num_x->u.dbl == num_y->u.dbl; 262 + } 263 + abort(); 264 + } 265 + 266 + abort(); 267 + } 268 + 269 + /** 216 270 * qnum_destroy_obj(): Free all memory allocated by a 217 271 * QNum object 218 272 */
+29
qobject/qobject.c
··· 27 27 assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX); 28 28 qdestroy[obj->type](obj); 29 29 } 30 + 31 + 32 + static bool (*qis_equal[QTYPE__MAX])(const QObject *, const QObject *) = { 33 + [QTYPE_NONE] = NULL, /* No such object exists */ 34 + [QTYPE_QNULL] = qnull_is_equal, 35 + [QTYPE_QNUM] = qnum_is_equal, 36 + [QTYPE_QSTRING] = qstring_is_equal, 37 + [QTYPE_QDICT] = qdict_is_equal, 38 + [QTYPE_QLIST] = qlist_is_equal, 39 + [QTYPE_QBOOL] = qbool_is_equal, 40 + }; 41 + 42 + bool qobject_is_equal(const QObject *x, const QObject *y) 43 + { 44 + /* We cannot test x == y because an object does not need to be 45 + * equal to itself (e.g. NaN floats are not). */ 46 + 47 + if (!x && !y) { 48 + return true; 49 + } 50 + 51 + if (!x || !y || x->type != y->type) { 52 + return false; 53 + } 54 + 55 + assert(QTYPE_NONE < x->type && x->type < QTYPE__MAX); 56 + 57 + return qis_equal[x->type](x, y); 58 + }
+9
qobject/qstring.c
··· 129 129 } 130 130 131 131 /** 132 + * qstring_is_equal(): Test whether the two QStrings are equal 133 + */ 134 + bool qstring_is_equal(const QObject *x, const QObject *y) 135 + { 136 + return !strcmp(qobject_to_qstring(x)->string, 137 + qobject_to_qstring(y)->string); 138 + } 139 + 140 + /** 132 141 * qstring_destroy_obj(): Free all memory allocated by a QString 133 142 * object 134 143 */