From 225d86dcfa31a3058529a884a36f09b60fa2b669 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss Date: Thu, 19 Mar 2009 02:45:17 +0000 Subject: [PATCH] MFH: Fix #47671 (cloning SplObjectStorage instances) --- NEWS | 1 + ext/spl/spl_observer.c | 181 ++++++++++++++++++++++++----------------- 2 files changed, 107 insertions(+), 75 deletions(-) diff --git a/NEWS b/NEWS index 297ae019c3..2b597d9279 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ PHP NEWS (Denis Giffeler, Moriyoshi) - Fixed bug #47678 (Allow loadExtension to be disabled in SQLite3). (Scott) +- Fixed bug #47671 (Cloning SplObjectStorage instances). (Etienne) - Fixed bug #47664 (get_class returns NULL instead of FALSE). (Dmitry) - Fixed bug #47593 (interface_exists() returns false when using absolute namespace path). (Kalle, Felipe) diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 926d88d0e1..6768499800 100755 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -106,6 +106,85 @@ static void spl_object_storage_dtor(spl_SplObjectStorageElement *element) /* {{{ zval_ptr_dtor(&element->inf); } /* }}} */ +spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */ +{ + spl_SplObjectStorageElement *element; + zend_object_value *pzvalue; +#if HAVE_PACKED_OBJECT_VALUE + pzvalue = &Z_OBJVAL_P(obj); +#else + zend_object_value zvalue; + memset(&zvalue, 0, sizeof(zend_object_value)); + zvalue.handle = Z_OBJ_HANDLE_P(obj); + zvalue.handlers = Z_OBJ_HT_P(obj); + pzvalue = &zvalue; +#endif + if (zend_hash_find(&intern->storage, (char*)pzvalue, sizeof(zend_object_value), (void**)&element) == SUCCESS) { + return element; + } else { + return NULL; + } +} /* }}} */ + +void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *inf TSRMLS_DC) /* {{{ */ +{ + spl_SplObjectStorageElement *pelement, element; + pelement = spl_object_storage_get(intern, obj TSRMLS_CC); + if (inf) { + Z_ADDREF_P(inf); + } else { + ALLOC_INIT_ZVAL(inf); + } + if (pelement) { + zval_ptr_dtor(&pelement->inf); + pelement->inf = inf; + return; + } + Z_ADDREF_P(obj); + element.obj = obj; + element.inf = inf; +#if HAVE_PACKED_OBJECT_VALUE + zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL); +#else + { + zend_object_value zvalue; + memset(&zvalue, 0, sizeof(zend_object_value)); + zvalue.handle = Z_OBJ_HANDLE_P(obj); + zvalue.handlers = Z_OBJ_HT_P(obj); + zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL); + } +#endif +} /* }}} */ + +void spl_object_storage_detach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */ +{ +#if HAVE_PACKED_OBJECT_VALUE + zend_hash_del(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value)); +#else + { + zend_object_value zvalue; + memset(&zvalue, 0, sizeof(zend_object_value)); + zvalue.handle = Z_OBJ_HANDLE_P(obj); + zvalue.handlers = Z_OBJ_HT_P(obj); + zend_hash_del(&intern->storage, (char*)&zvalue, sizeof(zend_object_value)); + } +#endif +} /* }}}*/ + +void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other TSRMLS_DC) { /* {{{ */ + HashPosition pos; + spl_SplObjectStorageElement *element; + + zend_hash_internal_pointer_reset_ex(&other->storage, &pos); + while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) { + spl_object_storage_attach(intern, element->obj, element->inf TSRMLS_CC); + zend_hash_move_forward_ex(&other->storage, &pos); + } + + zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); + intern->index = 0; +} /* }}} */ + static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */ { zend_object_value retval; @@ -123,10 +202,35 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage, NULL TSRMLS_CC); retval.handlers = &spl_handler_SplObjectStorage; + + if (orig) { + spl_SplObjectStorage *other = (spl_SplObjectStorage*)zend_object_store_get_object(orig TSRMLS_CC); + spl_object_storage_addall(intern, other TSRMLS_CC); + } + return retval; } /* }}} */ +/* {{{ spl_object_storage_clone */ +static zend_object_value spl_object_storage_clone(zval *zobject TSRMLS_DC) +{ + zend_object_value new_obj_val; + zend_object *old_object; + zend_object *new_object; + zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); + spl_SplObjectStorage *intern; + + old_object = zend_objects_get_address(zobject TSRMLS_CC); + new_obj_val = spl_object_storage_new_ex(old_object->ce, &intern, zobject TSRMLS_CC); + new_object = &intern->std; + + zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC); + + return new_obj_val; +} +/* }}} */ + static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */ { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC); @@ -218,71 +322,6 @@ int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *obj TSRMLS_D #endif } /* }}} */ -spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */ -{ - spl_SplObjectStorageElement *element; - zend_object_value *pzvalue; -#if HAVE_PACKED_OBJECT_VALUE - pzvalue = &Z_OBJVAL_P(obj); -#else - zend_object_value zvalue; - memset(&zvalue, 0, sizeof(zend_object_value)); - zvalue.handle = Z_OBJ_HANDLE_P(obj); - zvalue.handlers = Z_OBJ_HT_P(obj); - pzvalue = &zvalue; -#endif - if (zend_hash_find(&intern->storage, (char*)pzvalue, sizeof(zend_object_value), (void**)&element) == SUCCESS) { - return element; - } else { - return NULL; - } -} /* }}} */ - -void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *inf TSRMLS_DC) /* {{{ */ -{ - spl_SplObjectStorageElement *pelement, element; - pelement = spl_object_storage_get(intern, obj TSRMLS_CC); - if (inf) { - Z_ADDREF_P(inf); - } else { - ALLOC_INIT_ZVAL(inf); - } - if (pelement) { - zval_ptr_dtor(&pelement->inf); - pelement->inf = inf; - return; - } - Z_ADDREF_P(obj); - element.obj = obj; - element.inf = inf; -#if HAVE_PACKED_OBJECT_VALUE - zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL); -#else - { - zend_object_value zvalue; - memset(&zvalue, 0, sizeof(zend_object_value)); - zvalue.handle = Z_OBJ_HANDLE_P(obj); - zvalue.handlers = Z_OBJ_HT_P(obj); - zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL); - } -#endif -} /* }}} */ - -void spl_object_storage_detach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */ -{ -#if HAVE_PACKED_OBJECT_VALUE - zend_hash_del(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value)); -#else - { - zend_object_value zvalue; - memset(&zvalue, 0, sizeof(zend_object_value)); - zvalue.handle = Z_OBJ_HANDLE_P(obj); - zvalue.handlers = Z_OBJ_HT_P(obj); - zend_hash_del(&intern->storage, (char*)&zvalue, sizeof(zend_object_value)); - } -#endif -} /* }}}*/ - /* {{{ proto void SplObjectStorage::attach($obj, $inf = NULL) Attaches an object to the storage if not yet contained */ SPL_METHOD(SplObjectStorage, attach) @@ -339,8 +378,6 @@ SPL_METHOD(SplObjectStorage, addAll) zval *obj; spl_SplObjectStorage *intern = (spl_SplObjectStorage *)zend_object_store_get_object(getThis() TSRMLS_CC); spl_SplObjectStorage *other; - spl_SplObjectStorageElement *element; - HashPosition pos; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &obj, spl_ce_SplObjectStorage) == FAILURE) { return; @@ -348,14 +385,7 @@ SPL_METHOD(SplObjectStorage, addAll) other = (spl_SplObjectStorage *)zend_object_store_get_object(obj TSRMLS_CC); - zend_hash_internal_pointer_reset_ex(&other->storage, &pos); - while (zend_hash_get_current_data_ex(&other->storage, (void **)&element, &pos) == SUCCESS) { - spl_object_storage_attach(intern, element->obj, element->inf TSRMLS_CC); - zend_hash_move_forward_ex(&other->storage, &pos); - } - - zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); - intern->index = 0; + spl_object_storage_addall(intern, other TSRMLS_CC); RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ @@ -996,6 +1026,7 @@ PHP_MINIT_FUNCTION(spl_observer) spl_handler_SplObjectStorage.get_debug_info = spl_object_storage_debug_info; spl_handler_SplObjectStorage.compare_objects = spl_object_storage_compare_objects; + spl_handler_SplObjectStorage.clone_obj = spl_object_storage_clone; REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable); REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator); -- 2.40.0