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.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 523729e70c..873209dd0f 100755
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -65,10 +65,11 @@ typedef struct _spl_array_object {
HashPosition pos;
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;
+ zend_function *fptr_offset_get;
+ zend_function *fptr_offset_set;
+ zend_function *fptr_offset_has;
+ zend_function *fptr_offset_del;
+ zend_function *fptr_count;
zend_class_entry* ce_get_iterator;
} spl_array_object;
@@ -201,6 +202,10 @@ static zend_object_value spl_array_object_new_ex(zend_class_entry *class_type, s
if (intern->fptr_offset_del->common.scope == parent) {
intern->fptr_offset_del = NULL;
}
+ zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count);
+ if (intern->fptr_count->common.scope == parent) {
+ intern->fptr_count = NULL;
+ }
}
/* Cache iterator functions if ArrayIterator or derived. Check current's */
/* cache since only current is always required */
@@ -1171,9 +1176,8 @@ SPL_METHOD(Array, seek)
zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Seek position %ld is out of range", opos);
} /* }}} */
-int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
+int inline spl_array_object_count_elements_helper(spl_array_object *intern, long *count TSRMLS_DC) /* {{{ */
{
- spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
HashTable *aht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
HashPosition pos;
@@ -1200,14 +1204,37 @@ int spl_array_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{
}
} /* }}} */
+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);
+
+ if (intern->fptr_count) {
+ zval *rv;
+ zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
+ if (rv) {
+ zval_ptr_dtor(&intern->retval);
+ MAKE_STD_ZVAL(intern->retval);
+ ZVAL_ZVAL(intern->retval, rv, 1, 1);
+ convert_to_long(intern->retval);
+ *count = (long) Z_LVAL_P(intern->retval);
+ return SUCCESS;
+ }
+ *count = 0;
+ return FAILURE;
+ }
+ return spl_array_object_count_elements_helper(intern, count TSRMLS_CC);
+} /* }}} */
+
/* {{{ proto int ArrayObject::count()
proto int ArrayIterator::count()
Return the number of elements in the Iterator. */
SPL_METHOD(Array, count)
{
long count;
+ spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+
+ spl_array_object_count_elements_helper(intern, &count TSRMLS_CC);
- spl_array_object_count_elements(getThis(), &count TSRMLS_CC);
RETURN_LONG(count);
} /* }}} */
@@ -1226,9 +1253,9 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
return;
}
- zend_call_method(NULL, NULL, NULL, fname, fname_len, &return_value, 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, &return_value, 1, &tmp, NULL TSRMLS_CC);
+ zend_call_method(NULL, NULL, NULL, fname, fname_len, return_value_ptr, 1, &tmp, NULL TSRMLS_CC);
}
} /* }}} */