From: Max Reitz <mreitz@redhat.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
Max Reitz <mreitz@redhat.com>
Subject: [Qemu-devel] [PATCH 2/3] qdict: Extract non-QDicts in qdict_array_split()
Date: Fri, 21 Feb 2014 19:11:40 +0100 [thread overview]
Message-ID: <1393006301-22514-3-git-send-email-mreitz@redhat.com> (raw)
In-Reply-To: <1393006301-22514-1-git-send-email-mreitz@redhat.com>
Currently, qdict_array_split() only splits off entries with a key prefix
of "%u.", packing them into a new QDict. This patch makes it support
entries with the plain key "%u" as well, directly putting them into the
new QList without creating a QDict.
If there is both an entry with a key of "%u" and other entries with keys
prefixed "%u." (for the same index), the function simply terminates.
To do this, this patch also adds a static function which tests whether a
given QDict contains any keys with the given prefix. This is used to test
whether entries with a key prefixed "%u." do exist in the source QDict
without modifying it.
Signed-off-by: Max Reitz <mreitz@redhat.com>
---
qobject/qdict.c | 60 +++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 46 insertions(+), 14 deletions(-)
diff --git a/qobject/qdict.c b/qobject/qdict.c
index a3924f2..42ec4c0 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -597,18 +597,33 @@ void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start)
}
}
+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 of QDicts. Every entry in the original QDict with a key prefixed
- * "%u.", where %u designates an unsigned integer starting at 0 and
+ * 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. 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)
+ * 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)
{
@@ -617,19 +632,36 @@ void qdict_array_split(QDict *src, QList **dst)
*dst = qlist_new();
for (i = 0; i < UINT_MAX; i++) {
+ QObject *subqobj;
+ bool is_subqdict;
QDict *subqdict;
- char prefix[32];
+ 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);
- qdict_extract_subqdict(src, &subqdict, prefix);
- if (!qdict_size(subqdict)) {
- QDECREF(subqdict);
+ 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;
}
- qlist_append_obj(*dst, QOBJECT(subqdict));
+ 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));
}
}
--
1.9.0
next prev parent reply other threads:[~2014-02-21 18:09 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-02-21 18:11 [Qemu-devel] [PATCH 0/3] Extract non-QDicts in qdict_array_split() Max Reitz
2014-02-21 18:11 ` [Qemu-devel] [PATCH 1/3] qemu-config: Sections must consist of keys Max Reitz
2014-02-21 18:22 ` Eric Blake
2014-02-21 18:11 ` Max Reitz [this message]
2014-02-21 18:37 ` [Qemu-devel] [PATCH 2/3] qdict: Extract non-QDicts in qdict_array_split() Eric Blake
2014-02-21 19:40 ` Max Reitz
2014-02-21 18:11 ` [Qemu-devel] [PATCH 3/3] check-qdict: Adjust test for qdict_array_split() Max Reitz
2014-02-21 18:39 ` Eric Blake
2014-02-21 19:41 ` Max Reitz
2014-02-21 21:17 ` [Qemu-devel] [PATCH 0/3] Extract non-QDicts in qdict_array_split() Kevin Wolf
2014-02-21 22:32 ` Eric Blake
2014-02-26 17:16 ` Max Reitz
2014-02-26 18:18 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1393006301-22514-3-git-send-email-mreitz@redhat.com \
--to=mreitz@redhat.com \
--cc=kwolf@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).