From patchwork Wed Dec 11 18:23:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Max Reitz X-Patchwork-Id: 300261 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 8F2DA2C00A1 for ; Thu, 12 Dec 2013 05:22:52 +1100 (EST) Received: from localhost ([::1]:59274 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VqoQs-0000oW-0x for incoming@patchwork.ozlabs.org; Wed, 11 Dec 2013 13:22:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56407) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VqoQS-0000nt-K4 for qemu-devel@nongnu.org; Wed, 11 Dec 2013 13:22:30 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VqoQM-0006RG-LG for qemu-devel@nongnu.org; Wed, 11 Dec 2013 13:22:24 -0500 Received: from mx1.redhat.com ([209.132.183.28]:6966) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VqoQM-0006Qq-5h for qemu-devel@nongnu.org; Wed, 11 Dec 2013 13:22:18 -0500 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id rBBIMGZP025356 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 11 Dec 2013 13:22:17 -0500 Received: from localhost (ovpn-116-38.ams2.redhat.com [10.36.116.38]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id rBBIMDc2022123 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Wed, 11 Dec 2013 13:22:15 -0500 From: Max Reitz To: qemu-devel@nongnu.org Date: Wed, 11 Dec 2013 19:23:07 +0100 Message-Id: <1386786187-30471-1-git-send-email-mreitz@redhat.com> In-Reply-To: <1386785473-26157-5-git-send-email-mreitz@redhat.com> References: <1386785473-26157-5-git-send-email-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Kevin Wolf , Fam Zheng , Stefan Hajnoczi , Max Reitz Subject: [Qemu-devel] [PATCH v4 04/21] qapi: extend qdict_flatten() for QLists X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Reversing qdict_array_split(), qdict_flatten() should flatten QLists as well by interpreting them as QDicts where every entry's key is its index. This allows bringing QDicts with QLists from QMP commands to the same form as they would be given as command-line options, thereby allowing them to be parsed the same way. Signed-off-by: Max Reitz --- v4: - fixed a memory leak due to a missing g_free(new_key) in qdict_flatten_qlist() --- qobject/qdict.c | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/qobject/qdict.c b/qobject/qdict.c index fca1902..a90b7f4 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -477,7 +477,42 @@ 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()). Also, prefix can + * never be NULL. */ + + entry = qlist_first(qlist); + + for (i = 0; entry; entry = qlist_next(entry), i++) { + value = qlist_entry_obj(entry); + + qobject_incref(value); + new_key = g_strdup_printf("%s.%i", prefix, i); + qdict_put_obj(target, new_key, value); + + if (qobject_type(value) == QTYPE_QDICT) { + qdict_flatten_qdict(qobject_to_qdict(value), target, new_key); + } else { + qdict_flatten_qlist(qobject_to_qlist(value), target, new_key); + } + + g_free(new_key); + } +} + +static void qdict_flatten_qdict(QDict *qdict, QDict *target, const char *prefix) { QObject *value; const QDictEntry *entry, *next; @@ -500,8 +535,12 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) if (qobject_type(value) == QTYPE_QDICT) { /* Entries of QDicts are processed recursively, the QDict object * itself disappears. */ - qdict_do_flatten(qobject_to_qdict(value), target, - new_key ? new_key : entry->key); + 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. */ @@ -531,7 +570,7 @@ static void qdict_do_flatten(QDict *qdict, QDict *target, const char *prefix) */ 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 */