update travis/pecl
[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 #ifdef GC_ADDREF
47 GC_ADDREF(cb->fci.object);
48 #else
49 ++GC_REFCOUNT(cb->fci.object);
50 #endif
51 }
52 }
53
54 zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp)
55 {
56 php_pq_callback_addref(cb);
57
58 if (cb->fci.object) {
59 zval zo;
60
61 array_init_size(tmp, 2);
62 ZVAL_OBJ(&zo, cb->fci.object);
63 add_next_index_zval(tmp, &zo);
64 add_next_index_zval(tmp, &cb->fci.function_name);
65
66 return tmp;
67 }
68
69 return &cb->fci.function_name;
70 }
71
72 zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp)
73 {
74 if (cb->fci.object) {
75 zval zo;
76
77 array_init_size(tmp, 2);
78 ZVAL_OBJ(&zo, cb->fci.object);
79 add_next_index_zval(tmp, &zo);
80 add_next_index_zval(tmp, &cb->fci.function_name);
81
82 return tmp;
83 }
84
85 return &cb->fci.function_name;
86 }
87
88 zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb)
89 {
90 /* TODO: fixed in php7?
91 if (php_pq_callback_is_enabled(cb)) {
92 const zend_function *closure;
93 const zend_execute_data *ex;
94
95 if (Z_TYPE_P(cb->fci.function_name) != IS_OBJECT) {
96 return 0;
97 }
98
99 closure = zend_get_closure_method_def(cb->fci.function_name);
100 if (closure->type != ZEND_USER_FUNCTION) {
101 return 0;
102 }
103
104 for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
105 if (ex->op_array == &closure->op_array) {
106 return 1;
107 }
108 }
109 }
110 if (!php_pq_callback_is_recurrent(cb)) {
111 return 0;
112 }
113 return php_pq_callback_is_locked(cb->recursion);
114 */
115 return 0;
116 }
117
118 void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new)
119 {
120 if (php_pq_callback_is_locked(old)) {
121 php_pq_callback_recurse_ex(old, new);
122 } else {
123 php_pq_callback_dtor(old);
124 if (php_pq_callback_is_enabled(new)) {
125 php_pq_callback_addref(new);
126 memcpy(old, new, sizeof(*old));
127 new->fci.size = 0;
128 }
129 }
130 }
131
132 extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb)
133 {
134 return cb && cb->fci.size > 0;
135 }
136
137 extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb)
138 {
139 return cb && cb->recursion != NULL;
140 }
141
142 extern void php_pq_callback_disable(php_pq_callback_t *cb)
143 {
144 if (php_pq_callback_is_enabled(cb)) {
145 php_pq_callback_recurse_ex(cb, NULL);
146 }
147 }
148
149 extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new)
150 {
151 php_pq_callback_t *tmp = emalloc(sizeof(*tmp));
152
153 if (new) {
154 memcpy(tmp, old, sizeof(*tmp));
155 memcpy(old, new, sizeof(*old));
156 old->recursion = tmp;
157
158 php_pq_callback_addref(old);
159 php_pq_callback_disable(tmp);
160 } else {
161 memcpy(tmp, old, sizeof(*tmp));
162 memset(old, 0, sizeof(*old));
163 old->recursion = tmp;
164 }
165 }
166
167 /*
168 * Local variables:
169 * tab-width: 4
170 * c-basic-offset: 4
171 * End:
172 * vim600: noet sw=4 ts=4 fdm=marker
173 * vim<600: noet sw=4 ts=4
174 */