summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtienne Kneuss <colder@php.net>2008-01-26 23:04:43 +0000
committerEtienne Kneuss <colder@php.net>2008-01-26 23:04:43 +0000
commit6a7074c8377f5adb94c21c9977f0829eb4a8e2bb (patch)
tree38af0336eb9fffcf9d53d815e0a24aeeeeb31afd
parent65e86e459a6a1c987372daba412c1fc4279191b0 (diff)
downloadphp-git-6a7074c8377f5adb94c21c9977f0829eb4a8e2bb.tar.gz
MFH: Iterator implementation in SplDoublyLinkedList, SplStack, SplQueue
-rw-r--r--ext/spl/spl_dllist.c146
-rw-r--r--ext/spl/tests/dllist_007.phpt26
2 files changed, 136 insertions, 36 deletions
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index b7fdafe00c..0e2d5f5f0f 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -874,6 +874,67 @@ static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
}
/* }}} */
+static void spl_dllist_it_helper_rewind(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */
+{
+ SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr);
+
+ if (flags & SPL_DLLIST_IT_LIFO) {
+ *traverse_position_ptr = llist->count-1;
+ *traverse_pointer_ptr = llist->tail;
+ } else {
+ *traverse_position_ptr = 0;
+ *traverse_pointer_ptr = llist->head;
+ }
+
+ SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
+}
+/* }}} */
+
+static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */
+{
+ if (*traverse_pointer_ptr) {
+ spl_ptr_llist_element *old = *traverse_pointer_ptr;
+
+ if (flags & SPL_DLLIST_IT_LIFO) {
+ *traverse_pointer_ptr = old->prev;
+ (*traverse_position_ptr)--;
+
+ if (flags & SPL_DLLIST_IT_DELETE) {
+ zval *prev = (zval *)spl_ptr_llist_pop(llist);
+
+ if (prev) {
+ zval_ptr_dtor((zval **)&prev);
+ }
+ }
+ } else {
+ *traverse_pointer_ptr = old->next;
+ (*traverse_position_ptr)++;
+
+ if (flags & SPL_DLLIST_IT_DELETE) {
+ zval *prev = (zval *)spl_ptr_llist_shift(llist);
+
+ if (prev) {
+ zval_ptr_dtor((zval **)&prev);
+ }
+ }
+ }
+
+ SPL_LLIST_DELREF(old);
+ SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
+ }
+}
+/* }}} */
+
+static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+{
+ spl_dllist_it *iterator = (spl_dllist_it *)iter;
+ spl_dllist_object *object = iterator->object;
+ spl_ptr_llist *llist = object->llist;
+
+ spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC);
+}
+/* }}} */
+
static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
{
spl_dllist_it *iterator = (spl_dllist_it *)iter;
@@ -912,56 +973,63 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /*
zend_user_it_invalidate_current(iter TSRMLS_CC);
- if (iterator->traverse_pointer) {
- spl_ptr_llist_element *old = iterator->traverse_pointer;
+ spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC);
+}
+/* }}} */
- if (iterator->flags & SPL_DLLIST_IT_LIFO) {
- iterator->traverse_pointer = old->prev;
- iterator->traverse_position--;
+/* {{{ proto int SplDoublyLinkedList::key() U
+ Return current array key */
+SPL_METHOD(SplDoublyLinkedList, key)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- if (iterator->flags & SPL_DLLIST_IT_DELETE) {
- zval *prev = (zval *)spl_ptr_llist_pop(object->llist);
+ RETURN_LONG(intern->traverse_position);
+}
+/* }}} */
- if (prev) {
- zval_ptr_dtor((zval **)&prev);
- }
- }
- } else {
- iterator->traverse_pointer = old->next;
- iterator->traverse_position++;
+/* {{{ proto void SplDoublyLinkedList::next() U
+ Move to next entry */
+SPL_METHOD(SplDoublyLinkedList, next)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- if (iterator->flags & SPL_DLLIST_IT_DELETE) {
- zval *prev = (zval *)spl_ptr_llist_shift(object->llist);
+ spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
+}
+/* }}} */
- if (prev) {
- zval_ptr_dtor((zval **)&prev);
- }
- }
- }
+/* {{{ proto bool SplDoublyLinkedList::valid() U
+ Check whether the datastructure contains more entries */
+SPL_METHOD(SplDoublyLinkedList, valid)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- SPL_LLIST_DELREF(old);
- SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
- }
+ RETURN_BOOL(intern->traverse_pointer != NULL);
}
/* }}} */
-static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
+/* {{{ proto void SplDoublyLinkedList::rewind() U
+ Rewind the datastructure back to the start */
+SPL_METHOD(SplDoublyLinkedList, rewind)
{
- spl_dllist_it *iterator = (spl_dllist_it *)iter;
- spl_dllist_object *object = iterator->object;
- spl_ptr_llist *llist = object->llist;
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
- SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer);
+ spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
+}
+/* }}} */
- if (iterator->flags & SPL_DLLIST_IT_LIFO) {
- iterator->traverse_position = llist->count-1;
- iterator->traverse_pointer = llist->tail;
+/* {{{ proto mixed|NULL SplDoublyLinkedList::current() U
+ Return current datastructure entry */
+SPL_METHOD(SplDoublyLinkedList, current)
+{
+ spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
+ spl_ptr_llist_element *element = intern->traverse_pointer;
+
+ if (element == NULL || element->data == NULL) {
+ RETURN_NULL();
} else {
- iterator->traverse_position = 0;
- iterator->traverse_pointer = llist->head;
+ zval *data = (zval *)element->data;
+ RETURN_ZVAL(data, 1, 0);
}
-
- SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
}
/* }}} */
@@ -1047,6 +1115,11 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, rewind, NULL, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, current, NULL, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, key, NULL, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, next, NULL, ZEND_ACC_PUBLIC)
+ SPL_ME(SplDoublyLinkedList, valid, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
/* }}} */
@@ -1064,6 +1137,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_DELETE",SPL_DLLIST_IT_DELETE);
REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_KEEP", 0);
+ REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
diff --git a/ext/spl/tests/dllist_007.phpt b/ext/spl/tests/dllist_007.phpt
new file mode 100644
index 0000000000..46dc7ad47e
--- /dev/null
+++ b/ext/spl/tests/dllist_007.phpt
@@ -0,0 +1,26 @@
+--TEST--
+SPL: DoublyLinkedList: Iterator
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+$a = new SplDoublyLinkedList();
+$a->push(1);
+$a->push(2);
+$a->push(3);
+
+$a->rewind();
+while ($a->valid()) {
+ var_dump($a->current(), $a->next());
+}
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(1)
+NULL
+int(2)
+NULL
+int(3)
+NULL
+===DONE===