From mboxrd@z Thu Jan 1 00:00:00 1970 From: Wei Liu Subject: [PATCH v6 12/18] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Date: Mon, 9 Jun 2014 13:43:23 +0100 Message-ID: <1402317809-26833-13-git-send-email-wei.liu2@citrix.com> References: <1402317809-26833-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: <1402317809-26833-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 | 131 ++++++++++++++++++++++++++++++++++ tools/libxl/idl.py | 15 ++++ tools/libxl/idl.txt | 7 +- tools/libxl/libxl.h | 14 ++++ tools/libxl/libxl_types.idl | 29 ++++---- tools/libxl/libxl_types_internal.idl | 4 +- 6 files changed, 186 insertions(+), 14 deletions(-) diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py index 611c8af..ca49965 100644 --- a/tools/libxl/gentypes.py +++ b/tools/libxl/gentypes.py @@ -304,6 +304,116 @@ 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, discriminator = 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") + if discriminator is not None: + raise Exception("Only KeyedUnion can have discriminator") + 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 = libxl__calloc(NOGC, %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): + if discriminator is not None: + raise Exception("Only KeyedUnion can have discriminator") + 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") + if discriminator is None: + raise Excpetion("KeyedUnion type must have a discriminator") + for f in ty.fields: + if f.enumname != discriminator: + continue + (nparent,fexpr) = ty.member(v, f, parent is None) + if f.type is not None: + s += libxl_C_type_parse_json(f.type, w, fexpr, indent + " ", nparent) + elif isinstance(ty, idl.Struct) and (parent is None or ty.json_parse_fn is None): + if discriminator is not None: + raise Exception("Only KeyedUnion can have discriminator") + for f in [f for f in ty.fields if not f.const and not f.type.private]: + saved_var_name = "saved_%s" % f.name + s += "{\n" + s += " const libxl__json_object *%s = NULL;\n" % saved_var_name + s += " %s = x;\n" % saved_var_name + if isinstance(f.type, idl.KeyedUnion): + for x in f.type.fields: + s += " x = libxl__json_map_get(\"%s\", %s, JSON_MAP);\n" % \ + (f.type.keyvar.name + "." + x.name, w) + s += " if (x) {\n" + (nparent, fexpr) = ty.member(v, f.type.keyvar, parent is None) + s += " %s = %s;\n" % (fexpr, x.enumname) + (nparent,fexpr) = ty.member(v, f, parent is None) + s += libxl_C_type_parse_json(f.type, "x", fexpr, " ", nparent, x.enumname) + s += " }\n" + else: + 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 += " }\n" + s += " x = %s;\n" % saved_var_name + s += "}\n" + else: + if discriminator is not None: + raise Exception("Only KeyedUnion can have discriminator") + 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 @@ -382,6 +492,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))) @@ -411,6 +523,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() @@ -478,4 +594,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 14ca165..1405764 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 @@ -143,6 +151,7 @@ class Enumeration(Type): def __init__(self, typename, values, **kwargs): kwargs.setdefault('dispose_fn', None) kwargs.setdefault('init_val', '0') + kwargs.setdefault('json_parse_type', "JSON_STRING") Type.__init__(self, typename, **kwargs) self.value_namespace = kwargs.setdefault('value_namespace', @@ -172,6 +181,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: @@ -258,6 +268,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) @@ -271,12 +283,15 @@ uint64 = UInt(64, json_gen_fn = "libxl__uint64_gen_json") 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, init_val = "NULL") 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.h b/tools/libxl/libxl.h index d14f25f..1fad0d2 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -305,6 +305,20 @@ * * Generates a JSON object from "p" in the form of a NULL terminated * string. + * + * libxl__from_json(const char *json) + * int libxl__from_json(const char *json) + * + * Parses "json" and returns: + * + * an int value, if is enumeration type. The value is the enum value + * representing the respective string in "json". + * + * an instance of , if is aggregate type. The returned + * instance has its fields filled in by the parser according to "json". + * + * If the parsing fails, caller cannot rely on the value / instance + * returned. */ #ifndef LIBXL_H #define LIBXL_H diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index d510e2d..ac203bb 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -5,19 +5,24 @@ namespace("libxl_") -libxl_defbool = Builtin("defbool", passby=PASS_BY_REFERENCE, +libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, init_val="LIBXL__DEFBOOL_DEFAULT") -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_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 @@ -583,7 +588,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