rfc:internal_serialize_api
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
rfc:internal_serialize_api [2013/07/27 14:02] – php_serialize_hash_table bukka | rfc:internal_serialize_api [2013/12/15 18:26] – Set correct patch url bukka | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | |||
====== PHP RFC: Internal Serialize API ====== | ====== PHP RFC: Internal Serialize API ====== | ||
- | * Version: | + | * Version: |
* Date: 2013-07-27 | * Date: 2013-07-27 | ||
* Author: Jakub Zelenka, bukka@php.net | * Author: Jakub Zelenka, bukka@php.net | ||
Line 8: | Line 7: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | This RFC propose | + | This RFC proposes a new API for internal |
+ | The current methods of serializing/ | ||
+ | * Internal class has to to define object properties or use get_properties handler. The properties are then used for serialization. The object state can be restored using '' | ||
+ | * Using Serializable interface or serialize / unserialize '' | ||
+ | |||
+ | The first method has one side effect. After unserializing of object, the properties are saved to the object properties HashTable. This requires more allocated memory for the object than it's usualy necassary. The usual purpose of unserializing the internal object is to get the object to the state when it was before serialization. These data are mostly saved in the object bucket and there is no point to save them to properties table as well. There also is an performance issue with serialization. In addition the serialization is quite slow because HashTable must be created and populated with zvals. This is much slower than simply transforming the state of the object to the string (see benchmarks). | ||
+ | |||
+ | The second method requires generating and parsing serialized string which can require quite a lot of coding in C. Also the resulted string is never compatible with the string generate by the first method. It means that existing classes cannot be changed from the first method to the custom serialization without breaking BC. | ||
+ | |||
+ | The proposed API resolves all mentioned problems and also simplify the way how internal objects are serialized/ | ||
+ | |||
+ | | ||
===== Proposal ===== | ===== Proposal ===== | ||
- | The idea is that extension writers | + | The purpose of the proposed API is simplified custom object serialization and unserialization for extension writers |
+ | |||
+ | The proposed changes does not have any influence on user space serialization/ | ||
+ | |||
+ | |||
+ | ==== Serialization ==== | ||
+ | |||
+ | The first part of the proposal is API for generating serialized data for internal classes. | ||
=== Serialize hook changes === | === Serialize hook changes === | ||
- | Currently '' | + | Currently '' |
< | < | ||
Line 24: | Line 41: | ||
</ | </ | ||
- | If the return value is '' | + | If the return value is '' |
- | If the return value is '' | + | If the return value is '' |
- | + | ||
- | + | ||
- | === Serialization state structure === | + | |
- | + | ||
- | The new structure '' | + | |
=== Functions === | === Functions === | ||
+ | |||
+ | The RFC defines new PHPAPI exported helper functions that should be used for object serialization. | ||
< | < | ||
- | /* initialize serialize state */ | ||
- | int php_serialize_init(php_serialize_state *state, unsigned char **buffer, zend_uint *buf_len); | ||
- | |||
- | /* the final operations for internal data serialization */ | ||
- | int php_serialize_finish(php_serialize_state *state); | ||
- | |||
- | /* initialize serialize state and pre-allocate size of memory */ | ||
- | int php_serialize_init_ex(php_serialize_state *state, unsigned char **buffer, zend_uint *buf_len, size_t size); | ||
- | |||
/* add object serialization string prefix */ | /* add object serialization string prefix */ | ||
- | int php_serialize_object_start(php_serialize_state | + | PHPAPI void php_var_serialize_object_start(smart_str |
- | + | ||
- | /* add object serialization string prefix */ | + | |
- | int php_serialize_object_start_ex(php_serialize_state *state, const char *class_name, | + | |
/* append string that ends the object definition */ | /* append string that ends the object definition */ | ||
- | int php_serialize_object_end(php_serialize_state | + | PHPAPI void php_var_serialize_object_end(smart_str |
/* append null property */ | /* append null property */ | ||
- | int php_serialize_property_null(php_serialize_state | + | PHPAPI void php_var_serialize_property_null(smart_str |
/* append boolean property */ | /* append boolean property */ | ||
- | int php_serialize_property_bool(php_serialize_state | + | PHPAPI void php_var_serialize_property_bool(smart_str |
/* append long property */ | /* append long property */ | ||
- | int php_serialize_property_long(php_serialize_state | + | PHPAPI void php_var_serialize_property_long(smart_str |
/* append double property */ | /* append double property */ | ||
- | int php_serialize_property_double(php_serialize_state | + | PHPAPI void php_var_serialize_property_double(smart_str |
/* append string property */ | /* append string property */ | ||
- | int php_serialize_property_string(php_serialize_state | + | PHPAPI void php_var_serialize_property_string(smart_str |
/* append string property */ | /* append string property */ | ||
- | int php_serialize_property_stringl(php_serialize_state | + | PHPAPI void php_var_serialize_property_stringl(smart_str |
- | + | ||
- | /* allocate data to value buffer that needs to filled afterwards */ | + | |
- | int php_serialize_property_stringl_ptr(php_serialize_state *state, const char *key, char **value, size_t value_length); | + | |
/* append string property zval */ | /* append string property zval */ | ||
- | int php_serialize_property_zval(php_serialize_state | + | PHPAPI void php_var_serialize_property_zval(smart_str |
/* append properties taken from HashTable */ | /* append properties taken from HashTable */ | ||
- | int php_serialize_hash_table(php_serialize_state | + | PHPAPI void php_var_serialize_properties(smart_str |
</ | </ | ||
- | All defined function return SUCCESS on success, otherwise FAILURE (it can happen if they are called in order that is not allowed). Some functions | + | The functionality for all functions |
- | The functionality for all functions should be clear from the comments. The exception is function '' | + | === Example ==== |
- | ===== Examples ===== | + | This example shows how the new API could be used in extension. |
- | This example shows how the new API could be used in DateTime serialization. There would be some extra checks if it was used. This is just an example of the API. | + | < |
+ | static int test_object_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) | ||
+ | { | ||
+ | smart_str buf = {0}; | ||
+ | |||
+ | php_var_serialize_object_start(& | ||
+ | php_var_serialize_property_bool(& | ||
+ | php_var_serialize_property_long(& | ||
+ | php_var_serialize_property_double(& | ||
+ | php_var_serialize_property_string(& | ||
+ | php_var_serialize_object_end(& | ||
+ | |||
+ | return PHP_SERIALIZE_OBJECT; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Unserialization ==== | ||
+ | |||
+ | The second part of the proposal is API for parsing serialized string for internal classes. | ||
+ | |||
+ | === Unserialize hook changes === | ||
+ | |||
+ | Currently '' | ||
+ | |||
+ | The RFC proposes calling unserialize callback for custom classes as well as for normal internal classes (prefixed O:) that have '' | ||
+ | |||
+ | The return value is number of characters left in the buffer after processing serialized string. In case of error, the return value should | ||
+ | |||
+ | === Functions === | ||
+ | |||
+ | The RFC defines new PHPAPI exported helper functions that should be used for object unserialization. | ||
< | < | ||
- | int date_object_serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, | + | /* whether unserialization finished */ |
+ | PHPAPI | ||
+ | |||
+ | /* unserialize all properties of the serialized | ||
+ | PHPAPI int php_var_unserialize_properties(HashTable *ht, const unsigned char **buf, zend_uint *buf_len, | ||
+ | |||
+ | /* unserialize one property (key and value) of the serialized object */ | ||
+ | PHPAPI int php_var_unserialize_property(zval *key, zval *value, const unsigned char **buf, zend_uint *buf_len, zend_unserialize_data *data TSRMLS_DC); | ||
+ | </ | ||
+ | |||
+ | The functionality for all functions should be clear from the comments. | ||
+ | |||
+ | === Example ==== | ||
+ | |||
+ | This example shows how the new API could be used in extension. | ||
+ | |||
+ | < | ||
+ | static int test_object_unserialize(zval **object, zend_class_entry *ce, const unsigned char *buf, zend_uint buf_len, zend_unserialize_data | ||
{ | { | ||
- | | + | |
- | php_serialize_state state; | + | |
- | php_date_obj *dateobj = (php_date_obj *) zend_object_store_get_object(object TSRMLS_CC); | + | |
- | | + | |
- | | + | |
- | php_serialize_property_string(&state, " | + | if (!php_var_unserialize_property(&key, &value, &buf, & |
- | | + | |
- | | + | } |
- | | + | /* process key and value... */ |
- | | + | |
- | | + | zval_dtor(&key); |
+ | | ||
+ | | ||
- | return | + | return |
} | } | ||
</ | </ | ||
+ | |||
+ | ===== Benchmark and more examples ===== | ||
+ | |||
+ | The extension with tests and benchmarks is available at https:// | ||
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | Will be after agreeing on API spec... | + | PAtch is in my branch: https:// |
rfc/internal_serialize_api.txt · Last modified: 2018/06/18 10:15 by cmb