xref: /ext-ds/src/php/handlers/php_map_handlers.c (revision 53b57937)
1 #include "php_map_handlers.h"
2 #include "php_common_handlers.h"
3 #include "../../ds/ds_map.h"
4 #include "../objects/php_map.h"
5 
6 zend_object_handlers php_map_handlers;
7 
php_ds_map_read_dimension(zend_object * obj,zval * offset,int type,zval * rv)8 static zval *php_ds_map_read_dimension
9 #if PHP_VERSION_ID >= 80000
10 (zend_object *obj, zval *offset, int type, zval *rv) {
11     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
12 #else
13 (zval *obj, zval *offset, int type, zval *rv) {
14     ds_map_t *map = Z_DS_MAP_P(obj);
15 #endif
16     if (offset == NULL) {
17         ARRAY_ACCESS_PUSH_NOT_SUPPORTED();
18         return NULL;
19 
20     } else {
21         zval *value;
22 
23         // Dereference the offset if it's a reference.
24         ZVAL_DEREF(offset);
25 
26         // `??`
27         if (type == BP_VAR_IS) {
28             if ( ! ds_htable_isset(map->table, offset, 0)) {
29                 return &EG(uninitialized_zval);;
30             }
31         }
32 
33         // Get the value from the map.
34         value = ds_map_get(map, offset, NULL);
35 
36         // If we're accessing by reference we have to create a reference.
37         // This is for access like $map[$a][$b] = $c
38         if (value && type != BP_VAR_R && type != BP_VAR_IS) {
39             ZVAL_MAKE_REF(value);
40         }
41 
42         return value;
43     }
44 }
45 
46 static void php_ds_map_write_dimension
47 #if PHP_VERSION_ID >= 80000
48 (zend_object *obj, zval *offset, zval *value) {
49     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
50 #else
51 (zval *obj, zval *offset, zval *value) {
52     ds_map_t *map = Z_DS_MAP_P(obj);
53 #endif
54     if (offset == NULL) {
55         ARRAY_ACCESS_PUSH_NOT_SUPPORTED();
56         return;
57     }
58     ZVAL_DEREF(offset);
59     ds_htable_put(map->table, offset, value);
60 }
61 
62 static int php_ds_map_has_dimension
63 #if PHP_VERSION_ID >= 80000
64 (zend_object *obj, zval *offset, int check_empty) {
65     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
66 #else
67 (zval *obj, zval *offset, int check_empty) {
68     ds_map_t *map = Z_DS_MAP_P(obj);
69 #endif
70     ZVAL_DEREF(offset);
71     return ds_htable_isset(map->table, offset, check_empty);
72 }
73 
74 static void php_ds_map_unset_dimension
75 #if PHP_VERSION_ID >= 80000
76 (zend_object *obj, zval *offset) {
77     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
78 #else
79 (zval *obj, zval *offset) {
80     ds_map_t *map = Z_DS_MAP_P(obj);
81 #endif
82     ZVAL_DEREF(offset);
83     ds_htable_remove(map->table, offset, NULL);
84 }
85 
86 static int php_ds_map_count_elements
87 #if PHP_VERSION_ID >= 80000
88 (zend_object *obj, zend_long *count) {
89     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
90 #else
91 (zval *obj, zend_long *count) {
92     ds_map_t *map = Z_DS_MAP_P(obj);
93 #endif
94     *count = DS_MAP_SIZE(map);
95     return SUCCESS;
96 }
97 
98 static void php_ds_map_free_object(zend_object *object)
99 {
100     php_ds_map_t *intern = php_ds_map_fetch_object(object);
101     ds_map_free(intern->map);
102     zend_object_std_dtor(&intern->std);
103 }
104 
105 static HashTable *php_ds_map_get_debug_info
106 #if PHP_VERSION_ID >= 80000
107 (zend_object *obj, int *is_temp) {
108     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
109 #else
110 (zval *obj, int *is_temp) {
111     ds_map_t *map = Z_DS_MAP_P(obj);
112 #endif
113     *is_temp = 1;
114     return ds_map_pairs_to_php_hashtable(map);
115 }
116 
117 static zend_object *php_ds_map_clone_obj
118 #if PHP_VERSION_ID >= 80000
119 (zend_object *obj) {
120     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
121 #else
122 (zval *obj) {
123     ds_map_t *map = Z_DS_MAP_P(obj);
124 #endif
125     return php_ds_map_create_clone(map);
126 }
127 
128 static HashTable *php_ds_map_get_gc
129 #if PHP_VERSION_ID >= 80000
130 (zend_object *obj, zval **gc_data, int *gc_size) {
131     ds_map_t *map = php_ds_map_fetch_object(obj)->map;
132 #else
133 (zval *obj, zval **gc_data, int *gc_size) {
134     ds_map_t *map = Z_DS_MAP_P(obj);
135 #endif
136     if (DS_MAP_IS_EMPTY(map)) {
137         *gc_data  = NULL;
138         *gc_size = 0;
139     } else {
140         *gc_data = (zval*) map->table->buckets;
141         *gc_size = (int)   map->table->next * 2;
142     }
143     return NULL;
144 }
145 
146 void php_ds_register_map_handlers()
147 {
148     memcpy(&php_map_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
149 
150     php_map_handlers.offset             = XtOffsetOf(php_ds_map_t, std);
151     php_map_handlers.dtor_obj           = zend_objects_destroy_object;
152     php_map_handlers.get_gc             = php_ds_map_get_gc;
153     php_map_handlers.free_obj           = php_ds_map_free_object;
154     php_map_handlers.clone_obj          = php_ds_map_clone_obj;
155     php_map_handlers.get_debug_info     = php_ds_map_get_debug_info;
156     php_map_handlers.count_elements     = php_ds_map_count_elements;
157     php_map_handlers.read_dimension     = php_ds_map_read_dimension;
158     php_map_handlers.write_dimension    = php_ds_map_write_dimension;
159     php_map_handlers.has_dimension      = php_ds_map_has_dimension;
160     php_map_handlers.unset_dimension    = php_ds_map_unset_dimension;
161     php_map_handlers.cast_object        = php_ds_default_cast_object;
162 }
163