helly Thu May 19 11:52:02 2005 EDT
Modified files:
/php-src/ext/spl spl_array.c
Log:
- 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
http://cvs.php.net/diff.php/php-src/ext/spl/spl_array.c?r1=1.66&r2=1.67&ty=u
Index: php-src/ext/spl/spl_array.c
diff -u php-src/ext/spl/spl_array.c:1.66 php-src/ext/spl/spl_array.c:1.67
--- php-src/ext/spl/spl_array.c:1.66 Mon Mar 21 15:07:31 2005
+++ php-src/ext/spl/spl_array.c Thu May 19 11:52:02 2005
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_array.c,v 1.66 2005/03/21 20:07:31 helly Exp $ */
+/* $Id: spl_array.c,v 1.67 2005/05/19 15:52:02 helly Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -48,8 +48,11 @@
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_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 @@
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 @@
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_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 @@
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 @@
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 @@
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 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 @@
} 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 @@
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 @@
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 @@
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 @@
} 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 @@
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 @@
} 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 @@
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_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_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 @@
{
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 @@
{
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 @@
{
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 @@
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_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 @@
/* }}} */
/* {{{ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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 @@
{
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 @@
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);
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php