]> granicus.if.org Git - php/commitdiff
SplDoublyLinkedList uses iteration flags in iterator struct
authorAlex Dowad <alexinbeijing@gmail.com>
Thu, 23 Apr 2020 08:45:20 +0000 (10:45 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 12 May 2020 15:22:31 +0000 (17:22 +0200)
The 'flags' field in spl_dllist_it was formerly unused. This means that if one started to
iterate over an SplDoublyLinkedList using 'foreach', and then *changed* the iteration mode
halfway, the 'foreach' loop would start iterating in the opposite direction. Probably this
was not what was intended.

Therefore, use the 'flags' field in spl_dllist_it for iteration via 'foreach'. For explicit
iteration using methods like '::next()' and '::current()', continue to use the flags in
the SplDoublyLinkedList object itself.

ext/spl/spl_dllist.c
ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt [new file with mode: 0644]

index 7dbc3699d00ee94d6c5efebe22acd6b5effd624e..b11cfacc3c7fa0ef20bbcdf02e1231b47c015a49 100644 (file)
@@ -964,7 +964,7 @@ static void spl_dllist_it_rewind(zend_object_iterator *iter) /* {{{ */
        spl_dllist_object *object = Z_SPLDLLIST_P(&iter->data);
        spl_ptr_llist *llist = object->llist;
 
-       spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags);
+       spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, iterator->flags);
 }
 /* }}} */
 
@@ -1005,7 +1005,7 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter) /* {{{ */
 
        zend_user_it_invalidate_current(iter);
 
-       spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags);
+       spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, iterator->flags);
 }
 /* }}} */
 
diff --git a/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt b/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt
new file mode 100644 (file)
index 0000000..fa901dd
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Iteration over SplDoublyLinkedList via 'foreach' does not change direction partway
+--FILE--
+<?php
+
+$list = new SplDoublyLinkedList();
+$list->push(1);
+$list->push(2);
+$list->push(3);
+
+/* SplDoublyLinkedList would previously check the iteration mode *each time*
+   it would advance to the next item in a 'foreach' loop
+   This meant that it could move forward, then backward, then forward if the
+   iteration mode was changed in the middle of a loop */
+
+$list->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO);
+foreach ($list as $item) {
+  $list->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO);
+  echo $item, "\n";
+}
+
+echo "***\n";
+
+$list->setIteratorMode(SplDoublyLinkedList::IT_MODE_LIFO);
+foreach ($list as $item) {
+  $list->setIteratorMode(SplDoublyLinkedList::IT_MODE_FIFO);
+  echo $item, "\n";
+}
+
+
+?>
+--EXPECT--
+1
+2
+3
+***
+3
+2
+1