1 #include "../../common.h"
2 #include "../objects/php_stack.h"
3 #include "php_stack_iterator.h"
4
php_ds_stack_iterator_dtor(zend_object_iterator * iter)5 static void php_ds_stack_iterator_dtor(zend_object_iterator *iter)
6 {
7 php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter;
8
9 OBJ_RELEASE(iterator->object);
10 }
11
php_ds_stack_iterator_valid(zend_object_iterator * iter)12 static int php_ds_stack_iterator_valid(zend_object_iterator *iter)
13 {
14 return Z_ISUNDEF(iter->data) ? FAILURE : SUCCESS;
15 }
16
php_ds_stack_iterator_get_current_data(zend_object_iterator * iter)17 static zval *php_ds_stack_iterator_get_current_data(zend_object_iterator *iter)
18 {
19 return &iter->data;
20 }
21
php_ds_stack_iterator_get_current_key(zend_object_iterator * iter,zval * key)22 static void php_ds_stack_iterator_get_current_key(zend_object_iterator *iter, zval *key) {
23 ZVAL_LONG(key, ((php_ds_stack_iterator_t *) iter)->position);
24 }
25
php_ds_stack_iterator_set_current(ds_stack_t * stack,zval * data)26 static void php_ds_stack_iterator_set_current(ds_stack_t *stack, zval *data)
27 {
28 if (DS_STACK_IS_EMPTY(stack)) {
29 ZVAL_UNDEF(data);
30 } else {
31 ds_stack_pop(stack, data);
32 Z_TRY_DELREF_P(data);
33 }
34 }
35
php_ds_stack_iterator_move_forward(zend_object_iterator * iter)36 static void php_ds_stack_iterator_move_forward(zend_object_iterator *iter)
37 {
38 php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter;
39 php_ds_stack_iterator_set_current(iterator->stack, &iter->data);
40 iterator->position++;
41 }
42
php_ds_stack_iterator_rewind(zend_object_iterator * iter)43 static void php_ds_stack_iterator_rewind(zend_object_iterator *iter)
44 {
45 php_ds_stack_iterator_t *iterator = (php_ds_stack_iterator_t *) iter;
46 php_ds_stack_iterator_set_current(iterator->stack, &iter->data);
47 iterator->position = 0;
48 }
49
50 static zend_object_iterator_funcs php_ds_stack_iterator_funcs = {
51 php_ds_stack_iterator_dtor,
52 php_ds_stack_iterator_valid,
53 php_ds_stack_iterator_get_current_data,
54 php_ds_stack_iterator_get_current_key,
55 php_ds_stack_iterator_move_forward,
56 php_ds_stack_iterator_rewind
57 };
58
php_ds_stack_get_iterator(zend_class_entry * ce,zval * object,int by_ref)59 zend_object_iterator *php_ds_stack_get_iterator(zend_class_entry *ce, zval *object, int by_ref)
60 {
61 php_ds_stack_iterator_t *iterator;
62
63 if (by_ref) {
64 ITERATION_BY_REF_NOT_SUPPORTED();
65 return NULL;
66 }
67
68 iterator = ecalloc(1, sizeof(php_ds_stack_iterator_t));
69 zend_iterator_init((zend_object_iterator*) iterator);
70
71 iterator->intern.funcs = &php_ds_stack_iterator_funcs;
72 iterator->stack = Z_DS_STACK_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