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