From patchwork Tue Mar 6 17:55:56 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 144966 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id D4AB8B6F98 for ; Wed, 7 Mar 2012 04:56:57 +1100 (EST) Received: from localhost ([::1]:39055 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4yd5-0007Sm-DX for incoming@patchwork.ozlabs.org; Tue, 06 Mar 2012 12:56:55 -0500 Received: from eggs.gnu.org ([208.118.235.92]:56484) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4ycq-0007L0-38 for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:48 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S4yck-0002BG-IS for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:39 -0500 Received: from mail-yx0-f173.google.com ([209.85.213.173]:44429) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S4yck-0002B8-AN for qemu-devel@nongnu.org; Tue, 06 Mar 2012 12:56:34 -0500 Received: by yenr5 with SMTP id r5so2847104yen.4 for ; Tue, 06 Mar 2012 09:56:32 -0800 (PST) Received-SPF: pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.185.138 as permitted sender) client-ip=10.50.185.138; Authentication-Results: mr.google.com; spf=pass (google.com: domain of paolo.bonzini@gmail.com designates 10.50.185.138 as permitted sender) smtp.mail=paolo.bonzini@gmail.com; dkim=pass header.i=paolo.bonzini@gmail.com Received: from mr.google.com ([10.50.185.138]) by 10.50.185.138 with SMTP id fc10mr11295094igc.48.1331056592285 (num_hops = 1); Tue, 06 Mar 2012 09:56:32 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=1g340TPaJ3qqfyFkYmuppOe3+59liE1Ayrf3JLNq77U=; b=O9hmsfb71qSAhbSYHxZzuUumCgsaJfkeqlEuXVl/Amils3fNsaoNBP1tVxmWTiVL8V 5TxNlje1H+8gMV5oAVA58uWe5Hq9ZIInRhcQamCC5hLl268hWx5Zn+qI14LBZEQ54g+K ODcPNBekV1JAkBPBGPNF4SoHxgoHdsq0WdwaxwugdhhDZKQsKd8DZMbch4wDwYr89UxK 5/fSyEZervTmPAPBHzGDvJZlDRgXAtyyvlfqIBLSa2Hq8/sIZ4sHFHuyop7trXd6LipF dYHg6yXpW7eVgeTeIlAmDHtJVlOGgRHL3y9RAX+KUN7AJ96xaGMn0h8DZ8En/8GbrC9x YjHg== Received: by 10.50.185.138 with SMTP id fc10mr9451721igc.48.1331056592236; Tue, 06 Mar 2012 09:56:32 -0800 (PST) Received: from yakj.usersys.redhat.com (93-34-182-16.ip50.fastwebnet.it. [93.34.182.16]) by mx.google.com with ESMTPS id s8sm10504373igw.16.2012.03.06.09.56.28 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 06 Mar 2012 09:56:31 -0800 (PST) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 6 Mar 2012 18:55:56 +0100 Message-Id: <1331056563-7503-4-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.7.7.6 In-Reply-To: <1331056563-7503-1-git-send-email-pbonzini@redhat.com> References: <1331056563-7503-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.213.173 Cc: kwolf@redhat.com, fsimonce@redhat.com, eblake@redhat.com, stefanha@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v4 03/10] qapi: complete implementation of unions 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 Reviewed-by: Luiz Capitulino Signed-off-by: Paolo Bonzini --- qapi-schema-test.json | 10 ++++++++++ scripts/qapi-types.py | 6 ++++++ scripts/qapi-visit.py | 31 ++++++++++++++++++++++++++++++- test-qmp-input-visitor.c | 18 ++++++++++++++++++ test-qmp-output-visitor.c | 34 ++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 1 deletions(-) diff --git a/qapi-schema-test.json b/qapi-schema-test.json index 2b38919..8c7f9f7 100644 --- a/qapi-schema-test.json +++ b/qapi-schema-test.json @@ -22,6 +22,16 @@ 'dict2': { 'userdef1': 'UserDefOne', 'string2': 'str' }, '*dict3': { 'userdef2': 'UserDefOne', 'string3': 'str' } } } } +# for testing unions +{ 'type': 'UserDefA', + 'data': { 'boolean': 'bool' } } + +{ 'type': 'UserDefB', + 'data': { 'integer': 'int' } } + +{ 'union': 'UserDefUnion', + 'data': { 'a' : 'UserDefA', 'b' : 'UserDefB' } } + # testing commands { 'command': 'user_def_cmd', 'data': {} } { 'command': 'user_def_cmd1', 'data': {'ud1a': 'UserDefOne'} } diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index b56225b..727fb77 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -117,6 +117,7 @@ struct %(name)s { %(name)sKind kind; union { + void *data; ''', name=name) @@ -269,6 +270,7 @@ for expr in exprs: elif expr.has_key('union'): ret += generate_fwd_struct(expr['union'], expr['data']) + "\n" ret += generate_enum('%sKind' % expr['union'], expr['data'].keys()) + fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys())) else: continue fdecl.write(ret) @@ -283,6 +285,10 @@ for expr in exprs: fdef.write(generate_type_cleanup(expr['type']) + "\n") elif expr.has_key('union'): ret += generate_union(expr['union'], expr['data']) + ret += generate_type_cleanup_decl(expr['union'] + "List") + fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n") + ret += generate_type_cleanup_decl(expr['union']) + fdef.write(generate_type_cleanup(expr['union']) + "\n") else: continue fdecl.write(ret) diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 5160d83..54117d4 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -110,10 +110,38 @@ def generate_visit_union(name, members): void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) { -} + Error *err = NULL; + + visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); + visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); + if (err) { + error_propagate(errp, err); + goto end; + } + switch ((*obj)->kind) { ''', name=name) + for key in members: + ret += mcgen(''' + case %(abbrev)s_KIND_%(enum)s: + visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", errp); + break; +''', + abbrev = de_camel_case(name).upper(), + enum = de_camel_case(key).upper(), + c_type=members[key], + c_name=c_var(key)) + + ret += mcgen(''' + default: + abort(); + } +end: + visit_end_struct(m, errp); +} +''') + return ret def generate_declaration(name, members, genlist=True): @@ -242,6 +270,7 @@ for expr in exprs: fdecl.write(ret) elif expr.has_key('union'): ret = generate_visit_union(expr['union'], expr['data']) + ret += generate_visit_list(expr['union'], expr['data']) fdef.write(ret) ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys()) diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c index 926db5c..1996e49 100644 --- a/test-qmp-input-visitor.c +++ b/test-qmp-input-visitor.c @@ -234,6 +234,22 @@ static void test_visitor_in_list(TestInputVisitorData *data, qapi_free_UserDefOneList(head); } +static void test_visitor_in_union(TestInputVisitorData *data, + const void *unused) +{ + Visitor *v; + Error *err = NULL; + UserDefUnion *tmp; + + v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }"); + + visit_type_UserDefUnion(v, &tmp, NULL, &err); + g_assert(err == NULL); + g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B); + g_assert_cmpint(tmp->b->integer, ==, 42); + qapi_free_UserDefUnion(tmp); +} + static void input_visitor_test_add(const char *testpath, TestInputVisitorData *data, void (*test_func)(TestInputVisitorData *data, const void *user_data)) @@ -264,6 +280,8 @@ int main(int argc, char **argv) &in_visitor_data, test_visitor_in_struct_nested); input_visitor_test_add("/visitor/input/list", &in_visitor_data, test_visitor_in_list); + input_visitor_test_add("/visitor/input/union", + &in_visitor_data, test_visitor_in_union); g_test_run(); diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c index c94c208..78e5f2d 100644 --- a/test-qmp-output-visitor.c +++ b/test-qmp-output-visitor.c @@ -380,6 +380,38 @@ static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, qapi_free_UserDefNestedList(head); } +static void test_visitor_out_union(TestOutputVisitorData *data, + const void *unused) +{ + QObject *arg, *qvalue; + QDict *qdict, *value; + + Error *err = NULL; + + UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion)); + tmp->kind = USER_DEF_UNION_KIND_A; + tmp->a = g_malloc0(sizeof(UserDefA)); + tmp->a->boolean = true; + + visit_type_UserDefUnion(data->ov, &tmp, NULL, &err); + g_assert(err == NULL); + arg = qmp_output_get_qobject(data->qov); + + g_assert(qobject_type(arg) == QTYPE_QDICT); + qdict = qobject_to_qdict(arg); + + g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a"); + + qvalue = qdict_get(qdict, "data"); + g_assert(data != NULL); + g_assert(qobject_type(qvalue) == QTYPE_QDICT); + value = qobject_to_qdict(qvalue); + g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true); + + qapi_free_UserDefUnion(tmp); + QDECREF(qdict); +} + static void output_visitor_test_add(const char *testpath, TestOutputVisitorData *data, void (*test_func)(TestOutputVisitorData *data, const void *user_data)) @@ -416,6 +448,8 @@ int main(int argc, char **argv) &out_visitor_data, test_visitor_out_list); output_visitor_test_add("/visitor/output/list-qapi-free", &out_visitor_data, test_visitor_out_list_qapi_free); + output_visitor_test_add("/visitor/output/union", + &out_visitor_data, test_visitor_out_union); g_test_run();