WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH V3 09/13] libxl_json: Handle number abrove LONG_MAX.

To: QEMU-devel <qemu-devel@xxxxxxxxxx>, Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH V3 09/13] libxl_json: Handle number abrove LONG_MAX.
From: Anthony PERARD <anthony.perard@xxxxxxxxxx>
Date: Tue, 1 Nov 2011 16:07:22 +0000
Cc: Anthony PERARD <anthony.perard@xxxxxxxxxx>, Xen Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Tue, 01 Nov 2011 09:19:56 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1320163646-24291-1-git-send-email-anthony.perard@xxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <1320163646-24291-1-git-send-email-anthony.perard@xxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
The integers are now "long long" in the json_object.

If a number (decimal or integer) is too big (or too low), it is stored as it in
a string. So for that, we introduce a new type JSON_NUMBER.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 tools/libxl/libxl_internal.h |    6 ++-
 tools/libxl/libxl_json.c     |   74 ++++++++++++++++++++++++++++++------------
 2 files changed, 57 insertions(+), 23 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 942d45b..09e0c51 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -468,6 +468,8 @@ typedef enum {
     JSON_FALSE,
     JSON_INTEGER,
     JSON_DOUBLE,
+    /* number is store in string, it's too big to be a long long or a double */
+    JSON_NUMBER,
     JSON_STRING,
     JSON_MAP,
     JSON_ARRAY,
@@ -477,7 +479,7 @@ typedef enum {
 typedef struct libxl__json_object {
     libxl__json_node_type type;
     union {
-        long i;
+        long long i;
         double d;
         char *string;
         /* List of libxl__json_object */
@@ -536,7 +538,7 @@ flexarray_t *libxl__json_object_get_array(const 
libxl__json_object *o)
     else
         return NULL;
 }
-static inline long libxl__json_object_get_integer(const libxl__json_object *o)
+static inline long long libxl__json_object_get_integer(const 
libxl__json_object *o)
 {
     if (libxl__json_object_is_integer(o))
         return o->u.i;
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index 389b697..fd5e2aa 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -14,6 +14,7 @@
 
 #include <assert.h>
 #include <string.h>
+#include <math.h>
 
 #include <yajl/yajl_parse.h>
 #include <yajl/yajl_gen.h>
@@ -44,6 +45,7 @@ struct libxl__yajl_ctx {
 #  define DEBUG_GEN(ctx, type)              yajl_gen_##type(ctx->g)
 #  define DEBUG_GEN_VALUE(ctx, type, value) yajl_gen_##type(ctx->g, value)
 #  define DEBUG_GEN_STRING(ctx, str, n)     yajl_gen_string(ctx->g, str, n)
+#  define DEBUG_GEN_NUMBER(ctx, str, n)     yajl_gen_number(ctx->g, str, n)
 #  define DEBUG_GEN_REPORT(yajl_ctx) \
     do { \
         const unsigned char *buf = NULL; \
@@ -60,6 +62,7 @@ struct libxl__yajl_ctx {
 #  define DEBUG_GEN(ctx, type)                  ((void)0)
 #  define DEBUG_GEN_VALUE(ctx, type, value)     ((void)0)
 #  define DEBUG_GEN_STRING(ctx, value, lenght)  ((void)0)
+#  define DEBUG_GEN_NUMBER(ctx, value, lenght)  ((void)0)
 #  define DEBUG_GEN_REPORT(ctx)                 ((void)0)
 #endif
 
@@ -363,6 +366,7 @@ void libxl__json_object_free(libxl__gc *gc, 
libxl__json_object *obj)
         return;
     switch (obj->type) {
     case JSON_STRING:
+    case JSON_NUMBER:
         free(obj->u.string);
         break;
     case JSON_MAP: {
@@ -504,36 +508,64 @@ static int json_callback_boolean(void *opaque, int 
boolean)
     return 1;
 }
 
-static int json_callback_integer(void *opaque, long value)
+static bool is_decimal(const char *s, unsigned len)
+{
+    const char *end = s + len;
+    for (; s < end; s++) {
+        if (*s == '.')
+            return true;
+    }
+    return false;
+}
+
+static int json_callback_number(void *opaque, const char *s, unsigned int len)
 {
     libxl__yajl_ctx *ctx = opaque;
-    libxl__json_object *obj;
+    libxl__json_object *obj = NULL;
+    char *t = NULL;
 
-    DEBUG_GEN_VALUE(ctx, integer, value);
+    DEBUG_GEN_NUMBER(ctx, s, len);
 
-    if ((obj = json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL)
-        return 0;
-    obj->u.i = value;
+    if (is_decimal(s, len)) {
+        double d = strtod(s, NULL);
 
-    if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
-        libxl__json_object_free(ctx->gc, obj);
-        return 0;
-    }
+        if ((d == HUGE_VAL || d == HUGE_VAL) && errno == ERANGE) {
+            goto error;
+        }
 
-    return 1;
-}
+        if ((obj = json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL)
+            return 0;
+        obj->u.d = d;
+    } else {
+        long long i = strtoll(s, NULL, 10);
 
-static int json_callback_double(void *opaque, double value)
-{
-    libxl__yajl_ctx *ctx = opaque;
-    libxl__json_object *obj;
+        if ((i == LLONG_MIN || i == LLONG_MAX) && errno == ERANGE) {
+            goto error;
+        }
 
-    DEBUG_GEN_VALUE(ctx, double, value);
+        if ((obj = json_object_alloc(ctx->gc, JSON_INTEGER)) == NULL)
+            return 0;
+        obj->u.i = i;
+    }
+    goto out;
 
-    if ((obj = json_object_alloc(ctx->gc, JSON_DOUBLE)) == NULL)
+error:
+    /* If the conversion fail, we just store the original string. */
+    if ((obj = json_object_alloc(ctx->gc, JSON_NUMBER)) == NULL)
         return 0;
-    obj->u.d = value;
 
+    t = malloc(len + 1);
+    if (t == NULL) {
+        LIBXL__LOG_ERRNO(libxl__gc_owner(ctx->gc), LIBXL__LOG_ERROR,
+                         "Failed to allocate");
+        return 0;
+    }
+    strncpy(t, s, len);
+    t[len] = 0;
+
+    obj->u.string = t;
+
+out:
     if (json_object_append_to(ctx->gc, obj, ctx->current) == -1) {
         libxl__json_object_free(ctx->gc, obj);
         return 0;
@@ -706,9 +738,9 @@ static int json_callback_end_array(void *opaque)
 static yajl_callbacks callbacks = {
     json_callback_null,
     json_callback_boolean,
-    json_callback_integer,
-    json_callback_double,
     NULL,
+    NULL,
+    json_callback_number,
     json_callback_string,
     json_callback_start_map,
     json_callback_map_key,
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel