* See the COPYING.LIB file in the top-level directory.
*/
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qfloat.h"
+#include "qemu/osdep.h"
+#include "qapi/qmp/qnum.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qnull.h"
#include "qapi/qmp/qstring.h"
-#include "qapi/qmp/qobject.h"
-#include "qemu/queue.h"
-#include "qemu-common.h"
-
-static void qdict_destroy_obj(QObject *obj);
-
-static const QType qdict_type = {
- .code = QTYPE_QDICT,
- .destroy = qdict_destroy_obj,
-};
/**
* qdict_new(): Create a new QDict
QDict *qdict;
qdict = g_malloc0(sizeof(*qdict));
- QOBJECT_INIT(qdict, &qdict_type);
+ qobject_init(QOBJECT(qdict), QTYPE_QDICT);
return qdict;
}
-/**
- * qobject_to_qdict(): Convert a QObject into a QDict
- */
-QDict *qobject_to_qdict(const QObject *obj)
-{
- if (qobject_type(obj) != QTYPE_QDICT)
- return NULL;
-
- return container_of(obj, QDict, base);
-}
-
/**
* tdb_hash(): based on the hash agorithm from gdbm, via tdb
* (from module-init-tools)
entry = qdict_find(qdict, key, bucket);
if (entry) {
/* replace key's value */
- qobject_decref(entry->value);
+ qobject_unref(entry->value);
entry->value = value;
} else {
/* allocate a new entry */
}
}
+void qdict_put_int(QDict *qdict, const char *key, int64_t value)
+{
+ qdict_put(qdict, key, qnum_from_int(value));
+}
+
+void qdict_put_bool(QDict *qdict, const char *key, bool value)
+{
+ qdict_put(qdict, key, qbool_from_bool(value));
+}
+
+void qdict_put_str(QDict *qdict, const char *key, const char *value)
+{
+ qdict_put(qdict, key, qstring_from_str(value));
+}
+
+void qdict_put_null(QDict *qdict, const char *key)
+{
+ qdict_put(qdict, key, qnull());
+}
+
/**
* qdict_get(): Lookup for a given 'key'
*
return qdict->size;
}
-/**
- * qdict_get_obj(): Get a QObject of a specific type
- */
-static QObject *qdict_get_obj(const QDict *qdict, const char *key,
- qtype_code type)
-{
- QObject *obj;
-
- obj = qdict_get(qdict, key);
- assert(obj != NULL);
- assert(qobject_type(obj) == type);
-
- return obj;
-}
-
/**
* qdict_get_double(): Get an number mapped by 'key'
*
- * This function assumes that 'key' exists and it stores a
- * QFloat or QInt object.
+ * This function assumes that 'key' exists and it stores a QNum.
*
* Return number mapped by 'key'.
*/
double qdict_get_double(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get(qdict, key);
-
- assert(obj);
- switch (qobject_type(obj)) {
- case QTYPE_QFLOAT:
- return qfloat_get_double(qobject_to_qfloat(obj));
- case QTYPE_QINT:
- return qint_get_int(qobject_to_qint(obj));
- default:
- abort();
- }
+ return qnum_get_double(qobject_to(QNum, qdict_get(qdict, key)));
}
/**
* qdict_get_int(): Get an integer mapped by 'key'
*
* This function assumes that 'key' exists and it stores a
- * QInt object.
+ * QNum representable as int.
*
* Return integer mapped by 'key'.
*/
int64_t qdict_get_int(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get_obj(qdict, key, QTYPE_QINT);
- return qint_get_int(qobject_to_qint(obj));
+ return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key)));
}
/**
*
* Return bool mapped by 'key'.
*/
-int qdict_get_bool(const QDict *qdict, const char *key)
+bool qdict_get_bool(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL);
- return qbool_get_int(qobject_to_qbool(obj));
+ return qbool_get_bool(qobject_to(QBool, qdict_get(qdict, key)));
}
/**
- * qdict_get_qlist(): Get the QList mapped by 'key'
- *
- * This function assumes that 'key' exists and it stores a
- * QList object.
- *
- * Return QList mapped by 'key'.
+ * qdict_get_qlist(): If @qdict maps @key to a QList, return it, else NULL.
*/
QList *qdict_get_qlist(const QDict *qdict, const char *key)
{
- return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST));
+ return qobject_to(QList, qdict_get(qdict, key));
}
/**
- * qdict_get_qdict(): Get the QDict mapped by 'key'
- *
- * This function assumes that 'key' exists and it stores a
- * QDict object.
- *
- * Return QDict mapped by 'key'.
+ * qdict_get_qdict(): If @qdict maps @key to a QDict, return it, else NULL.
*/
QDict *qdict_get_qdict(const QDict *qdict, const char *key)
{
- return qobject_to_qdict(qdict_get_obj(qdict, key, QTYPE_QDICT));
+ return qobject_to(QDict, qdict_get(qdict, key));
}
/**
*/
const char *qdict_get_str(const QDict *qdict, const char *key)
{
- QObject *obj = qdict_get_obj(qdict, key, QTYPE_QSTRING);
- return qstring_get_str(qobject_to_qstring(obj));
+ return qstring_get_str(qobject_to(QString, qdict_get(qdict, key)));
}
/**
* qdict_get_try_int(): Try to get integer mapped by 'key'
*
- * Return integer mapped by 'key', if it is not present in
- * the dictionary or if the stored object is not of QInt type
- * 'def_value' will be returned.
+ * Return integer mapped by 'key', if it is not present in the
+ * dictionary or if the stored object is not a QNum representing an
+ * integer, 'def_value' will be returned.
*/
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
int64_t def_value)
{
- QObject *obj;
+ QNum *qnum = qobject_to(QNum, qdict_get(qdict, key));
+ int64_t val;
- obj = qdict_get(qdict, key);
- if (!obj || qobject_type(obj) != QTYPE_QINT)
+ if (!qnum || !qnum_get_try_int(qnum, &val)) {
return def_value;
+ }
- return qint_get_int(qobject_to_qint(obj));
+ return val;
}
/**
* dictionary or if the stored object is not of QBool type
* 'def_value' will be returned.
*/
-int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value)
+bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
{
- QObject *obj;
-
- obj = qdict_get(qdict, key);
- if (!obj || qobject_type(obj) != QTYPE_QBOOL)
- return def_value;
+ QBool *qbool = qobject_to(QBool, qdict_get(qdict, key));
- return qbool_get_int(qobject_to_qbool(obj));
+ return qbool ? qbool_get_bool(qbool) : def_value;
}
/**
*/
const char *qdict_get_try_str(const QDict *qdict, const char *key)
{
- QObject *obj;
-
- obj = qdict_get(qdict, key);
- if (!obj || qobject_type(obj) != QTYPE_QSTRING)
- return NULL;
+ QString *qstr = qobject_to(QString, qdict_get(qdict, key));
- return qstring_get_str(qobject_to_qstring(obj));
+ return qstr ? qstring_get_str(qstr) : NULL;
}
/**
for (i = 0; i < QDICT_BUCKET_MAX; i++) {
QLIST_FOREACH(entry, &src->table[i], next) {
- qobject_incref(entry->value);
- qdict_put_obj(dest, entry->key, entry->value);
+ qdict_put_obj(dest, entry->key, qobject_ref(entry->value));
}
}
assert(e->key != NULL);
assert(e->value != NULL);
- qobject_decref(e->value);
+ qobject_unref(e->value);
g_free(e->key);
g_free(e);
}
}
/**
- * qdict_destroy_obj(): Free all the memory allocated by a QDict
+ * 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).
*/
-static void qdict_destroy_obj(QObject *obj)
+bool qdict_is_equal(const QObject *x, const QObject *y)
{
- int i;
- QDict *qdict;
+ const QDict *dict_x = qobject_to(QDict, x);
+ const QDict *dict_y = qobject_to(QDict, y);
+ const QDictEntry *e;
- assert(obj != NULL);
- qdict = qobject_to_qdict(obj);
-
- for (i = 0; i < QDICT_BUCKET_MAX; i++) {
- QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
- while (entry) {
- QDictEntry *tmp = QLIST_NEXT(entry, next);
- QLIST_REMOVE(entry, next);
- qentry_destroy(entry);
- entry = tmp;
- }
+ if (qdict_size(dict_x) != qdict_size(dict_y)) {
+ return false;
}
- g_free(qdict);
-}
-
-static void qdict_flatten_qdict(QDict *qdict, QDict *target,
- const char *prefix);
+ 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));
-static void qdict_flatten_qlist(QList *qlist, QDict *target, const char *prefix)
-{
- QObject *value;
- const QListEntry *entry;
- char *new_key;
- int i;
-
- /* This function is never called with prefix == NULL, i.e., it is always
- * called from within qdict_flatten_q(list|dict)(). Therefore, it does not
- * need to remove list entries during the iteration (the whole list will be
- * deleted eventually anyway from qdict_flatten_qdict()). */
- assert(prefix);
-
- entry = qlist_first(qlist);
-
- for (i = 0; entry; entry = qlist_next(entry), i++) {
- value = qlist_entry_obj(entry);
- new_key = g_strdup_printf("%s.%i", prefix, i);
-
- if (qobject_type(value) == QTYPE_QDICT) {
- qdict_flatten_qdict(qobject_to_qdict(value), target, new_key);
- } else if (qobject_type(value) == QTYPE_QLIST) {
- qdict_flatten_qlist(qobject_to_qlist(value), target, new_key);
- } else {
- /* All other types are moved to the target unchanged. */
- qobject_incref(value);
- qdict_put_obj(target, new_key, value);
+ if (!qobject_is_equal(obj_x, obj_y)) {
+ return false;
}
-
- g_free(new_key);
}
-}
-
-static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix)
-{
- QObject *value;
- const QDictEntry *entry, *next;
- char *new_key;
- bool delete;
- entry = qdict_first(qdict);
-
- while (entry != NULL) {
-
- next = qdict_next(qdict, entry);
- value = qdict_entry_value(entry);
- new_key = NULL;
- delete = false;
-
- if (prefix) {
- new_key = g_strdup_printf("%s.%s", prefix, entry->key);
- }
-
- if (qobject_type(value) == QTYPE_QDICT) {
- /* Entries of QDicts are processed recursively, the QDict object
- * itself disappears. */
- qdict_flatten_qdict(qobject_to_qdict(value), target,
- new_key ? new_key : entry->key);
- delete = true;
- } else if (qobject_type(value) == QTYPE_QLIST) {
- qdict_flatten_qlist(qobject_to_qlist(value), target,
- new_key ? new_key : entry->key);
- delete = true;
- } else if (prefix) {
- /* All other objects are moved to the target unchanged. */
- qobject_incref(value);
- qdict_put_obj(target, new_key, value);
- delete = true;
- }
-
- g_free(new_key);
-
- if (delete) {
- qdict_del(qdict, entry->key);
-
- /* Restart loop after modifying the iterated QDict */
- entry = qdict_first(qdict);
- continue;
- }
-
- entry = next;
- }
+ return true;
}
/**
- * qdict_flatten(): For each nested QDict with key x, all fields with key y
- * are moved to this QDict and their key is renamed to "x.y". For each nested
- * QList with key x, the field at index y is moved to this QDict with the key
- * "x.y" (i.e., the reverse of what qdict_array_split() does).
- * This operation is applied recursively for nested QDicts and QLists.
+ * qdict_destroy_obj(): Free all the memory allocated by a QDict
*/
-void qdict_flatten(QDict *qdict)
+void qdict_destroy_obj(QObject *obj)
{
- qdict_flatten_qdict(qdict, qdict, NULL);
-}
-
-/* extract all the src QDict entries starting by start into dst */
-void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
-
-{
- const QDictEntry *entry, *next;
- const char *p;
+ int i;
+ QDict *qdict;
- *dst = qdict_new();
- entry = qdict_first(src);
+ assert(obj != NULL);
+ qdict = qobject_to(QDict, obj);
- while (entry != NULL) {
- next = qdict_next(src, entry);
- if (strstart(entry->key, start, &p)) {
- qobject_incref(entry->value);
- qdict_put_obj(*dst, p, entry->value);
- qdict_del(src, entry->key);
+ for (i = 0; i < QDICT_BUCKET_MAX; i++) {
+ QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
+ while (entry) {
+ QDictEntry *tmp = QLIST_NEXT(entry, next);
+ QLIST_REMOVE(entry, next);
+ qentry_destroy(entry);
+ entry = tmp;
}
- entry = next;
}
-}
-
-/**
- * qdict_array_split(): This function moves array-like elements of a QDict into
- * a new QList of QDicts. Every entry in the original QDict with a key prefixed
- * "%u.", where %u designates an unsigned integer starting at 0 and
- * incrementally counting up, will be moved to a new QDict at index %u in the
- * output QList with the key prefix removed. The function terminates when there
- * is no entry in the QDict with a prefix directly (incrementally) following the
- * last one.
- * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "3.y": 1, "o.o": 7}
- * (or {"1.x": 0, "3.y": 1, "0.a": 42, "o.o": 7, "0.b": 23})
- * => [{"a": 42, "b": 23}, {"x": 0}]
- * and {"3.y": 1, "o.o": 7} (remainder of the old QDict)
- */
-void qdict_array_split(QDict *src, QList **dst)
-{
- unsigned i;
-
- *dst = qlist_new();
- for (i = 0; i < UINT_MAX; i++) {
- QDict *subqdict;
- char prefix[32];
- size_t snprintf_ret;
-
- snprintf_ret = snprintf(prefix, 32, "%u.", i);
- assert(snprintf_ret < 32);
-
- qdict_extract_subqdict(src, &subqdict, prefix);
- if (!qdict_size(subqdict)) {
- QDECREF(subqdict);
- break;
- }
-
- qlist_append_obj(*dst, QOBJECT(subqdict));
- }
+ g_free(qdict);
}