Merge branch 'feature/cursor-async' of https://github.com/DaveRandom/pecl-database-pq
[m6w6/ext-pq] / src / php_pq_object.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
19 #include "php_pq_object.h"
20
21 void php_pq_object_to_zval(void *o, zval **zv TSRMLS_DC)
22 {
23 php_pq_object_t *obj = o;
24
25 if (!*zv) {
26 MAKE_STD_ZVAL(*zv);
27 }
28
29 zend_objects_store_add_ref_by_handle(obj->zv.handle TSRMLS_CC);
30
31 (*zv)->type = IS_OBJECT;
32 (*zv)->value.obj = obj->zv;
33 }
34
35 void php_pq_object_to_zval_no_addref(void *o, zval **zv TSRMLS_DC)
36 {
37 php_pq_object_t *obj = o;
38
39 if (!*zv) {
40 MAKE_STD_ZVAL(*zv);
41 }
42
43 /* no add ref */
44
45 (*zv)->type = IS_OBJECT;
46 (*zv)->value.obj = obj->zv;
47 }
48
49 void php_pq_object_addref(void *o TSRMLS_DC)
50 {
51 php_pq_object_t *obj = o;
52 zend_objects_store_add_ref_by_handle(obj->zv.handle TSRMLS_CC);
53 }
54
55 void php_pq_object_delref(void *o TSRMLS_DC)
56 {
57 php_pq_object_t *obj = o;
58 zend_objects_store_del_ref_by_handle_ex(obj->zv.handle, obj->zv.handlers TSRMLS_CC);
59 }
60
61 struct apply_pi_to_ht_arg {
62 HashTable *ht;
63 zval *object;
64 php_pq_object_t *pq_obj;
65 unsigned addref:1;
66 };
67
68 static int apply_pi_to_ht(void *p, void *a TSRMLS_DC)
69 {
70 zend_property_info *pi = p;
71 struct apply_pi_to_ht_arg *arg = a;
72 zval *property = zend_read_property(arg->pq_obj->zo.ce, arg->object, pi->name, pi->name_length, 0 TSRMLS_CC);
73
74 if (arg->addref) {
75 Z_ADDREF_P(property);
76 }
77 zend_hash_update(arg->ht, pi->name, pi->name_length + 1, (void *) &property, sizeof(zval *), NULL);
78
79 return ZEND_HASH_APPLY_KEEP;
80 }
81
82 HashTable *php_pq_object_debug_info(zval *object, int *temp TSRMLS_DC)
83 {
84 struct apply_pi_to_ht_arg arg = {NULL};
85
86 *temp = 1;
87 ALLOC_HASHTABLE(arg.ht);
88 ZEND_INIT_SYMTABLE(arg.ht);
89
90 arg.object = object;
91 arg.pq_obj = zend_object_store_get_object(object TSRMLS_CC);
92 arg.addref = 1;
93
94 zend_hash_apply_with_argument(&arg.pq_obj->zo.ce->properties_info, apply_pi_to_ht, &arg TSRMLS_CC);
95
96 return arg.ht;
97 }
98
99 HashTable *php_pq_object_properties(zval *object TSRMLS_DC)
100 {
101 struct apply_pi_to_ht_arg arg = {NULL};
102
103 arg.ht = zend_get_std_object_handlers()->get_properties(object TSRMLS_CC);
104 arg.object = object;
105 arg.pq_obj = zend_object_store_get_object(object TSRMLS_CC);
106 arg.addref = 1;
107
108 zend_hash_apply_with_argument(&arg.pq_obj->zo.ce->properties_info, apply_pi_to_ht, &arg TSRMLS_CC);
109
110 return arg.ht;
111 }
112
113 zend_class_entry *ancestor(zend_class_entry *ce)
114 {
115 while (ce->parent) {
116 ce = ce->parent;
117 }
118 return ce;
119 }
120
121 zval *php_pq_object_read_prop(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
122 {
123 php_pq_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
124 php_pq_object_prophandler_t *handler;
125 zval *return_value = NULL;
126
127 if (!obj->intern) {
128 php_error(E_RECOVERABLE_ERROR, "%s not initialized", ancestor(obj->zo.ce)->name);
129 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
130 } else if ((SUCCESS != zend_hash_find(obj->prophandler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) || !handler->read) {
131 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
132 } else if (type != BP_VAR_R) {
133 php_error(E_WARNING, "Cannot access %s properties by reference or array key/index", ancestor(obj->zo.ce)->name);
134 return_value = zend_get_std_object_handlers()->read_property(object, member, type, key TSRMLS_CC);
135 } else {
136 ALLOC_ZVAL(return_value);
137 Z_SET_REFCOUNT_P(return_value, 0);
138 Z_UNSET_ISREF_P(return_value);
139
140 handler->read(object, obj, return_value TSRMLS_CC);
141 }
142
143 return return_value;
144 }
145
146 void php_pq_object_write_prop(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC)
147 {
148 php_pq_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
149 php_pq_object_prophandler_t *handler;
150
151 if (!obj->intern) {
152 php_error(E_RECOVERABLE_ERROR, "%s not initialized", ancestor(obj->zo.ce)->name);
153 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
154 } else if (SUCCESS == zend_hash_find(obj->prophandler, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
155 if (handler->write) {
156 handler->write(object, obj, value TSRMLS_CC);
157 }
158 } else {
159 zend_get_std_object_handlers()->write_property(object, member, value, key TSRMLS_CC);
160 }
161 }
162