summaryrefslogtreecommitdiff
path: root/ext/json/json_encoder.c
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2021-03-01 22:37:05 +0300
committerDmitry Stogov <dmitry@zend.com>2021-03-01 22:37:05 +0300
commitf9f8c1c79cac1b03279190e0c5513a51881615f9 (patch)
tree38b607f8bd8330297aeb06ef7055e9ea84f105c8 /ext/json/json_encoder.c
parent87a5a0e2cb7bec3d308c2e5f879d4e729297dfb3 (diff)
downloadphp-git-f9f8c1c79cac1b03279190e0c5513a51881615f9.tar.gz
Optimized object encoding without rebulding properties HashTable
Diffstat (limited to 'ext/json/json_encoder.c')
-rw-r--r--ext/json/json_encoder.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c
index f608936349..e78a6495e9 100644
--- a/ext/json/json_encoder.c
+++ b/ext/json/json_encoder.c
@@ -115,6 +115,67 @@ static int php_json_encode_array(smart_str *buf, zval *val, int options, php_jso
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 if (Z_OBJ_P(val)->properties == NULL
+ && Z_OBJ_HT_P(val)->get_properties_for == NULL
+ && Z_OBJ_HT_P(val)->get_properties == zend_std_get_properties) {
+ /* Optimized version without rebulding properties HashTable */
+ zend_object *obj = Z_OBJ_P(val);
+ zend_class_entry *ce = obj->ce;
+ zend_property_info *prop_info;
+ zval *prop;
+ int i;
+
+ if (GC_IS_RECURSIVE(obj)) {
+ encoder->error_code = PHP_JSON_ERROR_RECURSION;
+ smart_str_appendl(buf, "null", 4);
+ return FAILURE;
+ }
+
+ PHP_JSON_HASH_PROTECT_RECURSION(obj);
+ smart_str_appendc(buf, '{');
+ for (i = 0; i < ce->default_properties_count; i++) {
+ prop_info = ce->properties_info_table[i];
+ if (!prop_info) {
+ continue;
+ }
+ if (ZSTR_VAL(prop_info->name)[0] == '\0' && ZSTR_LEN(prop_info->name) > 0) {
+ /* Skip protected and private members. */
+ continue;
+ }
+ prop = OBJ_PROP(obj, prop_info->offset);
+ if (Z_TYPE_P(prop) == IS_UNDEF) {
+ continue;
+ }
+
+ if (need_comma) {
+ smart_str_appendc(buf, ',');
+ } else {
+ need_comma = 1;
+ }
+
+ php_json_pretty_print_char(buf, options, '\n');
+ php_json_pretty_print_indent(buf, options, encoder);
+
+ if (php_json_escape_string(buf, ZSTR_VAL(prop_info->name), ZSTR_LEN(prop_info->name),
+ options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE &&
+ (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) &&
+ buf->s) {
+ ZSTR_LEN(buf->s) -= 4;
+ smart_str_appendl(buf, "\"\"", 2);
+ }
+
+ smart_str_appendc(buf, ':');
+ php_json_pretty_print_char(buf, options, ' ');
+
+ if (php_json_encode_zval(buf, prop, options, encoder) == FAILURE &&
+ !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
+ PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
+ return FAILURE;
+ }
+ }
+ smart_str_appendc(buf, '}');
+ PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
+ return SUCCESS;
} else {
prop_ht = myht = zend_get_properties_for(val, ZEND_PROP_PURPOSE_JSON);
r = PHP_JSON_OUTPUT_OBJECT;