1 #include "php_common_handlers.h"
2 #include "php_vector_handlers.h"
3
4 #include "../objects/php_vector.h"
5 #include "../../ds/ds_vector.h"
6
7 zend_object_handlers php_vector_handlers;
8
php_ds_vector_read_dimension(zend_object * obj,zval * offset,int type,zval * return_value)9 static zval *php_ds_vector_read_dimension
10 #if PHP_VERSION_ID >= 80000
11 (zend_object *obj, zval *offset, int type, zval *return_value) {
12 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
13 #else
14 (zval *obj, zval *offset, int type, zval *return_value) {
15 ds_vector_t *vector = Z_DS_VECTOR_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_vector_isset(vector, 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_vector_get(vector, 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_vector_write_dimension
48 #if PHP_VERSION_ID >= 80000
49 (zend_object *obj, zval *offset, zval *value) {
50 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
51 #else
52 (zval *obj, zval *offset, zval *value) {
53 ds_vector_t *vector = Z_DS_VECTOR_P(obj);
54 #endif
55 if (offset == NULL) { /* $v[] = ... */
56 ds_vector_push(vector, 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_vector_set(vector, Z_LVAL_P(offset), value);
65 }
66 }
67 }
68
69 static int php_ds_vector_has_dimension
70 #if PHP_VERSION_ID >= 80000
71 (zend_object *obj, zval *offset, int check_empty) {
72 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
73 #else
74 (zval *obj, zval *offset, int check_empty) {
75 ds_vector_t *vector = Z_DS_VECTOR_P(obj);
76 #endif
77 if (Z_TYPE_P(offset) != IS_LONG) {
78 return 0;
79 }
80 ZVAL_DEREF(offset);
81
82 return ds_vector_isset(vector, Z_LVAL_P(offset), check_empty);
83 }
84
85 static void php_ds_vector_unset_dimension
86 #if PHP_VERSION_ID >= 80000
87 (zend_object *obj, zval *offset) {
88 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
89 #else
90 (zval *obj, zval *offset) {
91 ds_vector_t *vector = Z_DS_VECTOR_P(obj);
92 #endif
93 zend_long index = 0;
94 ZVAL_DEREF(offset);
95
96 if (Z_TYPE_P(offset) == IS_LONG) {
97 index = Z_LVAL_P(offset);
98
99 } else {
100 if (zend_parse_parameter(ZEND_PARSE_PARAMS_QUIET, 1, offset, "l", &index) == FAILURE) {
101 return;
102 }
103 }
104
105 if (ds_vector_index_exists(vector, index)) { // to avoid OutOfBounds
106 ds_vector_remove(vector, index, NULL);
107 }
108 }
109
110 static int php_ds_vector_count_elements
111 #if PHP_VERSION_ID >= 80000
112 (zend_object *obj, zend_long *count) {
113 *count = php_ds_vector_fetch_object(obj)->vector->size; return SUCCESS;
114 #else
115 (zval *obj, zend_long *count) {
116 *count = Z_DS_VECTOR_P(obj)->size; return SUCCESS;
117 #endif
118 }
119
120 static void php_ds_vector_free_object(zend_object *obj)
121 {
122 php_ds_vector_t *vector = php_ds_vector_fetch_object(obj);
123 ds_vector_free(vector->vector);
124 zend_object_std_dtor(&vector->std);
125 }
126
127 static HashTable *php_ds_vector_get_debug_info
128 #if PHP_VERSION_ID >= 80000
129 (zend_object *obj, int *is_temp) {
130 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
131 #else
132 (zval *obj, int *is_temp) {
133 ds_vector_t *vector = Z_DS_VECTOR_P(obj);
134 #endif
135 zval arr;
136 *is_temp = 1;
137 ds_vector_to_array(vector, &arr);
138 return Z_ARRVAL(arr);
139 }
140
141 static zend_object *php_ds_vector_clone_obj
142 #if PHP_VERSION_ID >= 80000
143 (zend_object *obj) {
144 return php_ds_vector_create_clone(php_ds_vector_fetch_object(obj)->vector);
145 #else
146 (zval *obj) {
147 return php_ds_vector_create_clone(Z_DS_VECTOR_P(obj));
148 #endif
149 }
150
151 static HashTable *php_ds_vector_get_gc
152 #if PHP_VERSION_ID >= 80000
153 (zend_object *obj, zval **gc_data, int *gc_count) {
154 ds_vector_t *vector = php_ds_vector_fetch_object(obj)->vector;
155 #else
156 (zval *obj, zval **gc_data, int *gc_count) {
157 ds_vector_t *vector = Z_DS_VECTOR_P(obj);
158 #endif
159 *gc_data = vector->buffer;
160 *gc_count = (int) vector->size;
161
162 return NULL;
163 }
164
165 void php_register_vector_handlers()
166 {
167 memcpy(&php_vector_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
168
169 php_vector_handlers.offset = XtOffsetOf(php_ds_vector_t, std);
170
171 php_vector_handlers.dtor_obj = zend_objects_destroy_object;
172 php_vector_handlers.free_obj = php_ds_vector_free_object;
173 php_vector_handlers.get_gc = php_ds_vector_get_gc;
174 php_vector_handlers.clone_obj = php_ds_vector_clone_obj;
175 php_vector_handlers.cast_object = php_ds_default_cast_object;
176 php_vector_handlers.get_debug_info = php_ds_vector_get_debug_info;
177 php_vector_handlers.count_elements = php_ds_vector_count_elements;
178 php_vector_handlers.read_dimension = php_ds_vector_read_dimension;
179 php_vector_handlers.write_dimension = php_ds_vector_write_dimension;
180 php_vector_handlers.has_dimension = php_ds_vector_has_dimension;
181 php_vector_handlers.unset_dimension = php_ds_vector_unset_dimension;
182 }
183