From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: [PATCH V3 11/13] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Date: Wed, 23 Apr 2014 17:59:21 +0100 Message-ID: <1398272363-12133-12-git-send-email-wei.liu2@citrix.com> References: <1398272363-12133-1-git-send-email-wei.liu2@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1398272363-12133-1-git-send-email-wei.liu2@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: Wei Liu , ian.jackson@eu.citrix.com, ian.campbell@citrix.com List-Id: xen-devel@lists.xenproject.org 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 --- tools/libxl/gentypes.py | 114 ++++++++++++++++++++++++++++++++++ tools/libxl/idl.py | 15 +++++ tools/libxl/idl.txt | 7 ++- tools/libxl/libxl_types.idl | 31 +++++---- tools/libxl/libxl_types_internal.idl | 4 +- 5 files changed, 156 insertions(+), 15 deletions(-) diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py index 8d7183a..6aba75f 100644 --- a/tools/libxl/gentypes.py +++ b/tools/libxl/gentypes.py @@ -270,6 +270,99 @@ 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 += " if (!libxl__json_object_is_array(x)) {\n" + s += " rc = -1;\n" + s += " goto out;\n" + s += " }\n" + s += " %s = x->u.array->count;\n" % lenvar + s += " %s = calloc(%s, sizeof(*%s));\n" % (v, lenvar, v) + s += " if (!%s && %s != 0) {\n" % (v, lenvar) + 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 += " if (i != %s) {\n" % lenvar + s += " rc = -1;\n" + s += " goto out;\n" + s += " }\n" + s += "}\n" + elif isinstance(ty, idl.Enumeration): + s += "{\n" + s += " const char *enum_str;\n" + s += " if (!libxl__json_object_is_string(x)) {\n" + s += " rc = -1;\n" + s += " goto out;\n" + s += " }\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(gc, %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 +441,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 +472,10 @@ 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__gc *gc, 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 +543,19 @@ 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__gc *gc, 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") + if not isinstance(ty, idl.Enumeration): + f.write(" %s_init(p);\n" % ty.typename) + 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..9ce1e33 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,9 @@ 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") + # json_parse_fn might be overriden on specific type + kwargs.setdefault('json_parse_fn', "libxl__int_parse_json") self.signed = kwargs['signed'] Builtin.__init__(self, ctype, **kwargs) @@ -126,6 +133,7 @@ class UInt(Number): def __init__(self, w, **kwargs): kwargs.setdefault('namespace', None) kwargs.setdefault('dispose_fn', None) + kwargs.setdefault('json_parse_fn', "libxl__uint%d_parse_json" % w) Number.__init__(self, "uint%d_t" % w, **kwargs) self.width = w @@ -142,6 +150,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 +180,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 +267,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 +282,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/idl.txt b/tools/libxl/idl.txt index 6a53dd8..484d5d7 100644 --- a/tools/libxl/idl.txt +++ b/tools/libxl/idl.txt @@ -65,9 +65,14 @@ Type.json_gen_fn: (default: typename + "_gen_json" or None if type == None) The name of the C function which will generate a YAJL data structure representing this type. +Type.json_parse_fn: (default: typename + "_parse_json" or None if type == None) + + The name of the C function which will parse a libxl JSON structure + representing this type to C type. + Type.autogenerate_json: (default: True) - Indicates if the above named Type.json_gen_fn should be autogenerated. + Indicates if the above named Type.json_*_fn should be autogenerated. Other simple type-Classes ------------------------- diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 755c918..e064ce8 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__uint32_parse_json", + json_parse_type = "JSON_INTEGER", autogenerate_json = False) +libxl_devid = Builtin("devid", json_gen_fn = "yajl_gen_integer", json_parse_fn = "libxl__int_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..17533f1 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__uint32_parse_json", json_parse_type = "JSON_INTEGER", + autogenerate_json = False) libxl__qmp_message_type = Enumeration("qmp_message_type", [ (1, "QMP"), -- 1.7.10.4