17d7e70efeff025b9d2e6fb3cd2ed402ea3fbfd7
[m6w6/ext-pq] / src / php_pq_callback.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: pq |
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) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include <php.h>
18 #include <Zend/zend_closures.h>
19
20 #include "php_pq_callback.h"
21
22 void php_pq_callback_dtor(php_pq_callback_t *cb)
23 {
24 if (cb->recursion) {
25 php_pq_callback_dtor(cb->recursion);
26 efree(cb->recursion);
27 cb->recursion = NULL;
28 }
29 if (cb->fci.size > 0) {
30 zend_fcall_info_args_clear(&cb->fci, 1);
31 zval_ptr_dtor(&cb->fci.function_name);
32 if (cb->fci.object) {
33 zval tmp;
34
35 ZVAL_OBJ(&tmp, cb->fci.object);
36 zval_ptr_dtor(&tmp);
37 }
38 cb->fci.size = 0;
39 }
40 }
41
42 void php_pq_callback_addref(php_pq_callback_t *cb)
43 {
44 Z_TRY_ADDREF(cb->fci.function_name);
45 if (cb->fci.object) {
46 ++GC_REFCOUNT(cb->fci.object);
47 }
48 }
49
50 zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp)
51 {
52 php_pq_callback_addref(cb);
53
54 if (cb->fci.object) {
55 zval zo;
56
57 array_init_size(tmp, 2);
58 ZVAL_OBJ(&zo, cb->fci.object);
59 add_next_index_zval(tmp, &zo);
60 add_next_index_zval(tmp, &cb->fci.function_name);
61
62 return tmp;
63 }
64
65 return &cb->fci.function_name;
66 }
67
68 zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp)
69 {
70 if (cb->fci.object) {
71 zval zo;
72
73 array_init_size(tmp, 2);
74 ZVAL_OBJ(&zo, cb->fci.object);
75 add_next_index_zval(tmp, &zo);
76 add_next_index_zval(tmp, &cb->fci.function_name);
77
78 return tmp;
79 }
80
81 return &cb->fci.function_name;
82 }
83
84 zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb)
85 {
86 /* TODO: fixed in php7?
87 if (php_pq_callback_is_enabled(cb)) {
88 const zend_function *closure;
89 const zend_execute_data *ex;
90
91 if (Z_TYPE_P(cb->fci.function_name) != IS_OBJECT) {
92 return 0;
93 }
94
95 closure = zend_get_closure_method_def(cb->fci.function_name);
96 if (closure->type != ZEND_USER_FUNCTION) {
97 return 0;
98 }
99
100 for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
101 if (ex->op_array == &closure->op_array) {
102 return 1;
103 }
104 }
105 }
106 if (!php_pq_callback_is_recurrent(cb)) {
107 return 0;
108 }
109 return php_pq_callback_is_locked(cb->recursion);
110 */
111 return 0;
112 }
113
114 void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new)
115 {
116 if (php_pq_callback_is_locked(old)) {
117 php_pq_callback_recurse_ex(old, new);
118 } else {
119 php_pq_callback_dtor(old);
120 if (php_pq_callback_is_enabled(new)) {
121 php_pq_callback_addref(new);
122 memcpy(old, new, sizeof(*old));
123 new->fci.size = 0;
124 }
125 }
126 }
127
128 extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb)
129 {
130 return cb && cb->fci.size > 0;
131 }
132
133 extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb)
134 {
135 return cb && cb->recursion != NULL;
136 }
137
138 extern void php_pq_callback_disable(php_pq_callback_t *cb)
139 {
140 if (php_pq_callback_is_enabled(cb)) {
141 php_pq_callback_recurse_ex(cb, NULL);
142 }
143 }
144
145 extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new)
146 {
147 php_pq_callback_t *tmp = emalloc(sizeof(*tmp));
148
149 if (new) {
150 memcpy(tmp, old, sizeof(*tmp));
151 memcpy(old, new, sizeof(*old));
152 old->recursion = tmp;
153
154 php_pq_callback_addref(old);
155 php_pq_callback_disable(tmp);
156 } else {
157 memcpy(tmp, old, sizeof(*tmp));
158 memset(old, 0, sizeof(*old));
159 old->recursion = tmp;
160 }
161 }
162
163 /*
164 * Local variables:
165 * tab-width: 4
166 * c-basic-offset: 4
167 * End:
168 * vim600: noet sw=4 ts=4 fdm=marker
169 * vim<600: noet sw=4 ts=4
170 */