Skip to content

Instantly share code, notes, and snippets.

@krakjoe
Created November 28, 2021 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save krakjoe/26b8bd8210ff77581f6bc2c04c7cbe7c to your computer and use it in GitHub Desktop.
Save krakjoe/26b8bd8210ff77581f6bc2c04c7cbe7c to your computer and use it in GitHub Desktop.
json-caching
diff --git a/ext/json/json.c b/ext/json/json.c
index df46294cd6..f915a492c4 100644
--- a/ext/json/json.c
+++ b/ext/json/json.c
@@ -74,6 +74,7 @@ static PHP_MINIT_FUNCTION(json)
PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_IGNORE", PHP_JSON_INVALID_UTF8_IGNORE);
PHP_JSON_REGISTER_CONSTANT("JSON_INVALID_UTF8_SUBSTITUTE", PHP_JSON_INVALID_UTF8_SUBSTITUTE);
PHP_JSON_REGISTER_CONSTANT("JSON_THROW_ON_ERROR", PHP_JSON_THROW_ON_ERROR);
+ PHP_JSON_REGISTER_CONSTANT("JSON_ENABLE_CACHING", PHP_JSON_ENABLE_CACHE);
/* json error constants */
PHP_JSON_REGISTER_CONSTANT("JSON_ERROR_NONE", PHP_JSON_ERROR_NONE);
@@ -155,6 +156,8 @@ PHP_JSON_API int php_json_encode_ex(smart_str *buf, zval *val, int options, zend
return_code = php_json_encode_zval(buf, val, options, &encoder);
JSON_G(error_code) = encoder.error_code;
+
+ php_json_encode_destroy(&encoder);
return return_code;
}
diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c
index 92e4a10933..425133dd17 100644
--- a/ext/json/json_encoder.c
+++ b/ext/json/json_encoder.c
@@ -481,6 +481,16 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
return FAILURE;
}
+ if ((options & PHP_JSON_ENABLE_CACHE)) {
+ zend_string *cached = zend_hash_index_find_ptr(&encoder->cache, (zend_ulong) Z_OBJ_P(val));
+
+ if (cached) {
+ smart_str_append(buf, cached);
+
+ return SUCCESS;
+ }
+ }
+
PHP_JSON_HASH_PROTECT_RECURSION(myht);
ZVAL_STRING(&fname, "jsonSerialize");
@@ -510,17 +520,26 @@ static int php_json_encode_serializable_object(smart_str *buf, zval *val, int op
return FAILURE;
}
+ smart_str cache = {0};
+
if ((Z_TYPE(retval) == IS_OBJECT) &&
(Z_OBJ(retval) == Z_OBJ_P(val))) {
/* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
- return_code = php_json_encode_array(buf, &retval, options, encoder);
+ return_code = php_json_encode_array(options & PHP_JSON_ENABLE_CACHE ? &cache : buf, &retval, options, encoder);
} else {
/* All other types, encode as normal */
- return_code = php_json_encode_zval(buf, &retval, options, encoder);
+ return_code = php_json_encode_zval(options & PHP_JSON_ENABLE_CACHE ? &cache : buf, &retval, options, encoder);
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
}
+ if ((return_code == SUCCESS) && (options & PHP_JSON_ENABLE_CACHE)) {
+ smart_str_append_smart_str(buf, &cache);
+
+ zend_hash_index_update_ptr(
+ &encoder->cache, (zend_ulong) Z_OBJ_P(val), cache.s);
+ }
+
zval_ptr_dtor(&retval);
zval_ptr_dtor(&fname);
diff --git a/ext/json/php_json.h b/ext/json/php_json.h
index ee8affa1d1..b29a56b354 100644
--- a/ext/json/php_json.h
+++ b/ext/json/php_json.h
@@ -75,6 +75,7 @@ typedef enum {
#define PHP_JSON_INVALID_UTF8_IGNORE (1<<20)
#define PHP_JSON_INVALID_UTF8_SUBSTITUTE (1<<21)
#define PHP_JSON_THROW_ON_ERROR (1<<22)
+#define PHP_JSON_ENABLE_CACHE (1<<23)
/* Internal flags */
#define PHP_JSON_OUTPUT_ARRAY 0
diff --git a/ext/json/php_json_encoder.h b/ext/json/php_json_encoder.h
index 8d9825b4fb..45c5ad735e 100644
--- a/ext/json/php_json_encoder.h
+++ b/ext/json/php_json_encoder.h
@@ -25,12 +25,24 @@ typedef struct _php_json_encoder php_json_encoder;
struct _php_json_encoder {
int depth;
int max_depth;
+ HashTable cache;
php_json_error_code error_code;
};
+static inline void php_json_encode_cache_dtor(zval *zv) {
+ zend_string_release(Z_PTR_P(zv));
+}
+
static inline void php_json_encode_init(php_json_encoder *encoder)
{
memset(encoder, 0, sizeof(php_json_encoder));
+
+ zend_hash_init(&encoder->cache, 8, NULL, php_json_encode_cache_dtor, 0);
+}
+
+static inline void php_json_encode_destroy(php_json_encoder *encoder)
+{
+ zend_hash_destroy(&encoder->cache);
}
int php_json_encode_zval(smart_str *buf, zval *val, int options, php_json_encoder *encoder);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment