1 #include "../handlers/php_pair_handlers.h"
2 #include "../classes/php_pair_ce.h"
3 #include "php_pair.h"
4 
5 zend_object *php_ds_pair_create_object(zend_class_entry *ce)
6 {
7     php_ds_pair_t *obj = ecalloc(1, sizeof(php_ds_pair_t) + zend_object_properties_size(ce));
8     zend_object_std_init(&obj->std, php_ds_pair_ce);
9     object_properties_init(&obj->std, php_ds_pair_ce);
10     obj->std.handlers = &php_pair_handlers;
11 
12     return &obj->std;
13 }
14 
15 php_ds_pair_t *php_ds_pair()
16 {
17     return (php_ds_pair_t*) php_ds_pair_create_object(php_ds_pair_ce);
18 }
19 
20 php_ds_pair_t *php_ds_pair_ex(zval *key, zval *value)
21 {
22     php_ds_pair_t *obj = php_ds_pair();
23 
24     php_ds_pair_set_key(obj, key);
25     php_ds_pair_set_value(obj, value);
26 
27     return obj;
28 }
29 
30 zend_object *php_ds_pair_create_clone(php_ds_pair_t *obj)
31 {
32     zval *key = php_ds_pair_get_key(obj);
33     zval *val = php_ds_pair_get_value(obj);
34 
35     return (zend_object *) php_ds_pair_ex(key, val);
36 }
37 
38 void php_ds_pair_set_key(php_ds_pair_t *pair, zval *key)
39 {
40 #if PHP_VERSION_ID >= 80000
41     zend_update_property(php_ds_pair_ce, (zend_object*) pair, STR_AND_LEN("key"), key);
42 #else
43     zval tmp;
44     ZVAL_DS_PAIR(&tmp, pair);
45     zend_update_property(php_ds_pair_ce, &tmp, STR_AND_LEN("key"), key);
46 #endif
47 }
48 
49 void php_ds_pair_set_value(php_ds_pair_t *pair, zval *value)
50 {
51 #if PHP_VERSION_ID >= 80000
52     zend_update_property(php_ds_pair_ce, (zend_object*) pair, STR_AND_LEN("value"), value);
53 #else
54     zval tmp;
55     ZVAL_DS_PAIR(&tmp, pair);
56     zend_update_property(php_ds_pair_ce, &tmp, STR_AND_LEN("value"), value);
57 #endif
58 }
59 
60 zval *php_ds_pair_get_key(php_ds_pair_t *pair)
61 {
62     zval rv;
63 #if PHP_VERSION_ID >= 80000
64     return zend_read_property(php_ds_pair_ce, (zend_object*) pair, STR_AND_LEN("key"), false, &rv);
65 #else
66     zval tmp;
67     ZVAL_DS_PAIR(&tmp, pair);
68     return zend_read_property(php_ds_pair_ce, &tmp, STR_AND_LEN("key"), false, &rv);
69 #endif
70 }
71 
72 zval *php_ds_pair_get_value(php_ds_pair_t *pair)
73 {
74     zval rv;
75 #if PHP_VERSION_ID >= 80000
76     return zend_read_property(php_ds_pair_ce, (zend_object*) pair, STR_AND_LEN("value"), false, &rv);
77 #else
78     zval tmp;
79     ZVAL_DS_PAIR(&tmp, pair);
80     return zend_read_property(php_ds_pair_ce, &tmp, STR_AND_LEN("value"), false, &rv);
81 #endif
82 }
83 
84 void php_ds_pair_to_array(php_ds_pair_t *obj, zval *result)
85 {
86     zval *key = php_ds_pair_get_key(obj);
87     zval *val = php_ds_pair_get_value(obj);
88 
89     array_init_size(result, 2);
90 
91     add_assoc_zval(result, "key", key);
92     add_assoc_zval(result, "value", val);
93 
94     Z_TRY_ADDREF_P(key);
95     Z_TRY_ADDREF_P(val);
96 }
97 
98 int php_ds_pair_serialize(zval *object, unsigned char **buffer, size_t *length, zend_serialize_data *data)
99 {
100     zval *key, *val;
101     smart_str buf = {0};
102 
103     php_ds_pair_t *pair = Z_DS_PAIR_P(object);
104 
105     php_serialize_data_t serialize_data = (php_serialize_data_t) data;
106     PHP_VAR_SERIALIZE_INIT(serialize_data);
107 
108     key = php_ds_pair_get_key(pair);
109     val = php_ds_pair_get_value(pair);
110 
111     php_var_serialize(&buf, key, &serialize_data);
112     php_var_serialize(&buf, val, &serialize_data);
113 
114     smart_str_0(&buf);
115     SERIALIZE_SET_ZSTR(buf.s);
116     zend_string_release(buf.s);
117 
118     PHP_VAR_SERIALIZE_DESTROY(serialize_data);
119     return SUCCESS;
120 }
121 
122 int php_ds_pair_unserialize(zval *object, zend_class_entry *ce, const unsigned char *buffer, size_t length, zend_unserialize_data *data)
123 {
124     zval *key, *value;
125     php_unserialize_data_t unserialize_data = (php_unserialize_data_t) data;
126 
127     const unsigned char *pos = buffer;
128     const unsigned char *max = buffer + length;
129 
130     PHP_VAR_UNSERIALIZE_INIT(unserialize_data);
131 
132     key = var_tmp_var(&unserialize_data);
133     if ( ! php_var_unserialize(key, &pos, max, &unserialize_data)) {
134         goto error;
135     }
136 
137     value = var_tmp_var(&unserialize_data);
138     if ( ! php_var_unserialize(value, &pos, max, &unserialize_data)) {
139         goto error;
140     }
141 
142     ZVAL_DS_PAIR(object, php_ds_pair_ex(key, value));
143     PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data);
144     return SUCCESS;
145 
146 error:
147     PHP_VAR_UNSERIALIZE_DESTROY(unserialize_data);
148     UNSERIALIZE_ERROR();
149     return FAILURE;
150 }
151