From patchwork Tue Mar 1 05:14:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 8462041 Return-Path: X-Original-To: patchwork-qemu-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 9BF04C0553 for ; Tue, 1 Mar 2016 05:22:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A076020304 for ; Tue, 1 Mar 2016 05:22:40 +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 AE963201BC for ; Tue, 1 Mar 2016 05:22:39 +0000 (UTC) Received: from localhost ([::1]:40962 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aaclb-0005yj-0v for patchwork-qemu-devel@patchwork.kernel.org; Tue, 01 Mar 2016 00:22:39 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59821) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aacdz-0000Nj-Ad for qemu-devel@nongnu.org; Tue, 01 Mar 2016 00:14:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aacdy-0006SM-10 for qemu-devel@nongnu.org; Tue, 01 Mar 2016 00:14:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45182) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aacdx-0006SC-QK for qemu-devel@nongnu.org; Tue, 01 Mar 2016 00:14:45 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 8791763147; Tue, 1 Mar 2016 05:14:45 +0000 (UTC) Received: from red.redhat.com (ovpn-113-165.phx2.redhat.com [10.3.113.165]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u215EZ9a018132; Tue, 1 Mar 2016 00:14:45 -0500 From: Eric Blake To: qemu-devel@nongnu.org Date: Mon, 29 Feb 2016 22:14:30 -0700 Message-Id: <1456809272-14184-17-git-send-email-eblake@redhat.com> In-Reply-To: <1456809272-14184-1-git-send-email-eblake@redhat.com> References: <1456809272-14184-1-git-send-email-eblake@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 01 Mar 2016 05:14:45 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Cc: armbru@redhat.com, Michael Roth Subject: [Qemu-devel] [PATCH v12 16/18] qmp-input: Require struct push to visit members of top dict 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+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org 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 --- 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 b3ca93c..fb4582a 100644 --- a/include/qapi/visitor.h +++ b/include/qapi/visitor.h @@ -48,8 +48,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 6b69e9a..2daf83f 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -38,9 +38,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; @@ -57,36 +59,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; } @@ -372,7 +378,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); } @@ -399,7 +405,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;