libxl/gentypes.py: special-case KeyedUnion map handle generation
authorWei Liu <wei.liu2@citrix.com>
Mon, 9 Jun 2014 12:43:21 +0000 (13:43 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Tue, 10 Jun 2014 13:08:27 +0000 (14:08 +0100)
Generate JSON map handle according to KeyedUnion discriminator.

The original JSON output for a keyed union is like:
 {
   ...
   "u" : { FIELDS }
   ...
 }

The discriminator is not generated, so that the parser won't be able to
figure out the fields in the incoming stream.

So we need to change this to something more sensible. For example, for
keyed union libxl_domain_type, which has a discriminator called "type",
we generate following for HVM guest:
 {
   ...
   "type.hvm" : { HVM FIELDS }
   ...
 }

Parser then can know the type of this union and how to interpret the
incoming stream.

Note that we change the existing API here. However the original output is
quite broken anyway, we cannot make sensible use of it and I doubt that
there's existing user of existing API. So we are acutally fixing a
problem.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
tools/libxl/gentypes.py

index 61a2b3ddc951eafa0f626cc472dfdf68e28fd382..01416e7c63327694ab59ea338b96bd1e6ea267a5 100644 (file)
@@ -186,6 +186,26 @@ def libxl_C_type_member_init(ty, field):
     s += "\n"
     return s
 
+def libxl_C_type_gen_map_key(f, parent, indent = ""):
+    s = ""
+    if isinstance(f.type, idl.KeyedUnion):
+        s += "switch (%s) {\n" % (parent + f.type.keyvar.name)
+        for x in f.type.fields:
+            v = f.type.keyvar.name + "." + x.name
+            s += "case %s:\n" % x.enumname
+            s += "    s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (v, v)
+            s += "    if (s != yajl_gen_status_ok)\n"
+            s += "        goto out;\n"
+            s += "    break;\n"
+        s += "}\n"
+    else:
+        s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (f.name, f.name)
+        s += "if (s != yajl_gen_status_ok)\n"
+        s += "    goto out;\n"
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
 def libxl_C_type_gen_json(ty, v, indent = "    ", parent = None):
     s = ""
     if parent is None:
@@ -235,9 +255,7 @@ def libxl_C_type_gen_json(ty, v, indent = "    ", parent = None):
         s += "    goto out;\n"
         for f in [f for f in ty.fields if not f.const and not f.type.private]:
             (nparent,fexpr) = ty.member(v, f, parent is None)
-            s += "s = yajl_gen_string(hand, (const unsigned char *)\"%s\", sizeof(\"%s\")-1);\n" % (f.name, f.name)
-            s += "if (s != yajl_gen_status_ok)\n"
-            s += "    goto out;\n"
+            s += libxl_C_type_gen_map_key(f, nparent)
             s += libxl_C_type_gen_json(f.type, fexpr, "", nparent)
         s += "s = yajl_gen_map_close(hand);\n"
         s += "if (s != yajl_gen_status_ok)\n"