summaryrefslogtreecommitdiff
path: root/ext/json/JSON_parser.c
diff options
context:
space:
mode:
authorSara Golemon <pollita@php.net>2010-05-21 22:59:58 +0000
committerSara Golemon <pollita@php.net>2010-05-21 22:59:58 +0000
commit6eb4218433e5b2af2974648b31ca434b1aa4e314 (patch)
tree7107a79d39863c12df805228fc20dd27329c306c /ext/json/JSON_parser.c
parenta25482105ec71b40f14d1f6bf1ce0ee72622047b (diff)
downloadphp-git-6eb4218433e5b2af2974648b31ca434b1aa4e314.tar.gz
Add JSON_BIGINT_AS_STRING for json_decode() to parse large numbers
as strings rather than casting to double and loosing precision.
Diffstat (limited to 'ext/json/JSON_parser.c')
-rw-r--r--ext/json/JSON_parser.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c
index 259b77b084..ef05f3b43c 100644
--- a/ext/json/JSON_parser.c
+++ b/ext/json/JSON_parser.c
@@ -291,12 +291,14 @@ static int dehexchar(char c)
}
-static void json_create_zval(zval **z, smart_str *buf, int type)
+static void json_create_zval(zval **z, smart_str *buf, int type, int options)
{
ALLOC_INIT_ZVAL(*z);
if (type == IS_LONG)
{
+ zend_bool bigint = 0;
+
if (buf->c[0] == '-') {
buf->len--;
}
@@ -306,8 +308,21 @@ static void json_create_zval(zval **z, smart_str *buf, int type)
int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits);
if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) {
- goto use_double;
+ bigint = 1;
+ }
+ } else {
+ bigint = 1;
+ }
+ }
+
+ if (bigint) {
+ /* value too large to represent as a long */
+ if (options & PHP_JSON_BIGINT_AS_STRING) {
+ if (buf->c[0] == '-') {
+ /* Restore last char consumed above */
+ buf->len++;
}
+ goto use_string;
} else {
goto use_double;
}
@@ -322,6 +337,7 @@ use_double:
}
else if (type == IS_STRING)
{
+use_string:
ZVAL_STRINGL(*z, buf->c, buf->len, 1);
}
else if (type == IS_BOOL)
@@ -420,12 +436,13 @@ static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int ass
machine with a stack.
*/
int
-parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC)
+parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int options TSRMLS_DC)
{
int next_char; /* the next character */
int next_class; /* the next character class */
int next_state; /* the next state */
int the_index;
+ int assoc = options & PHP_JSON_OBJECT_AS_ARRAY;
smart_str buf = {0};
smart_str key = {0};
@@ -530,7 +547,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
zval *mval;
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
if (!assoc) {
add_property_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : "_empty_"), (key.len ? (key.len + 1) : sizeof("_empty_")), mval TSRMLS_CC);
@@ -558,7 +575,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
zval *mval;
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
add_next_index_zval(jp->the_zstack[jp->top], mval);
buf.len = 0;
JSON_RESET_TYPE();
@@ -669,7 +686,7 @@ parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int
jp->stack[jp->top] == MODE_ARRAY))
{
smart_str_0(&buf);
- json_create_zval(&mval, &buf, type);
+ json_create_zval(&mval, &buf, type, options);
}
switch (jp->stack[jp->top]) {