1 #include "php_common_handlers.h"
2 #include "php_deque_handlers.h"
3
4 #include "../objects/php_deque.h"
5 #include "../../ds/ds_deque.h"
6
7 zend_object_handlers php_deque_handlers;
8
php_ds_deque_read_dimension(zend_object * obj,zval * offset,int type,zval * return_value)9 static zval *php_ds_deque_read_dimension
10 #if PHP_VERSION_ID >= 80000
11 (zend_object *obj, zval *offset, int type, zval *return_value) {
12 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
13 #else
14 (zval *obj, zval *offset, int type, zval *return_value) {
15 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
16 #endif
17 zval *value;
18
19 // Dereference the offset if it's a reference.
20 ZVAL_DEREF(offset);
21
22 // `??`
23 if (type == BP_VAR_IS) {
24 if (Z_TYPE_P(offset) != IS_LONG || ! ds_deque_isset(deque, Z_LVAL_P(offset), 0)) {
25 return &EG(uninitialized_zval);
26 }
27 }
28
29 // Enforce strict integer index.
30 if (Z_TYPE_P(offset) != IS_LONG) {
31 INTEGER_INDEX_REQUIRED(offset);
32 return NULL;
33 }
34
35 // Access the value at the given index.
36 value = ds_deque_get(deque, Z_LVAL_P(offset));
37
38 // If we're accessing by reference we have to create a reference.
39 // This is for access like $deque[$a][$b] = $c
40 if (value && type != BP_VAR_R && type != BP_VAR_IS) {
41 ZVAL_MAKE_REF(value);
42 }
43
44 return value;
45 }
46
47 static void php_ds_deque_write_dimension
48 #if PHP_VERSION_ID >= 80000
49 (zend_object *obj, zval *offset, zval *value) {
50 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
51 #else
52 (zval *obj, zval *offset, zval *value) {
53 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
54 #endif
55 if (offset == NULL) { /* $v[] = ... */
56 ds_deque_push(deque, value);
57
58 } else {
59 ZVAL_DEREF(offset);
60
61 if (Z_TYPE_P(offset) != IS_LONG) {
62 INTEGER_INDEX_REQUIRED(offset);
63 } else {
64 ds_deque_set(deque, Z_LVAL_P(offset), value);
65 }
66 }
67 }
68
69 static int php_ds_deque_has_dimension
70 #if PHP_VERSION_ID >= 80000
71 (zend_object *obj, zval *offset, int check_empty) {
72 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
73 #else
74 (zval *obj, zval *offset, int check_empty) {
75 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
76 #endif
77 if (Z_TYPE_P(offset) != IS_LONG) {
78 return 0;
79 }
80
81 ZVAL_DEREF(offset);
82
83 return ds_deque_isset(deque, Z_LVAL_P(offset), check_empty);
84 }
85
86 static void php_ds_deque_unset_dimension
87 #if PHP_VERSION_ID >= 80000
88 (zend_object *obj, zval *offset) {
89 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
90 #else
91 (zval *obj, zval *offset) {
92 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
93 #endif
94 zend_long index = 0;
95 ZVAL_DEREF(offset);
96
97 if (Z_TYPE_P(offset) == IS_LONG) {
98 index = Z_LVAL_P(offset);
99
100 } else {
101 if (zend_parse_parameter(ZEND_PARSE_PARAMS_QUIET, 1, offset, "l", &index) == FAILURE) {
102 return;
103 }
104 }
105
106 if (ds_deque_index_exists(deque, index)) {
107 ds_deque_remove(deque, index, NULL);
108 }
109 }
110
111 static int php_ds_deque_count_elements
112 #if PHP_VERSION_ID >= 80000
113 (zend_object *obj, zend_long *count) {
114 *count = php_ds_deque_fetch_object(obj)->deque->size;
115 #else
116 (zval *obj, zend_long *count) {
117 *count = Z_DS_DEQUE_P(obj)->size;
118 #endif
119 return SUCCESS;
120 }
121
122 static void php_ds_deque_free_object(zend_object *object)
123 {
124 php_ds_deque_t *obj = php_ds_deque_fetch_object(object);
125 ds_deque_free(obj->deque);
126 zend_object_std_dtor(&obj->std);
127 }
128
129 static HashTable *php_ds_deque_get_debug_info
130 #if PHP_VERSION_ID >= 80000
131 (zend_object *obj, int *is_temp) {
132 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
133 #else
134 (zval *obj, int *is_temp) {
135 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
136 #endif
137 zval arr;
138 *is_temp = 1;
139 ds_deque_to_array(deque, &arr);
140 return Z_ARRVAL(arr);
141 }
142
143 static zend_object *php_ds_deque_clone_obj
144 #if PHP_VERSION_ID >= 80000
145 (zend_object *obj) {
146 return php_ds_deque_create_clone(php_ds_deque_fetch_object(obj)->deque);
147 #else
148 (zval *obj) {
149 return php_ds_deque_create_clone(Z_DS_DEQUE_P(obj));
150 #endif
151 }
152
153 static HashTable *php_ds_deque_get_gc
154 #if PHP_VERSION_ID >= 80000
155 (zend_object *obj, zval **gc_data, int *gc_count) {
156 ds_deque_t *deque = php_ds_deque_fetch_object(obj)->deque;
157 #else
158 (zval *obj, zval **gc_data, int *gc_count) {
159 ds_deque_t *deque = Z_DS_DEQUE_P(obj);
160 #endif
161 *gc_data = deque->buffer;
162 *gc_count = (int) (deque->head == 0 ? deque->size : deque->capacity);
163
164 return NULL;
165 }
166
167 void php_ds_register_deque_handlers()
168 {
169 memcpy(&php_deque_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
170
171 php_deque_handlers.offset = XtOffsetOf(php_ds_deque_t, std);
172
173 php_deque_handlers.dtor_obj = zend_objects_destroy_object;
174 php_deque_handlers.free_obj = php_ds_deque_free_object;
175 php_deque_handlers.get_gc = php_ds_deque_get_gc;
176 php_deque_handlers.cast_object = php_ds_default_cast_object;
177 php_deque_handlers.clone_obj = php_ds_deque_clone_obj;
178 php_deque_handlers.get_debug_info = php_ds_deque_get_debug_info;
179 php_deque_handlers.count_elements = php_ds_deque_count_elements;
180 php_deque_handlers.read_dimension = php_ds_deque_read_dimension;
181 php_deque_handlers.write_dimension = php_ds_deque_write_dimension;
182 php_deque_handlers.has_dimension = php_ds_deque_has_dimension;
183 php_deque_handlers.unset_dimension = php_ds_deque_unset_dimension;
184 }
185