PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
typedef struct _spl_SplObjectStorage { /* {{{ */
- zend_object std;
HashTable storage;
- long index;
+ zend_long index;
HashPosition pos;
- long flags;
+ zend_long flags;
zend_function *fptr_get_hash;
HashTable *debug_info;
- zval **gcdata;
- long gcdata_num;
++ zval *gcdata;
++ size_t gcdata_num;
+ zend_object std;
} spl_SplObjectStorage; /* }}} */
/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
zend_hash_destroy(intern->debug_info);
efree(intern->debug_info);
}
- efree(object);
+
+ if (intern->gcdata != NULL) {
+ efree(intern->gcdata);
+ }
+
} /* }}} */
-static char *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj, int *hash_len_ptr TSRMLS_DC) {
+static zend_string *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj) {
if (intern->fptr_get_hash) {
- zval *rv;
- zend_call_method_with_1_params(&this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj);
- if (rv) {
- if (Z_TYPE_P(rv) == IS_STRING) {
- int hash_len = Z_STRLEN_P(rv);
- char *hash = emalloc((hash_len+1)*sizeof(char));
- strncpy(hash, Z_STRVAL_P(rv), hash_len);
- hash[hash_len] = 0;
-
- zval_ptr_dtor(&rv);
- if (hash_len_ptr) {
- *hash_len_ptr = hash_len;
- }
- return hash;
+ zval rv;
+ zend_call_method_with_1_params(this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj);
+ if (!Z_ISUNDEF(rv)) {
+ if (Z_TYPE(rv) == IS_STRING) {
+ return Z_STR(rv);
} else {
- zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0 TSRMLS_CC);
+ zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0);
zval_ptr_dtor(&rv);
return NULL;
}
/* }}} */
- /* overriden for garbage collection
- * This is very hacky */
+ /* overriden for garbage collection */
-static HashTable *spl_object_storage_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
+static HashTable *spl_object_storage_get_gc(zval *obj, zval **table, int *n) /* {{{ */
{
- long i = 0;
- spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
++ int i = 0;
+ spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(obj);
spl_SplObjectStorageElement *element;
- HashTable *props;
- zval *gcdata_arr, tmp;
-
- props = std_object_handlers.get_properties(obj);
-
- *table = NULL;
- *n = 0;
- HashPosition pos;
- /* clean \x00gcdata, as it may be out of date */
- if ((gcdata_arr = zend_hash_str_find(props, "\x00gcdata", sizeof("\x00gcdata") - 1)) != NULL) {
- zend_hash_clean(Z_ARRVAL_P(gcdata_arr));
- }
-
- if (gcdata_arr == NULL) {
- array_init(&tmp);
- /* don't decrease refcount of members when destroying */
- Z_ARRVAL_P(&tmp)->pDestructor = NULL;
-
- /* name starts with \x00 to make tampering in user-land more difficult */
- zend_hash_str_add(props, "\x00gcdata", sizeof("\x00gcdata") - 1, &tmp);
- gcdata_arr = &tmp;
+ if (intern->storage.nNumOfElements > intern->gcdata_num) {
+ intern->gcdata_num = intern->storage.nNumOfElements * 2;
- intern->gcdata = (zval**)erealloc(intern->gcdata, sizeof(zval*) * intern->gcdata_num);
++ intern->gcdata = (zval*)erealloc(intern->gcdata, sizeof(zval) * intern->gcdata_num);
}
- zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
- while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
- intern->gcdata[i++] = element->obj;
- intern->gcdata[i++] = element->inf;
- zend_hash_move_forward_ex(&intern->storage, &pos);
- }
+ ZEND_HASH_FOREACH_PTR(&intern->storage, element) {
- add_next_index_zval(gcdata_arr, &element->obj);
- add_next_index_zval(gcdata_arr, &element->inf);
++ ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->obj);
++ ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->inf);
+ } ZEND_HASH_FOREACH_END();
- return props;
+ *table = intern->gcdata;
+ *n = i;
+
+ return std_object_handlers.get_properties(obj TSRMLS_CC);
}
/* }}} */
/* members */
smart_str_appendl(&buf, "m:", 2);
- INIT_PZVAL(&members);
- Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
- Z_TYPE(members) = IS_ARRAY;
+
- pmembers = &members;
- php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
+ ZVAL_ARR(&members, zend_array_dup(zend_std_get_properties(getThis())));
- zend_hash_str_del(Z_ARRVAL(members), "\x00gcdata", sizeof("\x00gcdata") - 1);
+ php_var_serialize(&buf, &members, &var_hash); /* finishes the string */
+ zval_ptr_dtor(&members);
/* done */
PHP_VAR_SERIALIZE_DESTROY(var_hash);