rename php_pq_clear_res -> php_pqres_clear
[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_ptr) {
33 zval_ptr_dtor(&cb->fci.object_ptr);
34 }
35 cb->fci.size = 0;
36 }
37 }
38
39 void php_pq_callback_addref(php_pq_callback_t *cb)
40 {
41 Z_ADDREF_P(cb->fci.function_name);
42 if (cb->fci.object_ptr) {
43 Z_ADDREF_P(cb->fci.object_ptr);
44 }
45 }
46
47 zval *php_pq_callback_to_zval(php_pq_callback_t *cb)
48 {
49 zval *zcb;
50
51 php_pq_callback_addref(cb);
52
53 if (cb->fci.object_ptr) {
54 MAKE_STD_ZVAL(zcb);
55 array_init_size(zcb, 2);
56 add_next_index_zval(zcb, cb->fci.object_ptr);
57 add_next_index_zval(zcb, cb->fci.function_name);
58 } else {
59 zcb = cb->fci.function_name;
60 }
61
62 return zcb;
63 }
64
65 zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb TSRMLS_DC)
66 {
67 if (php_pq_callback_is_enabled(cb)) {
68 const zend_function *closure;
69 const zend_execute_data *ex;
70
71 if (Z_TYPE_P(cb->fci.function_name) != IS_OBJECT) {
72 return 0;
73 }
74
75 closure = zend_get_closure_method_def(cb->fci.function_name TSRMLS_CC);
76 if (closure->type != ZEND_USER_FUNCTION) {
77 return 0;
78 }
79
80 for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
81 if (ex->op_array == &closure->op_array) {
82 return 1;
83 }
84 }
85 }
86
87 if (!php_pq_callback_is_recurrent(cb)) {
88 return 0;
89 }
90 return php_pq_callback_is_locked(cb->recursion TSRMLS_CC);
91 }
92
93 void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
94 {
95 if (php_pq_callback_is_locked(old TSRMLS_CC)) {
96 php_pq_callback_recurse_ex(old, new TSRMLS_CC);
97 } else {
98 php_pq_callback_dtor(old);
99 if (php_pq_callback_is_enabled(new)) {
100 php_pq_callback_addref(new);
101 memcpy(old, new, sizeof(*old));
102 new->fci.size = 0;
103 }
104 }
105 }
106
107 extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb)
108 {
109 return cb && cb->fci.size > 0;
110 }
111
112 extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb)
113 {
114 return cb && cb->recursion != NULL;
115 }
116
117 extern void php_pq_callback_disable(php_pq_callback_t *cb TSRMLS_DC)
118 {
119 if (php_pq_callback_is_enabled(cb)) {
120 php_pq_callback_recurse_ex(cb, NULL TSRMLS_CC);
121 }
122 }
123
124 extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
125 {
126 php_pq_callback_t *tmp = emalloc(sizeof(*tmp));
127
128 if (new) {
129 memcpy(tmp, old, sizeof(*tmp));
130 memcpy(old, new, sizeof(*old));
131 old->recursion = tmp;
132
133 php_pq_callback_addref(old);
134 php_pq_callback_disable(tmp TSRMLS_CC);
135 } else {
136 memcpy(tmp, old, sizeof(*tmp));
137 memset(old, 0, sizeof(*old));
138 old->recursion = tmp;
139 }
140 }
141
142 /*
143 * Local variables:
144 * tab-width: 4
145 * c-basic-offset: 4
146 * End:
147 * vim600: noet sw=4 ts=4 fdm=marker
148 * vim<600: noet sw=4 ts=4
149 */