helly           Tue Jul 22 22:54:35 2008 UTC

  Added files:                 (Branch: PHP_5_3)
    /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    NEWS 
    /php-src/ext/spl    php_spl.c spl_iterators.h spl_observer.c 
                        spl_observer.h 
    /php-src/ext/spl/internal   recursivetreeiterator.inc 
  Log:
  - MFH Add MultipleIterator (Arnaud, Marcus)
  
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.211&r2=1.2027.2.547.2.965.2.212&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.211 
php-src/NEWS:1.2027.2.547.2.965.2.212
--- php-src/NEWS:1.2027.2.547.2.965.2.211       Tue Jul 22 06:50:59 2008
+++ php-src/NEWS        Tue Jul 22 22:54:34 2008
@@ -118,6 +118,7 @@
   . Added FixedArray. (Etienne, Tony)
   . Added delaying exceptions in SPL's autoload mechanism. (Marcus)
   . Added RecursiveTreeIterator. (Arnaud, Marcus)
+  . Added MultipleIterator. (Arnaud, Marcus, Johannes)
 
 - Improved Zend Engine:
   . Added "compact" handler for Zend MM storage. (Dmitry)
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.52.2.28.2.17.2.22&r2=1.52.2.28.2.17.2.23&diff_format=u
Index: php-src/ext/spl/php_spl.c
diff -u php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.22 
php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.23
--- php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.22       Sun Jul 13 21:45:07 2008
+++ php-src/ext/spl/php_spl.c   Tue Jul 22 22:54:35 2008
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_spl.c,v 1.52.2.28.2.17.2.22 2008/07/13 21:45:07 helly Exp $ */
+/* $Id: php_spl.c,v 1.52.2.28.2.17.2.23 2008/07/22 22:54:35 helly Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -156,14 +156,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); \
@@ -180,6 +172,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); \
@@ -194,14 +187,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.h?r1=1.18.2.7.2.12.2.3&r2=1.18.2.7.2.12.2.4&diff_format=u
Index: php-src/ext/spl/spl_iterators.h
diff -u php-src/ext/spl/spl_iterators.h:1.18.2.7.2.12.2.3 
php-src/ext/spl/spl_iterators.h:1.18.2.7.2.12.2.4
--- php-src/ext/spl/spl_iterators.h:1.18.2.7.2.12.2.3   Sat Jul 19 15:49:21 2008
+++ php-src/ext/spl/spl_iterators.h     Tue Jul 22 22:54:35 2008
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_iterators.h,v 1.18.2.7.2.12.2.3 2008/07/19 15:49:21 helly Exp $ */
+/* $Id: spl_iterators.h,v 1.18.2.7.2.12.2.4 2008/07/22 22:54:35 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.2.2.6.2.3.2.7&r2=1.2.2.6.2.3.2.8&diff_format=u
Index: php-src/ext/spl/spl_observer.c
diff -u php-src/ext/spl/spl_observer.c:1.2.2.6.2.3.2.7 
php-src/ext/spl/spl_observer.c:1.2.2.6.2.3.2.8
--- php-src/ext/spl/spl_observer.c:1.2.2.6.2.3.2.7      Mon Jan 28 22:48:15 2008
+++ php-src/ext/spl/spl_observer.c      Tue Jul 22 22:54:35 2008
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_observer.c,v 1.2.2.6.2.3.2.7 2008/01/28 22:48:15 helly Exp $ */
+/* $Id: spl_observer.c,v 1.2.2.6.2.3.2.8 2008/07/22 22:54:35 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] 
*/
@@ -620,6 +623,297 @@
        {NULL, NULL, NULL}
 };
 
+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])
+   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()
+   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)
+   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
+   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) {
+                       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()
+   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()
+   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()
+   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:
+                                       add_assoc_zval_ex(return_value, 
Z_STRVAL_P(element->inf), Z_STRLEN_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
+   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()
+   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}
+};
+
 /* {{{ PHP_MINIT_FUNCTION(spl_observer) */
 PHP_MINIT_FUNCTION(spl_observer)
 {
@@ -635,6 +929,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.2.2.2.2.1.2.1&r2=1.2.2.2.2.1.2.2&diff_format=u
Index: php-src/ext/spl/spl_observer.h
diff -u php-src/ext/spl/spl_observer.h:1.2.2.2.2.1.2.1 
php-src/ext/spl/spl_observer.h:1.2.2.2.2.1.2.2
--- php-src/ext/spl/spl_observer.h:1.2.2.2.2.1.2.1      Mon Dec 31 07:17:14 2007
+++ php-src/ext/spl/spl_observer.h      Tue Jul 22 22:54:35 2008
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: spl_observer.h,v 1.2.2.2.2.1.2.1 2007/12/31 07:17:14 sebastian Exp $ */
+/* $Id: spl_observer.h,v 1.2.2.2.2.1.2.2 2008/07/22 22:54:35 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.2.2&r2=1.2.2.3&diff_format=u
Index: php-src/ext/spl/internal/recursivetreeiterator.inc
diff -u php-src/ext/spl/internal/recursivetreeiterator.inc:1.2.2.2 
php-src/ext/spl/internal/recursivetreeiterator.inc:1.2.2.3
--- php-src/ext/spl/internal/recursivetreeiterator.inc:1.2.2.2  Sat Jul 19 
15:49:21 2008
+++ php-src/ext/spl/internal/recursivetreeiterator.inc  Tue Jul 22 22:54:35 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

Reply via email to