From patchwork Tue Nov 1 16:07:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony PERARD X-Patchwork-Id: 123091 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 441E9B6F86 for ; Wed, 2 Nov 2011 03:09:39 +1100 (EST) Received: from localhost ([::1]:40588 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RLGu7-0003Ra-NV for incoming@patchwork.ozlabs.org; Tue, 01 Nov 2011 12:09:35 -0400 Received: from eggs.gnu.org ([140.186.70.92]:54611) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RLGsy-0001yM-Pd for qemu-devel@nongnu.org; Tue, 01 Nov 2011 12:08:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RLGsw-0004kR-Af for qemu-devel@nongnu.org; Tue, 01 Nov 2011 12:08:24 -0400 Received: from smtp02.citrix.com ([66.165.176.63]:23018) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RLGsv-0004j5-Qy for qemu-devel@nongnu.org; Tue, 01 Nov 2011 12:08:22 -0400 X-IronPort-AV: E=Sophos;i="4.69,438,1315195200"; d="scan'208";a="168952591" Received: from ftlpmailmx02.citrite.net ([10.13.107.66]) by FTLPIPO02.CITRIX.COM with ESMTP/TLS/RC4-MD5; 01 Nov 2011 12:08:06 -0400 Received: from smtp01.ad.xensource.com (10.219.128.104) by smtprelay.citrix.com (10.13.107.66) with Microsoft SMTP Server id 8.3.137.0; Tue, 1 Nov 2011 12:08:05 -0400 Received: from perard.uk.xensource.com (dhcp-3-28.uk.xensource.com [10.80.3.28] (may be forged)) by smtp01.ad.xensource.com (8.13.1/8.13.1) with ESMTP id pA1G7YNM014577; Tue, 1 Nov 2011 09:08:03 -0700 From: Anthony PERARD To: QEMU-devel , Stefano Stabellini Date: Tue, 1 Nov 2011 16:07:22 +0000 Message-ID: <1320163646-24291-10-git-send-email-anthony.perard@citrix.com> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <1320163646-24291-1-git-send-email-anthony.perard@citrix.com> References: <1320163646-24291-1-git-send-email-anthony.perard@citrix.com> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 66.165.176.63 Cc: Anthony PERARD , Xen Devel Subject: [Qemu-devel] [PATCH V3 09/13] libxl_json: Handle number abrove LONG_MAX. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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 #include +#include #include #include @@ -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,