summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Dowad <alexinbeijing@gmail.com>2020-04-23 10:45:20 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-05-12 17:22:31 +0200
commitd4d0852c2363fae2c7f979169ed8621379411a2c (patch)
treeaf6b5aae03f1e7048a1f3cb7d064ef5b696dff4f
parent9999e7faa3f7fc9eb7f654b703faab9b18328229 (diff)
downloadphp-git-d4d0852c2363fae2c7f979169ed8621379411a2c.tar.gz
SplDoublyLinkedList uses iteration flags in iterator struct
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.
-rw-r--r--ext/spl/spl_dllist.c4
-rw-r--r--ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt39
2 files changed, 41 insertions, 2 deletions
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 7dbc3699d0..b11cfacc3c 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -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
index 0000000000..fa901dda91
--- /dev/null
+++ b/ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt
@@ -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