Merge branch 'master' into phpng
[m6w6/ext-raphf] / php_raphf_test.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: raphf |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include <php.h>
14
15 struct user_cb {
16 zend_fcall_info fci;
17 zend_fcall_info_cache fcc;
18 };
19
20 struct raphf_user {
21 struct user_cb ctor;
22 struct user_cb copy;
23 struct user_cb dtor;
24 struct {
25 struct user_cb dtor;
26 zval data;
27 } data;
28 };
29
30 static inline void user_cb_addref(struct user_cb *cb)
31 {
32 Z_ADDREF(cb->fci.function_name);
33 if (cb->fci.object) {
34 Z_ADDREF_P((zval *) cb->fci.object);
35 }
36 }
37
38 static inline void user_cb_delref(struct user_cb *cb)
39 {
40 if (cb->fci.object) {
41 Z_DELREF_P((zval *) cb->fci.object);
42 }
43 }
44
45 static void raphf_user_dtor(void *opaque)
46 {
47 struct raphf_user *ru = opaque;
48
49 zend_fcall_info_argn(&ru->data.dtor.fci, 1, &ru->data.data);
50 zend_fcall_info_call(&ru->data.dtor.fci, &ru->data.dtor.fcc, NULL, NULL);
51 zend_fcall_info_args_clear(&ru->data.dtor.fci, 1);
52 user_cb_delref(&ru->data.dtor);
53 zend_fcall_info_args_clear(&ru->ctor.fci, 1);
54 user_cb_delref(&ru->ctor);
55 zend_fcall_info_args_clear(&ru->copy.fci, 1);
56 user_cb_delref(&ru->copy);
57 zend_fcall_info_args_clear(&ru->dtor.fci, 1);
58 user_cb_delref(&ru->dtor);
59 memset(ru, 0, sizeof(*ru));
60 efree(ru);
61 }
62
63 static void *user_ctor(void *opaque, void *init_arg TSRMLS_DC)
64 {
65 struct raphf_user *ru = opaque;
66 zval *zinit_arg = init_arg, *retval = ecalloc(1, sizeof(*retval));
67
68 zend_fcall_info_argn(&ru->ctor.fci, 2, &ru->data.data, zinit_arg);
69 zend_fcall_info_call(&ru->ctor.fci, &ru->ctor.fcc, retval, NULL);
70 zend_fcall_info_args_clear(&ru->ctor.fci, 0);
71
72 return retval;
73 }
74
75 static void *user_copy(void *opaque, void *handle TSRMLS_DC)
76 {
77 struct raphf_user *ru = opaque;
78 zval *zhandle = handle, *retval = ecalloc(1, sizeof(*retval));
79
80 zend_fcall_info_argn(&ru->copy.fci, 2, &ru->data.data, zhandle);
81 zend_fcall_info_call(&ru->copy.fci, &ru->copy.fcc, retval, NULL);
82 zend_fcall_info_args_clear(&ru->copy.fci, 0);
83
84 return retval;
85 }
86
87 static void user_dtor(void *opaque, void *handle TSRMLS_DC)
88 {
89 struct raphf_user *ru = opaque;
90 zval *zhandle = handle, retval;
91
92 ZVAL_UNDEF(&retval);
93 zend_fcall_info_argn(&ru->dtor.fci, 2, &ru->data.data, zhandle);
94 zend_fcall_info_call(&ru->dtor.fci, &ru->dtor.fcc, &retval, NULL);
95 zend_fcall_info_args_clear(&ru->dtor.fci, 0);
96 if (!Z_ISUNDEF(retval)) {
97 zval_ptr_dtor(&retval);
98 }
99 }
100
101 static php_resource_factory_ops_t user_ops = {
102 user_ctor,
103 user_copy,
104 user_dtor
105 };
106
107 static int raphf_user_le;
108
109 static void raphf_user_res_dtor(zend_resource *res TSRMLS_DC)
110 {
111 php_resource_factory_free((void *) &res->ptr);
112 }
113
114 static PHP_FUNCTION(raphf_provide)
115 {
116 struct raphf_user *ru;
117 char *name_str;
118 size_t name_len;
119 zval *zdata;
120
121 ru = ecalloc(1, sizeof(*ru));
122
123 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sfffzf",
124 &name_str, &name_len,
125 &ru->ctor.fci, &ru->ctor.fcc,
126 &ru->copy.fci, &ru->copy.fcc,
127 &ru->dtor.fci, &ru->dtor.fcc,
128 &zdata,
129 &ru->data.dtor.fci, &ru->data.dtor.fcc)) {
130 efree(ru);
131 return;
132 }
133
134 user_cb_addref(&ru->ctor);
135 user_cb_addref(&ru->copy);
136 user_cb_addref(&ru->dtor);
137 user_cb_addref(&ru->data.dtor);
138
139 ZVAL_COPY(&ru->data.data, zdata);
140
141 if (SUCCESS != php_persistent_handle_provide(name_str, name_len,
142 &user_ops, ru, raphf_user_dtor)) {
143 RETURN_FALSE;
144 }
145 RETURN_TRUE;
146 }
147
148 static PHP_FUNCTION(raphf_conceal)
149 {
150 zend_string *name;
151
152 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &name)) {
153 return;
154 }
155
156 RETURN_BOOL(FAILURE != zend_hash_del(&PHP_RAPHF_G->persistent_handle.hash, name));
157 }
158
159 static PHP_FUNCTION(raphf_concede)
160 {
161 char *name_str, *id_str;
162 size_t name_len, id_len;
163 php_persistent_handle_factory_t *pf;
164 php_resource_factory_t *rf;
165 php_resource_factory_ops_t *ops;
166
167 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss",
168 &name_str, &name_len, &id_str, &id_len)) {
169 return;
170 }
171
172 ops = php_persistent_handle_get_resource_factory_ops();
173 pf = php_persistent_handle_concede(NULL, name_str, name_len, id_str, id_len,
174 NULL, NULL TSRMLS_CC);
175 if (!pf) {
176 php_error_docref(NULL TSRMLS_CC, E_WARNING,
177 "Could not locate persistent handle factory '%s'", name_str);
178 RETURN_FALSE;
179 }
180 rf = php_resource_factory_init(NULL, ops, pf,
181 (void(*)(void*)) php_persistent_handle_abandon);
182 if (!rf) {
183 php_error_docref(NULL TSRMLS_CC, E_WARNING,
184 "Could not create resource factory "
185 "for persistent handle factory '%s'", name_str);
186 RETURN_FALSE;
187 }
188
189 zend_register_resource(return_value, rf, raphf_user_le);
190 }
191
192 static PHP_FUNCTION(raphf_dispute)
193 {
194 zval *zrf;
195
196 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zrf)) {
197 return;
198 }
199
200 RETURN_BOOL(SUCCESS == zend_list_close(Z_RES_P(zrf)));
201 }
202
203 static PHP_FUNCTION(raphf_handle_ctor)
204 {
205 zval *zrf, *zrv, *zinit_arg;
206
207 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
208 &zrf, &zinit_arg)) {
209 return;
210 }
211
212 zrv = php_resource_factory_handle_ctor(Z_RES_VAL_P(zrf), zinit_arg);
213 RETVAL_ZVAL(zrv, 0, 0);
214 efree(zrv);
215 }
216
217 static PHP_FUNCTION(raphf_handle_copy)
218 {
219 zval *zrf, *zrv, *zhandle;
220
221 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
222 &zrf, &zhandle)) {
223 return;
224 }
225
226 zrv = php_resource_factory_handle_copy(Z_RES_VAL_P(zrf), zhandle);
227 RETVAL_ZVAL(zrv, 0, 0);
228 efree(zrv);
229 }
230
231 static PHP_FUNCTION(raphf_handle_dtor)
232 {
233 zval *zrf, *zhandle;
234
235 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz",
236 &zrf, &zhandle)) {
237 return;
238 }
239
240 php_resource_factory_handle_dtor(Z_RES_VAL_P(zrf), zhandle);
241 }
242
243 static PHP_MINIT_FUNCTION(raphf_test)
244 {
245 zend_register_long_constant(ZEND_STRL("RAPHF_TEST"), PHP_RAPHF_TEST, CONST_CS|CONST_PERSISTENT, module_number);
246 raphf_user_le = zend_register_list_destructors_ex(raphf_user_res_dtor, NULL,
247 "raphf_user", module_number);
248 return SUCCESS;
249 }
250
251 static PHP_MSHUTDOWN_FUNCTION(raphf_test)
252 {
253 php_persistent_handle_cleanup(ZEND_STRL("test"), NULL, 0 TSRMLS_CC);
254 return SUCCESS;
255 }
256 /*
257 * Local variables:
258 * tab-width: 4
259 * c-basic-offset: 4
260 * End:
261 * vim600: noet sw=4 ts=4 fdm=marker
262 * vim<600: noet sw=4 ts=4
263 */