From patchwork Sat Mar 5 23:50:44 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Blake X-Patchwork-Id: 8511961 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 8F9819F2F0 for ; Sat, 5 Mar 2016 23:58:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9782B201EF for ; Sat, 5 Mar 2016 23:58:03 +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 5DE4D20204 for ; Sat, 5 Mar 2016 23:58:02 +0000 (UTC) Received: from localhost ([::1]:48532 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acM5B-0005BR-SE for patchwork-qemu-devel@patchwork.kernel.org; Sat, 05 Mar 2016 18:58:01 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39823) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acLyW-0008Pr-Rj for qemu-devel@nongnu.org; Sat, 05 Mar 2016 18:51:10 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1acLyU-0005l1-EN for qemu-devel@nongnu.org; Sat, 05 Mar 2016 18:51:08 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40310) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1acLyU-0005kO-4U for qemu-devel@nongnu.org; Sat, 05 Mar 2016 18:51:06 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id 62BC22DC363; Sat, 5 Mar 2016 23:51:04 +0000 (UTC) Received: from red.redhat.com (ovpn-113-165.phx2.redhat.com [10.3.113.165]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u25Np3ZA020509; Sat, 5 Mar 2016 18:51:03 -0500 From: Eric Blake To: qemu-devel@nongnu.org Date: Sat, 5 Mar 2016 16:50:44 -0700 Message-Id: <1457221861-18067-2-git-send-email-eblake@redhat.com> In-Reply-To: <1457221861-18067-1-git-send-email-eblake@redhat.com> References: <1457221861-18067-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 3.x X-Received-From: 209.132.183.28 Cc: armbru@redhat.com, Michael Roth Subject: [Qemu-devel] [PATCH v13 01/18] qapi-visit: Add visitor.type classification 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 We have three classes of QAPI visitors: input, output, and dealloc. Currently, all implementations of these visitors have one thing in common based on their visitor type: the implementation used for the visit_type_enum() callback. But since we plan to add more such common behavior, in relation to documenting and further refining the semantics, it makes more sense to have the visitor implementations advertise which class they belong to, so the common qapi-visit-core code can use that information in multiple places. For this patch, knowing the class of a visitor implementation lets us make input_type_enum() and output_type_enum() become static functions, by replacing the callback function Visitor.type_enum() with the simpler enum member Visitor.type. Share a common assertion in qapi-visit-core as part of the refactoring. Signed-off-by: Eric Blake --- v13: no change v12: new patch --- include/qapi/visitor-impl.h | 21 ++++++++++++--------- qapi/qapi-visit-core.c | 28 +++++++++++++++------------- qapi/opts-visitor.c | 12 ++---------- qapi/qapi-dealloc-visitor.c | 7 +------ qapi/qmp-input-visitor.c | 2 +- qapi/qmp-output-visitor.c | 2 +- qapi/string-input-visitor.c | 2 +- qapi/string-output-visitor.c | 2 +- 8 files changed, 34 insertions(+), 42 deletions(-) diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h index 2bd8f29..228a2a6 100644 --- a/include/qapi/visitor-impl.h +++ b/include/qapi/visitor-impl.h @@ -14,6 +14,15 @@ #include "qapi/visitor.h" +/* There are three classes of visitors; setting the class determines + * how QAPI enums are visited, as well as what additional restrictions + * can be asserted. */ +typedef enum VisitorType { + VISITOR_INPUT, + VISITOR_OUTPUT, + VISITOR_DEALLOC, +} VisitorType; + struct Visitor { /* Must be set */ @@ -36,10 +45,6 @@ struct Visitor void (*end_alternate)(Visitor *v); /* Must be set. */ - void (*type_enum)(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp); - - /* Must be set. */ void (*type_int64)(Visitor *v, const char *name, int64_t *obj, Error **errp); /* Must be set. */ @@ -58,11 +63,9 @@ struct Visitor /* May be NULL; most useful for input visitors. */ void (*optional)(Visitor *v, const char *name, bool *present); + + /* Must be set. */ + VisitorType type; }; -void input_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp); -void output_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp); - #endif diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c index 856606b..a08d073 100644 --- a/qapi/qapi-visit-core.c +++ b/qapi/qapi-visit-core.c @@ -71,12 +71,6 @@ bool visit_optional(Visitor *v, const char *name, bool *present) return *present; } -void visit_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) -{ - v->type_enum(v, name, obj, strings, errp); -} - void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) { v->type_int64(v, name, obj, errp); @@ -207,14 +201,13 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) v->type_any(v, name, obj, errp); } -void output_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) +static void output_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) { int i = 0; int value = *obj; char *enum_str; - assert(strings); while (strings[i++] != NULL); if (value < 0 || value >= i - 1) { error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null"); @@ -225,15 +218,13 @@ void output_type_enum(Visitor *v, const char *name, int *obj, visit_type_str(v, name, &enum_str, errp); } -void input_type_enum(Visitor *v, const char *name, int *obj, - const char *const strings[], Error **errp) +static void input_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) { Error *local_err = NULL; int64_t value = 0; char *enum_str; - assert(strings); - visit_type_str(v, name, &enum_str, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -256,3 +247,14 @@ void input_type_enum(Visitor *v, const char *name, int *obj, g_free(enum_str); *obj = value; } + +void visit_type_enum(Visitor *v, const char *name, int *obj, + const char *const strings[], Error **errp) +{ + assert(strings); + if (v->type == VISITOR_INPUT) { + input_type_enum(v, name, obj, strings, errp); + } else if (v->type == VISITOR_OUTPUT) { + output_type_enum(v, name, obj, strings, errp); + } +} diff --git a/qapi/opts-visitor.c b/qapi/opts-visitor.c index 73e4ace..f9a2346 100644 --- a/qapi/opts-visitor.c +++ b/qapi/opts-visitor.c @@ -506,6 +506,8 @@ opts_visitor_new(const QemuOpts *opts) ov = g_malloc0(sizeof *ov); + ov->visitor.type = VISITOR_INPUT; + ov->visitor.start_struct = &opts_start_struct; ov->visitor.end_struct = &opts_end_struct; @@ -513,16 +515,6 @@ opts_visitor_new(const QemuOpts *opts) ov->visitor.next_list = &opts_next_list; ov->visitor.end_list = &opts_end_list; - /* input_type_enum() covers both "normal" enums and union discriminators. - * The union discriminator field is always generated as "type"; it should - * match the "type" QemuOpt child of any QemuOpts. - * - * input_type_enum() will remove the looked-up key from the - * "unprocessed_opts" hash even if the lookup fails, because the removal is - * done earlier in opts_type_str(). This should be harmless. - */ - ov->visitor.type_enum = &input_type_enum; - ov->visitor.type_int64 = &opts_type_int64; ov->visitor.type_uint64 = &opts_type_uint64; ov->visitor.type_size = &opts_type_size; diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c index 6922179..c19a459 100644 --- a/qapi/qapi-dealloc-visitor.c +++ b/qapi/qapi-dealloc-visitor.c @@ -163,11 +163,6 @@ static void qapi_dealloc_type_anything(Visitor *v, const char *name, } } -static void qapi_dealloc_type_enum(Visitor *v, const char *name, int *obj, - const char * const strings[], Error **errp) -{ -} - Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v) { return &v->visitor; @@ -184,6 +179,7 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v = g_malloc0(sizeof(*v)); + v->visitor.type = VISITOR_DEALLOC; v->visitor.start_struct = qapi_dealloc_start_struct; v->visitor.end_struct = qapi_dealloc_end_struct; v->visitor.start_alternate = qapi_dealloc_start_alternate; @@ -191,7 +187,6 @@ QapiDeallocVisitor *qapi_dealloc_visitor_new(void) v->visitor.start_list = qapi_dealloc_start_list; v->visitor.next_list = qapi_dealloc_next_list; v->visitor.end_list = qapi_dealloc_end_list; - v->visitor.type_enum = qapi_dealloc_type_enum; v->visitor.type_int64 = qapi_dealloc_type_int64; v->visitor.type_uint64 = qapi_dealloc_type_uint64; v->visitor.type_bool = qapi_dealloc_type_bool; diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c index e659832..03dcb65 100644 --- a/qapi/qmp-input-visitor.c +++ b/qapi/qmp-input-visitor.c @@ -338,13 +338,13 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj) v = g_malloc0(sizeof(*v)); + v->visitor.type = VISITOR_INPUT; v->visitor.start_struct = qmp_input_start_struct; v->visitor.end_struct = qmp_input_end_struct; v->visitor.start_list = qmp_input_start_list; v->visitor.next_list = qmp_input_next_list; v->visitor.end_list = qmp_input_end_list; v->visitor.start_alternate = qmp_input_start_alternate; - v->visitor.type_enum = input_type_enum; v->visitor.type_int64 = qmp_input_type_int64; v->visitor.type_uint64 = qmp_input_type_uint64; v->visitor.type_bool = qmp_input_type_bool; diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c index d44c676..1f2a7ba 100644 --- a/qapi/qmp-output-visitor.c +++ b/qapi/qmp-output-visitor.c @@ -234,12 +234,12 @@ QmpOutputVisitor *qmp_output_visitor_new(void) v = g_malloc0(sizeof(*v)); + v->visitor.type = VISITOR_OUTPUT; v->visitor.start_struct = qmp_output_start_struct; v->visitor.end_struct = qmp_output_end_struct; v->visitor.start_list = qmp_output_start_list; v->visitor.next_list = qmp_output_next_list; v->visitor.end_list = qmp_output_end_list; - v->visitor.type_enum = output_type_enum; v->visitor.type_int64 = qmp_output_type_int64; v->visitor.type_uint64 = qmp_output_type_uint64; v->visitor.type_bool = qmp_output_type_bool; diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c index 59eb5dc..d591e67 100644 --- a/qapi/string-input-visitor.c +++ b/qapi/string-input-visitor.c @@ -347,7 +347,7 @@ StringInputVisitor *string_input_visitor_new(const char *str) v = g_malloc0(sizeof(*v)); - v->visitor.type_enum = input_type_enum; + v->visitor.type = VISITOR_INPUT; v->visitor.type_int64 = parse_type_int64; v->visitor.type_uint64 = parse_type_uint64; v->visitor.type_size = parse_type_size; diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c index c2e5c5b..0d44d7e 100644 --- a/qapi/string-output-visitor.c +++ b/qapi/string-output-visitor.c @@ -351,7 +351,7 @@ StringOutputVisitor *string_output_visitor_new(bool human) v->string = g_string_new(NULL); v->human = human; - v->visitor.type_enum = output_type_enum; + v->visitor.type = VISITOR_OUTPUT; v->visitor.type_int64 = print_type_int64; v->visitor.type_uint64 = print_type_uint64; v->visitor.type_size = print_type_size;