summaryrefslogtreecommitdiff
path: root/ext/spl/spl_array.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/spl/spl_array.c')
-rwxr-xr-xext/spl/spl_array.c185
1 files changed, 70 insertions, 115 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index fb4d12a7de..14a6553258 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -63,7 +63,6 @@ typedef struct _spl_array_object {
zval *array;
zval *retval;
HashPosition pos;
- ulong pos_h;
int ar_flags;
int is_self;
zend_function *fptr_offset_get;
@@ -93,44 +92,24 @@ static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int
static void spl_array_rewind(spl_array_object *intern TSRMLS_DC);
-static void spl_array_update_pos(spl_array_object* intern) /* {{{ */
-{
- Bucket *pos = intern->pos;
- if (pos != NULL) {
- intern->pos_h = pos->h;
- }
-} /* }}} */
-
-static void spl_array_set_pos(spl_array_object* intern, HashPosition pos) /* {{{ */
-{
- intern->pos = pos;
- spl_array_update_pos(intern);
-} /* }}} */
-
-SPL_API int spl_hash_verify_pos_ex(spl_array_object * intern, HashTable * ht TSRMLS_DC) /* {{{ */
+SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
{
+ HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
Bucket *p;
/* IS_CONSISTENT(ht);*/
/* HASH_PROTECT_RECURSION(ht);*/
- p = ht->arBuckets[intern->pos_h & ht->nTableMask];
+ p = ht->pListHead;
while (p != NULL) {
if (p == intern->pos) {
return SUCCESS;
}
- p = p->pNext;
+ p = p->pListNext;
}
/* HASH_UNPROTECT_RECURSION(ht); */
spl_array_rewind(intern TSRMLS_CC);
return FAILURE;
-
-} /* }}} */
-
-SPL_API int spl_hash_verify_pos(spl_array_object * intern TSRMLS_DC) /* {{{ */
-{
- HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
- return spl_hash_verify_pos_ex(intern, ht TSRMLS_CC);
}
/* }}} */
@@ -302,7 +281,6 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
zval **retval;
long index;
- HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
/* We cannot get the pointer pointer so we don't allow it here for now
if (check_inherited && intern->fptr_offset_get) {
@@ -315,17 +293,9 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
switch(Z_TYPE_P(offset)) {
case IS_STRING:
- if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
- if (type == BP_VAR_W || type == BP_VAR_RW) {
- zval *value;
- ALLOC_INIT_ZVAL(value);
- zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
- zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval);
- return retval;
- } else {
- zend_error(E_NOTICE, "Undefined index: %s", Z_STRVAL_P(offset));
- return &EG(uninitialized_zval_ptr);
- }
+ if (zend_symtable_find(spl_array_get_hash_table(intern, 0 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);
} else {
return retval;
}
@@ -338,17 +308,9 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object,
} else {
index = Z_LVAL_P(offset);
}
- if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
- if (type == BP_VAR_W || type == BP_VAR_RW) {
- zval *value;
- ALLOC_INIT_ZVAL(value);
- zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), NULL);
- zend_hash_index_find(ht, index, (void **) &retval);
- return retval;
- } else {
- zend_error(E_NOTICE, "Undefined offset: %ld", Z_LVAL_P(offset));
- return &EG(uninitialized_zval_ptr);
- }
+ if (zend_hash_index_find(spl_array_get_hash_table(intern, 0 TSRMLS_CC), index, (void **) &retval) == FAILURE) {
+ zend_error(E_NOTICE, "Undefined offset: %ld", Z_LVAL_P(offset));
+ return &EG(uninitialized_zval_ptr);
} else {
return retval;
}
@@ -630,7 +592,7 @@ void spl_array_iterator_append(zval *object, zval *append_value TSRMLS_DC) /* {{
spl_array_write_dimension(object, NULL, append_value TSRMLS_CC);
if (!intern->pos) {
- spl_array_set_pos(intern, aht->pListTail);
+ intern->pos = aht->pListTail;
}
} /* }}} */
@@ -770,11 +732,12 @@ static void spl_array_unset_property(zval *object, zval *member TSRMLS_DC) /* {{
std_object_handlers.unset_property(object, member TSRMLS_CC);
} /* }}} */
-static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */
+static int spl_array_skip_protected(spl_array_object *intern TSRMLS_DC) /* {{{ */
{
char *string_key;
uint string_length;
ulong num_key;
+ HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
if (Z_TYPE_P(intern->array) == IS_OBJECT) {
do {
@@ -789,39 +752,27 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR
return FAILURE;
}
zend_hash_move_forward_ex(aht, &intern->pos);
- spl_array_update_pos(intern);
} while (1);
}
return FAILURE;
-} /* }}} */
+}
+/* }}} */
-static int spl_array_next_no_verify(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */
+static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */
{
- zend_hash_move_forward_ex(aht, &intern->pos);
- spl_array_update_pos(intern);
- if (Z_TYPE_P(intern->array) == IS_OBJECT) {
- return spl_array_skip_protected(intern, aht TSRMLS_CC);
- } else {
- return zend_hash_has_more_elements_ex(aht, &intern->pos);
- }
-} /* }}} */
+ HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
-static int spl_array_next_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */
-{
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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 {
+ zend_hash_move_forward_ex(aht, &intern->pos);
+ if (Z_TYPE_P(intern->array) == IS_OBJECT) {
+ return spl_array_skip_protected(intern TSRMLS_CC);
+ } else {
+ return zend_hash_has_more_elements_ex(aht, &intern->pos);
+ }
}
-
- return spl_array_next_no_verify(intern, aht TSRMLS_CC);
-} /* }}} */
-
-static int spl_array_next(spl_array_object *intern TSRMLS_DC) /* {{{ */
-{
- HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
-
- return spl_array_next_ex(intern, aht TSRMLS_CC);
-
} /* }}} */
/* define an overloaded iterator structure */
@@ -855,7 +806,7 @@ static int spl_array_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
return FAILURE;
}
- if (object->pos && (object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht 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 {
@@ -895,7 +846,7 @@ static int spl_array_it_get_current_key(zend_object_iterator *iter, char **str_k
return HASH_KEY_NON_EXISTANT;
}
- if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht 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;
}
@@ -920,24 +871,15 @@ static void spl_array_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {
return;
}
- if ((object->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(object, aht 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_no_verify(object, aht TSRMLS_CC);
+ spl_array_next(object TSRMLS_CC);
}
}
}
/* }}} */
-static void spl_array_rewind_ex(spl_array_object *intern, HashTable *aht TSRMLS_DC) /* {{{ */
-{
-
- zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
- spl_array_update_pos(intern);
- spl_array_skip_protected(intern, aht TSRMLS_CC);
-
-} /* }}} */
-
static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */
{
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
@@ -947,7 +889,8 @@ static void spl_array_rewind(spl_array_object *intern TSRMLS_DC) /* {{{ */
return;
}
- spl_array_rewind_ex(intern, aht TSRMLS_CC);
+ zend_hash_internal_pointer_reset_ex(aht, &intern->pos);
+ spl_array_skip_protected(intern TSRMLS_CC);
}
/* }}} */
@@ -1049,32 +992,34 @@ SPL_METHOD(Array, __construct)
spl_array_object *intern;
zval **array;
long ar_flags = 0;
- zend_class_entry *ce_get_iterator = spl_ce_Iterator;
- zend_error_handling error_handling;
+ char *class_name;
+ int class_name_len;
+ zend_class_entry ** pce_get_iterator;
if (ZEND_NUM_ARGS() == 0) {
return; /* nothing to do */
}
- zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, &error_handling TSRMLS_CC);
+ zend_replace_error_handling(EH_THROW, spl_ce_InvalidArgumentException, NULL TSRMLS_CC);
intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lC", &array, &ar_flags, &ce_get_iterator) == FAILURE) {
- zend_restore_error_handling(&error_handling TSRMLS_CC);
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ls", &array, &ar_flags, &class_name, &class_name_len) == FAILURE) {
return;
}
if (ZEND_NUM_ARGS() > 2) {
- intern->ce_get_iterator = ce_get_iterator;
+ if (zend_lookup_class(class_name, class_name_len, &pce_get_iterator TSRMLS_CC) == FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException, "A class that implements Iterator must be specified", 0 TSRMLS_CC);
+ return;
+ }
+ intern->ce_get_iterator = *pce_get_iterator;
}
ar_flags &= ~SPL_ARRAY_INT_MASK;
spl_array_set_array(object, intern, array, ar_flags, ZEND_NUM_ARGS() == 1 TSRMLS_CC);
- zend_restore_error_handling(&error_handling TSRMLS_CC);
-
}
/* }}} */
@@ -1084,13 +1029,19 @@ SPL_METHOD(Array, setIteratorClass)
{
zval *object = getThis();
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
- zend_class_entry * ce_get_iterator = spl_ce_Iterator;
+ char *class_name;
+ int class_name_len;
+ zend_class_entry ** pce_get_iterator;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "C", &ce_get_iterator) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
return;
}
- intern->ce_get_iterator = ce_get_iterator;
+ if (zend_lookup_class(class_name, class_name_len, &pce_get_iterator TSRMLS_CC) == FAILURE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException, "A class that implements Iterator must be specified", 0 TSRMLS_CC);
+ return;
+ }
+ intern->ce_get_iterator = *pce_get_iterator;
}
/* }}} */
@@ -1237,7 +1188,7 @@ int static spl_array_object_count_elements_helper(spl_array_object *intern, long
while(intern->pos && spl_array_next(intern TSRMLS_CC) == SUCCESS) {
(*count)++;
}
- spl_array_set_pos(intern, pos);
+ intern->pos = pos;
return SUCCESS;
} else {
*count = zend_hash_num_elements(aht);
@@ -1284,7 +1235,6 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
zval *tmp, *arg;
- zval *retval_ptr = NULL;
MAKE_STD_ZVAL(tmp);
Z_TYPE_P(tmp) = IS_ARRAY;
@@ -1292,20 +1242,15 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
if (use_arg) {
if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z", &arg) == FAILURE) {
- Z_TYPE_P(tmp) = IS_NULL;
- zval_ptr_dtor(&tmp);
zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
return;
}
- zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, return_value_ptr, 2, tmp, arg TSRMLS_CC);
} else {
- zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, return_value_ptr, 1, tmp, NULL TSRMLS_CC);
}
Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */
zval_ptr_dtor(&tmp);
- if (retval_ptr) {
- COPY_PZVAL_TO_ZVAL(*return_value, retval_ptr);
- }
} /* }}} */
#define SPL_ARRAY_METHOD(cname, fname, use_arg) \
@@ -1358,7 +1303,7 @@ SPL_METHOD(Array, current)
return;
}
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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;
}
@@ -1390,7 +1335,7 @@ void spl_array_iterator_key(zval *object, zval *return_value TSRMLS_DC) /* {{{ *
return;
}
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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;
}
@@ -1421,7 +1366,7 @@ SPL_METHOD(Array, next)
return;
}
- spl_array_next_ex(intern, aht TSRMLS_CC);
+ spl_array_next(intern TSRMLS_CC);
}
/* }}} */
@@ -1438,7 +1383,7 @@ SPL_METHOD(Array, valid)
return;
}
- if (intern->pos && (intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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 {
@@ -1460,7 +1405,7 @@ SPL_METHOD(Array, hasChildren)
RETURN_FALSE;
}
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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_FALSE;
}
@@ -1486,7 +1431,7 @@ SPL_METHOD(Array, getChildren)
return;
}
- if ((intern->ar_flags & SPL_ARRAY_IS_REF) && spl_hash_verify_pos_ex(intern, aht 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;
}
@@ -1644,7 +1589,7 @@ void spl_array_unserialize_helper(spl_array_object *intern, const unsigned char
++p;
if (*p!='m') {
- if (*p!='a' && *p!='O' && *p!='C') {
+ if (*p!='a') {
goto outexcept;
}
intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
@@ -1752,43 +1697,53 @@ int spl_array_unserialize(zval **object, zend_class_entry *ce, const unsigned ch
/* }}} */
/* {{{ arginfo and function tbale */
+static
ZEND_BEGIN_ARG_INFO(arginfo_array___construct, 0)
ZEND_ARG_INFO(0, array)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetGet, 0, 0, 1)
ZEND_ARG_INFO(0, index)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO_EX(arginfo_array_offsetSet, 0, 0, 2)
ZEND_ARG_INFO(0, index)
ZEND_ARG_INFO(0, newval)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO(arginfo_array_append, 0)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
+static
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_BEGIN_ARG_INFO(arginfo_array_setIteratorClass, 0)
ZEND_ARG_INFO(0, iteratorClass)
ZEND_END_ARG_INFO()
+static
ZEND_BEGIN_ARG_INFO(arginfo_array_uXsort, 0)
ZEND_ARG_INFO(0, cmp_function)
ZEND_END_ARG_INFO();
+static
ZEND_BEGIN_ARG_INFO(arginfo_array_unserialize, 0)
ZEND_ARG_INFO(0, serialized)
ZEND_END_ARG_INFO();