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@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Wei Liu authored and Ian Campbell committed 2014-07-10 13:06:55 +01:00
1 parent c7857abd91
commit a4e5aea5d3
8 files changed
+221 -19

No files matched your search

+5 -3
View File
@@ -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)
+157 -3
View File
@@ -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()
+20
View File
@@ -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_')])
+6 -1
View File
@@ -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:
+14
View File
@@ -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
+2
View File
@@ -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)
+14 -11
View File
@@ -5,22 +5,25 @@
namespace("libxl_")
libxl_defbool = Builtin("defbool", passby=PASS_BY_REFERENCE, check_default_fn="libxl__defbool_is_default")
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", 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_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),
+3 -1
View File
@@ -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"),
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.