From: Anthony PERARD <anthony.perard@citrix.com>
To: QEMU-devel <qemu-devel@nongnu.org>,
Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Anthony PERARD <anthony.perard@citrix.com>,
Xen Devel <xen-devel@lists.xensource.com>
Subject: [Qemu-devel] [PATCH V3 09/13] libxl_json: Handle number abrove LONG_MAX.
Date: Tue, 1 Nov 2011 16:07:22 +0000 [thread overview]
Message-ID: <1320163646-24291-10-git-send-email-anthony.perard@citrix.com> (raw)
In-Reply-To: <1320163646-24291-1-git-send-email-anthony.perard@citrix.com>
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@citrix.com>
---
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
next prev parent reply other threads:[~2011-11-01 16:08 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-11-01 16:07 [Qemu-devel] [PATCH V3 00/13] libxl: QMP client improvement + pci passthrougth insert through QMP Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 01/13] libxl_qmp: Fix return check of fcntl Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 02/13] libxl_json: Check the parser status before to call parse_complete Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 03/13] libxl_qmp: Better error message after a parse error Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 04/13] libxl: Introduce dm-version xenstore key Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 05/13] libxl_qmp: Introduce an opaque argument to the callbacks Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 06/13] libxl_qmp: Introduce list of arguments to qmp_send Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 07/13] libxl_qmp: Always insert a command id in the callback_list Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 08/13] libxl_qmp: Introduce qmp_request_context Anthony PERARD
2011-11-01 16:07 ` Anthony PERARD [this message]
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 10/13] libxl_qmp: Introduce libxl__qmp_pci_add Anthony PERARD
2011-11-04 12:44 ` [Qemu-devel] [Xen-devel] [PATCH V3 10/13] libxl: " Ian Jackson
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 11/13] libxl: Use QMP to insert a passthrough device when using upstream QEMU Anthony PERARD
2011-11-04 14:51 ` [Qemu-devel] [Xen-devel] " Ian Jackson
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 12/13] libxl_qmp: Introduce libxl__qmp_pci_del Anthony PERARD
2011-11-01 16:07 ` [Qemu-devel] [PATCH V3 13/13] libxl: Remove a passthrough device through QMP Anthony PERARD
2011-11-01 16:26 ` [Qemu-devel] [PATCH V3 00/13] libxl: QMP client improvement + pci passthrougth insert " Anthony PERARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1320163646-24291-10-git-send-email-anthony.perard@citrix.com \
--to=anthony.perard@citrix.com \
--cc=qemu-devel@nongnu.org \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).