qapi: complete implementation of unions
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Acked-by: Luiz Capitulino <lcapitulino@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
parent
622d241998
commit
dc8fb6df5a
@ -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'} }
|
||||
|
@ -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)
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user