diff options
author | Florian Forster <octo@leeloo.lan.home.verplant.org> | 2010-08-09 23:53:17 +0200 |
---|---|---|
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | 2010-08-09 23:53:17 +0200 |
commit | 1296b16c29a69047e40ee09d094d08d0be8130e3 (patch) | |
tree | 8e7e753502bc3e5a9361d1878b855713855c1ce9 | |
parent | a87ac24a724c0febf3112a88f3dcb9947c7f83b3 (diff) | |
download | yajl-1296b16c29a69047e40ee09d094d08d0be8130e3.tar.gz |
src/yajl_tree.c: Parse JSON numbers to int and double and include that in the struct.
An additional "flags" field marks whether or not any problems occurred when
parsing the string. The check is very picky and even considers trailing
characters to be a problem. Especially when expecting an integer but the
string actually contains a double, the initial characters may form a valid
integer which differs greatly from the actual value of the double.
-rw-r--r-- | src/api/yajl_tree.h | 7 | ||||
-rw-r--r-- | src/yajl_tree.c | 25 |
2 files changed, 26 insertions, 6 deletions
diff --git a/src/api/yajl_tree.h b/src/api/yajl_tree.h index 8e0fc47..1a4c5c3 100644 --- a/src/api/yajl_tree.h +++ b/src/api/yajl_tree.h @@ -47,9 +47,14 @@ struct yajl_value_string_s }; typedef struct yajl_value_string_s yajl_value_string_t; +#define YAJL_NUMBER_INT_VALID 1 +#define YAJL_NUMBER_DOUBLE_VALID 2 struct yajl_value_number_s { - char *value; + char *value_raw; + int64_t value_int; + double value_double; + unsigned int flags; }; typedef struct yajl_value_number_s yajl_value_number_t; diff --git a/src/yajl_tree.c b/src/yajl_tree.c index 472b8f9..f29b20c 100644 --- a/src/yajl_tree.c +++ b/src/yajl_tree.c @@ -292,20 +292,35 @@ static int handle_number (void *ctx, /* {{{ */ { yajl_value_t *v; yajl_value_number_t *n; + char *endptr; v = value_alloc (VALUE_TYPE_STRING); if (v == NULL) return (STATUS_ABORT); n = &v->data.number; - n->value = malloc (string_length + 1); - if (n->value == NULL) + n->value_raw = malloc (string_length + 1); + if (n->value_raw == NULL) { free (v); return (STATUS_ABORT); } - memcpy (n->value, string, string_length); - n->value[string_length] = 0; + memcpy (n->value_raw, string, string_length); + n->value_raw[string_length] = 0; + + n->flags = 0; + + endptr = NULL; + errno = 0; + n->value_int = (int64_t) strtoll (n->value_raw, &endptr, /* base = */ 10); + if ((errno == 0) && (endptr != NULL) && (*endptr == 0)) + n->flags |= YAJL_NUMBER_INT_VALID; + + endptr = NULL; + errno = 0; + n->value_double = strtod (n->value_raw, &endptr); + if ((errno == 0) && (endptr != NULL) && (*endptr == 0)) + n->flags |= YAJL_NUMBER_DOUBLE_VALID; return ((context_add_value (ctx, v) == 0) ? STATUS_CONTINUE : STATUS_ABORT); } /* }}} int handle_number */ @@ -457,7 +472,7 @@ void yajl_tree_free (yajl_value_t *v) /* {{{ */ { yajl_value_number_t *n = &v->data.number; - free (n->value); + free (n->value_raw); free (v); return; |