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