summaryrefslogtreecommitdiff
path: root/ext/json/json_encoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/json_encoder.c')
-rw-r--r--ext/json/json_encoder.c163
1 files changed, 77 insertions, 86 deletions
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c
index 952e546c6c..c0fcbe3282 100644
--- a/ext/json/json_encoder.c
+++ b/ext/json/json_encoder.c
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2018 The PHP Group |
+ | Copyright (c) The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -130,19 +130,21 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
static int php_json_encode_array(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
{
int i, r, need_comma = 0;
- HashTable *myht;
+ HashTable *myht, *prop_ht;
if (Z_TYPE_P(val) == IS_ARRAY) {
myht = Z_ARRVAL_P(val);
+ prop_ht = NULL;
r = (options & PHP_JSON_FORCE_OBJECT) ? PHP_JSON_OUTPUT_OBJECT : php_json_determine_array_type(val);
} else {
- myht = Z_OBJPROP_P(val);
+ prop_ht = myht = zend_get_properties_for(val, ZEND_PROP_PURPOSE_JSON);
r = PHP_JSON_OUTPUT_OBJECT;
}
if (myht && GC_IS_RECURSIVE(myht)) {
encoder->error_code = PHP_JSON_ERROR_RECURSION;
smart_str_appendl(buf, "null", 4);
+ zend_release_properties(prop_ht);
return FAILURE;
}
@@ -218,6 +220,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
if (php_json_encode_zval(buf, data, options, encoder) == FAILURE &&
!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
+ zend_release_properties(prop_ht);
return FAILURE;
}
} ZEND_HASH_FOREACH_END();
@@ -228,6 +231,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
if (encoder->depth > encoder->max_depth) {
encoder->error_code = PHP_JSON_ERROR_DEPTH;
if (!(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
+ zend_release_properties(prop_ht);
return FAILURE;
}
}
@@ -245,6 +249,7 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
smart_str_appendc(buf, '}');
}
+ zend_release_properties(prop_ht);
return SUCCESS;
}
/* }}} */
@@ -279,97 +284,94 @@ static int php_json_escape_string(
}
}
- pos = 0;
checkpoint = buf->s ? ZSTR_LEN(buf->s) : 0;
/* pre-allocate for string length plus 2 quotes */
smart_str_alloc(buf, len+2, 0);
smart_str_appendc(buf, '"');
+ pos = 0;
+
do {
+ static const uint32_t charmap[8] = {
+ 0xffffffff, 0x500080c4, 0x10000000, 0x00000000,
+ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
+
us = (unsigned char)s[pos];
- if (UNEXPECTED(us >= 0x80)) {
+ if (EXPECTED(!ZEND_BIT_TEST(charmap, us))) {
+ pos++;
+ len--;
+ if (len == 0) {
+ smart_str_appendl(buf, s, pos);
+ break;
+ }
+ } else {
if (pos) {
smart_str_appendl(buf, s, pos);
s += pos;
pos = 0;
}
- us = php_next_utf8_char((unsigned char *)s, len, &pos, &status);
- len -= pos;
-
- /* check whether UTF8 character is correct */
- if (UNEXPECTED(status != SUCCESS)) {
- s += pos;
- pos = 0;
- if (options & PHP_JSON_INVALID_UTF8_IGNORE) {
- /* ignore invalid UTF8 character */
- continue;
- } else if (options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) {
- /* Use Unicode character 'REPLACEMENT CHARACTER' (U+FFFD) */
- if (options & PHP_JSON_UNESCAPED_UNICODE) {
- smart_str_appendl(buf, "\xef\xbf\xbd", 3);
+ us = (unsigned char)s[0];
+ if (UNEXPECTED(us >= 0x80)) {
+
+ us = php_next_utf8_char((unsigned char *)s, len, &pos, &status);
+
+ /* check whether UTF8 character is correct */
+ if (UNEXPECTED(status != SUCCESS)) {
+ if (options & PHP_JSON_INVALID_UTF8_IGNORE) {
+ /* ignore invalid UTF8 character */
+ } else if (options & PHP_JSON_INVALID_UTF8_SUBSTITUTE) {
+ /* Use Unicode character 'REPLACEMENT CHARACTER' (U+FFFD) */
+ if (options & PHP_JSON_UNESCAPED_UNICODE) {
+ smart_str_appendl(buf, "\xef\xbf\xbd", 3);
+ } else {
+ smart_str_appendl(buf, "\\ufffd", 6);
+ }
} else {
- smart_str_appendl(buf, "\\ufffd", 6);
+ ZSTR_LEN(buf->s) = checkpoint;
+ encoder->error_code = PHP_JSON_ERROR_UTF8;
+ if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+ smart_str_appendl(buf, "null", 4);
+ }
+ return FAILURE;
}
- continue;
+
+ /* Escape U+2028/U+2029 line terminators, UNLESS both
+ JSON_UNESCAPED_UNICODE and
+ JSON_UNESCAPED_LINE_TERMINATORS were provided */
+ } else if ((options & PHP_JSON_UNESCAPED_UNICODE)
+ && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS)
+ || us < 0x2028 || us > 0x2029)) {
+ smart_str_appendl(buf, s, pos);
} else {
- ZSTR_LEN(buf->s) = checkpoint;
- encoder->error_code = PHP_JSON_ERROR_UTF8;
- if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
- smart_str_appendl(buf, "null", 4);
+ /* From http://en.wikipedia.org/wiki/UTF16 */
+ if (us >= 0x10000) {
+ unsigned int next_us;
+
+ us -= 0x10000;
+ next_us = (unsigned short)((us & 0x3ff) | 0xdc00);
+ us = (unsigned short)((us >> 10) | 0xd800);
+ dst = smart_str_extend(buf, 6);
+ dst[0] = '\\';
+ dst[1] = 'u';
+ dst[2] = digits[(us >> 12) & 0xf];
+ dst[3] = digits[(us >> 8) & 0xf];
+ dst[4] = digits[(us >> 4) & 0xf];
+ dst[5] = digits[us & 0xf];
+ us = next_us;
}
- return FAILURE;
+ dst = smart_str_extend(buf, 6);
+ dst[0] = '\\';
+ dst[1] = 'u';
+ dst[2] = digits[(us >> 12) & 0xf];
+ dst[3] = digits[(us >> 8) & 0xf];
+ dst[4] = digits[(us >> 4) & 0xf];
+ dst[5] = digits[us & 0xf];
}
-
- /* Escape U+2028/U+2029 line terminators, UNLESS both
- JSON_UNESCAPED_UNICODE and
- JSON_UNESCAPED_LINE_TERMINATORS were provided */
- } else if ((options & PHP_JSON_UNESCAPED_UNICODE)
- && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS)
- || us < 0x2028 || us > 0x2029)) {
- smart_str_appendl(buf, s, pos);
s += pos;
+ len -= pos;
pos = 0;
- continue;
- }
- /* From http://en.wikipedia.org/wiki/UTF16 */
- if (us >= 0x10000) {
- unsigned int next_us;
-
- us -= 0x10000;
- next_us = (unsigned short)((us & 0x3ff) | 0xdc00);
- us = (unsigned short)((us >> 10) | 0xd800);
- dst = smart_str_extend(buf, 6);
- dst[0] = '\\';
- dst[1] = 'u';
- dst[2] = digits[(us >> 12) & 0xf];
- dst[3] = digits[(us >> 8) & 0xf];
- dst[4] = digits[(us >> 4) & 0xf];
- dst[5] = digits[us & 0xf];
- us = next_us;
- }
- dst = smart_str_extend(buf, 6);
- dst[0] = '\\';
- dst[1] = 'u';
- dst[2] = digits[(us >> 12) & 0xf];
- dst[3] = digits[(us >> 8) & 0xf];
- dst[4] = digits[(us >> 4) & 0xf];
- dst[5] = digits[us & 0xf];
- s += pos;
- pos = 0;
- } else {
- static const uint32_t charmap[4] = {
- 0xffffffff, 0x500080c4, 0x10000000, 0x00000000};
-
- len--;
- if (EXPECTED(!ZEND_BIT_TEST(charmap, us))) {
- pos++;
} else {
- if (pos) {
- smart_str_appendl(buf, s, pos);
- s += pos;
- pos = 0;
- }
s++;
switch (us) {
case '"':
@@ -455,13 +457,11 @@ static int php_json_escape_string(
dst[5] = digits[us & 0xf];
break;
}
+ len--;
}
}
} while (len);
- if (EXPECTED(pos)) {
- smart_str_appendl(buf, s, pos);
- }
smart_str_appendc(buf, '"');
return SUCCESS;
@@ -487,7 +487,7 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
ZVAL_STRING(&fname, "jsonSerialize");
- if (FAILURE == call_user_function(EG(function_table), val, &fname, &retval, 0, NULL) || Z_TYPE(retval) == IS_UNDEF) {
+ if (FAILURE == call_user_function(NULL, val, &fname, &retval, 0, NULL) || Z_TYPE(retval) == IS_UNDEF) {
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0, "Failed calling %s::jsonSerialize()", ZSTR_VAL(ce->name));
}
@@ -593,12 +593,3 @@ again:
return SUCCESS;
}
/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */