diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-06-26 20:28:10 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-07-07 16:25:44 +0900 |
commit | a15119db2ff5c2fdfdeb913b297bf8aa3399132e (patch) | |
tree | 7d6f779408bb772b11c029ab88000fc01856b599 /qobject | |
parent | 340f06c9eaee097e626c251bf7a013350649c091 (diff) | |
download | qemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.tar.gz qemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.tar.bz2 qemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.zip |
Imported Upstream version 2.0.0upstream/2.0.0
Change-Id: I081766c4314e7893f54fec80b920b1638d15021f
Diffstat (limited to 'qobject')
-rw-r--r-- | qobject/qdict.c | 158 | ||||
-rw-r--r-- | qobject/qerror.c | 12 |
2 files changed, 150 insertions, 20 deletions
diff --git a/qobject/qdict.c b/qobject/qdict.c index 472f106e2..42ec4c0d2 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -477,11 +477,47 @@ static void qdict_destroy_obj(QObject *obj) g_free(qdict); } -static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) +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; - const char *new_key; + char *new_key; bool delete; entry = qdict_first(qdict); @@ -494,18 +530,28 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) delete = false; if (prefix) { - qobject_incref(value); new_key = g_strdup_printf("%s.%s", prefix, entry->key); - qdict_put_obj(target, new_key, value); - delete = true; } if (qobject_type(value) == QTYPE_QDICT) { - qdict_do_flatten(qobject_to_qdict(value), target, - new_key ? new_key : entry->key); + /* 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); @@ -520,10 +566,102 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) /** * 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". This operation - * is applied recursively for nested QDicts. + * 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_do_flatten(qdict, qdict, NULL); + 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 bool qdict_has_prefixed_entries(const QDict *src, const char *start) +{ + const QDictEntry *entry; + + for (entry = qdict_first(src); entry; entry = qdict_next(src, entry)) { + if (strstart(entry->key, start, NULL)) { + return true; + } + } + + return false; +} + +/** + * 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); + + is_subqdict = qdict_has_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)); + } } diff --git a/qobject/qerror.c b/qobject/qerror.c index 3aee1cf6a..e3608e240 100644 --- a/qobject/qerror.c +++ b/qobject/qerror.c @@ -42,8 +42,8 @@ static QError *qerror_new(void) * * Return strong reference. */ -static QError *qerror_from_info(ErrorClass err_class, const char *fmt, - va_list *va) +static QError * GCC_FMT_ATTR(2, 0) +qerror_from_info(ErrorClass err_class, const char *fmt, va_list *va) { QError *qerr; @@ -121,14 +121,6 @@ void qerror_report_err(Error *err) } } -void assert_no_error(Error *err) -{ - if (err) { - qerror_report_err(err); - abort(); - } -} - /** * qobject_to_qerror(): Convert a QObject into a QError */ |