*/
#include "qemu/osdep.h"
-#include "qapi/qmp/qint.h"
-#include "qapi/qmp/qfloat.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"
/**
* qdict_new(): Create a new QDict
return qdict;
}
-/**
- * qobject_to_qdict(): Convert a QObject into a QDict
- */
-QDict *qobject_to_qdict(const QObject *obj)
-{
- if (!obj || 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 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)
{
- return qint_get_int(qobject_to_qint(qdict_get(qdict, key)));
+ return qnum_get_int(qobject_to(QNum, qdict_get(qdict, key)));
}
/**
*/
bool qdict_get_bool(const QDict *qdict, const char *key)
{
- return qbool_get_bool(qobject_to_qbool(qdict_get(qdict, key)));
+ 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(qdict, key));
+ return qobject_to(QDict, qdict_get(qdict, key));
}
/**
*/
const char *qdict_get_str(const QDict *qdict, const char *key)
{
- return qstring_get_str(qobject_to_qstring(qdict_get(qdict, key)));
+ 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)
{
- QInt *qint = qobject_to_qint(qdict_get(qdict, key));
+ QNum *qnum = qobject_to(QNum, qdict_get(qdict, key));
+ int64_t val;
- return qint ? qint_get_int(qint) : def_value;
+ if (!qnum || !qnum_get_try_int(qnum, &val)) {
+ return def_value;
+ }
+
+ return val;
}
/**
*/
bool qdict_get_try_bool(const QDict *qdict, const char *key, bool def_value)
{
- QBool *qbool = qobject_to_qbool(qdict_get(qdict, key));
+ QBool *qbool = qobject_to(QBool, qdict_get(qdict, key));
return qbool ? qbool_get_bool(qbool) : def_value;
}
*/
const char *qdict_get_try_str(const QDict *qdict, const char *key)
{
- QString *qstr = qobject_to_qstring(qdict_get(qdict, key));
+ QString *qstr = qobject_to(QString, qdict_get(qdict, key));
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_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
*/
QDict *qdict;
assert(obj != NULL);
- qdict = qobject_to_qdict(obj);
+ qdict = qobject_to(QDict, obj);
for (i = 0; i < QDICT_BUCKET_MAX; i++) {
QDictEntry *entry = QLIST_FIRST(&qdict->table[i]);
g_free(qdict);
}
-
-/**
- * qdict_copy_default(): If no entry mapped by 'key' exists in 'dst' yet, the
- * value of 'key' in 'src' is copied there (and the refcount increased
- * accordingly).
- */
-void qdict_copy_default(QDict *dst, QDict *src, const char *key)
-{
- QObject *val;
-
- if (qdict_haskey(dst, key)) {
- return;
- }
-
- val = qdict_get(src, key);
- if (val) {
- qobject_incref(val);
- qdict_put_obj(dst, key, val);
- }
-}
-
-/**
- * qdict_set_default_str(): If no entry mapped by 'key' exists in 'dst' yet, a
- * new QString initialised by 'val' is put there.
- */
-void qdict_set_default_str(QDict *dst, const char *key, const char *val)
-{
- if (qdict_haskey(dst, key)) {
- return;
- }
-
- qdict_put(dst, key, qstring_from_str(val));
-}
-
-static void qdict_flatten_qdict(QDict *qdict, QDict *target,
- const char *prefix);
-
-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);
- }
-
- 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;
- }
-}
-
-/**
- * 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.
- */
-void qdict_flatten(QDict *qdict)
-{
- 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;
-
- *dst = qdict_new();
- entry = qdict_first(src);
-
- 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);
- }
- entry = next;
- }
-}
-
-static int qdict_count_prefixed_entries(const QDict *src, const char *start)
-{
- const QDictEntry *entry;
- int count = 0;
-
- for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
- if (strstart(entry->key, start, NULL)) {
- if (count == INT_MAX) {
- return -ERANGE;
- }
- count++;
- }
- }
-
- return count;
-}
-
-/**
- * qdict_array_split(): This function moves array-like elements of a QDict into
- * a new QList. Every entry in the original QDict with a key "%u" or one
- * 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, if that prefix is "%u.". If the
- * whole key is just "%u", the whole QObject will be moved unchanged without
- * creating a new QDict. The function terminates when there is no entry in the
- * QDict with a prefix directly (incrementally) following the last one; it also
- * returns if there are both entries with "%u" and "%u." for the same index %u.
- * Example: {"0.a": 42, "0.b": 23, "1.x": 0, "4.y": 1, "o.o": 7, "2": 66}
- * (or {"1.x": 0, "4.y": 1, "0.a": 42, "o.o": 7, "0.b": 23, "2": 66})
- * => [{"a": 42, "b": 23}, {"x": 0}, 66]
- * and {"4.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++) {
- QObject *subqobj;
- bool is_subqdict;
- QDict *subqdict;
- char indexstr[32], prefix[32];
- size_t snprintf_ret;
-
- snprintf_ret = snprintf(indexstr, 32, "%u", i);
- assert(snprintf_ret < 32);
-
- subqobj = qdict_get(src, indexstr);
-
- snprintf_ret = snprintf(prefix, 32, "%u.", i);
- assert(snprintf_ret < 32);
-
- /* Overflow is the same as positive non-zero results */
- is_subqdict = qdict_count_prefixed_entries(src, prefix);
-
- // There may be either a single subordinate object (named "%u") or
- // multiple objects (each with a key prefixed "%u."), but not both.
- if (!subqobj == !is_subqdict) {
- break;
- }
-
- if (is_subqdict) {
- qdict_extract_subqdict(src, &subqdict, prefix);
- assert(qdict_size(subqdict) > 0);
- } else {
- qobject_incref(subqobj);
- qdict_del(src, indexstr);
- }
-
- qlist_append_obj(*dst, subqobj ?: QOBJECT(subqdict));
- }
-}
-
-/**
- * qdict_array_entries(): Returns the number of direct array entries if the
- * sub-QDict of src specified by the prefix in subqdict (or src itself for
- * prefix == "") is valid as an array, i.e. the length of the created list if
- * the sub-QDict would become empty after calling qdict_array_split() on it. If
- * the array is not valid, -EINVAL is returned.
- */
-int qdict_array_entries(QDict *src, const char *subqdict)
-{
- const QDictEntry *entry;
- unsigned i;
- unsigned entries = 0;
- size_t subqdict_len = strlen(subqdict);
-
- assert(!subqdict_len || subqdict[subqdict_len - 1] == '.');
-
- /* qdict_array_split() loops until UINT_MAX, but as we want to return
- * negative errors, we only have a signed return value here. Any additional
- * entries will lead to -EINVAL. */
- for (i = 0; i < INT_MAX; i++) {
- QObject *subqobj;
- int subqdict_entries;
- size_t slen = 32 + subqdict_len;
- char indexstr[slen], prefix[slen];
- size_t snprintf_ret;
-
- snprintf_ret = snprintf(indexstr, slen, "%s%u", subqdict, i);
- assert(snprintf_ret < slen);
-
- subqobj = qdict_get(src, indexstr);
-
- snprintf_ret = snprintf(prefix, slen, "%s%u.", subqdict, i);
- assert(snprintf_ret < slen);
-
- subqdict_entries = qdict_count_prefixed_entries(src, prefix);
- if (subqdict_entries < 0) {
- return subqdict_entries;
- }
-
- /* There may be either a single subordinate object (named "%u") or
- * multiple objects (each with a key prefixed "%u."), but not both. */
- if (subqobj && subqdict_entries) {
- return -EINVAL;
- } else if (!subqobj && !subqdict_entries) {
- break;
- }
-
- entries += subqdict_entries ? subqdict_entries : 1;
- }
-
- /* Consider everything handled that isn't part of the given sub-QDict */
- for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) {
- if (!strstart(qdict_entry_key(entry), subqdict, NULL)) {
- entries++;
- }
- }
-
- /* Anything left in the sub-QDict that wasn't handled? */
- if (qdict_size(src) != entries) {
- return -EINVAL;
- }
-
- return i;
-}
-
-/**
- * qdict_join(): Absorb the src QDict into the dest QDict, that is, move all
- * elements from src to dest.
- *
- * If an element from src has a key already present in dest, it will not be
- * moved unless overwrite is true.
- *
- * If overwrite is true, the conflicting values in dest will be discarded and
- * replaced by the corresponding values from src.
- *
- * Therefore, with overwrite being true, the src QDict will always be empty when
- * this function returns. If overwrite is false, the src QDict will be empty
- * iff there were no conflicts.
- */
-void qdict_join(QDict *dest, QDict *src, bool overwrite)
-{
- const QDictEntry *entry, *next;
-
- entry = qdict_first(src);
- while (entry) {
- next = qdict_next(src, entry);
-
- if (overwrite || !qdict_haskey(dest, entry->key)) {
- qobject_incref(entry->value);
- qdict_put_obj(dest, entry->key, entry->value);
- qdict_del(src, entry->key);
- }
-
- entry = next;
- }
-}