Skip to content

Commit

Permalink
qapi: Introduce a first class 'null' type
Browse files Browse the repository at this point in the history
I expect the 'null' type to be useful mostly for members of alternate
types.

Signed-off-by: Markus Armbruster <[email protected]>
Reviewed-by: Daniel P. Berrange <[email protected]>
Reviewed-by: Eric Blake <[email protected]>
Signed-off-by: Markus Armbruster <[email protected]>
  • Loading branch information
Markus Armbruster committed Jul 24, 2017
1 parent d2f95f4 commit 4d2d5c4
Show file tree
Hide file tree
Showing 8 changed files with 31 additions and 8 deletions.
10 changes: 6 additions & 4 deletions docs/devel/qapi-code-gen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ The following types are predefined, and map to C as follows:
size uint64_t like uint64_t, except StringInputVisitor
accepts size suffixes
bool bool JSON true or false
null QNull * JSON null
any QObject * any JSON value
QType QType JSON string matching enum QType values

Expand Down Expand Up @@ -536,10 +537,11 @@ can only express a choice between types represented differently in
JSON. If a branch is typed as the 'bool' built-in, the alternate
accepts true and false; if it is typed as any of the various numeric
built-ins, it accepts a JSON number; if it is typed as a 'str'
built-in or named enum type, it accepts a JSON string; and if it is
typed as a complex type (struct or union), it accepts a JSON object.
Two different complex types, for instance, aren't permitted, because
both are represented as a JSON object.
built-in or named enum type, it accepts a JSON string; if it is typed
as the 'null' built-in, it accepts JSON null; and if it is typed as a
complex type (struct or union), it accepts a JSON object. Two
different complex types, for instance, aren't permitted, because both
are represented as a JSON object.

The example alternate declaration above allows using both of the
following example objects:
Expand Down
4 changes: 2 additions & 2 deletions include/qapi/qmp/qobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ static inline QType qobject_type(const QObject *obj)
return obj->type;
}

typedef struct QNull {
struct QNull {
QObject base;
} QNull;
};

extern QNull qnull_;

Expand Down
1 change: 1 addition & 0 deletions include/qemu/typedefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ typedef struct QEMUSGList QEMUSGList;
typedef struct QEMUTimer QEMUTimer;
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
typedef struct QObject QObject;
typedef struct QNull QNull;
typedef struct RAMBlock RAMBlock;
typedef struct Range Range;
typedef struct SerialState SerialState;
Expand Down
5 changes: 4 additions & 1 deletion scripts/qapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from ordereddict import OrderedDict

builtin_types = {
'null': 'QTYPE_QNULL',
'str': 'QTYPE_QSTRING',
'int': 'QTYPE_QNUM',
'number': 'QTYPE_QNUM',
Expand Down Expand Up @@ -1056,6 +1057,7 @@ def json_type(self):

def alternate_qtype(self):
json2qtype = {
'null': 'QTYPE_QNULL',
'string': 'QTYPE_QSTRING',
'number': 'QTYPE_QNUM',
'int': 'QTYPE_QNUM',
Expand Down Expand Up @@ -1515,7 +1517,8 @@ def _def_predefineds(self):
('uint64', 'int', 'uint64_t'),
('size', 'int', 'uint64_t'),
('bool', 'boolean', 'bool'),
('any', 'value', 'QObject' + pointer_suffix)]:
('any', 'value', 'QObject' + pointer_suffix),
('null', 'null', 'QNull' + pointer_suffix)]:
self._def_builtin_type(*t)
self.the_empty_object_type = QAPISchemaObjectType(
'q_empty', None, None, None, [], None)
Expand Down
3 changes: 2 additions & 1 deletion tests/qapi-schema/qapi-schema-test.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@
{ 'struct': 'WrapAlternate',
'data': { 'alt': 'UserDefAlternate' } }
{ 'alternate': 'UserDefAlternate',
'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int' } }
'data': { 'udfu': 'UserDefFlatUnion', 'e': 'EnumOne', 'i': 'int',
'n': 'null' } }

{ 'struct': 'UserDefC',
'data': { 'string1': 'str', 'string2': 'str' } }
Expand Down
1 change: 1 addition & 0 deletions tests/qapi-schema/qapi-schema-test.out
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ alternate UserDefAlternate
case udfu: UserDefFlatUnion
case e: EnumOne
case i: int
case n: null
object UserDefB
member intb: int optional=False
member a-b: bool optional=True
Expand Down
5 changes: 5 additions & 0 deletions tests/test-qobject-input-visitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,11 @@ static void test_visitor_in_alternate(TestInputVisitorData *data,
g_assert_cmpint(tmp->u.e, ==, ENUM_ONE_VALUE1);
qapi_free_UserDefAlternate(tmp);

v = visitor_input_test_init(data, "null");
visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
g_assert_cmpint(tmp->type, ==, QTYPE_QNULL);
qapi_free_UserDefAlternate(tmp);

v = visitor_input_test_init(data, "{'integer':1, 'string':'str', "
"'enum1':'value1', 'boolean':true}");
visit_type_UserDefAlternate(v, NULL, &tmp, &error_abort);
Expand Down
10 changes: 10 additions & 0 deletions tests/test-qobject-output-visitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,16 @@ static void test_visitor_out_alternate(TestOutputVisitorData *data,

qapi_free_UserDefAlternate(tmp);

visitor_reset(data);
tmp = g_new0(UserDefAlternate, 1);
tmp->type = QTYPE_QNULL;
tmp->u.n = qnull();

visit_type_UserDefAlternate(data->ov, NULL, &tmp, &error_abort);
g_assert_cmpint(qobject_type(visitor_get(data)), ==, QTYPE_QNULL);

qapi_free_UserDefAlternate(tmp);

visitor_reset(data);
tmp = g_new0(UserDefAlternate, 1);
tmp->type = QTYPE_QDICT;
Expand Down

0 comments on commit 4d2d5c4

Please sign in to comment.