diff options
author | Alex Dowad <alexinbeijing@gmail.com> | 2020-04-23 10:45:20 +0200 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-05-12 17:22:31 +0200 |
commit | d4d0852c2363fae2c7f979169ed8621379411a2c (patch) | |
tree | af6b5aae03f1e7048a1f3cb7d064ef5b696dff4f | |
parent | 9999e7faa3f7fc9eb7f654b703faab9b18328229 (diff) | |
download | php-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.c | 4 | ||||
-rw-r--r-- | ext/spl/tests/SplDoublyLinkedList_consistent_iterator_mode.phpt | 39 |
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 |