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