diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt index 0ce045c0b3a0351605732d9ae8b96406a9d4b937..91f44d01b9522e56e8332516810fd3bf860afc69 100644 --- a/docs/qapi-code-gen.txt +++ b/docs/qapi-code-gen.txt @@ -53,6 +53,23 @@ The use of '*' as a prefix to the name means the member is optional. Optional members should always be added to the end of the dictionary to preserve backwards compatibility. + +A complex type definition can specify another complex type as its base. +In this case, the fields of the base type are included as top-level fields +of the new complex type's dictionary in the QMP wire format. An example +definition is: + + { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } } + { 'type': 'BlockdevOptionsGenericCOWFormat', + 'base': 'BlockdevOptionsGenericFormat', + 'data': { '*backing': 'str' } } + +An example BlockdevOptionsGenericCOWFormat object on the wire could use +both fields like this: + + { "file": "/some/place/my-image", + "backing": "/some/place/my-backing-file" } + === Enumeration types === An enumeration type is a dictionary containing a single key whose value is a diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py index 566fe5e4d958fe11b50f4c08832bf41c4d693747..4a1652b56f3c40e25dce0d7da4ebd334ce80322c 100644 --- a/scripts/qapi-types.py +++ b/scripts/qapi-types.py @@ -86,6 +86,7 @@ def generate_struct(expr): structname = expr.get('type', "") fieldname = expr.get('field', "") members = expr['data'] + base = expr.get('base') ret = mcgen(''' struct %(name)s @@ -93,6 +94,9 @@ struct %(name)s ''', name=structname) + if base: + ret += generate_struct_fields({'base': base}) + ret += generate_struct_fields(members) if len(fieldname): diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 1e44004a1e0b67d8c234c3f718e418917d307782..c39e6284b8d03e3f055ba68cd0e665717d014191 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -17,7 +17,7 @@ import os import getopt import errno -def generate_visit_struct_fields(name, field_prefix, fn_prefix, members): +def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None): substructs = [] ret = '' full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix) @@ -42,6 +42,19 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error * name=name, full_name=full_name) push_indent() + if base: + ret += mcgen(''' +visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err); +if (!err) { + visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err); + error_propagate(errp, err); + err = NULL; + visit_end_implicit_struct(m, &err); +} +''', + c_prefix=c_var(field_prefix), + type=type_name(base), c_name=c_var('base')) + for argname, argentry, optional, structured in parse_args(members): if optional: ret += mcgen(''' @@ -124,8 +137,9 @@ def generate_visit_struct(expr): name = expr['type'] members = expr['data'] + base = expr.get('base') - ret = generate_visit_struct_fields(name, "", "", members) + ret = generate_visit_struct_fields(name, "", "", members, base) ret += mcgen('''