1 #include "../../common.h"
2 
3 #include "../../ds/ds_deque.h"
4 #include "../objects/php_deque.h"
5 #include "php_deque_iterator.h"
6 
php_ds_deque_iterator_dtor(zend_object_iterator * iter)7 static void php_ds_deque_iterator_dtor(zend_object_iterator *iter)
8 {
9     php_ds_deque_iterator_t *iterator = (php_ds_deque_iterator_t *) iter;
10 
11     OBJ_RELEASE(iterator->object);
12 }
13 
php_ds_deque_iterator_valid(zend_object_iterator * iter)14 static int php_ds_deque_iterator_valid(zend_object_iterator *iter)
15 {
16     php_ds_deque_iterator_t *iterator = (php_ds_deque_iterator_t *) iter;
17 
18     if (iterator->position < iterator->deque->size) {
19         return SUCCESS;
20     }
21 
22     return FAILURE;
23 }
24 
php_ds_deque_iterator_get_current_data(zend_object_iterator * iter)25 static zval *php_ds_deque_iterator_get_current_data(zend_object_iterator *iter)
26 {
27     php_ds_deque_iterator_t *iterator = (php_ds_deque_iterator_t *) iter;
28     return ds_deque_get(iterator->deque, iterator->position);
29 }
30 
php_ds_deque_iterator_get_current_key(zend_object_iterator * iter,zval * key)31 static void php_ds_deque_iterator_get_current_key(zend_object_iterator *iter, zval *key) {
32     ZVAL_LONG(key, ((php_ds_deque_iterator_t *) iter)->position);
33 }
34 
php_ds_deque_iterator_move_forward(zend_object_iterator * iter)35 static void php_ds_deque_iterator_move_forward(zend_object_iterator *iter)
36 {
37     ((php_ds_deque_iterator_t *) iter)->position++;
38 }
39 
php_ds_deque_iterator_rewind(zend_object_iterator * iter)40 static void php_ds_deque_iterator_rewind(zend_object_iterator *iter)
41 {
42     ((php_ds_deque_iterator_t *) iter)->position = 0;
43 }
44 
45 static zend_object_iterator_funcs iterator_funcs = {
46     php_ds_deque_iterator_dtor,
47     php_ds_deque_iterator_valid,
48     php_ds_deque_iterator_get_current_data,
49     php_ds_deque_iterator_get_current_key,
50     php_ds_deque_iterator_move_forward,
51     php_ds_deque_iterator_rewind
52 };
53 
php_ds_deque_create_iterator(zval * obj,int by_ref)54 static zend_object_iterator *php_ds_deque_create_iterator(zval *obj, int by_ref)
55 {
56     php_ds_deque_iterator_t *iterator;
57 
58     if (by_ref) {
59         ITERATION_BY_REF_NOT_SUPPORTED();
60         return NULL;
61     }
62 
63     iterator = ecalloc(1, sizeof(php_ds_deque_iterator_t));
64     zend_iterator_init((zend_object_iterator*) iterator);
65 
66     iterator->intern.funcs = &iterator_funcs;
67     iterator->deque        = Z_DS_DEQUE_P(obj);
68     iterator->object       = Z_OBJ_P(obj);
69     iterator->position     = 0;
70 
71     // Add a reference to the object so that it doesn't get collected when
72     // the iterated object is implict, eg. foreach ($obj->getInstance() as $value){ ... }
73 #if PHP_VERSION_ID >= 70300
74     GC_ADDREF(iterator->object);
75 #else
76     ++GC_REFCOUNT(iterator->object);
77 #endif
78 
79     return (zend_object_iterator *) iterator;
80 }
81 
php_ds_deque_get_iterator(zend_class_entry * ce,zval * obj,int by_ref)82 zend_object_iterator *php_ds_deque_get_iterator(zend_class_entry *ce, zval *obj, int by_ref)
83 {
84     return php_ds_deque_create_iterator(obj, by_ref);
85 }
86