1 #include "../../common.h"
2 #include "../objects/php_queue.h"
3 #include "php_queue_iterator.h"
4
php_ds_queue_iterator_dtor(zend_object_iterator * iter)5 static void php_ds_queue_iterator_dtor(zend_object_iterator *iter)
6 {
7 ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter;
8
9 OBJ_RELEASE(iterator->object);
10 }
11
php_ds_queue_iterator_valid(zend_object_iterator * iter)12 static int php_ds_queue_iterator_valid(zend_object_iterator *iter)
13 {
14 return Z_ISUNDEF(iter->data) ? FAILURE : SUCCESS;
15 }
16
php_ds_queue_iterator_get_current_data(zend_object_iterator * iter)17 static zval *php_ds_queue_iterator_get_current_data(zend_object_iterator *iter)
18 {
19 return &iter->data;
20 }
21
php_ds_queue_iterator_get_current_key(zend_object_iterator * iter,zval * key)22 static void php_ds_queue_iterator_get_current_key(zend_object_iterator *iter, zval *key) {
23 ZVAL_LONG(key, ((ds_queue_iterator_t *) iter)->position);
24 }
25
php_ds_queue_iterator_set_current(ds_queue_t * queue,zval * data)26 static void php_ds_queue_iterator_set_current(ds_queue_t *queue, zval *data)
27 {
28 if (QUEUE_IS_EMPTY(queue)) {
29 ZVAL_UNDEF(data);
30 } else {
31 ds_queue_pop(queue, data);
32 Z_TRY_DELREF_P(data);
33 }
34 }
35
php_ds_queue_iterator_move_forward(zend_object_iterator * iter)36 static void php_ds_queue_iterator_move_forward(zend_object_iterator *iter)
37 {
38 ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter;
39 php_ds_queue_iterator_set_current(iterator->queue, &iter->data);
40 iterator->position++;
41 }
42
php_ds_queue_iterator_rewind(zend_object_iterator * iter)43 static void php_ds_queue_iterator_rewind(zend_object_iterator *iter)
44 {
45 ds_queue_iterator_t *iterator = (ds_queue_iterator_t *) iter;
46 php_ds_queue_iterator_set_current(iterator->queue, &iter->data);
47 iterator->position = 0;
48 }
49
50 static zend_object_iterator_funcs php_ds_queue_iterator_funcs = {
51 php_ds_queue_iterator_dtor,
52 php_ds_queue_iterator_valid,
53 php_ds_queue_iterator_get_current_data,
54 php_ds_queue_iterator_get_current_key,
55 php_ds_queue_iterator_move_forward,
56 php_ds_queue_iterator_rewind
57 };
58
php_ds_queue_get_iterator(zend_class_entry * ce,zval * object,int by_ref)59 zend_object_iterator *php_ds_queue_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
60 {
61 ds_queue_iterator_t *iterator;
62
63 if (by_ref) {
64 ITERATION_BY_REF_NOT_SUPPORTED();
65 return NULL;
66 }
67
68 iterator = ecalloc(1, sizeof(ds_queue_iterator_t));
69 zend_iterator_init((zend_object_iterator*) iterator);
70
71 iterator->intern.funcs = &php_ds_queue_iterator_funcs;
72 iterator->queue = Z_DS_QUEUE_P(object);
73 iterator->object = Z_OBJ_P(object);
74 iterator->position = 0;
75
76 // Add a reference to the object so that it doesn't get collected when
77 // the iterated object is implict, eg. foreach ($obj->getInstance() as $value){ ... }
78 #if PHP_VERSION_ID >= 70300
79 GC_ADDREF(iterator->object);
80 #else
81 ++GC_REFCOUNT(iterator->object);
82 #endif
83
84 return (zend_object_iterator *) iterator;
85 }
86