2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2012 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 +----------------------------------------------------------------------+
26 #include <ext/standard/info.h>
28 #include "php_propro.h"
32 PHP_PROPRO_API php_property_proxy_t
*php_property_proxy_init(zval
*container
, const char *member_str
, size_t member_len TSRMLS_DC
)
34 php_property_proxy_t
*proxy
= ecalloc(1, sizeof(*proxy
));
36 Z_ADDREF_P(container
);
37 proxy
->container
= container
;
38 proxy
->member_str
= estrndup(member_str
, member_len
);
39 proxy
->member_len
= member_len
;
44 PHP_PROPRO_API
void php_property_proxy_free(php_property_proxy_t
**proxy
)
47 zval_ptr_dtor(&(*proxy
)->container
);
48 efree((*proxy
)->member_str
);
54 static zend_class_entry
*php_property_proxy_class_entry
;
55 static zend_object_handlers php_property_proxy_object_handlers
;
57 PHP_PROPRO_API zend_class_entry
*php_property_proxy_get_class_entry(void)
59 return php_property_proxy_class_entry
;
62 PHP_PROPRO_API zend_object_value
php_property_proxy_object_new(zend_class_entry
*ce TSRMLS_DC
)
64 return php_property_proxy_object_new_ex(ce
, NULL
, NULL TSRMLS_CC
);
67 static void php_property_proxy_object_free(void *object TSRMLS_DC
)
69 php_property_proxy_object_t
*o
= object
;
72 php_property_proxy_free(&o
->proxy
);
75 zend_objects_store_del_ref_by_handle_ex(o
->parent
->zv
.handle
, o
->parent
->zv
.handlers TSRMLS_CC
);
78 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
82 PHP_PROPRO_API zend_object_value
php_property_proxy_object_new_ex(zend_class_entry
*ce
, php_property_proxy_t
*proxy
, php_property_proxy_object_t
**ptr TSRMLS_DC
)
84 php_property_proxy_object_t
*o
;
86 o
= ecalloc(1, sizeof(*o
));
87 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
88 object_properties_init((zend_object
*) o
, ce
);
95 o
->zv
.handle
= zend_objects_store_put(o
, NULL
, php_property_proxy_object_free
, NULL TSRMLS_CC
);
96 o
->zv
.handlers
= &php_property_proxy_object_handlers
;
101 static zval
*get_proxied_value(zval
*object TSRMLS_DC
);
102 static zval
*read_dimension(zval
*object
, zval
*offset
, int type TSRMLS_DC
);
103 static STATUS
cast_proxied_value(zval
*object
, zval
*return_value
, int type TSRMLS_DC
);
104 static void write_dimension(zval
*object
, zval
*offset
, zval
*value TSRMLS_DC
);
105 static void set_proxied_value(zval
**object
, zval
*value TSRMLS_DC
);
107 static zval
*get_proxied_value(zval
*object TSRMLS_DC
)
109 zval
**hash_value
, *value
= NULL
;
110 php_property_proxy_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
113 switch (Z_TYPE_P(obj
->proxy
->container
)) {
115 value
= zend_read_property(Z_OBJCE_P(obj
->proxy
->container
), obj
->proxy
->container
, obj
->proxy
->member_str
, obj
->proxy
->member_len
, 0 TSRMLS_CC
);
119 if (SUCCESS
== zend_hash_find(Z_ARRVAL_P(obj
->proxy
->container
), obj
->proxy
->member_str
, obj
->proxy
->member_len
+ 1, (void *) &hash_value
)) {
129 static STATUS
cast_proxied_value(zval
*object
, zval
*return_value
, int type TSRMLS_DC
)
133 if ((proxied_value
= get_proxied_value(object TSRMLS_CC
))) {
134 RETVAL_ZVAL(proxied_value
, 1, 0);
135 if (Z_TYPE_P(proxied_value
) != type
) {
136 convert_to_explicit_type(return_value
, type
);
144 static void set_proxied_value(zval
**object
, zval
*value TSRMLS_DC
)
146 php_property_proxy_object_t
*obj
= zend_object_store_get_object(*object TSRMLS_CC
);
149 switch (Z_TYPE_P(obj
->proxy
->container
)) {
151 zend_update_property(Z_OBJCE_P(obj
->proxy
->container
), obj
->proxy
->container
, obj
->proxy
->member_str
, obj
->proxy
->member_len
, value TSRMLS_CC
);
156 zend_symtable_update(Z_ARRVAL_P(obj
->proxy
->container
), obj
->proxy
->member_str
, obj
->proxy
->member_len
+ 1, (void *) &value
, sizeof(zval
*), NULL
);
162 MAKE_STD_ZVAL(zparent
);
163 zparent
->type
= IS_OBJECT
;
164 zparent
->value
.obj
= obj
->parent
->zv
;
165 set_proxied_value(&zparent
, obj
->proxy
->container TSRMLS_CC
);
170 static zval
*read_dimension(zval
*object
, zval
*offset
, int type TSRMLS_DC
)
175 if ((proxied_value
= get_proxied_value(object TSRMLS_CC
))) {
178 convert_to_string_ex(&o
);
180 if (Z_TYPE_P(proxied_value
) == IS_ARRAY
) {
182 if (SUCCESS
== zend_symtable_find(Z_ARRVAL_P(proxied_value
), Z_STRVAL_P(o
), Z_STRLEN_P(o
), (void *) &hash_value
)) {
183 Z_ADDREF_PP(hash_value
);
191 SEPARATE_ZVAL(&proxied_value
);
192 convert_to_array(proxied_value
);
194 MAKE_STD_ZVAL(value
);
196 zend_symtable_update(Z_ARRVAL_P(proxied_value
), Z_STRVAL_P(o
), Z_STRLEN_P(o
) + 1, (void *) &value
, sizeof(zval
*), (void *) &hash_value
);
198 Z_SET_ISREF_P(value
);
200 set_proxied_value(&object
, proxied_value TSRMLS_CC
);
211 static void write_dimension(zval
*object
, zval
*offset
, zval
*value TSRMLS_DC
)
215 if ((proxied_value
= get_proxied_value(object TSRMLS_CC
))) {
218 SEPARATE_ZVAL(&proxied_value
);
219 convert_to_array(proxied_value
);
221 if (Z_REFCOUNT_P(value
) > 1) {
222 SEPARATE_ZVAL(&value
);
227 convert_to_string_ex(&o
);
228 zend_symtable_update(Z_ARRVAL_P(proxied_value
), Z_STRVAL_P(o
), Z_STRLEN_P(o
) + 1, (void *) &value
, sizeof(zval
*), NULL
);
230 zend_hash_next_index_insert(Z_ARRVAL_P(proxied_value
), (void *) &value
, sizeof(zval
*), NULL
);
237 set_proxied_value(&object
, proxied_value TSRMLS_CC
);
241 ZEND_BEGIN_ARG_INFO_EX(ai_propro_construct
, 0, 0, 2)
242 ZEND_ARG_INFO(0, object
)
243 ZEND_ARG_INFO(0, member
)
244 ZEND_ARG_OBJ_INFO(0, parent
, php
\\PropertyProxy
, 1)
246 static PHP_METHOD(propro
, __construct
) {
247 zend_error_handling zeh
;
248 zval
*container
, *parent
= NULL
;
252 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
253 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "zs|O!", &container
, &member_str
, &member_len
, &parent
, php_property_proxy_class_entry
)) {
254 php_property_proxy_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
256 obj
->proxy
= php_property_proxy_init(container
, member_str
, member_len TSRMLS_CC
);
258 zend_objects_store_add_ref(parent TSRMLS_CC
);
259 obj
->parent
= zend_object_store_get_object(parent TSRMLS_CC
);
262 zend_restore_error_handling(&zeh TSRMLS_CC
);
265 static const zend_function_entry php_property_proxy_method_entry
[] = {
266 PHP_ME(propro
, __construct
, ai_propro_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
270 static PHP_MINIT_FUNCTION(propro
)
272 zend_class_entry ce
= {0};
274 INIT_NS_CLASS_ENTRY(ce
, "php", "PropertyProxy", php_property_proxy_method_entry
);
275 php_property_proxy_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
276 php_property_proxy_class_entry
->create_object
= php_property_proxy_object_new
;
277 php_property_proxy_class_entry
->ce_flags
|= ZEND_ACC_FINAL_CLASS
;
279 memcpy(&php_property_proxy_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
280 php_property_proxy_object_handlers
.set
= set_proxied_value
;
281 php_property_proxy_object_handlers
.get
= get_proxied_value
;
282 php_property_proxy_object_handlers
.cast_object
= cast_proxied_value
;
283 php_property_proxy_object_handlers
.read_dimension
= read_dimension
;
284 php_property_proxy_object_handlers
.write_dimension
= write_dimension
;
289 PHP_MINFO_FUNCTION(propro
)
291 php_info_print_table_start();
292 php_info_print_table_header(2, "Property proxy support", "enabled");
293 php_info_print_table_row(2, "Extension version", PHP_PROPRO_VERSION
);
294 php_info_print_table_end();
297 static const zend_function_entry propro_functions
[] = {
301 zend_module_entry propro_module_entry
= {
302 STANDARD_MODULE_HEADER
,
311 STANDARD_MODULE_PROPERTIES
314 #ifdef COMPILE_DL_PROPRO
315 ZEND_GET_MODULE(propro
)
324 * vim600: noet sw=4 ts=4 fdm=marker
325 * vim<600: noet sw=4 ts=4