From patchwork Fri Apr 8 16:13:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 8784721 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 443D29F36E for ; Fri, 8 Apr 2016 16:23:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 7BAEC202DD for ; Fri, 8 Apr 2016 16:23:46 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 8769C201C7 for ; Fri, 8 Apr 2016 16:23:45 +0000 (UTC) Received: from localhost ([::1]:57108 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoZCC-0003hu-Ss for patchwork-qemu-devel@patchwork.kernel.org; Fri, 08 Apr 2016 12:23:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37091) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoZ2C-0007pL-Px for qemu-devel@nongnu.org; Fri, 08 Apr 2016 12:13:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aoZ2B-0002R6-Fs for qemu-devel@nongnu.org; Fri, 08 Apr 2016 12:13:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:37461) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aoZ2B-0002Qt-49 for qemu-devel@nongnu.org; Fri, 08 Apr 2016 12:13:23 -0400 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D181A78225; Fri, 8 Apr 2016 16:13:22 +0000 (UTC) Received: from red.redhat.com (ovpn-113-199.phx2.redhat.com [10.3.113.199]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u38GDEGT012676; Fri, 8 Apr 2016 12:13:22 -0400 From: Eric Blake To: qemu-devel@nongnu.org Date: Fri, 8 Apr 2016 10:13:10 -0600 Message-Id: <1460131992-32278-18-git-send-email-eblake@redhat.com> In-Reply-To: <1460131992-32278-1-git-send-email-eblake@redhat.com> References: <1460131992-32278-1-git-send-email-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v14 17/19] qmp-input: Require struct push to visit members of top dict 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: armbru@redhat.com, Michael Roth Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Don't embed the root of the visit into the stack of current containers being visited. That way, we no longer get confused on whether the first visit of a dictionary is to the dictionary itself or to one of the members of the dictionary, and we no longer have to require the root visit to pass name=NULL. An audit of all qmp_input_visitor_new* call sites shows that the only places where the visit starts directly on a QDict, but where the first visit_type_* within the visit had passed a non-NULL name, were fixed in the previous two places to properly push into the object with visit_start_struct(). Signed-off-by: Eric Blake --- v14: no change v13: no change v12: new patch --- include/qapi/visitor.h | 3 +-- include/qapi/qmp-input-visitor.h | 8 ------ qapi/qmp-input-visitor.c | 54 ++++++++++++++++++++++------------------ 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h index 4c29722..e1213a3 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -47,8 +47,7 @@ * * The @name parameter of visit_type_FOO() describes the relation * between this QAPI value and its parent container. When visiting - * the root of a tree, @name is usually ignored (although some - * visitors require it to be NULL); when visiting a member of an + * the root of a tree, @name is ignored; when visiting a member of an * object, @name is the key associated with the value; and when * visiting a member of a list, @name is NULL. * diff --git a/include/qapi/qmp-input-visitor.h b/include/qapi/qmp-input-visitor.h index d75ff98..3ed499c 100644 --- a/include/qapi/qmp-input-visitor.h +++ b/include/qapi/qmp-input-visitor.h @@ -19,14 +19,6 @@ typedef struct QmpInputVisitor QmpInputVisitor; -/* - * FIXME: When visiting a QDict, passing a non-NULL @name for the - * first visit_type_FOO() when the root is a QDict will find that - * particular key within the QDict. In the future, the contract may - * be tightened to require visit_start_struct() with ignored @name as - * the first visit; in the meantime, the first visit is safest when - * using NULL for @name. - */ QmpInputVisitor *qmp_input_visitor_new(QObject *obj); QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj); diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index a94cfa9..16f2f5a 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -39,9 +39,11 @@ struct QmpInputVisitor { Visitor visitor; - /* Stack of objects being visited. stack[0] is root of visit, - * stack[1] and below correspond to visit_start_struct (nested - * QDict) and visit_start_list (nested QList). */ + /* Root of visit at visitor creation. */ + QObject *root; + + /* Stack of objects being visited (all entries will be either + * QDict or QList). */ StackObject stack[QIV_STACK_SIZE]; int nb_stack; @@ -58,36 +60,40 @@ static QObject *qmp_input_get_object(QmpInputVisitor *qiv, const char *name, bool consume) { - StackObject *tos = &qiv->stack[qiv->nb_stack - 1]; - QObject *qobj = tos->obj; + StackObject *tos; + QObject *qobj; + if (!qiv->nb_stack) { + /* Starting at root, name is ignored. */ + return qiv->root; + } + + /* We are in a container; find the next element */ + tos = &qiv->stack[qiv->nb_stack - 1]; + qobj = tos->obj; assert(qobj); - /* If we have a name, and we're in a dictionary, then return that - * value. */ - if (name && qobject_type(qobj) == QTYPE_QDICT) { + if (qobject_type(qobj) == QTYPE_QDICT) { + assert(name); qobj = qdict_get(qobject_to_qdict(qobj), name); if (tos->h && consume && qobj) { bool removed = g_hash_table_remove(tos->h, name); assert(removed); } - return qobj; - } - - /* If we are in the middle of a list, then return the next element - * of the list. */ - if (tos->entry) { + } else { assert(qobject_type(qobj) == QTYPE_QLIST); - assert(!tos->first); - qobj = qlist_entry_obj(tos->entry); - if (consume) { - tos->entry = qlist_next(tos->entry); + /* FIXME: assertion needs adjustment if we fix visit-core + * to pass "name.0" style name during lists. */ + assert(!name); + + if (tos->entry) { + assert(!tos->first); + qobj = qlist_entry_obj(tos->entry); + if (consume) { + tos->entry = qlist_next(tos->entry); + } } - return qobj; } - - /* Otherwise, we are at the root of the visit or the start of a - * list, and return the object as-is. */ return qobj; } @@ -373,7 +379,7 @@ Visitor *qmp_input_get_visitor(QmpInputVisitor *v) void qmp_input_visitor_cleanup(QmpInputVisitor *v) { - qobject_decref(v->stack[0].obj); + qobject_decref(v->root); g_free(v); } @@ -400,7 +406,7 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) v->visitor.type_null = qmp_input_type_null; v->visitor.optional = qmp_input_optional; - qmp_input_push(v, obj, NULL, NULL); + v->root = obj; qobject_incref(obj); return v;