All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v8 0/8] libxl: JSON infrastructure
@ 2014-06-19 17:44 Wei Liu
  2014-06-19 17:44 ` [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types Wei Liu
                   ` (7 more replies)
  0 siblings, 8 replies; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

V8 of the series. This series only contains JSON infrastructure patches.

The JSON infrastructure was tested with running testidl over and over again. A
new testidl executable was generated every run.

Rebased on top of staging.

Legend:
  A - acked
  D - previous acked, but new change introduced so acked-by dropped
  S - the same version as last round
  No marker - new patch

Wei.

Wei Liu (8):
 S libxl_internal: functions to check default values for builtin types
 A libxl/gentypes.py: don't generate default values
   libxl: clean up namespace violation
 D libxl IDL: generate code to parse libxl__json_object to libxl_FOO
     struct
 A libxl/gentest.py: test JSON parser
 A libxl: copy function for builtin types
 A libxl IDL: generate deep copy functions
 A libxl/gentest.py: test deep copy functions

 tools/libxl/Makefile                 |    4 +-
 tools/libxl/gentest.py               |   60 +++++++-
 tools/libxl/gentypes.py              |  260 +++++++++++++++++++++++++++++++++-
 tools/libxl/idl.py                   |   35 ++++-
 tools/libxl/idl.txt                  |   28 +++-
 tools/libxl/libxl.c                  |   70 ++++++++-
 tools/libxl/libxl.h                  |   26 ++++
 tools/libxl/libxl_cpuid.c            |   39 ++++-
 tools/libxl/libxl_internal.c         |    6 +
 tools/libxl/libxl_internal.h         |   66 ++++++---
 tools/libxl/libxl_json.c             |   26 ++--
 tools/libxl/libxl_nocpuid.c          |   12 +-
 tools/libxl/libxl_types.idl          |   45 +++---
 tools/libxl/libxl_types_internal.idl |    4 +-
 tools/libxl/libxl_utils.c            |   25 ++++
 tools/libxl/libxl_utils.h            |    4 +
 16 files changed, 643 insertions(+), 67 deletions(-)

-- 
1.7.10.4

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-27 11:36   ` Ian Campbell
  2014-06-19 17:44 ` [PATCH v8 2/8] libxl/gentypes.py: don't generate default values Wei Liu
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

They will be used in later patch to determine whether we should generate
JSON output for a type. If that type has default value we just skip
generating JSON output.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/libxl/libxl.c          |    3 +--
 tools/libxl/libxl_internal.c |    6 ++++++
 tools/libxl/libxl_internal.h |   27 +++++++++++++++++++++++++++
 3 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 62e251a..1d8e046 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2860,8 +2860,7 @@ int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
         nic->model = strdup("rtl8139");
         if (!nic->model) return ERROR_NOMEM;
     }
-    if (!nic->mac[0] && !nic->mac[1] && !nic->mac[2] &&
-        !nic->mac[3] && !nic->mac[4] && !nic->mac[5]) {
+    if (libxl__mac_is_default(&nic->mac)) {
         const uint8_t *r;
         libxl_uuid uuid;
 
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index 6c94d3e..81f8985 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -307,6 +307,12 @@ _hidden int libxl__compare_macs(libxl_mac *a, libxl_mac *b)
     return 0;
 }
 
+_hidden int libxl__mac_is_default(libxl_mac *mac)
+{
+    return (!(*mac)[0] && !(*mac)[1] && !(*mac)[2] &&
+            !(*mac)[3] && !(*mac)[4] && !(*mac)[5]);
+}
+
 _hidden int libxl__init_recursive_mutex(libxl_ctx *ctx, pthread_mutex_t *lock)
 {
     pthread_mutexattr_t attr;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index a0d4f24..2a8f552 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1551,6 +1551,8 @@ struct libxl__xen_console_reader {
 _hidden int libxl__parse_mac(const char *s, libxl_mac mac);
 /* compare mac address @a and @b. 0 if the same, -ve if a<b and +ve if a>b */
 _hidden int libxl__compare_macs(libxl_mac *a, libxl_mac *b);
+/* return true if mac address is all zero (the default value) */
+_hidden int libxl__mac_is_default(libxl_mac *mac);
 /* init a recursive mutex */
 _hidden int libxl__init_recursive_mutex(libxl_ctx *ctx, pthread_mutex_t *lock);
 
@@ -3097,6 +3099,10 @@ void libxl__numa_candidate_put_nodemap(libxl__gc *gc,
 #define LIBXL__DEFBOOL_STR_DEFAULT "<default>"
 #define LIBXL__DEFBOOL_STR_FALSE   "False"
 #define LIBXL__DEFBOOL_STR_TRUE    "True"
+static inline int libxl__defbool_is_default(libxl_defbool *db)
+{
+    return !db->val;
+}
 
 /*
  * Inserts "elm_new" into the sorted list "head".
@@ -3180,6 +3186,27 @@ int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
 int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
                              char **p);
 
+/* This always return false, there's no "default value" for hw cap */
+static inline int libxl__hwcap_is_default(libxl_hwcap *hwcap)
+{
+    return 0;
+}
+
+static inline int libxl__string_list_is_empty(libxl_string_list *psl)
+{
+    return !libxl_string_list_length(psl);
+}
+
+static inline int libxl__key_value_list_is_empty(libxl_key_value_list *pkvl)
+{
+    return !libxl_key_value_list_length(pkvl);
+}
+
+static inline int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl)
+{
+    return !libxl_cpuid_policy_list_length(pl);
+}
+
 #endif
 
 /*
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 2/8] libxl/gentypes.py: don't generate default values
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
  2014-06-19 17:44 ` [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-27 11:37   ` Ian Campbell
  2014-06-19 17:44 ` [PATCH v8 3/8] libxl: clean up namespace violation Wei Liu
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

If a field:
    0. is not of aggregate type
and
    1. is of array type and the array is not empty
or  2. is of a type which has init_val and has been set to init_val,
or  3. is of builtin type and has been set to internal default value,
or  4. is of a type which has no init_val and has been set to 0

then there's no need to generate output for that field in JSON
output.

Note that 0 can result in output like
  {
    ...
    FOO : { }
    ...
  }
where FOO is aggregate type but all its fields are set to default, hence
no JSON output in {} at all. This is not pretty, but it's still valid
JSON. And the parser should be able to skip touching those fields in the
resulting C structures. When the parser consumes that generated JSON
object, all default values should be automatically filled in.

Also change some non-zero init_vals to LIBXL_* for better readability in
generated C code.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/gentypes.py     |   33 +++++++++++++++++++++++++++++++--
 tools/libxl/idl.py          |    2 ++
 tools/libxl/idl.txt         |    9 +++++++++
 tools/libxl/libxl_types.idl |   29 +++++++++++++++++------------
 4 files changed, 59 insertions(+), 14 deletions(-)

diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py
index 01416e7..f06afd9 100644
--- a/tools/libxl/gentypes.py
+++ b/tools/libxl/gentypes.py
@@ -206,6 +206,29 @@ def libxl_C_type_gen_map_key(f, parent, indent = ""):
         s = indent + s
     return s.replace("\n", "\n%s" % indent).rstrip(indent)
 
+def get_init_val(f):
+    if f.init_val is not None:
+        return f.init_val
+    elif f.type.init_val is not None:
+        return f.type.init_val
+    return None
+
+def get_default_expr(f, nparent, fexpr):
+    if isinstance(f.type, idl.Aggregate):
+        return "1 /* always generate JSON output for aggregate type */"
+
+    if isinstance(f.type, idl.Array):
+        return "%s && %s" % (fexpr, nparent + f.type.lenvar.name)
+
+    init_val = get_init_val(f)
+    if init_val is not None:
+        return "%s != %s" % (fexpr, init_val)
+
+    if f.type.check_default_fn:
+        return "!%s(&%s)" % (f.type.check_default_fn, fexpr)
+
+    return "%s" % fexpr
+
 def libxl_C_type_gen_json(ty, v, indent = "    ", parent = None):
     s = ""
     if parent is None:
@@ -255,8 +278,14 @@ 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 += libxl_C_type_gen_map_key(f, nparent)
-            s += libxl_C_type_gen_json(f.type, fexpr, "", nparent)
+            default_expr = get_default_expr(f, nparent, fexpr)
+            s += "if (%s) {\n" % default_expr
+
+            s += libxl_C_type_gen_map_key(f, nparent, "    ")
+            s += libxl_C_type_gen_json(f.type, fexpr, "    ", nparent)
+
+            s += "}\n"
+
         s += "s = yajl_gen_map_close(hand);\n"
         s += "if (s != yajl_gen_status_ok)\n"
         s += "    goto out;\n"
diff --git a/tools/libxl/idl.py b/tools/libxl/idl.py
index 8b118dd..ada801a 100644
--- a/tools/libxl/idl.py
+++ b/tools/libxl/idl.py
@@ -64,6 +64,8 @@ class Type(object):
         self.init_val = kwargs.setdefault('init_val', None)
         self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', False)
 
+        self.check_default_fn = kwargs.setdefault('check_default_fn', None)
+
         if self.typename is not None and not self.private:
             self.json_gen_fn = kwargs.setdefault('json_gen_fn', self.typename + "_gen_json")
         else:
diff --git a/tools/libxl/idl.txt b/tools/libxl/idl.txt
index 6a53dd8..d47eba8 100644
--- a/tools/libxl/idl.txt
+++ b/tools/libxl/idl.txt
@@ -69,6 +69,15 @@ Type.autogenerate_json: (default: True)
 
  Indicates if the above named Type.json_gen_fn should be autogenerated.
 
+Type.check_default_fn:
+
+ If it's set then calling this function shall return true if this type
+ has been set to default value (internal libxl implementation).
+
+ If this is not set, that means we can check the type against init_val
+ (if it has one) or zero to determine whether the value is default
+ value.
+
 Other simple type-Classes
 -------------------------
 
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 1018142..7234519 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_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)
-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_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,
+                       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")
+
+libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE,
+                            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,
+                      check_default_fn="libxl__hwcap_is_default")
 
 #
 # Specific integer types
@@ -49,7 +54,7 @@ libxl_domain_type = Enumeration("domain_type", [
     (-1, "INVALID"),
     (1, "HVM"),
     (2, "PV"),
-    ], init_val = -1)
+    ], init_val = "LIBXL_DOMAIN_TYPE_INVALID")
 
 libxl_device_model_version = Enumeration("device_model_version", [
     (0, "UNKNOWN"),
@@ -95,7 +100,7 @@ libxl_action_on_shutdown = Enumeration("action_on_shutdown", [
 
     (5, "COREDUMP_DESTROY"),
     (6, "COREDUMP_RESTART"),
-    ], init_val = 1)
+    ], init_val = "LIBXL_ACTION_ON_SHUTDOWN_DESTROY")
 
 libxl_trigger = Enumeration("trigger", [
     (0, "UNKNOWN"),
@@ -154,7 +159,7 @@ libxl_vga_interface_type = Enumeration("vga_interface_type", [
     (1, "CIRRUS"),
     (2, "STD"),
     (3, "NONE"),
-    ], init_val = 1)
+    ], init_val = "LIBXL_VGA_INTERFACE_TYPE_CIRRUS")
 
 libxl_vendor_device = Enumeration("vendor_device", [
     (0, "NONE"),
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 3/8] libxl: clean up namespace violation
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
  2014-06-19 17:44 ` [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types Wei Liu
  2014-06-19 17:44 ` [PATCH v8 2/8] libxl/gentypes.py: don't generate default values Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-27 11:37   ` Ian Campbell
  2014-06-19 17:44 ` [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Wei Liu
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

In 752f181f ("libxl_json: introduce parser functions for builtin types")
a bunch of parser functions were introduced. Unfortunately they
polluted the public namespace with a prefix "libxl_", while they should
be internal functions.

This patch changes the prefix to "libxl__". No functional change
introduced.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/libxl/libxl_cpuid.c    |    6 +++---
 tools/libxl/libxl_internal.h |   36 ++++++++++++++++++------------------
 tools/libxl/libxl_json.c     |   26 +++++++++++++-------------
 tools/libxl/libxl_nocpuid.c  |    6 +++---
 4 files changed, 37 insertions(+), 37 deletions(-)

diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c
index 1f2bcd5..30c9ec3 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -398,9 +398,9 @@ out:
     return s;
 }
 
-int libxl_cpuid_policy_list_parse_json(libxl__gc *gc,
-                                       const libxl__json_object *o,
-                                       libxl_cpuid_policy_list *p)
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+                                        const libxl__json_object *o,
+                                        libxl_cpuid_policy_list *p)
 {
     int i, size;
     libxl_cpuid_policy_list l;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2a8f552..9e8bc4c 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3153,26 +3153,26 @@ static inline int libxl__defbool_is_default(libxl_defbool *db)
  */
 #define CTYPE(isfoo,c) (isfoo((unsigned char)(c)))
 
-int libxl_defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                             libxl_defbool *p);
+int libxl__defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                              libxl_defbool *p);
 int libxl__bool_parse_json(libxl__gc *gc, const libxl__json_object *o,
                            bool *p);
-int libxl_mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                         libxl_mac *p);
-int libxl_bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                            libxl_bitmap *p);
-int libxl_uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                          libxl_uuid *p);
-int libxl_cpuid_policy_list_parse_json(libxl__gc *gc,
-                                       const libxl__json_object *o,
-                                       libxl_cpuid_policy_list *p);
-int libxl_string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                                 libxl_string_list *p);
-int libxl_key_value_list_parse_json(libxl__gc *gc,
-                                    const libxl__json_object *o,
-                                    libxl_key_value_list *p);
-int libxl_hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                           libxl_hwcap *p);
+int libxl__mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                          libxl_mac *p);
+int libxl__bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                             libxl_bitmap *p);
+int libxl__uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                           libxl_uuid *p);
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+                                        const libxl__json_object *o,
+                                        libxl_cpuid_policy_list *p);
+int libxl__string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                                  libxl_string_list *p);
+int libxl__key_value_list_parse_json(libxl__gc *gc,
+                                     const libxl__json_object *o,
+                                     libxl_key_value_list *p);
+int libxl__hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                            libxl_hwcap *p);
 int libxl__int_parse_json(libxl__gc *gc, const libxl__json_object *o,
                           void *p);
 int libxl__uint8_parse_json(libxl__gc *gc, const libxl__json_object *o,
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index fb9baf8..dd0d73e 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -100,8 +100,8 @@ yajl_gen_status libxl_defbool_gen_json(yajl_gen hand,
     return libxl__yajl_gen_asciiz(hand, libxl_defbool_to_string(*db));
 }
 
-int libxl_defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                             libxl_defbool *p)
+int libxl__defbool_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                              libxl_defbool *p)
 {
     const char *s;
 
@@ -144,8 +144,8 @@ yajl_gen_status libxl_uuid_gen_json(yajl_gen hand,
     return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_UUID_FMTLEN);
 }
 
-int libxl_uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                          libxl_uuid *p)
+int libxl__uuid_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                           libxl_uuid *p)
 {
     if (!libxl__json_object_is_string(o))
         return ERROR_FAIL;
@@ -173,7 +173,7 @@ out:
     return s;
 }
 
-int libxl_bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+int libxl__bitmap_parse_json(libxl__gc *gc, const libxl__json_object *o,
                             libxl_bitmap *p)
 {
     int i;
@@ -234,8 +234,8 @@ out:
     return s;
 }
 
-int libxl_key_value_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                                    libxl_key_value_list *p)
+int libxl__key_value_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                                     libxl_key_value_list *p)
 {
     libxl__json_map_node *node = NULL;
     flexarray_t *maps = NULL;
@@ -290,8 +290,8 @@ out:
     return s;
 }
 
-int libxl_string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                                 libxl_string_list *p)
+int libxl__string_list_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                                  libxl_string_list *p)
 {
     const libxl__json_object *t;
     libxl_string_list l;
@@ -329,8 +329,8 @@ yajl_gen_status libxl_mac_gen_json(yajl_gen hand, libxl_mac *mac)
     return yajl_gen_string(hand, (const unsigned char *)buf, LIBXL_MAC_FMTLEN);
 }
 
-int libxl_mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                         libxl_mac *p)
+int libxl__mac_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                          libxl_mac *p)
 {
     if (!libxl__json_object_is_string(o))
         return ERROR_FAIL;
@@ -356,8 +356,8 @@ out:
     return s;
 }
 
-int libxl_hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
-                           libxl_hwcap *p)
+int libxl__hwcap_parse_json(libxl__gc *gc, const libxl__json_object *o,
+                            libxl_hwcap *p)
 {
     int i;
 
diff --git a/tools/libxl/libxl_nocpuid.c b/tools/libxl/libxl_nocpuid.c
index eb525fc..e98906a 100644
--- a/tools/libxl/libxl_nocpuid.c
+++ b/tools/libxl/libxl_nocpuid.c
@@ -44,9 +44,9 @@ yajl_gen_status libxl_cpuid_policy_list_gen_json(yajl_gen hand,
     return 0;
 }
 
-int libxl_cpuid_policy_list_parse_json(libxl__gc *gc,
-                                       const libxl__json_object *o,
-                                       libxl_cpuid_policy_list *p)
+int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
+                                        const libxl__json_object *o,
+                                        libxl_cpuid_policy_list *p)
 {
     return 0;
 }
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
                   ` (2 preceding siblings ...)
  2014-06-19 17:44 ` [PATCH v8 3/8] libxl: clean up namespace violation Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-27 11:40   ` Ian Campbell
  2014-06-19 17:44 ` [PATCH v8 5/8] libxl/gentest.py: test JSON parser Wei Liu
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

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>
---
Changes since last version:
1. use _private suffix for new header file name
2. use libxl__ namespace
3. generate function prototypes to proper header files

Change since last version: output parser function definitions to
dedicated header file.
---
 tools/libxl/Makefile                 |    4 +-
 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         |    3 +
 tools/libxl/libxl_types.idl          |   27 +++---
 tools/libxl/libxl_types_internal.idl |    4 +-
 8 files changed, 221 insertions(+), 18 deletions(-)

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 7fc42c8..b1ad8d4 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -184,8 +184,10 @@ $(LIBXL_OBJS) $(LIBXL_TEST_OBJS) $(LIBXLU_OBJS) \
 $(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
+	$(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 69ceac8..e52a43f 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.
+ *
+ * <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 9e8bc4c..a5803d2 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3186,6 +3186,9 @@ int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
 int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
                              char **p);
 
+#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 7234519..2cb856c 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")
 
 #
@@ -586,7 +589,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

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 5/8] libxl/gentest.py: test JSON parser
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
                   ` (3 preceding siblings ...)
  2014-06-19 17:44 ` [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-19 17:44 ` [PATCH v8 6/8] libxl: copy function for builtin types Wei Liu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

The test is done in following steps:

1. initialise libxl_FOO struct
2. generate JSON string A for libxl_FOO struct FOO1
3. convert JSON string A to libxl_FOO struct FOO2
4. generate JSON string B for libxl_FOO struct FOO2
5. compare A and B

If A and B are identical then we are good.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/gentest.py |   23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/libxl/gentest.py b/tools/libxl/gentest.py
index eb9a21b..b92d092 100644
--- a/tools/libxl/gentest.py
+++ b/tools/libxl/gentest.py
@@ -225,10 +225,11 @@ int main(int argc, char **argv)
 """)
 
     for ty in types:
-        f.write("    %s %s_val;\n" % (ty.typename, ty.typename))
+        f.write("    %s %s_val, %s_val_new;\n" % \
+                (ty.typename, ty.typename, ty.typename))
     f.write("""
     int rc;
-    char *s;
+    char *s, *new_s;
     xentoollog_logger_stdiostream *logger;
     libxl_ctx *ctx;
 
@@ -240,20 +241,36 @@ int main(int argc, char **argv)
         exit(1);
     }
 """)
-    f.write("    printf(\"Testing TYPE_to_json()\\n\");\n")
+    f.write("    printf(\"Testing TYPE_to/from_json()\\n\");\n")
     f.write("    printf(\"----------------------\\n\");\n")
     f.write("    printf(\"\\n\");\n")
     for ty in [t for t in types if t.json_gen_fn is not None]:
         arg = ty.typename + "_val"
         f.write("    %s_rand_init(%s);\n" % (ty.typename, \
             ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        if not isinstance(ty, idl.Enumeration):
+            f.write("    %s_init(%s_new);\n" % (ty.typename, \
+                ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
         f.write("    s = %s_to_json(ctx, %s);\n" % \
                 (ty.typename, ty.pass_arg(arg, isref=False)))
         f.write("    printf(\"%%s: %%s\\n\", \"%s\", s);\n" % ty.typename)
         f.write("    if (s == NULL) abort();\n")
+        f.write("    rc = %s_from_json(ctx, &%s_val_new, s);\n" % \
+                (ty.typename, ty.typename))
+        f.write("    if (rc) abort();\n")
+        f.write("    new_s = %s_to_json(ctx, %s_new);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (new_s == NULL) abort();\n")
+        f.write("    if (strcmp(s, new_s)) {\n")
+        f.write("        printf(\"Huh? Regenerated string different from original string.\\n\");\n")
+        f.write("        printf(\"Regenerated string: %s\\n\", new_s);\n")
+        f.write("        abort();\n")
+        f.write("    }\n")
         f.write("    free(s);\n")
+        f.write("    free(new_s);\n")
         if ty.dispose_fn is not None:
             f.write("    %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+            f.write("    %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
         f.write("\n")
 
     f.write("    printf(\"Testing Enumerations\\n\");\n")
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 6/8] libxl: copy function for builtin types
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
                   ` (4 preceding siblings ...)
  2014-06-19 17:44 ` [PATCH v8 5/8] libxl/gentest.py: test JSON parser Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-19 17:44 ` [PATCH v8 7/8] libxl IDL: generate deep copy functions Wei Liu
  2014-06-19 17:44 ` [PATCH v8 8/8] libxl/gentest.py: test " Wei Liu
  7 siblings, 0 replies; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

These functions will be used in later patch to deep-copy a structure.

Functions introduced:
 * libxl_string_list_copy
 * libxl_key_value_list_copy
 * libxl_hwcap_copy
 * libxl_mac_copy
 * libxl_cpuid_policy_list_copy
 * libxl_string_copy
 * libxl_bitmap_copy_alloc

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/libxl.c         |   67 +++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h         |   12 ++++++++
 tools/libxl/libxl_cpuid.c   |   33 +++++++++++++++++++++
 tools/libxl/libxl_nocpuid.c |    6 ++++
 tools/libxl/libxl_utils.c   |   25 ++++++++++++++++
 tools/libxl/libxl_utils.h   |    4 +++
 6 files changed, 147 insertions(+)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1d8e046..183a832 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -205,6 +205,29 @@ void libxl_string_list_dispose(libxl_string_list *psl)
     free(sl);
 }
 
+void libxl_string_list_copy(libxl_ctx *ctx,
+                            libxl_string_list *dst,
+                            libxl_string_list *src)
+{
+    GC_INIT(ctx);
+    int i, len;
+
+    if (!*src) {
+        *dst = NULL;
+        goto out;
+    }
+
+    len = libxl_string_list_length(src);
+    /* one extra slot for sentinel */
+    *dst = libxl__calloc(NOGC, len + 1, sizeof(char *));
+
+    for (i = 0; i < len; i++)
+        (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
+
+out:
+    GC_FREE;
+}
+
 int libxl_string_list_length(const libxl_string_list *psl)
 {
     int i = 0;
@@ -245,6 +268,34 @@ void libxl_key_value_list_dispose(libxl_key_value_list *pkvl)
     free(kvl);
 }
 
+void libxl_key_value_list_copy(libxl_ctx *ctx,
+                               libxl_key_value_list *dst,
+                               libxl_key_value_list *src)
+{
+    GC_INIT(ctx);
+    int i, len;
+
+    if (*src == NULL) {
+        *dst = NULL;
+        goto out;
+    }
+
+    len = libxl_key_value_list_length(src);
+    /* one extra slot for sentinel */
+    *dst = libxl__calloc(NOGC, len * 2 + 1, sizeof(char *));
+
+    for (i = 0; i < len * 2; i += 2) {
+        (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
+        if ((*src)[i+1])
+            (*dst)[i+1] = libxl__strdup(NOGC, (*src)[i+1]);
+        else
+            (*dst)[i+1] = NULL;
+    }
+
+out:
+    GC_FREE;
+}
+
 void libxl_defbool_set(libxl_defbool *db, bool b)
 {
     db->val = b ? LIBXL__DEFBOOL_TRUE : LIBXL__DEFBOOL_FALSE;
@@ -5692,6 +5743,22 @@ int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int cloexec)
 int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
   { return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
 
+
+void libxl_hwcap_copy(libxl_ctx *ctx,libxl_hwcap *dst, libxl_hwcap *src)
+{
+    int i;
+
+    for (i = 0; i < 8; i++)
+        (*dst)[i] = (*src)[i];
+}
+
+void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src)
+{
+    int i;
+
+    for (i = 0; i < 6; i++)
+        (*dst)[i] = (*src)[i];
+}
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index e52a43f..1fb365d 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -542,20 +542,29 @@ typedef struct libxl__ctx libxl_ctx;
  */
 #define LIBXL_HAVE_CPUPOOL_NAME 1
 
+typedef struct libxl__ctx libxl_ctx;
+
 typedef uint8_t libxl_mac[6];
 #define LIBXL_MAC_FMT "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx"
 #define LIBXL_MAC_FMTLEN ((2*6)+5) /* 6 hex bytes plus 5 colons */
 #define LIBXL_MAC_BYTES(mac) mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
+void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, libxl_mac *src);
 
 typedef char **libxl_string_list;
 void libxl_string_list_dispose(libxl_string_list *sl);
 int libxl_string_list_length(const libxl_string_list *sl);
+void libxl_string_list_copy(libxl_ctx *ctx, libxl_string_list *dst,
+                            libxl_string_list *src);
 
 typedef char **libxl_key_value_list;
 void libxl_key_value_list_dispose(libxl_key_value_list *kvl);
 int libxl_key_value_list_length(libxl_key_value_list *kvl);
+void libxl_key_value_list_copy(libxl_ctx *ctx,
+                               libxl_key_value_list *dst,
+                               libxl_key_value_list *src);
 
 typedef uint32_t libxl_hwcap[8];
+void libxl_hwcap_copy(libxl_ctx *ctx, libxl_hwcap *dst, libxl_hwcap *src);
 
 typedef uint64_t libxl_ev_user;
 
@@ -574,6 +583,9 @@ typedef struct libxl__cpuid_policy libxl_cpuid_policy;
 typedef libxl_cpuid_policy * libxl_cpuid_policy_list;
 void libxl_cpuid_dispose(libxl_cpuid_policy_list *cpuid_list);
 int libxl_cpuid_policy_list_length(libxl_cpuid_policy_list *l);
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+                                  libxl_cpuid_policy_list *dst,
+                                  libxl_cpuid_policy_list *src);
 
 #define LIBXL_PCI_FUNC_ALL (~0U)
 
diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c
index 30c9ec3..6fa00be 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -468,6 +468,39 @@ int libxl_cpuid_policy_list_length(libxl_cpuid_policy_list *pl)
     return i;
 }
 
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+                                  libxl_cpuid_policy_list *dst,
+                                  libxl_cpuid_policy_list *src)
+{
+    GC_INIT(ctx);
+    int i, j, len;
+
+    if (*src == NULL) {
+        *dst = NULL;
+        goto out;
+    }
+
+    len = libxl_cpuid_policy_list_length(src);
+    /* one extra slot for sentinel */
+    *dst = libxl__calloc(NOGC, len + 1, sizeof(libxl_cpuid_policy));
+    (*dst)[len].input[0] = XEN_CPUID_INPUT_UNUSED;
+    (*dst)[len].input[1] = XEN_CPUID_INPUT_UNUSED;
+
+    for (i = 0; i < len; i++) {
+        for (j = 0; j < 2; j++)
+            (*dst)[i].input[j] = (*src)[i].input[j];
+        for (j = 0; j < 4; j++)
+            if ((*src)[i].policy[j])
+                (*dst)[i].policy[j] =
+                    libxl__strdup(NOGC, (*src)[i].policy[j]);
+            else
+                (*dst)[i].policy[j] = NULL;
+    }
+
+out:
+    GC_FREE;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_nocpuid.c b/tools/libxl/libxl_nocpuid.c
index e98906a..8b567d0 100644
--- a/tools/libxl/libxl_nocpuid.c
+++ b/tools/libxl/libxl_nocpuid.c
@@ -51,6 +51,12 @@ int libxl__cpuid_policy_list_parse_json(libxl__gc *gc,
     return 0;
 }
 
+void libxl_cpuid_policy_list_copy(libxl_ctx *ctx,
+                                  libxl_cpuid_policy_list *dst,
+                                  libxl_cpuid_policy_list *src)
+{
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 16b734e..6053017 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -614,6 +614,19 @@ void libxl_bitmap_copy(libxl_ctx *ctx, libxl_bitmap *dptr,
     memcpy(dptr->map, sptr->map, sz * sizeof(*dptr->map));
 }
 
+void libxl_bitmap_copy_alloc(libxl_ctx *ctx,
+                             libxl_bitmap *dptr,
+                             const libxl_bitmap *sptr)
+{
+    GC_INIT(ctx);
+
+    dptr->map = libxl__calloc(NOGC, sptr->size, sizeof(*sptr->map));
+    dptr->size = sptr->size;
+    memcpy(dptr->map, sptr->map, sptr->size * sizeof(*sptr->map));
+
+    GC_FREE;
+}
+
 int libxl_bitmap_is_full(const libxl_bitmap *bitmap)
 {
     int i;
@@ -1013,6 +1026,18 @@ int libxl_domid_valid_guest(uint32_t domid)
     return domid > 0 && domid < DOMID_FIRST_RESERVED;
 }
 
+void libxl_string_copy(libxl_ctx *ctx, char **dst, char **src)
+{
+    GC_INIT(ctx);
+
+    if (*src)
+        *dst = libxl__strdup(NOGC, *src);
+    else
+        *dst = NULL;
+
+    GC_FREE;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 8bfb81b..cc528d2 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -76,6 +76,8 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
      * called by the application when done. */
+void libxl_bitmap_copy_alloc(libxl_ctx *ctx, libxl_bitmap *dptr,
+                             const libxl_bitmap *sptr);
 void libxl_bitmap_copy(libxl_ctx *ctx, libxl_bitmap *dptr,
                        const libxl_bitmap *sptr);
 int libxl_bitmap_is_full(const libxl_bitmap *bitmap);
@@ -121,6 +123,8 @@ int libxl_cpumap_to_nodemap(libxl_ctx *ctx,
     return (s + 1023) / 1024;
 }
 
+void libxl_string_copy(libxl_ctx *ctx, char **dst, char **src);
+
 #endif
 
 /*
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 7/8] libxl IDL: generate deep copy functions
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
                   ` (5 preceding siblings ...)
  2014-06-19 17:44 ` [PATCH v8 6/8] libxl: copy function for builtin types Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  2014-06-19 17:44 ` [PATCH v8 8/8] libxl/gentest.py: test " Wei Liu
  7 siblings, 0 replies; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

Introduces copy_fn for a type.

For most builtin types we can use direct assignment. For those builtin
types which cannot use direct assignment we use the copy functions in
previous patch.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/gentypes.py              |   67 ++++++++++++++++++++++++++++++++++
 tools/libxl/idl.py                   |   13 ++++++-
 tools/libxl/idl.txt                  |   12 ++++++
 tools/libxl/libxl_types.idl          |   27 ++++++++------
 tools/libxl/libxl_types_internal.idl |    2 +-
 5 files changed, 108 insertions(+), 13 deletions(-)

diff --git a/tools/libxl/gentypes.py b/tools/libxl/gentypes.py
index 6cdeaa8..4b0c996 100644
--- a/tools/libxl/gentypes.py
+++ b/tools/libxl/gentypes.py
@@ -100,6 +100,61 @@ def libxl_C_type_dispose(ty, v, indent = "    ", parent = None):
         s = indent + s
     return s.replace("\n", "\n%s" % indent).rstrip(indent)
 
+def libxl_C_type_copy(ty, v, w, indent = "    ", vparent = None, wparent = None):
+    s = ""
+
+    if vparent is None:
+        s += "GC_INIT(ctx);\n";
+
+    if isinstance(ty, idl.KeyedUnion):
+        if vparent is None or wparent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        s += "%s = %s;\n" % ((vparent + ty.keyvar.name), (wparent + ty.keyvar.name))
+        s += "switch (%s) {\n" % (wparent + ty.keyvar.name)
+        for f in ty.fields:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+            s += "case %s:\n" % f.enumname
+            if f.type is not None:
+                s += libxl_C_type_copy(f.type, vfexpr, wfexpr, indent + "    ",
+                                       vnparent, wnparent)
+            s += "    break;\n"
+        s += "}\n"
+    elif isinstance(ty, idl.Array):
+        if vparent is None or wparent is None:
+            raise Exception("Array type must have a parent")
+        s += "%s = libxl__calloc(NOGC, %s, sizeof(*%s));\n" % (ty.pass_arg(v, vparent is None),
+                                                               (wparent + ty.lenvar.name),
+                                                               ty.pass_arg(w, wparent is None))
+        s += "%s = %s;\n" % ((vparent + ty.lenvar.name), (wparent + ty.lenvar.name))
+        s += "{\n"
+        s += "    int i;\n"
+        s += "    for (i=0; i<%s; i++)\n" % (wparent + ty.lenvar.name)
+        s += libxl_C_type_copy(ty.elem_type, v+"[i]", w+"[i]",
+                               indent + "        ", vparent, wparent)
+        s += "}\n"
+    elif isinstance(ty, idl.Struct) and ((vparent is None and wparent is None) or ty.copy_fn is None):
+        for f in [f for f in ty.fields if not f.const and not f.type.private]:
+            (vnparent,vfexpr) = ty.member(v, f, vparent is None)
+            (wnparent,wfexpr) = ty.member(w, f, wparent is None)
+            s += libxl_C_type_copy(f.type, vfexpr, wfexpr, "", vnparent, wnparent)
+    else:
+        if ty.copy_fn is not None:
+            s += "%s(ctx, %s, %s);\n" % (ty.copy_fn,
+                                         ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_REFERENCE),
+                                         ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_REFERENCE))
+
+        else:
+            s += "%s = %s;\n" % (ty.pass_arg(v, vparent is None, passby=idl.PASS_BY_VALUE),
+                                 ty.pass_arg(w, wparent is None, passby=idl.PASS_BY_VALUE))
+
+    if vparent is None:
+        s += "GC_FREE;\n"
+
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
 def libxl_init_members(ty, nesting = 0):
     """Returns a list of members of ty which require a separate init"""
 
@@ -489,6 +544,9 @@ if __name__ == '__main__':
         f.write(libxl_C_type_define(ty) + ";\n")
         if ty.dispose_fn is not None:
             f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.dispose_fn, ty.make_arg("p")))
+        if ty.copy_fn is not None:
+            f.write("%svoid %s(libxl_ctx *ctx, %s, %s);\n" % (ty.hidden(), ty.copy_fn,
+                                              ty.make_arg("dst"), ty.make_arg("src")))
         if ty.init_fn is not None:
             f.write("%svoid %s(%s);\n" % (ty.hidden(), ty.init_fn, ty.make_arg("p")))
             for field in libxl_init_members(ty):
@@ -590,6 +648,15 @@ if __name__ == '__main__':
         f.write("    memset(p, LIBXL_DTOR_POISON, sizeof(*p));\n")
         f.write("}\n")
         f.write("\n")
+
+    for ty in [t for t in types if t.copy_fn and t.autogenerate_copy_fn]:
+        f.write("void %s(libxl_ctx *ctx, %s, %s)\n" % (ty.copy_fn,
+                                       ty.make_arg("dst", passby=idl.PASS_BY_REFERENCE),
+                                       ty.make_arg("src", passby=idl.PASS_BY_REFERENCE)))
+        f.write("{\n")
+        f.write(libxl_C_type_copy(ty, "dst", "src"))
+        f.write("}\n")
+        f.write("\n")
         
     for ty in [t for t in types if t.init_fn is not None and t.autogenerate_init_fn]:
         f.write(libxl_C_type_init(ty))
diff --git a/tools/libxl/idl.py b/tools/libxl/idl.py
index 63557db..437049e 100644
--- a/tools/libxl/idl.py
+++ b/tools/libxl/idl.py
@@ -60,6 +60,13 @@ class Type(object):
 
         self.autogenerate_dispose_fn = kwargs.setdefault('autogenerate_dispose_fn', True)
 
+        if self.typename is not None:
+            self.copy_fn = kwargs.setdefault('copy_fn', self.typename + "_copy")
+        else:
+            self.copy_fn = kwargs.setdefault('copy_fn', None)
+
+        self.autogenerate_copy_fn = kwargs.setdefault('autogenerate_copy_fn', True)
+
         self.init_fn = kwargs.setdefault('init_fn', None)
         self.init_val = kwargs.setdefault('init_val', None)
         self.autogenerate_init_fn = kwargs.setdefault('autogenerate_init_fn', False)
@@ -128,6 +135,7 @@ class Number(Builtin):
     def __init__(self, ctype, **kwargs):
         kwargs.setdefault('namespace', None)
         kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('copy_fn', None)
         kwargs.setdefault('signed', False)
         kwargs.setdefault('json_gen_fn', "yajl_gen_integer")
         kwargs.setdefault('json_parse_type', "JSON_INTEGER")
@@ -141,6 +149,7 @@ class UInt(Number):
         kwargs.setdefault('namespace', None)
         kwargs.setdefault('dispose_fn', None)
         kwargs.setdefault('json_parse_fn', "libxl__uint%d_parse_json" % w)
+        kwargs.setdefault('copy_fn', None)
         Number.__init__(self, "uint%d_t" % w, **kwargs)
 
         self.width = w
@@ -157,6 +166,7 @@ class EnumerationValue(object):
 class Enumeration(Type):
     def __init__(self, typename, values, **kwargs):
         kwargs.setdefault('dispose_fn', None)
+        kwargs.setdefault('copy_fn', None)
         kwargs.setdefault('json_parse_type', "JSON_STRING")
         Type.__init__(self, typename, **kwargs)
 
@@ -273,6 +283,7 @@ class KeyedUnion(Aggregate):
 
 void = Builtin("void *", namespace = None)
 bool = Builtin("bool", namespace = None,
+               copy_fn=None,
                json_gen_fn = "yajl_gen_bool",
                json_parse_type = "JSON_BOOL",
                json_parse_fn = "libxl__bool_parse_json",
@@ -287,7 +298,7 @@ uint16 = UInt(16)
 uint32 = UInt(32)
 uint64 = UInt(64, json_gen_fn = "libxl__uint64_gen_json")
 
-string = Builtin("char *", namespace = None, dispose_fn = "free",
+string = Builtin("char *", namespace = None, copy_fn = "libxl_string_copy", dispose_fn = "free",
                  json_gen_fn = "libxl__string_gen_json",
                  json_parse_type = "JSON_STRING | JSON_NULL",
                  json_parse_fn = "libxl__string_parse_json",
diff --git a/tools/libxl/idl.txt b/tools/libxl/idl.txt
index 87c4952..7440fb3 100644
--- a/tools/libxl/idl.txt
+++ b/tools/libxl/idl.txt
@@ -44,6 +44,18 @@ Type.autogenerate_dispose_fn: (default: True)
  Indicates if the above named Type.dispose_fn should be
  autogenerated.
 
+Type.copy_fn: (default: typename + "_copy" or None if type == None)
+
+ The name of the C function which will deep copy all fields within
+ this type.
+
+Type.autogenerate_copy_fn: (default: True)
+
+ Indicates if the above named Type.copy_fn should be
+ autogenerated.
+
+Type.autogenerate_copy_fn
+
 Type.init_val: (default: None)
 
  C expression for the value to initialise instances of this type to.
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 2cb856c..d40b5c7 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -5,26 +5,31 @@
 
 namespace("libxl_")
 
-libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE,
+libxl_defbool = Builtin("defbool", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, copy_fn=None,
                         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)
+                      json_parse_type = "JSON_INTEGER", autogenerate_json = False, copy_fn=None)
 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")
+                      json_parse_type = "JSON_INTEGER", autogenerate_json = False, signed = True, init_val="-1",
+                      copy_fn=None)
+libxl_uuid = Builtin("uuid", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, check_default_fn="libxl_uuid_is_nil",
+                     copy_fn="libxl_uuid_copy")
+libxl_mac = Builtin("mac", json_parse_type="JSON_STRING", passby=PASS_BY_REFERENCE, check_default_fn="libxl__mac_is_default",
+                    copy_fn="libxl_mac_copy")
 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")
+                       check_default_fn="libxl_bitmap_is_empty", copy_fn="libxl_bitmap_copy_alloc")
 libxl_cpuid_policy_list = Builtin("cpuid_policy_list", dispose_fn="libxl_cpuid_dispose", passby=PASS_BY_REFERENCE,
-                                  json_parse_type="JSON_ARRAY", check_default_fn="libxl__cpuid_policy_is_empty")
+                                  json_parse_type="JSON_ARRAY", check_default_fn="libxl__cpuid_policy_is_empty",
+                                  copy_fn="libxl_cpuid_policy_list_copy")
 
 libxl_string_list = Builtin("string_list", dispose_fn="libxl_string_list_dispose", passby=PASS_BY_REFERENCE,
-                            json_parse_type="JSON_ARRAY", check_default_fn="libxl__string_list_is_empty")
+                            json_parse_type="JSON_ARRAY", check_default_fn="libxl__string_list_is_empty",
+                            copy_fn="libxl_string_list_copy")
 libxl_key_value_list = Builtin("key_value_list", dispose_fn="libxl_key_value_list_dispose", passby=PASS_BY_REFERENCE,
-                               json_parse_type="JSON_MAP", check_default_fn="libxl__key_value_list_is_empty")
+                               json_parse_type="JSON_MAP", check_default_fn="libxl__key_value_list_is_empty",
+                               copy_fn="libxl_key_value_list_copy")
 libxl_hwcap = Builtin("hwcap", passby=PASS_BY_REFERENCE, json_parse_type="JSON_ARRAY",
-                      check_default_fn="libxl__hwcap_is_default")
+                      check_default_fn="libxl__hwcap_is_default", copy_fn="libxl_hwcap_copy")
 
 #
 # Specific integer types
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 17533f1..800361b 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -3,7 +3,7 @@ hidden(True)
 
 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)
+		      autogenerate_json = False, copy_fn = None)
 
 libxl__qmp_message_type = Enumeration("qmp_message_type", [
     (1, "QMP"),
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v8 8/8] libxl/gentest.py: test deep copy functions
  2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
                   ` (6 preceding siblings ...)
  2014-06-19 17:44 ` [PATCH v8 7/8] libxl IDL: generate deep copy functions Wei Liu
@ 2014-06-19 17:44 ` Wei Liu
  7 siblings, 0 replies; 14+ messages in thread
From: Wei Liu @ 2014-06-19 17:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Wei Liu, ian.jackson, ian.campbell

The test is done as followed:
1. initialise libxl_FOO struct A
2. deep-copy A to B
3. generate JSON string for A and B
4. compare two JSON strings

If two strings are identical then we're good.

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
 tools/libxl/gentest.py |   37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/tools/libxl/gentest.py b/tools/libxl/gentest.py
index b92d092..07ffd31 100644
--- a/tools/libxl/gentest.py
+++ b/tools/libxl/gentest.py
@@ -273,6 +273,43 @@ int main(int argc, char **argv)
             f.write("    %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
         f.write("\n")
 
+    f.write("    printf(\"Testing TYPE_copy()\\n\");\n")
+    f.write("    printf(\"----------------------\\n\");\n")
+    f.write("    printf(\"\\n\");\n")
+    for ty in [t for t in types if t.copy_fn is not None]:
+        f.write("    printf(\"Testing %s_copy, \");\n" % ty.typename)
+        arg = ty.typename + "_val"
+        f.write("    %s_init(%s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_rand_init(%s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_init(%s_new);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    %s_copy(ctx, %s_new, %s);\n" % (ty.typename, \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE), \
+            ty.pass_arg(arg, isref=False, passby=idl.PASS_BY_REFERENCE)))
+        f.write("    s = %s_to_json(ctx, %s);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (s == NULL) abort();\n")
+        f.write("    new_s = %s_to_json(ctx, %s_new);\n" % \
+                (ty.typename, ty.pass_arg(arg, isref=False)))
+        f.write("    if (new_s == NULL) abort();\n")
+        f.write("    if (strcmp(s, new_s)) {\n")
+        f.write("        printf(\"Huh? Deep copy for %s failed. Regenerated string different from original string.\\n\");\n" \
+                % ty.typename)
+        f.write("        printf(\"Original string: %s\\n\", s);\n")
+        f.write("        printf(\"Regenerated string: %s\\n\", new_s);\n")
+        f.write("        abort();\n")
+        f.write("    }\n")
+        f.write("    free(s);\n")
+        f.write("    free(new_s);\n")
+        if ty.dispose_fn is not None:
+            f.write("    %s(&%s_val);\n" % (ty.dispose_fn, ty.typename))
+            f.write("    %s(&%s_val_new);\n" % (ty.dispose_fn, ty.typename))
+        f.write("    printf(\"done\\n\");\n")
+        f.write("\n")
+
+    f.write("    printf(\"\\n\");\n")
     f.write("    printf(\"Testing Enumerations\\n\");\n")
     f.write("    printf(\"--------------------\\n\");\n")
     f.write("    printf(\"\\n\");\n")
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types
  2014-06-19 17:44 ` [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types Wei Liu
@ 2014-06-27 11:36   ` Ian Campbell
  0 siblings, 0 replies; 14+ messages in thread
From: Ian Campbell @ 2014-06-27 11:36 UTC (permalink / raw)
  To: Wei Liu; +Cc: ian.jackson, xen-devel

On Thu, 2014-06-19 at 18:44 +0100, Wei Liu wrote:
> They will be used in later patch to determine whether we should generate
> JSON output for a type. If that type has default value we just skip
> generating JSON output.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v8 2/8] libxl/gentypes.py: don't generate default values
  2014-06-19 17:44 ` [PATCH v8 2/8] libxl/gentypes.py: don't generate default values Wei Liu
@ 2014-06-27 11:37   ` Ian Campbell
  2014-07-09  8:53     ` Wei Liu
  0 siblings, 1 reply; 14+ messages in thread
From: Ian Campbell @ 2014-06-27 11:37 UTC (permalink / raw)
  To: Wei Liu; +Cc: ian.jackson, xen-devel

On Thu, 2014-06-19 at 18:44 +0100, Wei Liu wrote:

Unfortunately there was a conflict in libxl_types.idl against David's
addition of the generation id type. The reject itself was trivial but I
think the addition of that type means you need a check_default_fn for
it.

Sorry.

Ian.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v8 3/8] libxl: clean up namespace violation
  2014-06-19 17:44 ` [PATCH v8 3/8] libxl: clean up namespace violation Wei Liu
@ 2014-06-27 11:37   ` Ian Campbell
  0 siblings, 0 replies; 14+ messages in thread
From: Ian Campbell @ 2014-06-27 11:37 UTC (permalink / raw)
  To: Wei Liu; +Cc: ian.jackson, xen-devel

On Thu, 2014-06-19 at 18:44 +0100, Wei Liu wrote:
> In 752f181f ("libxl_json: introduce parser functions for builtin types")
> a bunch of parser functions were introduced. Unfortunately they
> polluted the public namespace with a prefix "libxl_", while they should
> be internal functions.
> 
> This patch changes the prefix to "libxl__". No functional change
> introduced.
> 
> Signed-off-by: Wei Liu <wei.liu2@citrix.com>

Acked-by: Ian Campbell <ian.campbell@citrix.com>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct
  2014-06-19 17:44 ` [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Wei Liu
@ 2014-06-27 11:40   ` Ian Campbell
  0 siblings, 0 replies; 14+ messages in thread
From: Ian Campbell @ 2014-06-27 11:40 UTC (permalink / raw)
  To: Wei Liu; +Cc: ian.jackson, xen-devel

On Thu, 2014-06-19 at 18:44 +0100, Wei Liu wrote:
> 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>

But you should consider two things:

> diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
> index 7fc42c8..b1ad8d4 100644
> --- a/tools/libxl/Makefile
> +++ b/tools/libxl/Makefile
> @@ -184,8 +184,10 @@ $(LIBXL_OBJS) $(LIBXL_TEST_OBJS) $(LIBXLU_OBJS) \
>  $(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

Listing the new output file as a target here (before the :).

and whether you should be extending the existing:

        libxl.h: _libxl_types.h
        libxl_json.h: _libxl_types_json.h
        libxl_internal.h: _libxl_types_internal.h _paths.h
        libxl_internal_json.h: _libxl_types_internal_json.h
        xl.h: _paths.h

To declare the new relationships from:
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 9e8bc4c..a5803d2 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -3186,6 +3186,9 @@ int libxl__uint64_parse_json(libxl__gc *gc, const libxl__json_object *o,
>  int libxl__string_parse_json(libxl__gc *gc, const libxl__json_object *o,
>                               char **p);
>  
> +#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)
>  {

Ian.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v8 2/8] libxl/gentypes.py: don't generate default values
  2014-06-27 11:37   ` Ian Campbell
@ 2014-07-09  8:53     ` Wei Liu
  0 siblings, 0 replies; 14+ messages in thread
From: Wei Liu @ 2014-07-09  8:53 UTC (permalink / raw)
  To: Ian Campbell; +Cc: ian.jackson, Wei Liu, xen-devel

On Fri, Jun 27, 2014 at 12:37:11PM +0100, Ian Campbell wrote:
> On Thu, 2014-06-19 at 18:44 +0100, Wei Liu wrote:
> 
> Unfortunately there was a conflict in libxl_types.idl against David's
> addition of the generation id type. The reject itself was trivial but I
> think the addition of that type means you need a check_default_fn for
> it.
> 

David already provided a function called libxl_ms_vm_genid_is_zero, I
will use it in my patch.

Wei.

> Sorry.
> 
> Ian.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2014-07-09  8:53 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-19 17:44 [PATCH v8 0/8] libxl: JSON infrastructure Wei Liu
2014-06-19 17:44 ` [PATCH v8 1/8] libxl_internal: functions to check default values for builtin types Wei Liu
2014-06-27 11:36   ` Ian Campbell
2014-06-19 17:44 ` [PATCH v8 2/8] libxl/gentypes.py: don't generate default values Wei Liu
2014-06-27 11:37   ` Ian Campbell
2014-07-09  8:53     ` Wei Liu
2014-06-19 17:44 ` [PATCH v8 3/8] libxl: clean up namespace violation Wei Liu
2014-06-27 11:37   ` Ian Campbell
2014-06-19 17:44 ` [PATCH v8 4/8] libxl IDL: generate code to parse libxl__json_object to libxl_FOO struct Wei Liu
2014-06-27 11:40   ` Ian Campbell
2014-06-19 17:44 ` [PATCH v8 5/8] libxl/gentest.py: test JSON parser Wei Liu
2014-06-19 17:44 ` [PATCH v8 6/8] libxl: copy function for builtin types Wei Liu
2014-06-19 17:44 ` [PATCH v8 7/8] libxl IDL: generate deep copy functions Wei Liu
2014-06-19 17:44 ` [PATCH v8 8/8] libxl/gentest.py: test " Wei Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.