From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: mdroth@linux.vnet.ibm.com, marcandre.lureau@redhat.com,
eblake@redhat.com
Subject: [Qemu-devel] [PATCH RFC 04/14] qapi: generate a literal qobject for introspection
Date: Mon, 12 Feb 2018 08:21:57 +0100 [thread overview]
Message-ID: <20180212072207.9367-5-armbru@redhat.com> (raw)
In-Reply-To: <20180212072207.9367-1-armbru@redhat.com>
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Replace the generated json string with a literal qobject. The later is
easier to deal with, at run time as well as compile time: adding #if
conditionals will be easier than in a json string.
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
FIXME doc diffs
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
docs/devel/qapi-code-gen.txt | 29 +++++++++-----
monitor.c | 2 +-
scripts/qapi/introspect.py | 80 ++++++++++++++++++++++----------------
tests/test-qobject-input-visitor.c | 11 ++++--
4 files changed, 73 insertions(+), 49 deletions(-)
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 0c4fc342fe..cb6175ba4d 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -1318,18 +1318,27 @@ Example:
#ifndef EXAMPLE_QMP_INTROSPECT_H
#define EXAMPLE_QMP_INTROSPECT_H
- extern const char example_qmp_schema_json[];
+ extern const QLitObject qmp_schema_qlit;
#endif
$ cat qapi-generated/example-qapi-introspect.c
[Uninteresting stuff omitted...]
- const char example_qmp_schema_json[] = "["
- "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": \"MY_EVENT\"}, "
- "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": \"my-command\", \"ret-type\": \"2\"}, "
- "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
- "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], \"meta-type\": \"object\", \"name\": \"1\"}, "
- "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
- "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": \"[2]\"}, "
- "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": \"int\"}, "
- "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": \"str\"}]";
+ const QLitObject example_qmp_schema_qlit = QLIT_QLIST(((QLitObject[]) {
+ QLIT_QDICT(((QLitDictEntry[]) {
+ { "arg-type", QLIT_QSTR("0") },
+ { "meta-type", QLIT_QSTR("event") },
+ { "name", QLIT_QSTR("Event") },
+ { }
+ })),
+ QLIT_QDICT(((QLitDictEntry[]) {
+ { "members", QLIT_QLIST(((QLitObject[]) {
+ { }
+ })) },
+ { "meta-type", QLIT_QSTR("object") },
+ { "name", QLIT_QSTR("0") },
+ { }
+ })),
+ ...
+ { }
+ }));
diff --git a/monitor.c b/monitor.c
index d0e8d350fd..877b90f16d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -956,7 +956,7 @@ EventInfoList *qmp_query_events(Error **errp)
static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
Error **errp)
{
- *ret_data = qobject_from_json(qmp_schema_json, &error_abort);
+ *ret_data = qobject_from_qlit(&qmp_schema_qlit);
}
/*
diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py
index 6c86673a09..e5c491d936 100644
--- a/scripts/qapi/introspect.py
+++ b/scripts/qapi/introspect.py
@@ -13,26 +13,35 @@ See the COPYING file in the top-level directory.
from qapi.common import *
-# Caveman's json.dumps() replacement (we're stuck at Python 2.4)
-# TODO try to use json.dumps() once we get unstuck
-def to_json(obj, level=0):
+def to_qlit(obj, level=0, suppress_first_indent=False):
+
+ def indent(level):
+ return level * 4 * ' '
+
+ if not suppress_first_indent:
+ ret = indent(level)
if obj is None:
- ret = 'null'
+ ret = 'QLIT_QNULL'
elif isinstance(obj, str):
- ret = '"' + obj.replace('"', r'\"') + '"'
+ ret = 'QLIT_QSTR(' + to_c_string(obj) + ')'
elif isinstance(obj, list):
- elts = [to_json(elt, level + 1)
+ elts = [to_qlit(elt, level + 1)
for elt in obj]
- ret = '[' + ', '.join(elts) + ']'
+ elts.append(indent(level + 1) + "{}")
+ ret = 'QLIT_QLIST(((QLitObject[]) {\n'
+ ret += ',\n'.join(elts) + '\n'
+ ret += indent(level) + '}))'
elif isinstance(obj, dict):
- elts = ['"%s": %s' % (key.replace('"', r'\"'),
- to_json(obj[key], level + 1))
- for key in sorted(obj.keys())]
- ret = '{' + ', '.join(elts) + '}'
+ elts = []
+ for key, value in sorted(obj.iteritems()):
+ elts.append(indent(level + 1) + '{ %s, %s }' %
+ (to_c_string(key), to_qlit(value, level + 1, True)))
+ elts.append(indent(level + 1) + '{}')
+ ret = 'QLIT_QDICT(((QLitDictEntry[]) {\n'
+ ret += ',\n'.join(elts) + '\n'
+ ret += indent(level) + '}))'
else:
assert False # not implemented
- if level == 1:
- ret = '\n' + ret
return ret
@@ -48,38 +57,41 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor):
' * QAPI/QMP schema introspection', __doc__)
self._unmask = unmask
self._schema = None
- self._jsons = []
+ self._qlits = None
+ self._used_types = None
+ self._name_map = None
+
+ def visit_begin(self, schema):
+ self._schema = schema
+ self._qlits = []
self._used_types = []
self._name_map = {}
- var = c_name(self._prefix, protect=False) + 'qmp_schema_json'
+ var = c_name(self._prefix, protect=False) + 'qmp_schema_qlit'
self._genc.add(mcgen('''
#include "qemu/osdep.h"
#include "%(prefix)sqapi-introspect.h"
-const char %(var)s[] = ''',
- var=var, prefix=prefix))
+const QLitObject %(var)s = ''',
+ var=var, prefix=self._prefix))
self._genh.add(mcgen('''
-extern const char %(var)s[];
+#include "qapi/qmp/qlit.h"
+
+extern const QLitObject %(var)s;
''',
var=var))
- def visit_begin(self, schema):
- self._schema = schema
-
def visit_end(self):
# visit the types that are actually used
for typ in self._used_types:
typ.visit(self)
# generate C
# TODO can generate awfully long lines
- lines = to_json(self._jsons).split('\n')
- c_string = '\n '.join([to_c_string(line) for line in lines])
self._genc.add(mcgen('''
%(c_string)s;
''',
- c_string=c_string))
+ c_string=to_qlit(self._qlits)))
self._schema = None
- self._jsons = []
+ self._qlits = None
self._used_types = []
self._name_map = {}
@@ -113,12 +125,12 @@ extern const char %(var)s[];
return '[' + self._use_type(typ.element_type) + ']'
return self._name(typ.name)
- def _gen_json(self, name, mtype, obj):
+ def _gen_qlit(self, name, mtype, obj):
if mtype not in ('command', 'event', 'builtin', 'array'):
name = self._name(name)
obj['name'] = name
obj['meta-type'] = mtype
- self._jsons.append(obj)
+ self._qlits.append(obj)
def _gen_member(self, member):
ret = {'name': member.name, 'type': self._use_type(member.type)}
@@ -134,24 +146,24 @@ extern const char %(var)s[];
return {'case': variant.name, 'type': self._use_type(variant.type)}
def visit_builtin_type(self, name, info, json_type):
- self._gen_json(name, 'builtin', {'json-type': json_type})
+ self._gen_qlit(name, 'builtin', {'json-type': json_type})
def visit_enum_type(self, name, info, values, prefix):
- self._gen_json(name, 'enum', {'values': values})
+ self._gen_qlit(name, 'enum', {'values': values})
def visit_array_type(self, name, info, element_type):
element = self._use_type(element_type)
- self._gen_json('[' + element + ']', 'array', {'element-type': element})
+ self._gen_qlit('[' + element + ']', 'array', {'element-type': element})
def visit_object_type_flat(self, name, info, members, variants):
obj = {'members': [self._gen_member(m) for m in members]}
if variants:
obj.update(self._gen_variants(variants.tag_member.name,
variants.variants))
- self._gen_json(name, 'object', obj)
+ self._gen_qlit(name, 'object', obj)
def visit_alternate_type(self, name, info, variants):
- self._gen_json(name, 'alternate',
+ self._gen_qlit(name, 'alternate',
{'members': [{'type': self._use_type(m.type)}
for m in variants.variants]})
@@ -159,13 +171,13 @@ extern const char %(var)s[];
gen, success_response, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
ret_type = ret_type or self._schema.the_empty_object_type
- self._gen_json(name, 'command',
+ self._gen_qlit(name, 'command',
{'arg-type': self._use_type(arg_type),
'ret-type': self._use_type(ret_type)})
def visit_event(self, name, info, arg_type, boxed):
arg_type = arg_type or self._schema.the_empty_object_type
- self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)})
+ self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)})
def gen_introspect(schema, output_dir, prefix, opt_unmask):
diff --git a/tests/test-qobject-input-visitor.c b/tests/test-qobject-input-visitor.c
index 79b1a8cb17..55db6bdef1 100644
--- a/tests/test-qobject-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1250,24 +1250,27 @@ static void test_visitor_in_fail_alternate(TestInputVisitorData *data,
}
static void do_test_visitor_in_qmp_introspect(TestInputVisitorData *data,
- const char *schema_json)
+ const QLitObject *qlit)
{
SchemaInfoList *schema = NULL;
+ QObject *obj = qobject_from_qlit(qlit);
Visitor *v;
- v = visitor_input_test_init_raw(data, schema_json);
+ v = qobject_input_visitor_new(obj);
visit_type_SchemaInfoList(v, NULL, &schema, &error_abort);
g_assert(schema);
qapi_free_SchemaInfoList(schema);
+ qobject_decref(obj);
+ visit_free(v);
}
static void test_visitor_in_qmp_introspect(TestInputVisitorData *data,
const void *unused)
{
- do_test_visitor_in_qmp_introspect(data, test_qmp_schema_json);
- do_test_visitor_in_qmp_introspect(data, qmp_schema_json);
+ do_test_visitor_in_qmp_introspect(data, &test_qmp_schema_qlit);
+ do_test_visitor_in_qmp_introspect(data, &qmp_schema_qlit);
}
int main(int argc, char **argv)
--
2.13.6
next prev parent reply other threads:[~2018-02-12 7:22 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20180212072207.9367-1-armbru@redhat.com>
2018-02-12 7:21 ` [Qemu-devel] [PATCH RFC 01/14] qlit: use QType instead of int Markus Armbruster
2018-02-12 7:21 ` [Qemu-devel] [PATCH RFC 02/14] qlit: add qobject_from_qlit() Markus Armbruster
2018-02-12 7:21 ` [Qemu-devel] [PATCH RFC 03/14] qapi/introspect: Simplify WIP Markus Armbruster
2018-02-12 7:21 ` Markus Armbruster [this message]
2018-02-12 7:21 ` [Qemu-devel] [PATCH RFC 05/14] qapi2texi: minor python code simplification Markus Armbruster
2018-02-12 7:21 ` [Qemu-devel] [PATCH RFC 06/14] qapi: add 'if' to top-level expressions Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 07/14] qapi: pass 'if' condition into QAPISchemaEntity objects Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 08/14] qapi: leave the ifcond attribute undefined until check() Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 09/14] qapi: Pass ifcond to visitors Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 10/14] qapi: mcgen() shouldn't indent # lines Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 11/14] qapi: add #if/#endif helpers Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 12/14] qapi-introspect: modify to_qlit() to append ', ' on level > 0 Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 13/14] qapi-introspect: Add #if conditions to introspection value Markus Armbruster
2018-02-12 7:22 ` [Qemu-devel] [PATCH RFC 14/14] qapi: Add #if conditions to commands, events, types, visitors Markus Armbruster
2018-02-14 15:28 ` Marc-Andre Lureau
2018-02-23 18:13 ` Markus Armbruster
2018-04-19 22:35 ` Eric Blake
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180212072207.9367-5-armbru@redhat.com \
--to=armbru@redhat.com \
--cc=eblake@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mdroth@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.