def gen_visit_fields_decl(typ):
- ret = ''
- if typ.name not in struct_fields_seen:
- ret += mcgen('''
+ if typ.name in struct_fields_seen:
+ return ''
+ struct_fields_seen.add(typ.name)
+ return mcgen('''
-static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s **obj, Error **errp);
+static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s *obj, Error **errp);
''',
- c_type=typ.c_name())
- struct_fields_seen.add(typ.name)
- return ret
+ c_type=typ.c_name())
def gen_visit_implicit_struct(typ):
visit_start_implicit_struct(v, (void **)obj, sizeof(%(c_type)s), &err);
if (!err) {
- visit_type_%(c_type)s_fields(v, obj, errp);
+ visit_type_%(c_type)s_fields(v, *obj, errp);
visit_end_implicit_struct(v);
}
error_propagate(errp, err);
struct_fields_seen.add(name)
ret += mcgen('''
-static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **errp)
+static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s *obj, Error **errp)
{
Error *err = NULL;
if base:
ret += mcgen('''
- visit_type_%(c_type)s_fields(v, (%(c_type)s **)obj, &err);
+ visit_type_%(c_type)s_fields(v, (%(c_type)s *)obj, &err);
''',
c_type=base.c_name())
ret += gen_err_check()
- ret += gen_visit_fields(members, prefix='(*obj)->')
+ ret += gen_visit_fields(members, prefix='obj->')
if variants:
ret += mcgen('''
- if (!visit_start_union(v, !!(*obj)->u.data, &err) || err) {
+ if (!visit_start_union(v, !!obj->u.data, &err) || err) {
goto out;
}
- switch ((*obj)->%(c_name)s) {
+ switch (obj->%(c_name)s) {
''',
c_name=c_name(variants.tag_member.name))
variants.tag_member.type.prefix))
if simple_union_type:
ret += mcgen('''
- visit_type_%(c_type)s(v, "data", &(*obj)->u.%(c_name)s, &err);
+ visit_type_%(c_type)s(v, "data", &obj->u.%(c_name)s, &err);
''',
c_type=simple_union_type.c_name(),
c_name=c_name(var.name))
else:
ret += mcgen('''
- visit_type_implicit_%(c_type)s(v, &(*obj)->u.%(c_name)s, &err);
+ visit_type_implicit_%(c_type)s(v, &obj->u.%(c_name)s, &err);
''',
c_type=var.type.c_name(),
c_name=c_name(var.name))
return ret
-def gen_visit_struct(name, base, members):
- ret = gen_visit_struct_fields(name, base, members, None)
-
- # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
- # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
- # rather than leaving it non-NULL. As currently written, the caller must
- # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
- ret += mcgen('''
-
-void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
-{
- Error *err = NULL;
-
- visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), &err);
- if (err) {
- goto out;
- }
- if (!*obj) {
- goto out_obj;
- }
- visit_type_%(c_name)s_fields(v, obj, &err);
- error_propagate(errp, err);
- err = NULL;
-out_obj:
- visit_end_struct(v, &err);
-out:
- error_propagate(errp, err);
-}
-''',
- c_name=c_name(name))
-
- return ret
-
-
def gen_visit_list(name, element_type):
# FIXME: if *obj is NULL on entry, and the first visit_next_list()
# assigns to *obj, while a later one fails, we should clean up *obj
}
for (prev = (GenericList **)obj;
- !err && (i = visit_next_list(v, prev)) != NULL;
+ !err && (i = visit_next_list(v, prev, sizeof(**obj))) != NULL;
prev = &i) {
%(c_name)s *native_i = (%(c_name)s *)i;
visit_type_%(c_elt_type)s(v, NULL, &native_i->value, &err);
def gen_visit_alternate(name, variants):
promote_int = 'true'
+ ret = ''
for var in variants.variants:
if var.type.alternate_qtype() == 'QTYPE_QINT':
promote_int = 'false'
+ if isinstance(var.type, QAPISchemaObjectType):
+ ret += gen_visit_fields_decl(var.type)
- ret = mcgen('''
+ ret += mcgen('''
void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
{
}
switch ((*obj)->type) {
''',
- c_name=c_name(name), promote_int=promote_int)
+ c_name=c_name(name), promote_int=promote_int)
for var in variants.variants:
ret += mcgen('''
case %(case)s:
+''',
+ case=var.type.alternate_qtype())
+ if isinstance(var.type, QAPISchemaObjectType):
+ ret += mcgen('''
+ visit_start_struct(v, name, NULL, 0, &err);
+ if (err) {
+ break;
+ }
+ visit_type_%(c_type)s_fields(v, &(*obj)->u.%(c_name)s, &err);
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_struct(v, &err);
+''',
+ c_type=var.type.c_name(),
+ c_name=c_name(var.name))
+ else:
+ ret += mcgen('''
visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, &err);
- break;
''',
- case=var.type.alternate_qtype(),
- c_type=var.type.c_name(),
- c_name=c_name(var.name))
+ c_type=var.type.c_name(),
+ c_name=c_name(var.name))
+ ret += mcgen('''
+ break;
+''')
ret += mcgen('''
default:
return ret
-def gen_visit_union(name, base, members, variants):
+def gen_visit_object(name, base, members, variants):
ret = gen_visit_struct_fields(name, base, members, variants)
+ # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
+ # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
+ # rather than leaving it non-NULL. As currently written, the caller must
+ # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
ret += mcgen('''
void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
if (!*obj) {
goto out_obj;
}
- visit_type_%(c_name)s_fields(v, obj, &err);
+ visit_type_%(c_name)s_fields(v, *obj, &err);
error_propagate(errp, err);
err = NULL;
out_obj:
def visit_object_type(self, name, info, base, members, variants):
self.decl += gen_visit_decl(name)
- if variants:
- self.defn += gen_visit_union(name, base, members, variants)
- else:
- self.defn += gen_visit_struct(name, base, members)
+ self.defn += gen_visit_object(name, base, members, variants)
def visit_alternate_type(self, name, info, variants):
self.decl += gen_visit_decl(name)