diff options
author | Sara Golemon <pollita@php.net> | 2010-05-21 22:59:58 +0000 |
---|---|---|
committer | Sara Golemon <pollita@php.net> | 2010-05-21 22:59:58 +0000 |
commit | 6eb4218433e5b2af2974648b31ca434b1aa4e314 (patch) | |
tree | 7107a79d39863c12df805228fc20dd27329c306c /ext/json/JSON_parser.c | |
parent | a25482105ec71b40f14d1f6bf1ce0ee72622047b (diff) | |
download | php-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.c | 29 |
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]) { |