From e8cbf4c66355b20796733d94d004f4b83de10c60 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss Date: Sun, 6 Jul 2008 23:45:38 +0000 Subject: [PATCH] First part of count/handlers related fixes --- ext/spl/spl_array.c | 46 +++++++++++++++++++++++++------ ext/spl/spl_dllist.c | 24 ++++++++++++++-- ext/spl/spl_fixedarray.c | 23 +++++++++++++--- ext/spl/spl_heap.c | 29 +++++++++++++++---- ext/spl/tests/array_024.phpt | 17 ++++++++++++ ext/spl/tests/dllist_008.phpt | 21 ++++++++++++++ ext/spl/tests/fixedarray_018.phpt | 17 ++++++++++++ ext/spl/tests/heap_010.phpt | 21 ++++++++++++++ ext/spl/tests/sxe_004.phpt | 2 +- ext/spl/tests/sxe_005.phpt | 2 +- 10 files changed, 180 insertions(+), 22 deletions(-) create mode 100644 ext/spl/tests/array_024.phpt create mode 100644 ext/spl/tests/dllist_008.phpt create mode 100644 ext/spl/tests/fixedarray_018.phpt create mode 100644 ext/spl/tests/heap_010.phpt diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 950c21eef6..796ac5c4b9 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -66,10 +66,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; @@ -202,6 +203,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 */ @@ -1164,9 +1169,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; @@ -1193,14 +1197,36 @@ 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() U proto int ArrayIterator::count() U 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(getThis(), &count TSRMLS_CC); + spl_array_object_count_elements_helper(intern, &count TSRMLS_CC); RETURN_LONG(count); } /* }}} */ @@ -1220,9 +1246,11 @@ 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); + zval_ptr_dtor(return_value_ptr); + 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); + zval_ptr_dtor(return_value_ptr); + zend_call_method(NULL, NULL, NULL, fname, fname_len, return_value_ptr, 1, &tmp, NULL TSRMLS_CC); } } /* }}} */ diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 86d034f7b2..560f188372 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -92,6 +92,7 @@ struct _spl_dllist_object { 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; }; @@ -432,6 +433,10 @@ static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, 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; + } } return retval; @@ -467,8 +472,22 @@ static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC); - *count = spl_ptr_llist_count(intern->llist); + 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; + } + *count = spl_ptr_llist_count(intern->llist); return SUCCESS; } /* }}} */ @@ -655,12 +674,13 @@ SPL_METHOD(SplDoublyLinkedList, bottom) SPL_METHOD(SplDoublyLinkedList, count) { long count; + spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_parse_parameters_none() == FAILURE) { return; } - spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC); + count = spl_ptr_llist_count(intern->llist); RETURN_LONG(count); } /* }}} */ diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 8982dff791..3fa03d587e 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -61,6 +61,7 @@ typedef struct _spl_fixedarray_object { /* {{{ */ zend_function *fptr_it_current; zend_function *fptr_it_key; zend_function *fptr_it_valid; + zend_function *fptr_count; int current; zend_class_entry *ce_get_iterator; } spl_fixedarray_object; @@ -292,6 +293,10 @@ static zend_object_value spl_fixedarray_object_new_ex(zend_class_entry *class_ty if (intern->fptr_it_valid->common.scope == parent) { intern->fptr_it_valid = 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; + } } return retval; @@ -512,12 +517,23 @@ static int spl_fixedarray_object_count_elements(zval *object, long *count TSRMLS spl_fixedarray_object *intern; intern = (spl_fixedarray_object *)zend_object_store_get_object(object TSRMLS_CC); - if (intern->array) { + 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; + } + } else if (intern->array) { *count = intern->array->size; - } else { - *count = 0; + return SUCCESS; } + *count = 0; return SUCCESS; } /* }}} */ @@ -945,7 +961,6 @@ PHP_MINIT_FUNCTION(spl_fixedarray) memcpy(&spl_handler_SplFixedArray, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); spl_handler_SplFixedArray.clone_obj = spl_fixedarray_object_clone; - spl_handler_SplFixedArray.count_elements = spl_fixedarray_object_count_elements; spl_handler_SplFixedArray.read_dimension = spl_fixedarray_object_read_dimension; spl_handler_SplFixedArray.write_dimension = spl_fixedarray_object_write_dimension; spl_handler_SplFixedArray.unset_dimension = spl_fixedarray_object_unset_dimension; diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 0b84242147..f6cb6cab78 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -75,6 +75,7 @@ struct _spl_heap_object { int flags; zend_class_entry *ce_get_iterator; zend_function *fptr_cmp; + zend_function *fptr_count; }; /* define an overloaded iterator structure */ @@ -441,10 +442,13 @@ static zend_object_value spl_heap_object_new_ex(zend_class_entry *class_type, sp if (inherited) { zend_hash_find(&class_type->function_table, "compare", sizeof("compare"), (void **) &intern->fptr_cmp); - if (intern->fptr_cmp->common.scope == parent) { intern->fptr_cmp = 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; + } } return retval; @@ -480,6 +484,21 @@ static int spl_heap_object_count_elements(zval *object, long *count TSRMLS_DC) / { spl_heap_object *intern = (spl_heap_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; + } + *count = spl_ptr_heap_count(intern->heap); return SUCCESS; @@ -545,12 +564,13 @@ static HashTable* spl_pqueue_object_get_debug_info(zval *obj, int *is_temp TSRML SPL_METHOD(SplHeap, count) { long count; + spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } - spl_heap_object_count_elements(getThis(), &count TSRMLS_CC); + count = spl_ptr_heap_count(intern->heap); RETURN_LONG(count); } /* }}} */ @@ -559,14 +579,13 @@ SPL_METHOD(SplHeap, count) Return true if the heap is empty. */ SPL_METHOD(SplHeap, isEmpty) { - long count; + spl_heap_object *intern = (spl_heap_object*)zend_object_store_get_object(getThis() TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { return; } - spl_heap_object_count_elements(getThis(), &count TSRMLS_CC); - RETURN_BOOL(count==0); + RETURN_BOOL(spl_ptr_heap_count(intern->heap)==0); } /* }}} */ diff --git a/ext/spl/tests/array_024.phpt b/ext/spl/tests/array_024.phpt new file mode 100644 index 0000000000..0c073bfe78 --- /dev/null +++ b/ext/spl/tests/array_024.phpt @@ -0,0 +1,17 @@ +--TEST-- +SPL: ArrayObject with overriden count() +--FILE-- + +--EXPECT-- +int(2) +int(-2) diff --git a/ext/spl/tests/dllist_008.phpt b/ext/spl/tests/dllist_008.phpt new file mode 100644 index 0000000000..ab37d83afa --- /dev/null +++ b/ext/spl/tests/dllist_008.phpt @@ -0,0 +1,21 @@ +--TEST-- +SPL: SplDoublyLinkedList with overriden count() +--FILE-- + +--EXPECT-- +int(2) +int(-2) diff --git a/ext/spl/tests/fixedarray_018.phpt b/ext/spl/tests/fixedarray_018.phpt new file mode 100644 index 0000000000..4965bb5279 --- /dev/null +++ b/ext/spl/tests/fixedarray_018.phpt @@ -0,0 +1,17 @@ +--TEST-- +SPL: SplFixedArray with overriden count() +--FILE-- + +--EXPECT-- +int(2) +int(-2) diff --git a/ext/spl/tests/heap_010.phpt b/ext/spl/tests/heap_010.phpt new file mode 100644 index 0000000000..8c7d8d5c96 --- /dev/null +++ b/ext/spl/tests/heap_010.phpt @@ -0,0 +1,21 @@ +--TEST-- +SPL: SplHeap with overriden count() +--FILE-- +insert(1); +$obj->insert(2); +var_dump(count($obj)); +class SplMaxHeap2 extends SplMaxHeap{ + public function count() { + return -parent::count(); + } +} +$obj = new SplMaxHeap2(); +$obj->insert(1); +$obj->insert(2); +var_dump(count($obj)); +?> +--EXPECT-- +int(2) +int(-2) diff --git a/ext/spl/tests/sxe_004.phpt b/ext/spl/tests/sxe_004.phpt index 6c44133584..30d4b10a78 100755 --- a/ext/spl/tests/sxe_004.phpt +++ b/ext/spl/tests/sxe_004.phpt @@ -1,5 +1,5 @@ --TEST-- -SPL: SimpleXMLIterator and getChildren() +SPL: SimpleXMLIterator and overridden iterator methods() --SKIPIF--