From nobody Thu Oct 30 15:17:03 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1525886936443894.9608933760151; Wed, 9 May 2018 10:28:56 -0700 (PDT) Received: from localhost ([::1]:57945 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGStW-0006CZ-EM for importer@patchew.org; Wed, 09 May 2018 13:28:50 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59857) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fGSNi-0003k3-Lv for qemu-devel@nongnu.org; Wed, 09 May 2018 12:55:59 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fGSNf-0006yj-OE for qemu-devel@nongnu.org; Wed, 09 May 2018 12:55:58 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:54984 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fGSNb-0006pR-EM; Wed, 09 May 2018 12:55:51 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C139A40201A3; Wed, 9 May 2018 16:55:50 +0000 (UTC) Received: from localhost (unknown [10.40.205.23]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 6EE72202342D; Wed, 9 May 2018 16:55:50 +0000 (UTC) From: Max Reitz To: qemu-block@nongnu.org Date: Wed, 9 May 2018 18:55:26 +0200 Message-Id: <20180509165530.29561-10-mreitz@redhat.com> In-Reply-To: <20180509165530.29561-1-mreitz@redhat.com> References: <20180509165530.29561-1-mreitz@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 09 May 2018 16:55:50 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Wed, 09 May 2018 16:55:50 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'mreitz@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PATCH 09/13] qdict: Make qdict_flatten() shallow-clone-friendly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , qemu-devel@nongnu.org, Markus Armbruster , Michael Roth , Max Reitz Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" In its current form, qdict_flatten() removes all entries from nested QDicts that are moved to the root QDict. It is completely sufficient to remove all old entries from the root QDict, however. If the nested dicts have a refcount of 1, this will automatically delete them, too. And if they have a greater refcount, we probably do not want to modify them in the first place. The latter observation means that it was currently (in general) impossible to qdict_flatten() a shallowly cloned dict because that would empty nested QDicts in the original dict as well. This patch changes this, so you can now use qdict_flatten(qdict_shallow_clone(dict)) to get a flattened copy without disturbing the original. Signed-off-by: Max Reitz Reviewed-by: Eric Blake --- qobject/qdict.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/qobject/qdict.c b/qobject/qdict.c index 83678c4951..63dcb43e73 100644 --- a/qobject/qdict.c +++ b/qobject/qdict.c @@ -537,7 +537,7 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *ta= rget, const char *prefix) QObject *value; const QDictEntry *entry, *next; char *new_key; - bool delete; + bool copied_value; =20 entry =3D qdict_first(qdict); =20 @@ -546,7 +546,7 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *ta= rget, const char *prefix) next =3D qdict_next(qdict, entry); value =3D qdict_entry_value(entry); new_key =3D NULL; - delete =3D false; + copied_value =3D false; =20 if (prefix) { new_key =3D g_strdup_printf("%s.%s", prefix, entry->key); @@ -557,23 +557,32 @@ static void qdict_flatten_qdict(QDict *qdict, QDict *= target, const char *prefix) * itself disappears. */ qdict_flatten_qdict(qobject_to(QDict, value), target, new_key ? new_key : entry->key); - delete =3D true; + copied_value =3D true; } else if (qobject_type(value) =3D=3D QTYPE_QLIST) { qdict_flatten_qlist(qobject_to(QList, value), target, new_key ? new_key : entry->key); - delete =3D true; + copied_value =3D true; } else if (prefix) { /* All other objects are moved to the target unchanged. */ qdict_put_obj(target, new_key, qobject_ref(value)); - delete =3D true; + copied_value =3D true; } =20 g_free(new_key); =20 - if (delete) { + if (copied_value && qdict =3D=3D target) { + /* If we have copied a value, and if we are on the root + * level, we need to remove the old entry. Otherwise, we + * do not, because by removing these entries on the root + * level, the reference counts of nested dicts and listed + * will be reduced automatically. In fact, we probably do + * not want to modify nested dicts and lists with + * refcounts greater than 1 anyway. */ qdict_del(qdict, entry->key); =20 - /* Restart loop after modifying the iterated QDict */ + /* Restart loop after modifying the iterated QDict. We + * only need to do this if qdict =3D=3D target, because + * otherwise copying the value did not affect qdict. */ entry =3D qdict_first(qdict); continue; } --=20 2.14.3