mirror of
https://github.com/php/php-src.git
synced 2026-04-26 17:38:14 +02:00
- Add ability to reference the object itself
- Add ability to exchange the refrenced object - Add ArrayObject::getFlags/setFlags and 2nd param to __construct to control operation modes
This commit is contained in:
+250
-66
@@ -48,8 +48,11 @@ SPL_METHOD(Array, offsetSet);
|
||||
SPL_METHOD(Array, offsetUnset);
|
||||
SPL_METHOD(Array, append);
|
||||
SPL_METHOD(Array, getArrayCopy);
|
||||
SPL_METHOD(Array, exchangeArray);
|
||||
SPL_METHOD(Array, seek);
|
||||
SPL_METHOD(Array, count);
|
||||
SPL_METHOD(Array, getFlags);
|
||||
SPL_METHOD(Array, setFlags);
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
|
||||
@@ -77,6 +80,16 @@ ZEND_BEGIN_ARG_INFO(arginfo_array_seek, 0)
|
||||
ZEND_ARG_INFO(0, position)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_exchangeArray, 0)
|
||||
ZEND_ARG_INFO(0, array)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_array_setFlags, 0)
|
||||
ZEND_ARG_INFO(0, flags)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry spl_funcs_ArrayObject[] = {
|
||||
SPL_ME(Array, __construct, arginfo_array___construct, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, offsetExists, arginfo_array_offsetGet, ZEND_ACC_PUBLIC)
|
||||
@@ -86,8 +99,11 @@ static zend_function_entry spl_funcs_ArrayObject[] = {
|
||||
SPL_ME(Array, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayObject specific */
|
||||
SPL_ME(Array, getIterator, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, exchangeArray, arginfo_array_exchangeArray, ZEND_ACC_PUBLIC)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -100,6 +116,8 @@ static zend_function_entry spl_funcs_ArrayIterator[] = {
|
||||
SPL_ME(Array, append, arginfo_array_append, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getArrayCopy, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, count, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, getFlags, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, setFlags, arginfo_array_setFlags, ZEND_ACC_PUBLIC)
|
||||
/* ArrayIterator specific */
|
||||
SPL_ME(Array, rewind, NULL, ZEND_ACC_PUBLIC)
|
||||
SPL_ME(Array, current, NULL, ZEND_ACC_PUBLIC)
|
||||
@@ -123,20 +141,36 @@ PHPAPI zend_class_entry *spl_ce_ArrayIterator;
|
||||
|
||||
PHPAPI zend_class_entry *spl_ce_Countable;
|
||||
|
||||
#define SPL_ARRAY_STD_PROP_LIST 0x00000001
|
||||
#define SPL_ARRAY_ARRAY_AS_PROPS 0x00000002
|
||||
#define SPL_ARRAY_IS_REF 0x01000000
|
||||
#define SPL_ARRAY_IS_SELF 0x02000000
|
||||
#define SPL_ARRAY_INT_MASK 0xFF000000
|
||||
#define SPL_ARRAY_CLONE_MASK 0x03000003
|
||||
|
||||
typedef struct _spl_array_object {
|
||||
zend_object std;
|
||||
zval *array;
|
||||
HashPosition pos;
|
||||
int is_ref;
|
||||
int ar_flags;
|
||||
int is_self;
|
||||
zend_function * fptr_offset_get;
|
||||
zend_function * fptr_offset_set;
|
||||
zend_function * fptr_offset_has;
|
||||
zend_function * fptr_offset_del;
|
||||
} spl_array_object;
|
||||
|
||||
static inline HashTable *spl_array_get_hash_table(spl_array_object* intern TSRMLS_DC) {
|
||||
if ((intern->ar_flags & (SPL_ARRAY_STD_PROP_LIST|SPL_ARRAY_IS_SELF)) != 0) {
|
||||
return intern->std.properties;
|
||||
} else {
|
||||
return HASH_OF(intern->array);
|
||||
}
|
||||
}
|
||||
|
||||
SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
HashTable *ht = HASH_OF(intern->array);
|
||||
HashTable *ht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
Bucket *p;
|
||||
|
||||
/* IS_CONSISTENT(ht);*/
|
||||
@@ -150,7 +184,7 @@ SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
|
||||
p = p->pListNext;
|
||||
}
|
||||
/* HASH_UNPROTECT_RECURSION(ht); */
|
||||
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
|
||||
zend_hash_internal_pointer_reset_ex(spl_array_get_hash_table(intern TSRMLS_CC), &intern->pos);
|
||||
return FAILURE;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -187,16 +221,17 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
|
||||
zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
||||
|
||||
intern->ar_flags = 0;
|
||||
if (orig) {
|
||||
intern->array = orig->array;
|
||||
ZVAL_ADDREF(intern->array);
|
||||
intern->is_ref = 1;
|
||||
intern->ar_flags &= ~ SPL_ARRAY_CLONE_MASK;
|
||||
intern->ar_flags |= (orig->ar_flags & SPL_ARRAY_CLONE_MASK) | SPL_ARRAY_IS_REF;
|
||||
} else {
|
||||
MAKE_STD_ZVAL(intern->array);
|
||||
array_init(intern->array);
|
||||
intern->is_ref = 0;
|
||||
intern->ar_flags &= ~SPL_ARRAY_IS_REF;
|
||||
}
|
||||
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
|
||||
|
||||
retval.handle = zend_objects_store_put(intern, NULL, (zend_objects_free_object_storage_t) spl_array_object_free_storage, NULL TSRMLS_CC);
|
||||
while (parent) {
|
||||
@@ -231,6 +266,7 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
|
||||
intern->fptr_offset_del = NULL;
|
||||
}
|
||||
}
|
||||
zend_hash_internal_pointer_reset_ex(spl_array_get_hash_table(intern TSRMLS_CC), &intern->pos);
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
@@ -262,23 +298,24 @@ static zend_object_value spl_array_object_clone(zval *zobject TSRMLS_DC)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
|
||||
static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
zval **retval, *rv;
|
||||
zval **retval;
|
||||
long index;
|
||||
|
||||
/* We cannot get the pointer pointer so we don't allow it here for now
|
||||
if (check_inherited && intern->fptr_offset_get) {
|
||||
return zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset);
|
||||
}
|
||||
return zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", NULL, offset);
|
||||
}*/
|
||||
|
||||
switch(Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (zend_symtable_find(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
|
||||
if (zend_symtable_find(spl_array_get_hash_table(intern TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
|
||||
zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(offset));
|
||||
return EG(uninitialized_zval_ptr);
|
||||
return &EG(uninitialized_zval_ptr);
|
||||
} else {
|
||||
return *retval;
|
||||
return retval;
|
||||
}
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
@@ -289,19 +326,31 @@ static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_find(HASH_OF(intern->array), index, (void **) &retval) == FAILURE) {
|
||||
if (zend_hash_index_find(spl_array_get_hash_table(intern TSRMLS_CC), index, (void **) &retval) == FAILURE) {
|
||||
zend_error(E_NOTICE, "Undefined offset: %ld", Z_LVAL_P(offset));
|
||||
return EG(uninitialized_zval_ptr);
|
||||
return &EG(uninitialized_zval_ptr);
|
||||
} else {
|
||||
return *retval;
|
||||
return retval;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
return EG(uninitialized_zval_ptr);
|
||||
return &EG(uninitialized_zval_ptr);
|
||||
}
|
||||
} /* }}} */
|
||||
|
||||
static zval *spl_array_read_dimension_ex(int check_inherited, zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
if (check_inherited) {
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
if (intern->fptr_offset_get) {
|
||||
zval *rv;
|
||||
return zend_call_method_with_1_params(&object, Z_OBJCE_P(object), &intern->fptr_offset_get, "offsetGet", &rv, offset);
|
||||
}
|
||||
}
|
||||
return *spl_array_get_dimension_ptr_ptr(check_inherited, object, offset, type TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static zval *spl_array_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
return spl_array_read_dimension_ex(1, object, offset, type TSRMLS_CC);
|
||||
@@ -320,13 +369,13 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
|
||||
|
||||
if (!offset) {
|
||||
value->refcount++;
|
||||
zend_hash_next_index_insert(HASH_OF(intern->array), (void**)&value, sizeof(void*), NULL);
|
||||
zend_hash_next_index_insert(spl_array_get_hash_table(intern TSRMLS_CC), (void**)&value, sizeof(void*), NULL);
|
||||
return;
|
||||
}
|
||||
switch(Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
value->refcount++;
|
||||
zend_symtable_update(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
|
||||
zend_symtable_update(spl_array_get_hash_table(intern TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
|
||||
return;
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
@@ -338,7 +387,7 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
value->refcount++;
|
||||
zend_hash_index_update(HASH_OF(intern->array), index, (void**)&value, sizeof(void*), NULL);
|
||||
zend_hash_index_update(spl_array_get_hash_table(intern TSRMLS_CC), index, (void**)&value, sizeof(void*), NULL);
|
||||
return;
|
||||
default:
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
@@ -364,12 +413,12 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
|
||||
|
||||
switch(Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
if (HASH_OF(intern->array) == &EG(symbol_table)) {
|
||||
if (spl_array_get_hash_table(intern TSRMLS_CC) == &EG(symbol_table)) {
|
||||
if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) {
|
||||
zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
|
||||
}
|
||||
} else {
|
||||
if (zend_symtable_del(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
|
||||
if (zend_symtable_del(spl_array_get_hash_table(intern TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
|
||||
zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
|
||||
}
|
||||
}
|
||||
@@ -383,7 +432,7 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
if (zend_hash_index_del(HASH_OF(intern->array), index) == FAILURE) {
|
||||
if (zend_hash_index_del(spl_array_get_hash_table(intern TSRMLS_CC), index) == FAILURE) {
|
||||
zend_error(E_NOTICE,"Undefined offset: %ld", Z_LVAL_P(offset));
|
||||
}
|
||||
break;
|
||||
@@ -417,7 +466,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
|
||||
|
||||
switch(Z_TYPE_P(offset)) {
|
||||
case IS_STRING:
|
||||
return zend_symtable_exists(HASH_OF(intern->array), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
return zend_symtable_exists(spl_array_get_hash_table(intern TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1);
|
||||
case IS_DOUBLE:
|
||||
case IS_RESOURCE:
|
||||
case IS_BOOL:
|
||||
@@ -427,7 +476,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
|
||||
} else {
|
||||
index = Z_LVAL_P(offset);
|
||||
}
|
||||
return zend_hash_index_exists(HASH_OF(intern->array), index);
|
||||
return zend_hash_index_exists(spl_array_get_hash_table(intern TSRMLS_CC), index);
|
||||
default:
|
||||
zend_error(E_WARNING, "Illegal offset type");
|
||||
}
|
||||
@@ -480,7 +529,7 @@ SPL_METHOD(Array, offsetSet)
|
||||
void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
@@ -531,24 +580,83 @@ SPL_METHOD(Array, getArrayCopy)
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
array_init(return_value);
|
||||
zend_hash_copy(HASH_OF(return_value), HASH_OF(intern->array), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
|
||||
zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
|
||||
} /* }}} */
|
||||
|
||||
/* {{{ spl_array_get_properties */
|
||||
static HashTable *spl_array_get_properties(zval *object TSRMLS_DC)
|
||||
static HashTable *spl_array_get_properties(zval *object TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
return HASH_OF(intern->array);
|
||||
}
|
||||
/* }}} */
|
||||
return spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static zval *spl_array_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
|
||||
&& !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
|
||||
return spl_array_read_dimension(object, member, type TSRMLS_CC);
|
||||
}
|
||||
return std_object_handlers.read_property(object, member, type TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static void spl_array_write_property(zval *object, zval *member, zval *value TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
|
||||
&& !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
|
||||
return spl_array_write_dimension(object, member, value TSRMLS_CC);
|
||||
}
|
||||
std_object_handlers.write_property(object, member, value TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static zval **spl_array_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
|
||||
&& !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
|
||||
return spl_array_get_dimension_ptr_ptr(1, object, member, 0 TSRMLS_CC);
|
||||
}
|
||||
return std_object_handlers.get_property_ptr_ptr(object, member TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static int spl_array_has_property(zval *object, zval *member, int has_set_exists TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0) {
|
||||
if (!std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
|
||||
return spl_array_has_dimension(object, member, has_set_exists TSRMLS_CC);
|
||||
}
|
||||
return 0; /* if prop doesn't exist at all mode 0/1 cannot return 1 */
|
||||
}
|
||||
return std_object_handlers.has_property(object, member, has_set_exists TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static void spl_array_rewind(spl_array_object *intern TSRMLS_DC);
|
||||
|
||||
static void spl_array_unset_property(zval *object, zval *member TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
|
||||
&& !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
|
||||
spl_array_unset_dimension(object, member TSRMLS_CC);
|
||||
spl_array_rewind(intern TSRMLS_CC); /* because deletion might invalidate position */
|
||||
return;
|
||||
}
|
||||
std_object_handlers.unset_property(object, member TSRMLS_CC);
|
||||
} /* }}} */
|
||||
|
||||
static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
char *string_key;
|
||||
uint string_length;
|
||||
ulong num_key;
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (Z_TYPE_P(intern->array) == IS_OBJECT) {
|
||||
do {
|
||||
@@ -571,9 +679,9 @@ static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ *
|
||||
|
||||
static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
|
||||
return FAILURE;
|
||||
} else {
|
||||
@@ -606,14 +714,14 @@ static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_it *iterator = (spl_array_it *)iter;
|
||||
spl_array_object *object = iterator->object;
|
||||
HashTable *aht = HASH_OF(object->array);
|
||||
HashTable *aht = spl_array_get_hash_table(object TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and is no longer an array");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (object->pos && object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::valid(): Array was modified outside object and internal position is no longer valid");
|
||||
return FAILURE;
|
||||
} else {
|
||||
@@ -626,7 +734,7 @@ static void spl_array_it_get_current_data(zend_object_iterator *iter, zval ***da
|
||||
{
|
||||
spl_array_it *iterator = (spl_array_it *)iter;
|
||||
spl_array_object *object = iterator->object;
|
||||
HashTable *aht = HASH_OF(object->array);
|
||||
HashTable *aht = spl_array_get_hash_table(object TSRMLS_CC);
|
||||
|
||||
if (zend_hash_get_current_data_ex(aht, (void**)data, &object->pos) == FAILURE) {
|
||||
*data = NULL;
|
||||
@@ -638,14 +746,14 @@ static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_k
|
||||
{
|
||||
spl_array_it *iterator = (spl_array_it *)iter;
|
||||
spl_array_object *object = iterator->object;
|
||||
HashTable *aht = HASH_OF(object->array);
|
||||
HashTable *aht = spl_array_get_hash_table(object TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array");
|
||||
return HASH_KEY_NON_EXISTANT;
|
||||
}
|
||||
|
||||
if (object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and internal position is no longer valid");
|
||||
return HASH_KEY_NON_EXISTANT;
|
||||
}
|
||||
@@ -659,14 +767,14 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
|
||||
spl_array_it *iterator = (spl_array_it *)iter;
|
||||
spl_array_object *object = iterator->object;
|
||||
|
||||
HashTable *aht = HASH_OF(object->array);
|
||||
HashTable *aht = spl_array_get_hash_table(object TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::current(): Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (object->is_ref && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(object TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::next(): Array was modified outside object and internal position is no longer valid");
|
||||
} else {
|
||||
spl_array_next(object TSRMLS_CC);
|
||||
@@ -676,7 +784,7 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
|
||||
|
||||
static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array");
|
||||
@@ -722,13 +830,14 @@ zend_object_iterator *spl_array_get_iterator(zend_class_entry *ce, zval *object
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void ArrayObject::__construct(array|object ar = array())
|
||||
proto void ArrayIterator::__construct(array|object ar = array())
|
||||
proto void ArrayIterator::__construct(array|object ar = array() [, int flags = 0])
|
||||
Cronstructs a new array iterator from a path. */
|
||||
SPL_METHOD(Array, __construct)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern;
|
||||
zval **array;
|
||||
zval *array;
|
||||
long ar_flags = 0;
|
||||
|
||||
if (ZEND_NUM_ARGS() == 0) {
|
||||
return; /* nothing to do */
|
||||
@@ -737,29 +846,98 @@ SPL_METHOD(Array, __construct)
|
||||
|
||||
intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &array, &ar_flags) == FAILURE) {
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Z_TYPE_P(array) == IS_OBJECT && (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator)) {
|
||||
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(array TSRMLS_CC);
|
||||
zval_ptr_dtor(&intern->array);
|
||||
intern->array = other->array;
|
||||
} else {
|
||||
if (Z_TYPE_P(array) != IS_OBJECT && Z_TYPE_P(array) != IS_ARRAY) {
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
zval_ptr_dtor(&intern->array);
|
||||
intern->array = array;
|
||||
}
|
||||
if (object == array) {
|
||||
intern->ar_flags |= SPL_ARRAY_IS_SELF;
|
||||
} else {
|
||||
intern->ar_flags &= ~SPL_ARRAY_IS_SELF;
|
||||
}
|
||||
intern->ar_flags |= ar_flags & ~SPL_ARRAY_INT_MASK;
|
||||
ZVAL_ADDREF(intern->array);
|
||||
|
||||
spl_array_rewind(intern TSRMLS_CC);
|
||||
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto int ArrayObject::getFlags()
|
||||
Get flags */
|
||||
SPL_METHOD(Array, getFlags)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
RETURN_LONG(intern->ar_flags & ~SPL_ARRAY_INT_MASK);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto void ArrayObject::setFlags(int flags)
|
||||
Set flags */
|
||||
SPL_METHOD(Array, setFlags)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
long ar_flags = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ar_flags) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
intern->ar_flags = (intern->ar_flags & SPL_ARRAY_INT_MASK) | (ar_flags & ~SPL_ARRAY_INT_MASK);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto Array|Object ArrayObject::exchangeArray(Array|Object ar = array())
|
||||
Replace the referenced array or object with a new one and return the old one (right now copy - to be changed) */
|
||||
SPL_METHOD(Array, exchangeArray)
|
||||
{
|
||||
zval *object = getThis(), *tmp, **array;
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
array_init(return_value);
|
||||
zend_hash_copy(HASH_OF(return_value), spl_array_get_hash_table(intern TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, &tmp, sizeof(zval*));
|
||||
|
||||
if (ZEND_NUM_ARGS() > 1 || zend_get_parameters_ex(1, &array) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
if (Z_TYPE_PP(array) == IS_OBJECT && (Z_OBJ_HT_PP(array) == &spl_handler_ArrayObject || Z_OBJ_HT_PP(array) == &spl_handler_ArrayIterator)) {
|
||||
spl_array_object *other = (spl_array_object*)zend_object_store_get_object(*array TSRMLS_CC);
|
||||
zval_dtor(intern->array);
|
||||
FREE_ZVAL(intern->array);
|
||||
zval_ptr_dtor(&intern->array);
|
||||
intern->array = other->array;
|
||||
} else {
|
||||
if (!HASH_OF(*array)) {
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
if (Z_TYPE_PP(array) != IS_OBJECT && !HASH_OF(*array)) {
|
||||
zend_throw_exception(spl_ce_InvalidArgumentException, "Passed variable is not an array or object, using empty array instead", 0 TSRMLS_CC);
|
||||
return;
|
||||
}
|
||||
zval_dtor(intern->array);
|
||||
FREE_ZVAL(intern->array);
|
||||
zval_ptr_dtor(&intern->array);
|
||||
intern->array = *array;
|
||||
}
|
||||
if (object == *array) {
|
||||
intern->ar_flags |= SPL_ARRAY_IS_SELF;
|
||||
} else {
|
||||
intern->ar_flags &= ~SPL_ARRAY_IS_SELF;
|
||||
}
|
||||
ZVAL_ADDREF(intern->array);
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(HASH_OF(intern->array), &intern->pos);
|
||||
|
||||
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
||||
spl_array_rewind(intern TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -770,7 +948,7 @@ SPL_METHOD(Array, getIterator)
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
spl_array_object *iterator;
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
@@ -802,7 +980,7 @@ SPL_METHOD(Array, seek)
|
||||
long opos, position;
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
int result;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &position) == FAILURE) {
|
||||
@@ -821,7 +999,7 @@ SPL_METHOD(Array, seek)
|
||||
|
||||
while (position-- > 0 && (result = spl_array_next(intern TSRMLS_CC)) == SUCCESS);
|
||||
|
||||
if (intern->pos && intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
/* fail */
|
||||
} else {
|
||||
if (zend_hash_has_more_elements_ex(aht, &intern->pos) == SUCCESS) {
|
||||
@@ -835,7 +1013,7 @@ SPL_METHOD(Array, seek)
|
||||
int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
HashPosition pos;
|
||||
|
||||
if (!aht) {
|
||||
@@ -879,14 +1057,14 @@ SPL_METHOD(Array, current)
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
zval **entry;
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
|
||||
return;
|
||||
}
|
||||
@@ -907,14 +1085,14 @@ SPL_METHOD(Array, key)
|
||||
char *string_key;
|
||||
uint string_length;
|
||||
ulong num_key;
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
|
||||
return;
|
||||
}
|
||||
@@ -938,7 +1116,7 @@ SPL_METHOD(Array, next)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
@@ -955,14 +1133,14 @@ SPL_METHOD(Array, valid)
|
||||
{
|
||||
zval *object = getThis();
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
HashTable *aht = HASH_OF(intern->array);
|
||||
HashTable *aht = spl_array_get_hash_table(intern TSRMLS_CC);
|
||||
|
||||
if (!aht) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and is no longer an array");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intern->pos && intern->is_ref && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos(intern TSRMLS_CC) == FAILURE) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Array was modified outside object and internal position is no longer valid");
|
||||
RETURN_FALSE;
|
||||
} else {
|
||||
@@ -983,9 +1161,15 @@ PHP_MINIT_FUNCTION(spl_array)
|
||||
spl_handler_ArrayObject.write_dimension = spl_array_write_dimension;
|
||||
spl_handler_ArrayObject.unset_dimension = spl_array_unset_dimension;
|
||||
spl_handler_ArrayObject.has_dimension = spl_array_has_dimension;
|
||||
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
|
||||
spl_handler_ArrayObject.count_elements = spl_array_object_count_elements;
|
||||
|
||||
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
|
||||
spl_handler_ArrayObject.read_property = spl_array_read_property;
|
||||
spl_handler_ArrayObject.write_property = spl_array_write_property;
|
||||
spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr;
|
||||
spl_handler_ArrayObject.has_property = spl_array_has_property;
|
||||
spl_handler_ArrayObject.unset_property = spl_array_unset_property;
|
||||
|
||||
REGISTER_SPL_STD_CLASS_EX(ArrayIterator, spl_array_object_new, spl_funcs_ArrayIterator);
|
||||
REGISTER_SPL_IMPLEMENTS(ArrayIterator, Iterator);
|
||||
REGISTER_SPL_IMPLEMENTS(ArrayIterator, ArrayAccess);
|
||||
|
||||
Reference in New Issue
Block a user