From b30c7fe2639aba8453a4808a285fc2acea36d7bd Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 23 Apr 2014 21:44:26 +0200 Subject: Port JSON --- ext/json/JSON_parser.c | 166 ++++++++++++++++++++++++------------------------- 1 file changed, 81 insertions(+), 85 deletions(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index dd832a7cbd..3b943fd336 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -248,7 +248,7 @@ new_JSON_parser(int depth) jp->error_code = PHP_JSON_ERROR_NONE; jp->stack = (int*)ecalloc(depth, sizeof(int)); if (depth > JSON_PARSER_DEFAULT_DEPTH) { - jp->the_zstack = (zval **)safe_emalloc(depth, sizeof(zval), 0); + jp->the_zstack = (zval *) safe_emalloc(depth, sizeof(zval), 0); } else { jp->the_zstack = &jp->the_static_zstack[0]; } @@ -291,23 +291,21 @@ static int dehexchar(char c) } -static void json_create_zval(zval **z, smart_str *buf, int type, int options) +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--; + if (buf->s->val[0] == '-') { + buf->s->len--; } - if (buf->len >= MAX_LENGTH_OF_LONG - 1) { - if (buf->len == MAX_LENGTH_OF_LONG - 1) { - int cmp = strcmp(buf->c + (buf->c[0] == '-'), long_min_digits); + if (buf->s->len >= MAX_LENGTH_OF_LONG - 1) { + if (buf->s->len == MAX_LENGTH_OF_LONG - 1) { + int cmp = strcmp(buf->s->val + (buf->s->val[0] == '-'), long_min_digits); - if (!(cmp < 0 || (cmp == 0 && buf->c[0] == '-'))) { + if (!(cmp < 0 || (cmp == 0 && buf->s->val[0] == '-'))) { bigint = 1; } } else { @@ -318,9 +316,9 @@ static void json_create_zval(zval **z, smart_str *buf, int type, int options) if (bigint) { /* value too large to represent as a long */ if (options & PHP_JSON_BIGINT_AS_STRING) { - if (buf->c[0] == '-') { + if (buf->s->val[0] == '-') { /* Restore last char consumed above */ - buf->len++; + buf->s->len++; } goto use_string; } else { @@ -328,25 +326,31 @@ static void json_create_zval(zval **z, smart_str *buf, int type, int options) } } - ZVAL_LONG(*z, strtol(buf->c, NULL, 10)); + ZVAL_LONG(z, strtol(buf->s->val, NULL, 10)); } else if (type == IS_DOUBLE) { use_double: - ZVAL_DOUBLE(*z, zend_strtod(buf->c, NULL)); + ZVAL_DOUBLE(z, zend_strtod(buf->s->val, NULL)); } else if (type == IS_STRING) { use_string: - ZVAL_STRINGL(*z, buf->c, buf->len, 1); + if (buf->s) { + ZVAL_STRINGL(z, buf->s->val, buf->s->len); + } else { + ZVAL_EMPTY_STRING(z); + } } - else if (type == IS_BOOL) - { - ZVAL_BOOL(*z, (*(buf->c) == 't')); + else if (type == IS_FALSE) { + ZVAL_FALSE(z); + } + else if (type == IS_TRUE) { + ZVAL_TRUE(z); } else /* type == IS_NULL) || type unknown */ { - ZVAL_NULL(*z); + ZVAL_NULL(z); } } @@ -363,18 +367,18 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16) smart_str_appendc(buf, 0x80 | (utf16 & 0x3f)); } else if ((utf16 & 0xfc00) == 0xdc00 - && buf->len >= 3 - && ((unsigned char) buf->c[buf->len - 3]) == 0xed - && ((unsigned char) buf->c[buf->len - 2] & 0xf0) == 0xa0 - && ((unsigned char) buf->c[buf->len - 1] & 0xc0) == 0x80) + && buf->s->len >= 3 + && ((unsigned char) buf->s->val[buf->s->len - 3]) == 0xed + && ((unsigned char) buf->s->val[buf->s->len - 2] & 0xf0) == 0xa0 + && ((unsigned char) buf->s->val[buf->s->len - 1] & 0xc0) == 0x80) { /* found surrogate pair */ unsigned long utf32; - utf32 = (((buf->c[buf->len - 2] & 0xf) << 16) - | ((buf->c[buf->len - 1] & 0x3f) << 10) + utf32 = (((buf->s->val[buf->s->len - 2] & 0xf) << 16) + | ((buf->s->val[buf->s->len - 1] & 0x3f) << 10) | (utf16 & 0x3ff)) + 0x10000; - buf->len -= 3; + buf->s->len -= 3; smart_str_appendc(buf, (unsigned char) (0xf0 | (utf32 >> 18))); smart_str_appendc(buf, 0x80 | ((utf32 >> 12) & 0x3f)); @@ -389,10 +393,24 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16) } } +static inline void add_assoc_or_property(int assoc, zval *target, smart_str *key, zval *zv TSRMLS_DC) +{ + zend_bool empty_key = !key->s || key->s->len == 0; + if (!assoc) { + add_property_zval_ex(target, empty_key ? "_empty_" : key->s->val, empty_key ? sizeof("_empty_")-1 : key->s->len, zv TSRMLS_CC); + if (Z_REFCOUNTED_P(zv)) Z_DELREF_P(zv); + } else { + add_assoc_zval_ex(target, empty_key ? "" : key->s->val, empty_key ? 0 : key->s->len, zv); + } + if (key->s) { + key->s->len = 0; + } +} + static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int assoc TSRMLS_DC) { - zval *root = jp->the_zstack[up]; - zval *child = jp->the_zstack[cur]; + zval *root = &jp->the_zstack[up]; + zval *child = &jp->the_zstack[cur]; int up_mode = jp->stack[up]; if (up_mode == MODE_ARRAY) @@ -401,30 +419,20 @@ static void attach_zval(JSON_parser jp, int up, int cur, smart_str *key, int ass } else if (up_mode == MODE_OBJECT) { - if (!assoc) - { - add_property_zval_ex(root, (key->len ? key->c : "_empty_"), (key->len ? (key->len + 1) : sizeof("_empty_")), child TSRMLS_CC); - Z_DELREF_P(child); - } - else - { - add_assoc_zval_ex(root, (key->len ? key->c : ""), (key->len ? (key->len + 1) : sizeof("")), child); - } - key->len = 0; + add_assoc_or_property(assoc, root, key, child TSRMLS_CC); } } #define FREE_BUFFERS() smart_str_free(&buf); smart_str_free(&key); #define SWAP_BUFFERS(from, to) do { \ - char *t1 = from.c; \ + zend_string *t1 = from.s; \ int t2 = from.a; \ - from.c = to.c; \ + from.s = to.s; \ from.a = to.a; \ - to.c = t1; \ + to.s = t1; \ to.a = t2; \ - to.len = from.len; \ - from.len = 0; \ + if (from.s) { from.s->len = 0; } \ } while(0); #define JSON_RESET_TYPE() type = -1; @@ -519,8 +527,10 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, smart_str_appendc(&buf, next_char); } else if (type < IS_STRING && next_class == C_QUOTE) { type = IS_STRING; - } else if (type < IS_BOOL && ((jp->state == T3 && next_state == OK) || (jp->state == F4 && next_state == OK))) { - type = IS_BOOL; + } else if (type < IS_FALSE && (jp->state == F4 && next_state == OK)) { + type = IS_FALSE; + } else if (type < IS_TRUE && (jp->state == T3 && next_state == OK)) { + type = IS_TRUE; } else if (type < IS_NULL && jp->state == N3 && next_state == OK) { type = IS_NULL; } else if (type != IS_STRING && next_class > C_WHITE) { @@ -544,19 +554,14 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, case -8: if (type != -1 && jp->stack[jp->top] == MODE_OBJECT) { - zval *mval; + zval mval; smart_str_0(&buf); 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); - Z_DELREF_P(mval); - } else { - add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval); - } - key.len = 0; - buf.len = 0; + add_assoc_or_property(assoc, &jp->the_zstack[jp->top], &key, &mval TSRMLS_CC); + + if (buf.s) { buf.s->len = 0; } JSON_RESET_TYPE(); } @@ -572,12 +577,12 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, { if (type != -1 && jp->stack[jp->top] == MODE_ARRAY) { - zval *mval; + zval mval; smart_str_0(&buf); json_create_zval(&mval, &buf, type, options); - add_next_index_zval(jp->the_zstack[jp->top], mval); - buf.len = 0; + add_next_index_zval(&jp->the_zstack[jp->top], &mval); + buf.s->len = 0; JSON_RESET_TYPE(); } @@ -597,13 +602,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, jp->state = OB; if (jp->top > 0) { - zval *obj; - - if (jp->top == 1) { - obj = z; - } else { - ALLOC_INIT_ZVAL(obj); - } + zval *obj = &jp->the_zstack[jp->top]; if (!assoc) { object_init(obj); @@ -611,7 +610,9 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, array_init(obj); } - jp->the_zstack[jp->top] = obj; + if (jp->top == 1) { + ZVAL_COPY_VALUE(z, obj); + } if (jp->top > 1) { attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC); @@ -630,16 +631,13 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, jp->state = AR; if (jp->top > 0) { - zval *arr; - - if (jp->top == 1) { - arr = z; - } else { - ALLOC_INIT_ZVAL(arr); - } + zval *arr = &jp->the_zstack[jp->top]; array_init(arr); - jp->the_zstack[jp->top] = arr; + + if (jp->top == 1) { + ZVAL_COPY_VALUE(z, arr); + } if (jp->top > 1) { attach_zval(jp, jp->top - 1, jp->top, &key, assoc TSRMLS_CC); @@ -665,8 +663,12 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, break; case MODE_DONE: if (type == IS_STRING) { - smart_str_0(&buf); - ZVAL_STRINGL(z, buf.c, buf.len, 1); + if (buf.s) { + smart_str_0(&buf); + ZVAL_STRINGL(z, buf.s->val, buf.s->len); + } else { + ZVAL_EMPTY_STRING(z); + } jp->state = OK; break; } @@ -680,7 +682,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, /* , */ case -3: { - zval *mval; + zval mval; if (type != -1 && (jp->stack[jp->top] == MODE_OBJECT || @@ -694,20 +696,14 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, case MODE_OBJECT: if (pop(jp, MODE_OBJECT) && push(jp, MODE_KEY)) { if (type != -1) { - 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); - Z_DELREF_P(mval); - } else { - add_assoc_zval_ex(jp->the_zstack[jp->top], (key.len ? key.c : ""), (key.len ? (key.len + 1) : sizeof("")), mval); - } - key.len = 0; + add_assoc_or_property(assoc, &jp->the_zstack[jp->top], &key, &mval TSRMLS_CC); } jp->state = KE; } break; case MODE_ARRAY: if (type != -1) { - add_next_index_zval(jp->the_zstack[jp->top], mval); + add_next_index_zval(&jp->the_zstack[jp->top], &mval); } jp->state = VA; break; @@ -716,7 +712,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, jp->error_code = PHP_JSON_ERROR_SYNTAX; return false; } - buf.len = 0; + buf.s->len = 0; JSON_RESET_TYPE(); } break; -- cgit v1.2.1 From 4d22be992ca23e9ec6f46962b88277229d7f4ace Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 5 May 2014 17:28:22 +0200 Subject: Fix ZTS --- ext/json/JSON_parser.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index 3b943fd336..c7fc6b4f2f 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -291,7 +291,7 @@ static int dehexchar(char c) } -static void json_create_zval(zval *z, smart_str *buf, int type, int options) +static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRMLS_DC) { if (type == IS_LONG) { @@ -557,7 +557,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, zval mval; smart_str_0(&buf); - json_create_zval(&mval, &buf, type, options); + json_create_zval(&mval, &buf, type, options TSRMLS_CC); add_assoc_or_property(assoc, &jp->the_zstack[jp->top], &key, &mval TSRMLS_CC); @@ -580,7 +580,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, zval mval; smart_str_0(&buf); - json_create_zval(&mval, &buf, type, options); + json_create_zval(&mval, &buf, type, options TSRMLS_CC); add_next_index_zval(&jp->the_zstack[jp->top], &mval); buf.s->len = 0; JSON_RESET_TYPE(); @@ -689,7 +689,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, jp->stack[jp->top] == MODE_ARRAY)) { smart_str_0(&buf); - json_create_zval(&mval, &buf, type, options); + json_create_zval(&mval, &buf, type, options TSRMLS_CC); } switch (jp->stack[jp->top]) { -- cgit v1.2.1 From bfff679d903c7ef1648d3d009f42566baa7d6232 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 29 May 2014 12:53:32 +0200 Subject: Fix length reset in JSON parser --- ext/json/JSON_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index c7fc6b4f2f..116fc0c9b6 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -712,7 +712,7 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, jp->error_code = PHP_JSON_ERROR_SYNTAX; return false; } - buf.s->len = 0; + if (buf.s) { buf.s->len = 0; } JSON_RESET_TYPE(); } break; -- cgit v1.2.1 From 63d3f0b844b3a5f1c94be3c97bca29235dc2b3fc Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 08:07:31 +0200 Subject: basic macro replacements, all at once --- ext/json/JSON_parser.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index 116fc0c9b6..a4e34b07bc 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -293,7 +293,7 @@ static int dehexchar(char c) static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRMLS_DC) { - if (type == IS_LONG) + if (type == IS_INT) { zend_bool bigint = 0; @@ -301,9 +301,9 @@ static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRM buf->s->len--; } - if (buf->s->len >= MAX_LENGTH_OF_LONG - 1) { - if (buf->s->len == MAX_LENGTH_OF_LONG - 1) { - int cmp = strcmp(buf->s->val + (buf->s->val[0] == '-'), long_min_digits); + if (buf->s->len >= MAX_LENGTH_OF_ZEND_INT - 1) { + if (buf->s->len == MAX_LENGTH_OF_ZEND_INT - 1) { + int cmp = strcmp(buf->s->val + (buf->s->val[0] == '-'), int_min_digits); if (!(cmp < 0 || (cmp == 0 && buf->s->val[0] == '-'))) { bigint = 1; @@ -326,7 +326,7 @@ static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRM } } - ZVAL_LONG(z, strtol(buf->s->val, NULL, 10)); + ZVAL_INT(z, strtol(buf->s->val, NULL, 10)); } else if (type == IS_DOUBLE) { @@ -516,10 +516,10 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, utf16 += dehexchar(next_char); utf16_to_utf8(&buf, utf16); } - } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) { - type = IS_LONG; + } else if (type < IS_INT && (next_class == C_DIGIT || next_class == C_ZERO)) { + type = IS_INT; smart_str_appendc(&buf, next_char); - } else if (type == IS_LONG && next_state == E1) { + } else if (type == IS_INT && next_state == E1) { type = IS_DOUBLE; smart_str_appendc(&buf, next_char); } else if (type < IS_DOUBLE && next_class == C_POINT) { -- cgit v1.2.1 From 19588572258d3c3216e93ee1c9db7e28c6007e20 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 19 Aug 2014 20:15:59 +0200 Subject: ported ext/json --- ext/json/JSON_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index a4e34b07bc..f2a1ee4dda 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -373,7 +373,7 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16) && ((unsigned char) buf->s->val[buf->s->len - 1] & 0xc0) == 0x80) { /* found surrogate pair */ - unsigned long utf32; + php_uint_t utf32; utf32 = (((buf->s->val[buf->s->len - 2] & 0xf) << 16) | ((buf->s->val[buf->s->len - 1] & 0x3f) << 10) -- cgit v1.2.1 From c3e3c98ec666812daaaca896cf5ef758a8a6df14 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Mon, 25 Aug 2014 19:24:55 +0200 Subject: master renames phase 1 --- ext/json/JSON_parser.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index f2a1ee4dda..a9f1b0a7ae 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -293,7 +293,7 @@ static int dehexchar(char c) static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRMLS_DC) { - if (type == IS_INT) + if (type == IS_LONG) { zend_bool bigint = 0; @@ -301,9 +301,9 @@ static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRM buf->s->len--; } - if (buf->s->len >= MAX_LENGTH_OF_ZEND_INT - 1) { - if (buf->s->len == MAX_LENGTH_OF_ZEND_INT - 1) { - int cmp = strcmp(buf->s->val + (buf->s->val[0] == '-'), int_min_digits); + if (buf->s->len >= MAX_LENGTH_OF_LONG - 1) { + if (buf->s->len == MAX_LENGTH_OF_LONG - 1) { + int cmp = strcmp(buf->s->val + (buf->s->val[0] == '-'), long_min_digits); if (!(cmp < 0 || (cmp == 0 && buf->s->val[0] == '-'))) { bigint = 1; @@ -326,7 +326,7 @@ static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRM } } - ZVAL_INT(z, strtol(buf->s->val, NULL, 10)); + ZVAL_LONG(z, strtol(buf->s->val, NULL, 10)); } else if (type == IS_DOUBLE) { @@ -373,7 +373,7 @@ static void utf16_to_utf8(smart_str *buf, unsigned short utf16) && ((unsigned char) buf->s->val[buf->s->len - 1] & 0xc0) == 0x80) { /* found surrogate pair */ - php_uint_t utf32; + zend_ulong utf32; utf32 = (((buf->s->val[buf->s->len - 2] & 0xf) << 16) | ((buf->s->val[buf->s->len - 1] & 0x3f) << 10) @@ -516,10 +516,10 @@ parse_JSON_ex(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, utf16 += dehexchar(next_char); utf16_to_utf8(&buf, utf16); } - } else if (type < IS_INT && (next_class == C_DIGIT || next_class == C_ZERO)) { - type = IS_INT; + } else if (type < IS_LONG && (next_class == C_DIGIT || next_class == C_ZERO)) { + type = IS_LONG; smart_str_appendc(&buf, next_char); - } else if (type == IS_INT && next_state == E1) { + } else if (type == IS_LONG && next_state == E1) { type = IS_DOUBLE; smart_str_appendc(&buf, next_char); } else if (type < IS_DOUBLE && next_class == C_POINT) { -- cgit v1.2.1 From 993ae7e9f6df9c565ec5f0b17a8bad3da32470a7 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 26 Aug 2014 00:24:38 +0200 Subject: fix strtol call --- ext/json/JSON_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ext/json/JSON_parser.c') diff --git a/ext/json/JSON_parser.c b/ext/json/JSON_parser.c index a9f1b0a7ae..d78ec35a2e 100644 --- a/ext/json/JSON_parser.c +++ b/ext/json/JSON_parser.c @@ -326,7 +326,7 @@ static void json_create_zval(zval *z, smart_str *buf, int type, int options TSRM } } - ZVAL_LONG(z, strtol(buf->s->val, NULL, 10)); + ZVAL_LONG(z, ZEND_STRTOL(buf->s->val, NULL, 10)); } else if (type == IS_DOUBLE) { -- cgit v1.2.1