helly Tue Jul 22 22:54:15 2008 UTC
Added files:
/php-src/ext/spl/internal multipleiterator.inc
/php-src/ext/spl/tests multiple_iterator_001.phpt
Removed files:
/php-src/ext/spl/examples multipleiterator.inc
Modified files:
/php-src/ext/spl php_spl.c spl_iterators.c spl_iterators.h
spl_observer.c spl_observer.h
/php-src/ext/spl/internal recursivetreeiterator.inc
Log:
- Add MultipleIterator (Arnaud, Marcus)
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.136&r2=1.137&diff_format=u
Index: php-src/ext/spl/php_spl.c
diff -u php-src/ext/spl/php_spl.c:1.136 php-src/ext/spl/php_spl.c:1.137
--- php-src/ext/spl/php_spl.c:1.136 Sun Jul 13 21:38:58 2008
+++ php-src/ext/spl/php_spl.c Tue Jul 22 22:54:14 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_spl.c,v 1.136 2008/07/13 21:38:58 helly Exp $ */
+/* $Id: php_spl.c,v 1.137 2008/07/22 22:54:14 helly Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -150,14 +150,6 @@
SPL_ADD_CLASS(AppendIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(ArrayIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(ArrayObject, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplDoublyLinkedList, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplQueue, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplStack, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplHeap, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \
- SPL_ADD_CLASS(SplFixedArray, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(BadFunctionCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(BadMethodCallException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(CachingIterator, z_list, sub, allow, ce_flags); \
@@ -174,6 +166,7 @@
SPL_ADD_CLASS(LengthException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LimitIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(LogicException, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(MultipleIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(NoRewindIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OuterIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(OutOfBoundsException, z_list, sub, allow, ce_flags); \
@@ -188,14 +181,23 @@
SPL_ADD_CLASS(RecursiveIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RecursiveIteratorIterator, z_list, sub, allow, ce_flags);
\
SPL_ADD_CLASS(RecursiveRegexIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(RecursiveTreeIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RegexIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(RuntimeException, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SeekableIterator, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SimpleXMLIterator, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplDoublyLinkedList, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFileInfo, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplFileObject, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplFixedArray, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplHeap, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplMinHeap, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplMaxHeap, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplObjectStorage, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplObserver, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplPriorityQueue, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplQueue, z_list, sub, allow, ce_flags); \
+ SPL_ADD_CLASS(SplStack, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplSubject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(SplTempFileObject, z_list, sub, allow, ce_flags); \
SPL_ADD_CLASS(UnderflowException, z_list, sub, allow, ce_flags); \
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_iterators.c?r1=1.173&r2=1.174&diff_format=u
Index: php-src/ext/spl/spl_iterators.c
diff -u php-src/ext/spl/spl_iterators.c:1.173
php-src/ext/spl/spl_iterators.c:1.174
--- php-src/ext/spl/spl_iterators.c:1.173 Sat Jul 19 19:45:25 2008
+++ php-src/ext/spl/spl_iterators.c Tue Jul 22 22:54:14 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_iterators.c,v 1.173 2008/07/19 19:45:25 colder Exp $ */
+/* $Id: spl_iterators.c,v 1.174 2008/07/22 22:54:14 helly Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -35,6 +35,7 @@
#include "spl_directory.h"
#include "spl_array.h"
#include "spl_exceptions.h"
+#include "spl_observer.h"
#include "ext/standard/php_smart_str.h"
#ifdef accept
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_iterators.h?r1=1.45&r2=1.46&diff_format=u
Index: php-src/ext/spl/spl_iterators.h
diff -u php-src/ext/spl/spl_iterators.h:1.45
php-src/ext/spl/spl_iterators.h:1.46
--- php-src/ext/spl/spl_iterators.h:1.45 Sat Jul 19 15:43:35 2008
+++ php-src/ext/spl/spl_iterators.h Tue Jul 22 22:54:14 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_iterators.h,v 1.45 2008/07/19 15:43:35 helly Exp $ */
+/* $Id: spl_iterators.h,v 1.46 2008/07/22 22:54:14 helly Exp $ */
#ifndef SPL_ITERATORS_H
#define SPL_ITERATORS_H
@@ -35,6 +35,7 @@
extern PHPAPI zend_class_entry *spl_ce_RecursiveIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveIteratorIterator;
+extern PHPAPI zend_class_entry *spl_ce_RecursiveTreeIterator;
extern PHPAPI zend_class_entry *spl_ce_FilterIterator;
extern PHPAPI zend_class_entry *spl_ce_RecursiveFilterIterator;
extern PHPAPI zend_class_entry *spl_ce_ParentIterator;
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_observer.c?r1=1.23&r2=1.24&diff_format=u
Index: php-src/ext/spl/spl_observer.c
diff -u php-src/ext/spl/spl_observer.c:1.23 php-src/ext/spl/spl_observer.c:1.24
--- php-src/ext/spl/spl_observer.c:1.23 Mon Jan 28 22:43:21 2008
+++ php-src/ext/spl/spl_observer.c Tue Jul 22 22:54:14 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_observer.c,v 1.23 2008/01/28 22:43:21 helly Exp $ */
+/* $Id: spl_observer.c,v 1.24 2008/07/22 22:54:14 helly Exp $ */
#ifdef HAVE_CONFIG_H
# include "config.h"
@@ -73,6 +73,8 @@
PHPAPI zend_class_entry *spl_ce_SplObserver;
PHPAPI zend_class_entry *spl_ce_SplSubject;
PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
+PHPAPI zend_class_entry *spl_ce_MultipleIterator;
+
PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
typedef struct _spl_SplObjectStorage { /* {{{ */
@@ -80,6 +82,7 @@
HashTable storage;
long index;
HashPosition pos;
+ long flags;
} spl_SplObjectStorage; /* }}} */
/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf]
*/
@@ -595,6 +598,298 @@
ZEND_ARG_INFO(0, info)
ZEND_END_ARG_INFO()
+typedef enum {
+ MIT_NEED_ANY = 0,
+ MIT_NEED_ALL = 1,
+ MIT_KEYS_NUMERIC = 0,
+ MIT_KEYS_ASSOC = 2
+} MultipleIteratorFlags;
+
+#define SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT 1
+#define SPL_MULTIPLE_ITERATOR_GET_ALL_KEY 2
+
+/* {{{ proto void MultipleIterator::__construct([int flags =
MIT_NEED_ALL|MIT_KEYS_NUMERIC]) U
+ Iterator that iterates over several iterators one after the other */
+SPL_METHOD(MultipleIterator, __construct)
+{
+ spl_SplObjectStorage *intern;
+ long flags = MIT_NEED_ALL|MIT_KEYS_NUMERIC;
+
+ php_set_error_handling(EH_THROW, spl_ce_InvalidArgumentException
TSRMLS_CC);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &flags) ==
FAILURE) {
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+ return;
+ }
+
+ php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
+
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+ intern->flags = flags;
+}
+/* }}} */
+
+/* {{{ proto int MultipleIterator::getFlags() U
+ Return current flags */
+SPL_METHOD(MultipleIterator, getFlags)
+{
+ spl_SplObjectStorage *intern =
(spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ RETURN_LONG(intern->flags);
+}
+/* }}} */
+
+/* {{{ proto int MultipleIterator::setFlags(int flags) U
+ Set flags */
+SPL_METHOD(MultipleIterator, setFlags)
+{
+ spl_SplObjectStorage *intern;
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l",
&intern->flags) == FAILURE) {
+ return;
+ }
+}
+/* }}} */
+
+/* {{{ proto void attachIterator(Iterator iterator[, mixed info]) throws
InvalidArgumentException U
+ Attach a new iterator */
+SPL_METHOD(MultipleIterator, attachIterator)
+{
+ spl_SplObjectStorage *intern;
+ zval *iterator = NULL, *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|z!", &iterator,
zend_ce_iterator, &info) == FAILURE) {
+ return;
+ }
+
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ if (info != NULL) {
+ spl_SplObjectStorageElement *element;
+ zval compare_result;
+
+ if (Z_TYPE_P(info) != IS_LONG && Z_TYPE_P(info) != IS_STRING &&
Z_TYPE_P(info) != IS_UNICODE) {
+ zend_throw_exception(spl_ce_InvalidArgumentException,
"Info must be NULL, integer or string", 0 TSRMLS_CC);
+ return;
+ }
+
+ zend_hash_internal_pointer_reset_ex(&intern->storage,
&intern->pos);
+ while (zend_hash_get_current_data_ex(&intern->storage,
(void**)&element, &intern->pos) == SUCCESS) {
+ is_identical_function(&compare_result, info,
element->inf TSRMLS_CC);
+ if (Z_LVAL(compare_result)) {
+
zend_throw_exception(spl_ce_InvalidArgumentException, "Key duplication error",
0 TSRMLS_CC);
+ return;
+ }
+ zend_hash_move_forward_ex(&intern->storage,
&intern->pos);
+ }
+ }
+
+ spl_object_storage_attach(intern, iterator, info TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ proto void MultipleIterator::rewind() U
+ Rewind all attached iterator instances */
+SPL_METHOD(MultipleIterator, rewind)
+{
+ spl_SplObjectStorage *intern;
+ spl_SplObjectStorageElement *element;
+ zval *it;
+
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
+ while (zend_hash_get_current_data_ex(&intern->storage,
(void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
+ it = element->obj;
+ zend_call_method_with_0_params(&it, Z_OBJCE_P(it),
&Z_OBJCE_P(it)->iterator_funcs.zf_rewind, "rewind", NULL);
+ zend_hash_move_forward_ex(&intern->storage, &intern->pos);
+ }
+}
+/* }}} */
+
+/* {{{ proto void MultipleIterator::next() U
+ Move all attached iterator instances forward */
+SPL_METHOD(MultipleIterator, next)
+{
+ spl_SplObjectStorage *intern;
+ spl_SplObjectStorageElement *element;
+ zval *it;
+
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
+ while (zend_hash_get_current_data_ex(&intern->storage,
(void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
+ it = element->obj;
+ zend_call_method_with_0_params(&it, Z_OBJCE_P(it),
&Z_OBJCE_P(it)->iterator_funcs.zf_next, "next", NULL);
+ zend_hash_move_forward_ex(&intern->storage, &intern->pos);
+ }
+}
+/* }}} */
+
+/* {{{ proto bool MultipleIterator::valid() U
+ Return whether all or one sub iterator is valid depending on flags */
+SPL_METHOD(MultipleIterator, valid)
+{
+ spl_SplObjectStorage *intern;
+ spl_SplObjectStorageElement *element;
+ zval *it, *retval = NULL;
+ long expect, valid;
+
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ if (!zend_hash_num_elements(&intern->storage)) {
+ RETURN_FALSE;
+ }
+
+ expect = (intern->flags & MIT_NEED_ALL) ? 1 : 0;
+
+ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
+ while (zend_hash_get_current_data_ex(&intern->storage,
(void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
+ it = element->obj;
+ zend_call_method_with_0_params(&it, Z_OBJCE_P(it),
&Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
+
+ if (retval) {
+ valid = Z_LVAL_P(retval);
+ zval_ptr_dtor(&retval);
+ } else {
+ valid = 0;
+ }
+
+ if (expect != valid) {
+ RETURN_BOOL(!expect);
+ }
+
+ zend_hash_move_forward_ex(&intern->storage, &intern->pos);
+ }
+
+ RETURN_BOOL(expect);
+}
+/* }}} */
+
+static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int
get_type, zval *return_value TSRMLS_DC) /* {{{ */
+{
+ spl_SplObjectStorageElement *element;
+ zval *it, *retval = NULL;
+ int valid = 1, num_elements;
+
+ num_elements = zend_hash_num_elements(&intern->storage);
+ if (num_elements < 1) {
+ RETURN_FALSE;
+ }
+
+ array_init_size(return_value, num_elements);
+
+ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
+ while (zend_hash_get_current_data_ex(&intern->storage,
(void**)&element, &intern->pos) == SUCCESS && !EG(exception)) {
+ it = element->obj;
+ zend_call_method_with_0_params(&it, Z_OBJCE_P(it),
&Z_OBJCE_P(it)->iterator_funcs.zf_valid, "valid", &retval);
+
+ if (retval) {
+ valid = Z_LVAL_P(retval);
+ zval_ptr_dtor(&retval);
+ } else {
+ valid = 0;
+ }
+
+ if (valid) {
+ if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
+ zend_call_method_with_0_params(&it,
Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_current, "current", &retval);
+ } else {
+ zend_call_method_with_0_params(&it,
Z_OBJCE_P(it), &Z_OBJCE_P(it)->iterator_funcs.zf_key, "key", &retval);
+ }
+ if (!retval) {
+ zend_throw_exception(spl_ce_RuntimeException,
"Failed to call sub iterator method", 0 TSRMLS_CC);
+ return;
+ }
+ } else if (intern->flags & MIT_NEED_ALL) {
+ if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) {
+ zend_throw_exception(spl_ce_RuntimeException,
"Called current() with non valid sub iterator", 0 TSRMLS_CC);
+ } else {
+ zend_throw_exception(spl_ce_RuntimeException,
"Called key() with non valid sub iterator", 0 TSRMLS_CC);
+ }
+ return;
+ } else {
+ ALLOC_INIT_ZVAL(retval);
+ }
+
+ if (intern->flags & MIT_KEYS_ASSOC) {
+ switch (Z_TYPE_P(element->inf)) {
+ case IS_LONG:
+ add_index_zval(return_value,
Z_LVAL_P(element->inf), retval);
+ break;
+ case IS_STRING:
+ case IS_UNICODE:
+ add_u_assoc_zval_ex(return_value,
Z_TYPE_P(element->inf), Z_UNIVAL_P(element->inf), Z_UNILEN_P(element->inf)+1U,
retval);
+ break;
+ default:
+ zval_ptr_dtor(&retval);
+
zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is
associated with NULL", 0 TSRMLS_CC);
+ return;
+ }
+ } else {
+ add_next_index_zval(return_value, retval);
+ }
+
+ zend_hash_move_forward_ex(&intern->storage, &intern->pos);
+ }
+}
+/* }}} */
+
+/* {{{ proto array current() throws RuntimeException throws
InvalidArgumentException U
+ Return an array of all registered Iterator instances current() result */
+SPL_METHOD(MultipleIterator, current)
+{
+ spl_SplObjectStorage *intern;
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ spl_multiple_iterator_get_all(intern,
SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT, return_value TSRMLS_CC);
+}
+/* }}} */
+
+/* {{{ proto array MultipleIterator::key() U
+ Return an array of all registered Iterator instances key() result */
+SPL_METHOD(MultipleIterator, key)
+{
+ spl_SplObjectStorage *intern;
+ intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis()
TSRMLS_CC);
+
+ spl_multiple_iterator_get_all(intern,
SPL_MULTIPLE_ITERATOR_GET_ALL_KEY, return_value TSRMLS_CC);
+}
+/* }}} */
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_attachIterator, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+ ZEND_ARG_INFO(0, infos)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_detachIterator, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_MultipleIterator_containsIterator, 0, 0, 1)
+ ZEND_ARG_OBJ_INFO(0, iterator, Iterator, 0)
+ZEND_END_ARG_INFO();
+
+static const zend_function_entry spl_funcs_MultipleIterator[] = {
+ SPL_ME(MultipleIterator, __construct, NULL,
0)
+ SPL_ME(MultipleIterator, getFlags, NULL,
0)
+ SPL_ME(MultipleIterator, setFlags, NULL,
0)
+ SPL_ME(MultipleIterator, attachIterator,
arginfo_MultipleIterator_attachIterator, 0)
+ SPL_MA(MultipleIterator, detachIterator, SplObjectStorage,
detach, arginfo_MultipleIterator_detachIterator, 0)
+ SPL_MA(MultipleIterator, containsIterator, SplObjectStorage,
contains, arginfo_MultipleIterator_containsIterator, 0)
+ SPL_MA(MultipleIterator, countIterators, SplObjectStorage,
count, NULL, 0)
+ /* Iterator */
+ SPL_ME(MultipleIterator, rewind, NULL,
0)
+ SPL_ME(MultipleIterator, valid, NULL,
0)
+ SPL_ME(MultipleIterator, key, NULL,
0)
+ SPL_ME(MultipleIterator, current, NULL,
0)
+ SPL_ME(MultipleIterator, next, NULL,
0)
+ {NULL, NULL, NULL}
+};
+
static const zend_function_entry spl_funcs_SplObjectStorage[] = {
SPL_ME(SplObjectStorage, attach, arginfo_attach, 0)
SPL_ME(SplObjectStorage, detach, arginfo_Object, 0)
@@ -635,6 +930,14 @@
REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Serializable);
REGISTER_SPL_IMPLEMENTS(SplObjectStorage, ArrayAccess);
+ REGISTER_SPL_STD_CLASS_EX(MultipleIterator, spl_SplObjectStorage_new,
spl_funcs_MultipleIterator);
+ REGISTER_SPL_ITERATOR(MultipleIterator);
+
+ REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ANY",
MIT_NEED_ANY);
+ REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_NEED_ALL",
MIT_NEED_ALL);
+ REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_NUMERIC",
MIT_KEYS_NUMERIC);
+ REGISTER_SPL_CLASS_CONST_LONG(MultipleIterator, "MIT_KEYS_ASSOC",
MIT_KEYS_ASSOC);
+
return SUCCESS;
}
/* }}} */
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/spl_observer.h?r1=1.7&r2=1.8&diff_format=u
Index: php-src/ext/spl/spl_observer.h
diff -u php-src/ext/spl/spl_observer.h:1.7 php-src/ext/spl/spl_observer.h:1.8
--- php-src/ext/spl/spl_observer.h:1.7 Mon Dec 31 07:12:15 2007
+++ php-src/ext/spl/spl_observer.h Tue Jul 22 22:54:15 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: spl_observer.h,v 1.7 2007/12/31 07:12:15 sebastian Exp $ */
+/* $Id: spl_observer.h,v 1.8 2008/07/22 22:54:15 helly Exp $ */
#ifndef SPL_OBSERVER_H
#define SPL_OBSERVER_H
@@ -27,6 +27,7 @@
extern PHPAPI zend_class_entry *spl_ce_SplObserver;
extern PHPAPI zend_class_entry *spl_ce_SplSubject;
extern PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
+extern PHPAPI zend_class_entry *spl_ce_MultipleIterator;
PHP_MINIT_FUNCTION(spl_observer);
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/internal/recursivetreeiterator.inc?r1=1.2&r2=1.3&diff_format=u
Index: php-src/ext/spl/internal/recursivetreeiterator.inc
diff -u php-src/ext/spl/internal/recursivetreeiterator.inc:1.2
php-src/ext/spl/internal/recursivetreeiterator.inc:1.3
--- php-src/ext/spl/internal/recursivetreeiterator.inc:1.2 Sat Jul 19
15:48:07 2008
+++ php-src/ext/spl/internal/recursivetreeiterator.inc Tue Jul 22 22:54:15 2008
@@ -1,7 +1,7 @@
<?php
/** @file recursivetreeiterator.inc
- * @ingroup Examples
+ * @ingroup SPL
* @brief class RecursiveTreeIterator
* @author Marcus Boerger, Johannes Schlueter
* @date 2005
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/internal/multipleiterator.inc?view=markup&rev=1.1
Index: php-src/ext/spl/internal/multipleiterator.inc
+++ php-src/ext/spl/internal/multipleiterator.inc
<?php
/** @file multipleiterator.inc
* @ingroup SPL
* @brief class MultipleIterator
* @author Johannes Schlueter
* @author Marcus Boerger
* @date 2008
*
* SPL - Standard PHP Library
*/
/** @ingroup SPL
* @brief Iterator that iterates over several iterators one after the other
* @author Johannes Schlueter
* @author Marcus Boerger
* @version 1.0
* @since PHP 5.3
*/
class MultipleIterator implements Iterator
{
/** Inner Iterators */
private $iterators;
/** Flags: const MIT_* */
private $flags;
/** do not require all sub iterators to be valid in iteration */
const MIT_NEED_ANY = 0;
/** require all sub iterators to be valid in iteration */
const MIT_NEED_ALL = 1;
/** keys are created from sub iterators position */
const MIT_KEYS_NUMERIC = 0;
/** keys are created from sub iterators associated infromation */
const MIT_KEYS_ASSOC = 2;
/** Construct a new empty MultipleIterator
* @param flags MIT_* flags
*/
public function __construct($flags =
self::MIT_NEED_ALL|self::MIT_KEYS_NUMERIC)
{
$this->iterators = new SplObjectStorage();
$this->flags = $flags;
}
/** @return current flags MIT_* */
public function getFlags()
{
return $this->flags;
}
/** @param $flags new flags. */
public function setFlags($flags)
{
$this->flags = $flags;
}
/** @param $iter new Iterator to attach.
* @param $inf associative info forIteraotr, must be NULL, integer or
string
*
* @throws IllegalValueException if a inf is none of NULL, integer or
string
* @throws IllegalValueException if a inf is already an associated info
*/
public function attachIterator(Iterator $iter, $inf = NULL)
{
if (!is_null($inf))
{
if (!is_int($inf) && !is_string($inf))
{
throw new IllegalValueException('Inf must be
NULL, integer or string');
}
foreach($this->iterators as $iter)
{
if ($inf == $this->iterators->getInfo())
{
throw new IllegalValueException('Key
duplication error');
}
}
}
$this->iterators->attach($iter, $inf);
}
/** @param $iter attached Iterator that should be detached. */
public function detachIterator(Iterator $iter)
{
$this->iterators->detach($iter);
}
/** @param $iter Iterator to check
* @return whether $iter is attached or not
*/
public function containsIterator(Iterator $iter)
{
return $this->iterator->contains($iter);
}
/** @return number of attached Iterator instances. */
public function countIterators()
{
return $this->iterators->count();
}
/** Rewind all attached Iterator instances. */
public function rewind()
{
foreach($this->iterators as $iter)
{
$iter->rewind();
}
}
/**
* @return whether all or one sub iterator is valid depending on flags.
* In mode MIT_NEED_ALL we expect all sub iterators to be valid and
* return flase on the first non valid one. If that flag is not set we
* return true on the first valid sub iterator found. If no Iterator
* is attached, we always return false.
*/
public function valid()
{
if (!sizeof($this->iterators)) {
return false;
}
// The following code is an optimized version that executes as
few
// valid() calls as necessary and that only checks the flags
once.
$expect = $this->flags & self::MIT_NEED_ALL ? true : false;
foreach($this->iterators as $iter)
{
if ($expect != $iter->valid())
{
return !$expect;
}
}
return $expect;
}
/** Move all attached Iterator instances forward. That is invoke
* their next() method regardless of their state.
*/
public function next()
{
foreach($this->iterators as $iter)
{
$iter->next();
}
}
/** @return false if no sub Iterator is attached and an array of
* all registered Iterator instances current() result.
* @throws RuntimeException if mode MIT_NEED_ALL is set and at
least one
* attached Iterator is not valid().
* @throws IllegalValueException if a key is NULL and MIT_KEYS_ASSOC is
set.
*/
public function current()
{
if (!sizeof($this->iterators))
{
return false;
}
$retval = array();
foreach($this->iterators as $iter)
{
if ($it->valid())
{
if ($this->flags & self::MIT_KEYS_ASSOC)
{
$key = $this->iterators->getInfo();
if (is_null($key))
{
throw new
IllegalValueException('Sub-Iterator is associated with NULL');
}
$retval[$key] = $iter->current();
}
else
{
$retval[] = $iter->current();
}
}
else if ($this->flags & self::MIT_NEED_ALL)
{
throw new RuntimeException('Called current()
with non valid sub iterator');
}
else
{
$retval[] = NULL;
}
}
return $retval;
}
/** @return false if no sub Iterator is attached and an array of
* all registered Iterator instances key() result.
* @throws LogicException if mode MIT_NEED_ALL is set and at least one
* attached Iterator is not valid().
*/
public function key()
{
if (!sizeof($this->iterators))
{
return false;
}
$retval = array();
foreach($this->iterators as $iter)
{
if ($it->valid())
{
$retval[] = $iter->key();
}
else if ($this->flags & self::MIT_NEED_ALL)
{
throw new LogicException('Called key() with non
valid sub iterator');
}
else
{
$retval[] = NULL;
}
}
return $retval;
}
}
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/multiple_iterator_001.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/multiple_iterator_001.phpt
+++ php-src/ext/spl/tests/multiple_iterator_001.phpt
--TEST--
SPL: MultipleIterator
--FILE--
<?php
$iter1 = new ArrayIterator(array(1,2,3));
$iter2 = new ArrayIterator(array(1,2));
$iter3 = new ArrayIterator(array(new stdClass(),"string",3));
$m = new MultipleIterator();
echo "-- Default flags, no iterators --\n";
foreach($m as $value) {
var_dump($value);
}
var_dump($m->current());
$m->attachIterator($iter1);
$m->attachIterator($iter2);
$m->attachIterator($iter3);
echo "-- Default flags, MultipleIterator::MIT_NEED_ALL |
MultipleIterator::MIT_KEYS_NUMERIC --\n";
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ALL |
MultipleIterator::MIT_KEYS_NUMERIC));
foreach($m as $value) {
var_dump($m->key(), $value);
}
try {
$m->current();
} catch(RuntimeException $e) {
echo "RuntimeException thrown: " . $e->getMessage() . "\n";
}
try {
$m->key();
} catch(RuntimeException $e) {
echo "RuntimeException thrown: " . $e->getMessage() . "\n";
}
echo "-- Flags = MultipleIterator::MIT_NEED_ANY |
MultipleIterator::MIT_KEYS_NUMERIC --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ANY |
MultipleIterator::MIT_KEYS_NUMERIC);
var_dump($m->getFlags() === (MultipleIterator::MIT_NEED_ANY |
MultipleIterator::MIT_KEYS_NUMERIC));
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Default flags, added element --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ALL |
MultipleIterator::MIT_KEYS_NUMERIC);
$iter2[] = 3;
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated
with NULL --\n";
$m->setFlags(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_ASSOC);
$m->rewind();
try {
$m->current();
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Flags |= MultipleIterator::MIT_KEYS_ASSOC --\n";
$m->attachIterator($iter1, "iter1");
$m->attachIterator($iter2, b"iter2");
$m->attachIterator($iter3, 3);
foreach($m as $value) {
var_dump($m->key(), $value);
}
echo "-- Associate with invalid value --\n";
try {
$m->attachIterator($iter3, new stdClass());
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Associate with duplicate value --\n";
try {
$m->attachIterator($iter3, "iter1");
} catch(InvalidArgumentException $e) {
echo "InvalidArgumentException thrown: " . $e->getMessage() . "\n";
}
echo "-- Count, contains, detach, count, contains, iterate --\n";
var_dump($m->countIterators());
var_dump($m->containsIterator($iter2));
var_dump($m->detachIterator($iter2));
var_dump($m->countIterators());
var_dump($m->containsIterator($iter2));
foreach($m as $value) {
var_dump($m->key(), $value);
}
?>
--EXPECTF--
-- Default flags, no iterators --
bool(false)
-- Default flags, MultipleIterator::MIT_NEED_ALL |
MultipleIterator::MIT_KEYS_NUMERIC --
bool(true)
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
RuntimeException thrown: Called current() with non valid sub iterator
RuntimeException thrown: Called key() with non valid sub iterator
-- Flags = MultipleIterator::MIT_NEED_ANY | MultipleIterator::MIT_KEYS_NUMERIC
--
bool(true)
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
array(3) {
[0]=>
int(2)
[1]=>
NULL
[2]=>
int(2)
}
array(3) {
[0]=>
int(3)
[1]=>
NULL
[2]=>
int(3)
}
-- Default flags, added element --
array(3) {
[0]=>
int(0)
[1]=>
int(0)
[2]=>
int(0)
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[0]=>
int(1)
[1]=>
int(1)
[2]=>
int(1)
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
unicode(6) "string"
}
array(3) {
[0]=>
int(2)
[1]=>
int(2)
[2]=>
int(2)
}
array(3) {
[0]=>
int(3)
[1]=>
int(3)
[2]=>
int(3)
}
-- Flags |= MultipleIterator::MIT_KEYS_ASSOC, with iterator associated with
NULL --
InvalidArgumentException thrown: Sub-Iterator is associated with NULL
-- Flags |= MultipleIterator::MIT_KEYS_ASSOC --
array(3) {
[u"iter1"]=>
int(0)
["iter2"]=>
int(0)
[3]=>
int(0)
}
array(3) {
[u"iter1"]=>
int(1)
["iter2"]=>
int(1)
[3]=>
object(stdClass)#%d (0) {
}
}
array(3) {
[u"iter1"]=>
int(1)
["iter2"]=>
int(1)
[3]=>
int(1)
}
array(3) {
[u"iter1"]=>
int(2)
["iter2"]=>
int(2)
[3]=>
unicode(6) "string"
}
array(3) {
[u"iter1"]=>
int(2)
["iter2"]=>
int(2)
[3]=>
int(2)
}
array(3) {
[u"iter1"]=>
int(3)
["iter2"]=>
int(3)
[3]=>
int(3)
}
-- Associate with invalid value --
InvalidArgumentException thrown: Info must be NULL, integer or string
-- Associate with duplicate value --
InvalidArgumentException thrown: Key duplication error
-- Count, contains, detach, count, contains, iterate --
int(3)
bool(true)
NULL
int(2)
bool(false)
array(2) {
[u"iter1"]=>
int(0)
[3]=>
int(0)
}
array(2) {
[u"iter1"]=>
int(1)
[3]=>
object(stdClass)#%d (0) {
}
}
array(2) {
[u"iter1"]=>
int(1)
[3]=>
int(1)
}
array(2) {
[u"iter1"]=>
int(2)
[3]=>
unicode(6) "string"
}
array(2) {
[u"iter1"]=>
int(2)
[3]=>
int(2)
}
array(2) {
[u"iter1"]=>
int(3)
[3]=>
int(3)
}
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php