6b0213f8ac5ed744ce58c4a685d419bcb5fd5149
[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 zend_objects_store_del(cb->fci.object);
34 }
35 cb->fci.size = 0;
36 }
37 }
38
39 void php_pq_callback_addref(php_pq_callback_t *cb)
40 {
41 Z_TRY_ADDREF(cb->fci.function_name);
42 if (cb->fci.object) {
43 ++GC_REFCOUNT(cb->fci.object);
44 }
45 }
46
47 zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp)
48 {
49 php_pq_callback_addref(cb);
50
51 if (cb->fci.object) {
52 zval zo;
53
54 array_init_size(tmp, 2);
55 ZVAL_OBJ(&zo, cb->fci.object);
56 add_next_index_zval(tmp, &zo);
57 add_next_index_zval(tmp, &cb->fci.function_name);
58
59 return tmp;
60 }
61
62 return &cb->fci.function_name;
63 }
64
65 zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb)
66 {
67 /* TODO: fixed in php7?
68 if (cb->fci.size > 0 && Z_TYPE_P(cb->fci.function_name) == IS_OBJECT) {
69 const zend_function *closure = zend_get_closure_method_def(cb->fci.function_name);
70
71 if (closure->type == ZEND_USER_FUNCTION) {
72 zend_execute_data *ex = EG(current_execute_data);
73
74 while (ex) {
75 if (ex->op_array == &closure->op_array) {
76 return 1;
77 }
78 ex = ex->prev_execute_data;
79 }
80 }
81 }
82 */
83 return 0;
84 }
85
86 void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
87 {
88 if (new && new->fci.size > 0 && php_pq_callback_is_locked(old TSRMLS_CC)) {
89 new->recursion = emalloc(sizeof(*old));
90 memcpy(new->recursion, old, sizeof(*old));
91 } else if (new && new->fci.size > 0) {
92 php_pq_callback_dtor(old);
93 php_pq_callback_addref(new);
94 memcpy(old, new, sizeof(*old));
95 new->fci.size = 0;
96 } else {
97 php_pq_callback_dtor(old);
98 }
99 }
100
101 /*
102 * Local variables:
103 * tab-width: 4
104 * c-basic-offset: 4
105 * End:
106 * vim600: noet sw=4 ts=4 fdm=marker
107 * vim<600: noet sw=4 ts=4
108 */