Skip to content

Commit

Permalink
MFH: Fix #47671 (cloning SplObjectStorage instances)
Browse files Browse the repository at this point in the history
  • Loading branch information
colder committed Mar 19, 2009
1 parent 61bdfaa commit 225d86d
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 75 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
181 changes: 106 additions & 75 deletions ext/spl/spl_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -339,23 +378,14 @@ 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;
}

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));
} /* }}} */
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 225d86d

Please sign in to comment.