[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v9 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct
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. The new function definitions are generated to new header files called __libxl_types_*_private.h so that they don't contaminate public header. The suffix "private is chosen so we can avoid clashing with libxl_types_internal.idl stuffs. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> --- change since last version: declare dependency on new header files in Makefile. --- tools/libxl/Makefile | 8 +- tools/libxl/gentypes.py | 160 +++++++++++++++++++++++++++++++++- tools/libxl/idl.py | 20 +++++ tools/libxl/idl.txt | 7 +- tools/libxl/libxl.h | 14 +++ tools/libxl/libxl_internal.h | 2 + tools/libxl/libxl_types.idl | 27 +++--- tools/libxl/libxl_types_internal.idl | 4 +- 8 files changed, 222 insertions(+), 20 deletions(-) diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile index 78c1996..dd3dd8f 100644 --- a/tools/libxl/Makefile +++ b/tools/libxl/Makefile @@ -176,7 +176,7 @@ _libxl_save_msgs_helper.h _libxl_save_msgs_callout.h: \ libxl.h: _libxl_types.h libxl_json.h: _libxl_types_json.h -libxl_internal.h: _libxl_types_internal.h _paths.h +libxl_internal.h: _libxl_types_internal.h _libxl_types_private.h _libxl_types_internal_private.h _paths.h libxl_internal_json.h: _libxl_types_internal_json.h xl.h: _paths.h @@ -184,9 +184,11 @@ $(LIBXL_OBJS) $(LIBXL_TEST_OBJS) $(LIBXLU_OBJS) \ $(XL_OBJS) $(TEST_PROG_OBJS) $(SAVE_HELPER_OBJS): libxl.h $(LIBXL_OBJS) $(LIBXL_TEST_OBJS): libxl_internal.h -_libxl_type%.h _libxl_type%_json.h _libxl_type%.c: libxl_type%.idl gentypes.py idl.py - $(PYTHON) gentypes.py libxl_type$*.idl __libxl_type$*.h __libxl_type$*_json.h __libxl_type$*.c +_libxl_type%.h _libxl_type%_json.h _libxl_type%_private.h _libxl_type%.c: libxl_type%.idl gentypes.py idl.py + $(PYTHON) gentypes.py libxl_type$*.idl __libxl_type$*.h __libxl_type$*_private.h \ + __libxl_type$*_json.h __libxl_type$*.c $(call move-if-changed,__libxl_type$*.h,_libxl_type$*.h) + $(call move-if-changed,__libxl_type$*_private.h,_libxl_type$*_private.h) $(call move-if-changed,__libxl_type$*_json.h,_libxl_type$*_json.h) $(call move-if-changed,__libxl_type$*.c,_libxl_type$*.c) diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py index f06afd9..6cdeaa8 100644 --- a/tools/libxl/gentypes.py +++ b/tools/libxl/gentypes.py @@ -312,6 +312,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_init_type(%s, %s);\n" % (ty.typename, v, 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.namespace + "_" + ty.rawname) + 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 @@ -350,11 +460,11 @@ def libxl_C_enum_from_string(ty, str, e, indent = " "): if __name__ == '__main__': - if len(sys.argv) != 5: - print >>sys.stderr, "Usage: gentypes.py <idl> <header> <header-json> <implementation>" + if len(sys.argv) != 6: + print >>sys.stderr, "Usage: gentypes.py <idl> <header> <header-private> <header-json> <implementation>" sys.exit(1) - (_, idlname, header, header_json, impl) = sys.argv + (_, idlname, header, header_private, header_json, impl) = sys.argv (builtins,types) = idl.parse(idlname) @@ -390,6 +500,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))) @@ -423,6 +535,32 @@ if __name__ == '__main__': f.write("""#endif /* %s */\n""" % header_json_define) f.close() + print "outputting libxl type internal definitions to %s" % header_private + + f = open(header_private, "w") + + header_private_define = header_private.upper().replace('.','_') + f.write("""#ifndef %s +#define %s + +/* + * DO NOT EDIT. + * + * This file is autogenerated by + * "%s" + */ + +""" % (header_private_define, header_private_define, " ".join(sys.argv))) + + 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.namespace + "_" + ty.rawname, + ty.make_arg("p", passby=idl.PASS_BY_REFERENCE))) + + f.write("\n") + f.write("""#endif /* %s */\n""" % header_json_define) + f.close() + print "outputting libxl type implementations to %s" % impl f = open(impl, "w") @@ -486,4 +624,20 @@ 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.namespace + "_" + ty.rawname,"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 ada801a..63557db 100644 --- a/tools/libxl/idl.py +++ b/tools/libxl/idl.py @@ -68,8 +68,17 @@ 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") + if self.namespace is not None: + self.json_parse_fn = kwargs.setdefault('json_parse_fn', + self.namespace + "_" + self.rawname + "_parse_json") + else: + 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) @@ -121,6 +130,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) @@ -128,6 +140,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 @@ -144,6 +157,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', @@ -173,6 +187,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: @@ -259,6 +274,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) @@ -272,12 +289,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) 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 d47eba8..87c4952 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. Type.check_default_fn: diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index 459557d..4ab1617 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -317,6 +317,20 @@ * * Generates a JSON object from "p" in the form of a NULL terminated * string. + * + * <type *> libxl_<type>_from_json(const char *json) + * int libxl_<type>_from_json(const char *json) + * + * Parses "json" and returns: + * + * an int value, if <type> is enumeration type. The value is the enum value + * representing the respective string in "json". + * + * an instance of <type>, if <type> 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_internal.h b/tools/libxl/libxl_internal.h index ac8cfdf..177a8be 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -3198,6 +3198,8 @@ int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len); #else #define BUILD_BUG_ON(p) ((void)sizeof(char[1 - 2 * !!(p)])) #endif +#include "_libxl_types_private.h" +#include "_libxl_types_internal_private.h" /* This always return false, there's no "default value" for hw cap */ static inline int libxl__hwcap_is_default(libxl_hwcap *hwcap) diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index 439095a..244075a 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -5,22 +5,25 @@ namespace("libxl_") -libxl_defbool = Builtin("defbool", passby=PASS_BY_REFERENCE, check_default_fn="libxl__defbool_is_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, check_default_fn="libxl_uuid_is_nil") -libxl_mac = Builtin("mac", passby=PASS_BY_REFERENCE, check_default_fn="libxl__mac_is_default") -libxl_bitmap = Builtin("bitmap", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE, +libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, + check_default_fn="libxl__defbool_is_default") + +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, check_default_fn="libxl_uuid_is_nil") +libxl_mac = Builtin("mac", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, check_default_fn="libxl__mac_is_default") +libxl_bitmap = Builtin("bitmap", json_parse_type="JSON_ARRAY", dispose_fn="libxl_bitmap_dispose", passby=PASS_BY_REFERENCE, check_default_fn="libxl_bitmap_is_empty") libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE, - check_default_fn="libxl__cpuid_policy_is_empty") + json_parse_type="JSON_ARRAY", check_default_fn="libxl__cpuid_policy_is_empty") libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE, - check_default_fn="libxl__string_list_is_empty") + json_parse_type="JSON_ARRAY", check_default_fn="libxl__string_list_is_empty") libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE, - check_default_fn="libxl__key_value_list_is_empty") -libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE, + json_parse_type="JSON_MAP", check_default_fn="libxl__key_value_list_is_empty") +libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE, json_parse_type="JSON_ARRAY", check_default_fn="libxl__hwcap_is_default") libxl_ms_vm_genid = Builtin("ms_vm_genid", passby=PASS_BY_REFERENCE, check_default_fn="libxl_ms_vm_genid_is_zero") @@ -591,7 +594,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 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |