summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>2010-08-09 23:53:17 +0200
committerFlorian Forster <octo@leeloo.lan.home.verplant.org>2010-08-09 23:53:17 +0200
commit1296b16c29a69047e40ee09d094d08d0be8130e3 (patch)
tree8e7e753502bc3e5a9361d1878b855713855c1ce9
parenta87ac24a724c0febf3112a88f3dcb9947c7f83b3 (diff)
downloadyajl-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.h7
-rw-r--r--src/yajl_tree.c25
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;