From: Wei Liu <wei.liu2@citrix.com>
To: xen-devel@lists.xen.org
Cc: Wei Liu <wei.liu2@citrix.com>,
ian.jackson@eu.citrix.com, ian.campbell@citrix.com
Subject: [PATCH RFC V2 08/10] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct
Date: Thu, 17 Apr 2014 12:13:09 +0100 [thread overview]
Message-ID: <1397733191-31892-9-git-send-email-wei.liu2@citrix.com> (raw)
In-Reply-To: <1397733191-31892-1-git-send-email-wei.liu2@citrix.com>
libxl_FOO_parse_json functions are generated.
Note that these functions are used to parse libxl__json_object to
libxl__FOO struct. They don't consume JSON string.
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
tools/libxl/gentypes.py | 102 ++++++++++++++++++++++++++++++++++
tools/libxl/idl.py | 13 +++++
tools/libxl/libxl_types.idl | 31 ++++++-----
tools/libxl/libxl_types_internal.idl | 4 +-
4 files changed, 136 insertions(+), 14 deletions(-)
diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py
index 8d7183a..d2671cb 100644
--- a/tools/libxl/gentypes.py
+++ b/tools/libxl/gentypes.py
@@ -270,6 +270,90 @@ def libxl_C_type_to_json(ty, v, indent = " "):
s = indent + s
return s.replace("\n", "\n%s" % indent).rstrip(indent)
+def libxl_C_type_parse_json(ty, w, v, indent = " ", parent = None):
+ s = ""
+ if parent is None:
+ s += "int rc = 0;\n"
+ s += "const libxl__json_object *x = o;\n"
+
+ if isinstance(ty, idl.Array):
+ if parent is None:
+ raise Exception("Array type must have a parent")
+ lenvar = parent + ty.lenvar.name
+ s += "{\n"
+ s += " libxl__json_object *t;\n"
+ s += " int i;\n"
+ s += " assert(libxl__json_object_is_array(x));\n"
+ s += " %s = x->u.array->count;\n" % lenvar
+ s += " %s = calloc(%s, sizeof(*%s));\n" % (v, lenvar, v)
+ s += " if (!%s) {\n" % v
+ s += " rc = -1;\n"
+ s += " goto out;\n"
+ s += " }\n"
+ s += " for (i=0; (t=libxl__json_array_get(x,i)); i++) {\n"
+ s += libxl_C_type_parse_json(ty.elem_type, "t", v+"[i]",
+ indent + " ", parent)
+ s += " }\n"
+ s += " assert(i == %s);\n" % lenvar
+ s += "}\n"
+ elif isinstance(ty, idl.Enumeration):
+ s += "{\n"
+ s += " const char *enum_str;\n"
+ s += " assert(libxl__json_object_is_string(x));\n"
+ s += " enum_str = libxl__json_object_get_string(x);\n"
+ s += " rc = %s_from_string(enum_str, %s);\n" % (ty.typename, ty.pass_arg(v, parent is None, idl.PASS_BY_REFERENCE))
+ s += " if (rc)\n"
+ s += " goto out;\n"
+ s += "}\n"
+ elif isinstance(ty, idl.KeyedUnion):
+ if parent is None:
+ raise Exception("KeyedUnion type must have a parent")
+ s += "switch (%s) {\n" % (parent + ty.keyvar.name)
+ for f in ty.fields:
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ s += "case %s:\n" % f.enumname
+ if f.type is not None:
+ s += libxl_C_type_parse_json(f.type, w, fexpr, indent + " ", nparent)
+ s += " break;\n"
+ s += "}\n"
+ elif isinstance(ty, idl.Struct) and (parent is None or ty.json_parse_fn is None):
+ for f in [f for f in ty.fields if not f.const and not f.type.private]:
+ if isinstance(f.type, idl.KeyedUnion):
+ s += "x = libxl__json_map_get(\"%s\", %s, %s);\n" % \
+ (f.type.keyvar.name, w, f.type.keyvar.type.json_parse_type)
+ s += "if (x) {\n"
+ (nparent,fexpr) = ty.member(v, f.type.keyvar, parent is None)
+ s += libxl_C_type_parse_json(f.type.keyvar.type, "x", fexpr, " ", nparent)
+ s += "}\n"
+ s += "x = libxl__json_map_get(\"%s\", %s, %s);\n" % (f.name, w, f.type.json_parse_type)
+ s += "if (x) {\n"
+ (nparent,fexpr) = ty.member(v, f, parent is None)
+ s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent)
+ s += " x = x->parent;\n"
+ s += "}\n"
+ else:
+ if ty.json_parse_fn is not None:
+ s += "rc = %s(ctx, %s, &%s);\n" % (ty.json_parse_fn, w, v)
+ s += "if (rc)\n"
+ s += " goto out;\n"
+
+ if parent is None:
+ s += "out:\n"
+ s += "return rc;\n"
+
+ if s != "":
+ s = indent +s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
+def libxl_C_type_from_json(ty, v, w, indent = " "):
+ s = ""
+ parse = "(libxl__json_parse_callback)&%s_parse_json" % ty.typename
+ s += "return libxl__object_from_json(ctx, \"%s\", %s, %s, %s);\n" % (ty.typename, parse, v, w)
+
+ if s != "":
+ s = indent + s
+ return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
def libxl_C_enum_to_string(ty, e, indent = " "):
s = ""
s += "switch(%s) {\n" % e
@@ -348,6 +432,8 @@ if __name__ == '__main__':
ku.keyvar.type.make_arg(ku.keyvar.name)))
if ty.json_gen_fn is not None:
f.write("%schar *%s_to_json(libxl_ctx *ctx, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p")))
+ if ty.json_parse_fn is not None:
+ f.write("%sint %s_from_json(libxl_ctx *ctx, %s, const char *s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
if isinstance(ty, idl.Enumeration):
f.write("%sconst char *%s_to_string(%s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p")))
f.write("%sint %s_from_string(const char *s, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("e", passby=idl.PASS_BY_REFERENCE)))
@@ -377,6 +463,9 @@ if __name__ == '__main__':
for ty in [ty for ty in types if ty.json_gen_fn is not None]:
f.write("%syajl_gen_status %s_gen_json(yajl_gen hand, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+ for ty in [ty for ty in types if ty.json_parse_fn is not None]:
+ f.write("%sint %s_parse_json(libxl_ctx *ctx, const libxl__json_object *o, %s);\n" % (ty.hidden(), ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+
f.write("\n")
f.write("""#endif /* %s */\n""" % header_json_define)
f.close()
@@ -444,4 +533,17 @@ if __name__ == '__main__':
f.write("}\n")
f.write("\n")
+ for ty in [t for t in types if t.json_parse_fn is not None]:
+ f.write("int %s_parse_json(libxl_ctx *ctx, const libxl__json_object *%s, %s)\n" % (ty.typename,"o",ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+ f.write("{\n")
+ f.write(libxl_C_type_parse_json(ty, "o", "p"))
+ f.write("}\n")
+ f.write("\n")
+
+ f.write("int %s_from_json(libxl_ctx *ctx, %s, const char *s)\n" % (ty.typename, ty.make_arg("p", passby=idl.PASS_BY_REFERENCE)))
+ f.write("{\n")
+ f.write(libxl_C_type_from_json(ty, "p", "s"))
+ f.write("}\n")
+ f.write("\n")
+
f.close()
diff --git a/tools/libxl/idl.py b/tools/libxl/idl.py
index 92133a3..ec1c429 100644
--- a/tools/libxl/idl.py
+++ b/tools/libxl/idl.py
@@ -66,8 +66,12 @@ class Type(object):
if self.typename is not None and not self.private:
self.json_gen_fn = kwargs.setdefault('json_gen_fn', self.typename + "_gen_json")
+ self.json_parse_type = kwargs.setdefault('json_parse_type', "JSON_ANY")
+ self.json_parse_fn = kwargs.setdefault('json_parse_fn', self.typename + "_parse_json")
else:
self.json_gen_fn = kwargs.setdefault('json_gen_fn', None)
+ self.json_parse_type = kwargs.setdefault('json_parse_type', None)
+ self.json_parse_fn = kwargs.setdefault('json_parse_fn', None)
self.autogenerate_json = kwargs.setdefault('autogenerate_json', True)
@@ -119,6 +123,8 @@ class Number(Builtin):
kwargs.setdefault('dispose_fn', None)
kwargs.setdefault('signed', False)
kwargs.setdefault('json_gen_fn', "yajl_gen_integer")
+ kwargs.setdefault('json_parse_type', "JSON_INTEGER")
+ kwargs.setdefault('json_parse_fn', "libxl__integer_parse_json")
self.signed = kwargs['signed']
Builtin.__init__(self, ctype, **kwargs)
@@ -142,6 +148,7 @@ class EnumerationValue(object):
class Enumeration(Type):
def __init__(self, typename, values, **kwargs):
kwargs.setdefault('dispose_fn', None)
+ kwargs.setdefault('json_parse_type', "JSON_STRING")
Type.__init__(self, typename, **kwargs)
self.value_namespace = kwargs.setdefault('value_namespace',
@@ -171,6 +178,7 @@ class Field(object):
class Aggregate(Type):
"""A type containing a collection of other types"""
def __init__(self, kind, typename, fields, **kwargs):
+ kwargs.setdefault('json_parse_type', "JSON_MAP")
Type.__init__(self, typename, **kwargs)
if self.typename is not None:
@@ -257,6 +265,8 @@ class KeyedUnion(Aggregate):
void = Builtin("void *", namespace = None)
bool = Builtin("bool", namespace = None,
json_gen_fn = "yajl_gen_bool",
+ json_parse_type = "JSON_BOOL",
+ json_parse_fn = "libxl__bool_parse_json",
autogenerate_json = False)
size_t = Number("size_t", namespace = None)
@@ -270,12 +280,15 @@ uint64 = UInt(64)
string = Builtin("char *", namespace = None, dispose_fn = "free",
json_gen_fn = "libxl__string_gen_json",
+ json_parse_type = "JSON_STRING | JSON_NULL",
+ json_parse_fn = "libxl__string_parse_json",
autogenerate_json = False)
class Array(Type):
"""An array of the same type"""
def __init__(self, elem_type, lenvar_name, **kwargs):
kwargs.setdefault('dispose_fn', 'free')
+ kwargs.setdefault('json_parse_type', 'JSON_ARRAY')
Type.__init__(self, namespace=elem_type.namespace, typename=elem_type.rawname + " *", **kwargs)
lv_kwargs = dict([(x.lstrip('lenvar_'),y) for (x,y) in kwargs.items() if x.startswith('lenvar_')])
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 755c918..77601ff 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -5,18 +5,23 @@
namespace("libxl_")
-libxl_defbool = Builtin("defbool", passby=PASS_BY_REFERENCE)
-
-libxl_domid = Builtin("domid", json_gen_fn = "yajl_gen_integer", autogenerate_json = False)
-libxl_devid = Builtin("devid", json_gen_fn = "yajl_gen_integer", autogenerate_json = False, signed = True, init_val="-1")
-libxl_uuid = Builtin("uuid", passby=PASS_BY_REFERENCE)
-libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE)
-libxl_bitmap = Builtin("bitmap", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE)
-libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE)
-
-libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE)
-libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE)
-libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE)
+libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE)
+
+libxl_domid = Builtin("domid", json_gen_fn = "yajl_gen_integer", json_parse_fn = "libxl__integer_parse_json",
+ json_parse_type = "JSON_INTEGER", autogenerate_json = False)
+libxl_devid = Builtin("devid", json_gen_fn = "yajl_gen_integer", json_parse_fn = "libxl__integer_parse_json",
+ json_parse_type = "JSON_INTEGER", autogenerate_json = False, signed = True, init_val="-1")
+libxl_uuid = Builtin("uuid", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE)
+libxl_mac = Builtin("mac", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE)
+libxl_bitmap = Builtin("bitmap", json_parse_type="JSON_ARRAY", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE)
+libxl_cpuid_policy_list = Builtin("cpuid_policy_list", json_parse_type="JSON_ARRAY",
+ dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE)
+
+libxl_string_list = Builtin("string_list", json_parse_type="JSON_ARRAY",
+ dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE)
+libxl_key_value_list = Builtin("key_value_list", json_parse_type="JSON_MAP",
+ dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE)
+libxl_hwcap = Builtin("hwcap", json_parse_type="JSON_ARRAY", passby=PASS_BY_REFERENCE)
#
# Specific integer types
@@ -575,7 +580,7 @@ libxl_event_type = Enumeration("event_type", [
libxl_ev_user = UInt(64)
-libxl_ev_link = Builtin("ev_link", passby=PASS_BY_REFERENCE, private=True)
+libxl_ev_link = Builtin("ev_link", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, private=True)
libxl_event = Struct("event",[
("link", libxl_ev_link),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index a964851..125dbac 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -1,7 +1,9 @@
namespace("libxl__")
hidden(True)
-libxl_domid = Builtin("domid", namespace="libxl_", json_gen_fn = "yajl_gen_integer")
+libxl_domid = Builtin("domid", namespace="libxl_", json_gen_fn = "yajl_gen_integer",
+ json_parse_fn = "libxl__integer_parse_json", json_parse_type = "JSON_INTEGER",
+ autogenerate_json = False)
libxl__qmp_message_type = Enumeration("qmp_message_type", [
(1, "QMP"),
--
1.7.10.4
next prev parent reply other threads:[~2014-04-17 11:13 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-17 11:13 [PATCH RFC V2 00/10] xl/libxl: JSON infrastructure and new "xl-json" format Wei Liu
2014-04-17 11:13 ` [PATCH RFC V2 01/10] libxl IDL: rename json_fn to json_gen_fn Wei Liu
2014-04-17 11:13 ` [PATCH RFC V2 02/10] libxl_json: introduce libx__object_from_json Wei Liu
2014-04-22 14:49 ` Ian Campbell
2014-04-17 11:13 ` [PATCH RFC V2 03/10] libxl_internal: make JSON_* types bit-field Wei Liu
2014-04-22 14:50 ` Ian Campbell
2014-04-17 11:13 ` [PATCH RFC V2 04/10] libxl_internal: introduce libxl__json_object_is_{null, number, double} Wei Liu
2014-04-17 11:13 ` [PATCH RFC V2 05/10] libxl_json: introduce parser functions for builtin types Wei Liu
2014-04-22 15:09 ` Ian Campbell
2014-04-23 10:01 ` Wei Liu
2014-04-23 10:12 ` Ian Campbell
2014-04-23 10:19 ` Wei Liu
2014-04-23 10:31 ` Ian Campbell
2014-04-23 10:42 ` Wei Liu
2014-04-23 11:14 ` Wei Liu
2014-04-23 11:41 ` Ian Campbell
2014-04-23 12:00 ` Wei Liu
2014-04-24 15:28 ` Ian Jackson
2014-04-23 15:20 ` Wei Liu
2014-04-24 15:29 ` Ian Jackson
2014-04-17 11:13 ` [PATCH RFC V2 06/10] libxl_json: allow basic JSON type objects generation Wei Liu
2014-04-22 15:22 ` Ian Campbell
2014-04-23 10:15 ` Wei Liu
2014-04-23 10:30 ` Ian Campbell
2014-04-23 10:36 ` Wei Liu
2014-04-23 11:39 ` Ian Campbell
2014-04-17 11:13 ` [PATCH RFC V2 07/10] libxl/gentypes.py: generate JSON object for keyed-union discriminator Wei Liu
2014-04-22 15:27 ` Ian Campbell
2014-04-22 15:32 ` Wei Liu
2014-04-17 11:13 ` Wei Liu [this message]
2014-04-22 15:46 ` [PATCH RFC V2 08/10] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Ian Campbell
2014-04-22 15:54 ` Wei Liu
2014-04-22 16:01 ` Ian Campbell
2014-04-22 16:12 ` Wei Liu
2014-04-17 11:13 ` [PATCH RFC V2 09/10] libxl/gentest.py: test JSON parser Wei Liu
2014-04-22 15:47 ` Ian Campbell
2014-04-22 15:49 ` Wei Liu
2014-04-22 15:58 ` Ian Campbell
2014-04-17 11:13 ` [PATCH RFC V2 10/10] xl: introduce "xl-json" format Wei Liu
2014-04-19 8:35 ` Wei Liu
2014-04-22 10:15 ` Ian Campbell
2014-04-22 10:25 ` Wei Liu
2014-04-22 10:33 ` Ian Campbell
2014-04-22 13:50 ` Ian Jackson
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=1397733191-31892-9-git-send-email-wei.liu2@citrix.com \
--to=wei.liu2@citrix.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=xen-devel@lists.xen.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).