X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=src%2Fphp_propro_api.c;h=631f707c3a9a77d9944c77240851a0df6ff4489e;hb=c5b306a3e265073a7d05a039e0470b8281c45f58;hp=108cdbb6e255414c1de0e69d5a991b2194ce08b5;hpb=107ea2284072f3f2bf9ea568ad82c047f8206963;p=m6w6%2Fext-propro diff --git a/src/php_propro_api.c b/src/php_propro_api.c index 108cdbb..631f707 100644 --- a/src/php_propro_api.c +++ b/src/php_propro_api.c @@ -20,21 +20,20 @@ #include "php_propro_api.h" -#define DEBUG_PROPRO 1 +#define DEBUG_PROPRO 0 static inline php_property_proxy_object_t *get_propro(zval *object); -static zval *get_parent_proxied_value(zval *object, zval *return_value); -static zval *get_proxied_value(zval *object, zval *return_value); -static void set_proxied_value(zval *object, zval *value); +static inline zval *get_proxied_value(zval *object, zval *return_value); +static inline void set_proxied_value(zval *object, zval *value); + static zval *read_dimension(zval *object, zval *offset, int type, zval *return_value); -static ZEND_RESULT_CODE cast_proxied_value(zval *object, zval *return_value, int type); -static void write_dimension(zval *object, zval *offset, zval *value); +static ZEND_RESULT_CODE cast_obj(zval *object, zval *return_value, int type); +static void write_dimension(zval *object, zval *offset, zval *input_value); #if DEBUG_PROPRO /* we do not really care about TS when debugging */ static int level = 1; -static const char space[] = " "; -static const char *inoutstr[] = {"< return","="," > enter"}; +static const char *inoutstr[] = {"< return","= "," > enter "}; static const char *types[] = { "UNDEF", "NULL", @@ -48,7 +47,7 @@ static const char *types[] = { "resource", "reference", "constant", - "constant AST", + "const AST", "_BOOL", "callable", "indirect", @@ -56,36 +55,69 @@ static const char *types[] = { "pointer" }; -static void _walk(php_property_proxy_object_t *obj) +static const char *_type(zval *zv) +{ + switch (Z_TYPE_P(zv)) { + case IS_OBJECT: + if (zv->value.obj->ce == php_property_proxy_get_class_entry()) { + return "PROPRO"; + } + /* no break */ + default: + return types[Z_TYPE_P(zv)]; + } +} + +static int _walk(php_property_proxy_object_t *obj) { + int p = 0; + if (obj) { if (!Z_ISUNDEF(obj->parent)) { - _walk(get_propro(&obj->parent)); + p += _walk(get_propro(&obj->parent)); } if (obj->proxy) { - fprintf(stderr, ".%s", obj->proxy->member->val); + p += fprintf(stderr, ".%s", obj->proxy->member->val); } } + + return p; } +static inline zval *get_container(zval *object, zval *tmp); +static inline zval *get_container_value(zval *container, zend_string *member, zval *return_value); + static void debug_propro(int inout, const char *f, php_property_proxy_object_t *obj, php_property_proxy_t *proxy, zval *offset, zval *value) { + int width; + zval tmp, *container = &tmp; + if (!proxy && obj) { proxy = obj->proxy; } - fprintf(stderr, "#PP %p (%p) %s %s %s ", - proxy, - proxy->container.value.counted, - &space[sizeof(space)-level], - inoutstr[inout+1], f); + fprintf(stderr, "#PP %14p %*c %s %s\t", proxy, level, ' ', inoutstr[inout + 1], f); level += inout; - _walk(obj); + if (proxy) { + ZVAL_UNDEF(&tmp); + if (!obj) { + container = &proxy->container; + } else if (Z_ISUNDEF(obj->parent)) { + container = &obj->proxy->container; + } + fprintf(stderr, " container= %-14p < %-10s rc=%-2d%s> ", + Z_REFCOUNTED_P(container) ? Z_COUNTED_P(container) : NULL, + _type(container), + Z_REFCOUNTED_P(container) ? Z_REFCOUNT_P(container) : 0, + Z_ISREF_P(container) ? "(ref) ":"(noref)"); + } + + width = _walk(obj); if (*f++=='d' && *f++=='i' @@ -99,21 +131,22 @@ static void debug_propro(int inout, const char *f, offset_str = Z_STRVAL_P(o); } - fprintf(stderr, ".%s", offset_str); + width += fprintf(stderr, ".%s", offset_str); if (o && o != offset) { zval_ptr_dtor(o); } } if (value) { + fprintf(stderr, "%.*s", 32-width, " "); if (Z_ISUNDEF_P(value)) { fprintf(stderr, " = UNDEF"); } else { - fprintf(stderr, " = (%s", types[Z_TYPE_P(value)&0xf]); - if (Z_REFCOUNTED_P(value)) { - fprintf(stderr, " rc=%u is_ref=%d", Z_REFCOUNT_P(value), Z_ISREF_P(value)); - } - fprintf(stderr, ") "); + fprintf(stderr, " = %-14p < %-10s rc=%-2d%s> ", + Z_REFCOUNTED_P(value) ? Z_COUNTED_P(value) : NULL, + _type(value), + Z_REFCOUNTED_P(value) ? Z_REFCOUNT_P(value) : 0, + Z_ISREF_P(value) ? "(ref) " : "(noref)"); if (!Z_ISUNDEF_P(value) && Z_TYPE_P(value) != IS_INDIRECT) { zend_print_flat_zval_r(value TSRMLS_CC); } @@ -135,15 +168,12 @@ php_property_proxy_t *php_property_proxy_init(zval *container, zend_string *memb ZVAL_STR_COPY(&offset, member); #endif - debug_propro(1, "init", NULL, proxy, &offset, container); - - ZVAL_COPY(&proxy->container, container); - if (Z_TYPE_P(container) == IS_ARRAY) { - HT_ALLOW_COW_VIOLATION(Z_ARRVAL_P(container)); + if (container) { + ZVAL_COPY(&proxy->container, container); } proxy->member = zend_string_copy(member); - debug_propro(-1, "init", NULL, proxy, &offset, container); + debug_propro(0, "init", NULL, proxy, &offset, NULL); #if DEBUG_PROPRO zval_dtor(&offset); @@ -155,25 +185,23 @@ php_property_proxy_t *php_property_proxy_init(zval *container, zend_string *memb void php_property_proxy_free(php_property_proxy_t **proxy) { #if DEBUG_PROPRO - php_property_proxy_t *proxy_ptr = *proxy; zval offset; - ZVAL_STR_COPY(&offset, proxy_ptr->member); + ZVAL_STR_COPY(&offset, (*proxy)->member); + debug_propro(0, "free", NULL, *proxy, &offset, NULL); #endif - debug_propro(1, "dtor", NULL, *proxy, &offset, NULL); - if (*proxy) { - debug_propro(0, "dtor", NULL, *proxy, &offset, &(*proxy)->container); - - zval_ptr_dtor(&(*proxy)->container); + if (!Z_ISUNDEF((*proxy)->container)) { + zval_ptr_dtor(&(*proxy)->container); + ZVAL_UNDEF(&(*proxy)->container); + } zend_string_release((*proxy)->member); + (*proxy)->member = NULL; efree(*proxy); *proxy = NULL; } - debug_propro(-1, "dtor", NULL, proxy_ptr, &offset, NULL); - #if DEBUG_PROPRO zval_dtor(&offset); #endif @@ -227,164 +255,233 @@ static void destroy_obj(zend_object *object) static inline php_property_proxy_object_t *get_propro(zval *object) { - switch (Z_TYPE_P(object)) { - case IS_OBJECT: - break; + ZEND_ASSERT(Z_TYPE_P(object) == IS_OBJECT); + return PHP_PROPRO_PTR(Z_OBJ_P(object)); +} - EMPTY_SWITCH_DEFAULT_CASE(); +static HashTable *get_gc(zval *object, zval **table, int *n) +{ + php_property_proxy_object_t *o = get_propro(object); + + if (Z_ISUNDEF(o->parent)) { + *table = &o->proxy->container; + } else { + *table = &o->parent; } - return PHP_PROPRO_PTR(Z_OBJ_P(object)); + *n = 1; + return NULL; } -static inline zend_bool got_value(zval *container, zval *value) +static HashTable *get_debug_info(zval *object, int *is_temp) { - zval identical; + HashTable *ht; + zval *zmember; + php_property_proxy_object_t *obj = get_propro(object); - if (!Z_ISUNDEF_P(value)) { - if (SUCCESS == is_identical_function(&identical, value, container)) { - if (Z_TYPE(identical) != IS_TRUE) { - return 1; - } - } + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, 3, NULL, NULL, 0); + + if (Z_ISUNDEF(obj->parent)) { + zend_hash_str_add_empty_element(ht, "parent", sizeof("parent")-1); + zend_hash_str_add(ht, "container", sizeof("container")-1, &obj->proxy->container); + } else { + zend_hash_str_add(ht, "parent", sizeof("parent")-1, &obj->parent); + zend_hash_str_add_empty_element(ht, "container", sizeof("container")-1); } - return 0; + zmember = zend_hash_str_add_empty_element(ht, "member", sizeof("member")-1); + ZVAL_STR(zmember, obj->proxy->member); + + *is_temp = 1; + return ht; } -static zval *get_parent_proxied_value(zval *object, zval *return_value) +static ZEND_RESULT_CODE cast_obj(zval *object, zval *return_value, int type) { - php_property_proxy_object_t *obj; + zval tmp; - obj = get_propro(object); - debug_propro(1, "parent_get", obj, NULL, NULL, NULL); + ZVAL_UNDEF(&tmp); + RETVAL_ZVAL(get_proxied_value(object, &tmp), 1, 0); - if (obj->proxy) { - if (!Z_ISUNDEF(obj->parent)) { - get_proxied_value(&obj->parent, return_value); - } + debug_propro(0, "cast", get_propro(object), NULL, NULL, return_value); + + if (!Z_ISUNDEF_P(return_value)) { + ZVAL_DEREF(return_value); + convert_to_explicit_type_ex(return_value, type); + return SUCCESS; } - debug_propro(-1, "parent_get", obj, NULL, NULL, return_value); + return FAILURE; +} + +static zval *get_obj(zval *object, zval *return_value) +{ + zval tmp; + ZVAL_UNDEF(&tmp); + RETVAL_ZVAL(get_proxied_value(object, &tmp), 1, 0); return return_value; } -static zval *get_proxied_value(zval *object, zval *return_value) +static void set_obj(zval *object, zval *value) { + set_proxied_value(object, value); +} + +static inline zval *get_container(zval *object, zval *tmp) { - php_property_proxy_object_t *obj; + php_property_proxy_object_t *obj = get_propro(object); + zval *container; - obj = get_propro(object); - debug_propro(1, "get", obj, NULL, NULL, NULL); + if (Z_ISUNDEF(obj->parent)) { + container = &obj->proxy->container; + } else { + container = get_proxied_value(&obj->parent, tmp); + } + return container; +} - if (obj->proxy) { - zval parent_value, *ref, *found_value = NULL, prop_tmp; +static inline void set_container(zval *object, zval *container) +{ + php_property_proxy_object_t *obj = get_propro(object); - ZVAL_UNDEF(&parent_value); - if (!Z_ISUNDEF(obj->parent)) { - get_parent_proxied_value(object, &parent_value); - ref = &parent_value; - } + if (Z_ISUNDEF(obj->parent)) { + if (container != &obj->proxy->container) { + zval tmp; - if (Z_ISUNDEF(parent_value)) { - ref = &obj->proxy->container; - } else { - zval_ptr_dtor(&obj->proxy->container); - ZVAL_COPY(&obj->proxy->container, &parent_value); + ZVAL_COPY_VALUE(&tmp, &obj->proxy->container); + ZVAL_COPY(&obj->proxy->container, container); + zval_ptr_dtor(&tmp); } + } else { + set_proxied_value(&obj->parent, container); + } +} - ZVAL_DEREF(ref); +static inline zval *get_container_value(zval *container, zend_string *member, zval *return_value) +{ + zval *found_value = NULL, prop_tmp; - switch (Z_TYPE_P(ref)) { - case IS_OBJECT: - found_value = zend_read_property(Z_OBJCE_P(ref), ref, - obj->proxy->member->val, obj->proxy->member->len, 0, - &prop_tmp); + ZVAL_DEREF(container); + switch (Z_TYPE_P(container)) { + case IS_OBJECT: + ZVAL_UNDEF(&prop_tmp); + found_value = zend_read_property(Z_OBJCE_P(container), container, + member->val, member->len, 0, &prop_tmp); + break; - break; + case IS_ARRAY: + found_value = zend_symtable_find(Z_ARRVAL_P(container), member); + break; + } - case IS_ARRAY: - found_value = zend_symtable_find(Z_ARRVAL_P(ref), obj->proxy->member); - break; - } + if (found_value) { + RETVAL_ZVAL(found_value, 0, 0); + } - if (found_value) { - RETVAL_ZVAL(found_value, 1, 0); - } + return return_value; +} - if (!Z_ISUNDEF(obj->parent)) { - zval_ptr_dtor(&parent_value); - } +static inline void cleanup_container(zval *object, zval *container, zend_bool separated) +{ + if (separated) { + zval_ptr_dtor(container); } +} - debug_propro(-1, "get", obj, NULL, NULL, return_value); +static inline zend_bool separate_container(zval *object, zval *container) +{ + switch (Z_TYPE_P(container)) { + case IS_OBJECT: + return 0; - return return_value; + case IS_ARRAY: + /* always duplicate for PHP-7.0 and 7.1 on travis */ + ZVAL_ARR(container, zend_array_dup(Z_ARRVAL_P(container))); + break; + + case IS_UNDEF: + array_init(container); + break; + + default: + SEPARATE_ZVAL(container); + Z_TRY_ADDREF_P(container); + convert_to_array(container); + break; + } + + return 1; } -static ZEND_RESULT_CODE cast_proxied_value(zval *object, zval *return_value, - int type) +static inline zval *set_container_value(zval *container, zend_string *member, zval *value) { - get_proxied_value(object, return_value); + ZVAL_DEREF(container); + switch (Z_TYPE_P(container)) { + case IS_OBJECT: + zend_update_property(Z_OBJCE_P(container), container, + member->val, member->len, value); + break; - debug_propro(0, "cast", get_propro(object), NULL, NULL, return_value); + case IS_ARRAY: + Z_TRY_ADDREF_P(value); + if (member) { + value = zend_symtable_update(Z_ARRVAL_P(container), member, value); + } else { + value = zend_hash_next_index_insert(Z_ARRVAL_P(container), value); + } + break; - if (!Z_ISUNDEF_P(return_value)) { - convert_to_explicit_type_ex(return_value, type); - return SUCCESS; + default: + ZEND_ASSERT(0); + break; } - return FAILURE; + return value; } -static void set_proxied_value(zval *object, zval *value) + +static zval *get_proxied_value(zval *object, zval *return_value) { - zval parent_value, *ref = NULL; - php_property_proxy_object_t *obj; + php_property_proxy_object_t *obj = get_propro(object); - obj = get_propro(object); - debug_propro(1, "set", obj, NULL, NULL, value); + debug_propro(1, "get", obj, NULL, NULL, NULL); if (obj->proxy) { - ZVAL_UNDEF(&parent_value); - if (!Z_ISUNDEF(obj->parent)) { - get_parent_proxied_value(object, &parent_value); - ref = &parent_value; - } - if (Z_ISUNDEF(parent_value)) { - ref = &obj->proxy->container; - } else { - zval_ptr_dtor(&obj->proxy->container); - ZVAL_COPY(&obj->proxy->container, &parent_value); - } + zval tmp, *container; - ZVAL_DEREF(ref); + ZVAL_UNDEF(&tmp); + container = get_container(object, &tmp); - switch (Z_TYPE_P(ref)) { - case IS_OBJECT: - zend_update_property(Z_OBJCE_P(ref), ref, - obj->proxy->member->val, obj->proxy->member->len, value); - break; + return_value = get_container_value(container, obj->proxy->member, return_value); + } - case IS_ARRAY: - Z_TRY_ADDREF_P(value); - zend_symtable_update(Z_ARRVAL_P(ref), obj->proxy->member, value); - break; + debug_propro(-1, "get", obj, NULL, NULL, return_value); - default: -#if DEBUG_PROPRO - fprintf(stderr, "set_proxied_value: %d: %s\n", - Z_TYPE_P(ref), - types[Z_TYPE_P(ref)]); -#endif - ZEND_ASSERT(0); - } + return return_value; +} - debug_propro(0, "set", obj, NULL, NULL, ref); +static void set_proxied_value(zval *object, zval *value) +{ + php_property_proxy_object_t *obj = get_propro(object); - if (!Z_ISUNDEF(obj->parent)) { - set_proxied_value(&obj->parent, ref); - zval_ptr_dtor(&parent_value); - } + debug_propro(1, "set", obj, NULL, NULL, value); + + if (obj->proxy) { + zval tmp, *container; + zend_bool separated; + + Z_TRY_ADDREF_P(value); + + ZVAL_UNDEF(&tmp); + container = get_container(object, &tmp); + separated = separate_container(object, container); + set_container_value(container, obj->proxy->member, value); + set_container(object, container); + cleanup_container(object, container, separated); + + Z_TRY_DELREF_P(value); + + debug_propro(0, "set", obj, NULL, NULL, value); } debug_propro(-1, "set", obj, NULL, NULL, value); @@ -392,57 +489,54 @@ static void set_proxied_value(zval *object, zval *value) static zval *read_dimension(zval *object, zval *offset, int type, zval *return_value) { - zval proxied_value; + zval *value, tmp; zend_string *member = offset ? zval_get_string(offset) : NULL; - debug_propro(1, type == BP_VAR_R ? "dim_read" : "dim_read_ref", + debug_propro(1, type == BP_VAR_R ? "dim_r" : "dim_R", get_propro(object), NULL, offset, NULL); - ZVAL_UNDEF(&proxied_value); - get_proxied_value(object, &proxied_value); + ZVAL_UNDEF(&tmp); + value = get_proxied_value(object, &tmp); - if (BP_VAR_R == type && member && !Z_ISUNDEF(proxied_value)) { - if (Z_TYPE(proxied_value) == IS_ARRAY) { - zval *hash_value; + if (type == BP_VAR_R || type == BP_VAR_IS) { + ZEND_ASSERT(member); - hash_value = zend_symtable_find(Z_ARRVAL(proxied_value), member); + if (!Z_ISUNDEF_P(value)) { + zval tmp; - if (hash_value) { - RETVAL_ZVAL(hash_value, 1, 0); - } + ZVAL_UNDEF(&tmp); + RETVAL_ZVAL(get_container_value(value, member, &tmp), 1, 0); } } else { php_property_proxy_t *proxy; php_property_proxy_object_t *proxy_obj; - if (!Z_ISUNDEF(proxied_value)) { - SEPARATE_ZVAL(&proxied_value); - convert_to_array(&proxied_value); - } else { - array_init(&proxied_value); + if (Z_ISUNDEF_P(value)) { + ZVAL_NULL(value); } - set_proxied_value(object, &proxied_value); - if (!member) { - member = zend_long_to_str(zend_hash_next_free_element( - Z_ARRVAL_P(Z_REFVAL(proxied_value)))); + if (Z_TYPE_P(value) == IS_ARRAY) { + member = zend_long_to_str(zend_hash_next_free_element( + Z_ARRVAL_P(value))); + } else if (Z_TYPE_P(value) != IS_OBJECT){ + member = zend_long_to_str(0); + } } - proxy = php_property_proxy_init(&proxied_value, member); - + proxy = php_property_proxy_init(NULL, member); proxy_obj = php_property_proxy_object_new_ex(NULL, proxy); ZVAL_COPY(&proxy_obj->parent, object); RETVAL_OBJ(&proxy_obj->zo); + + debug_propro(0, "dim_R pp", get_propro(object), NULL, offset, return_value); } if (member) { zend_string_release(member); } - zval_ptr_dtor(&proxied_value); - - debug_propro(-1, type == BP_VAR_R ? "dim_read" : "dim_read_ref", + debug_propro(-1, type == BP_VAR_R ? "dim_r" : "dim_R", get_propro(object), NULL, offset, return_value); return return_value; @@ -450,25 +544,22 @@ static zval *read_dimension(zval *object, zval *offset, int type, zval *return_v static int has_dimension(zval *object, zval *offset, int check_empty) { - zval proxied_value; + zval *value, tmp; int exists = 0; - debug_propro(1, "dim_exists", get_propro(object), NULL, offset, NULL); + debug_propro(1, "dim_e", get_propro(object), NULL, offset, NULL); - ZVAL_UNDEF(&proxied_value); - get_proxied_value(object, &proxied_value); + ZVAL_UNDEF(&tmp); + value = get_proxied_value(object, &tmp); - if (Z_ISUNDEF(proxied_value)) { - exists = 0; - } else { + if (!Z_ISUNDEF_P(value)) { zend_string *zs = zval_get_string(offset); - if (Z_TYPE(proxied_value) == IS_ARRAY) { - zval *zentry = zend_symtable_find(Z_ARRVAL(proxied_value), zs); + ZVAL_DEREF(value); + if (Z_TYPE_P(value) == IS_ARRAY) { + zval *zentry = zend_symtable_find(Z_ARRVAL_P(value), zs); - if (!zentry) { - exists = 0; - } else { + if (zentry) { if (check_empty) { exists = !Z_ISNULL_P(zentry); } else { @@ -480,104 +571,88 @@ static int has_dimension(zval *object, zval *offset, int check_empty) zend_string_release(zs); } - zval_ptr_dtor(&proxied_value); - - debug_propro(-1, "dim_exists", get_propro(object), NULL, offset, NULL); + debug_propro(-1, "dim_e", get_propro(object), NULL, offset, NULL); return exists; } -static void write_dimension(zval *object, zval *offset, zval *value) +static void write_dimension(zval *object, zval *offset, zval *input_value) { - zval proxied_value; - - debug_propro(1, "dim_write", get_propro(object), NULL, offset, value); + zval *array, tmp; + zend_string *zs = NULL; + zend_bool separated; - ZVAL_UNDEF(&proxied_value); - get_proxied_value(object, &proxied_value); + debug_propro(1, "dim_w", get_propro(object), NULL, offset, input_value); - if (!Z_ISUNDEF(proxied_value)) { - if (Z_TYPE(proxied_value) == IS_ARRAY) { - SEPARATE_ZVAL(&proxied_value); - } else { - convert_to_array(&proxied_value); - } - } else { - array_init(&proxied_value); + if (offset) { + zs = zval_get_string(offset); } - Z_TRY_ADDREF_P(value); + ZVAL_UNDEF(&tmp); + array = get_proxied_value(object, &tmp); + separated = separate_container(object, array); + set_container_value(array, zs, input_value); + set_proxied_value(object, array); + cleanup_container(object, array, separated); - HT_ALLOW_COW_VIOLATION(Z_ARRVAL(proxied_value)); - if (offset) { - zend_string *zs = zval_get_string(offset); - zend_symtable_update(Z_ARRVAL(proxied_value), zs, value); + if (zs) { zend_string_release(zs); - } else { - zend_hash_next_index_insert(Z_ARRVAL(proxied_value), value); } - set_proxied_value(object, &proxied_value); - - zval_ptr_dtor(&proxied_value); - - debug_propro(-1, "dim_write", get_propro(object), NULL, offset, &proxied_value); + debug_propro(-1, "dim_w", get_propro(object), NULL, offset, input_value); } static void unset_dimension(zval *object, zval *offset) { - zval proxied_value; + zval *array, *value, tmp; - debug_propro(1, "dim_unset", get_propro(object), NULL, offset, NULL); + debug_propro(1, "dim_u", get_propro(object), NULL, offset, NULL); - ZVAL_UNDEF(&proxied_value); - get_proxied_value(object, &proxied_value); + ZVAL_UNDEF(&tmp); + value = get_proxied_value(object, &tmp); + array = value; + ZVAL_DEREF(array); - if (Z_TYPE(proxied_value) == IS_ARRAY) { + if (Z_TYPE_P(array) == IS_ARRAY) { zend_string *o = zval_get_string(offset); - SEPARATE_ZVAL(&proxied_value); + SEPARATE_ARRAY(array); + zend_symtable_del(Z_ARRVAL_P(array), o); - zend_symtable_del(Z_ARRVAL(proxied_value), o); - set_proxied_value(object, &proxied_value); + set_proxied_value(object, value); zend_string_release(o); } - zval_ptr_dtor(&proxied_value); - - debug_propro(-1, "dim_unset", get_propro(object), NULL, offset, &proxied_value); + debug_propro(-1, "dim_u", get_propro(object), NULL, offset, NULL); } ZEND_BEGIN_ARG_INFO_EX(ai_propro_construct, 0, 0, 2) - ZEND_ARG_INFO(1, object) + ZEND_ARG_INFO(0, object) ZEND_ARG_INFO(0, member) ZEND_ARG_OBJ_INFO(0, parent, php\\PropertyProxy, 1) ZEND_END_ARG_INFO(); static PHP_METHOD(propro, __construct) { zend_error_handling zeh; - zval *container, *parent = NULL; + zval *reference, *parent = NULL; zend_string *member; zend_replace_error_handling(EH_THROW, NULL, &zeh); - if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z/S|O!", - &container, &member, &parent, + if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "o!S|O!", + &reference, &member, &parent, php_property_proxy_class_entry)) { php_property_proxy_object_t *obj; - switch (Z_TYPE_P(container)) { - case IS_OBJECT: - case IS_ARRAY: - break; - default: - convert_to_array(container); - } - obj = get_propro(getThis()); - obj->proxy = php_property_proxy_init(container, member); if (parent) { ZVAL_COPY(&obj->parent, parent); + obj->proxy = php_property_proxy_init(NULL, member); + } else if (reference) { + zval *container = reference; + obj->proxy = php_property_proxy_init(container, member); + } else { + php_error(E_WARNING, "Either object or parent must be set"); } } zend_restore_error_handling(&zeh); @@ -602,9 +677,11 @@ static PHP_MINIT_FUNCTION(propro) sizeof(zend_object_handlers)); php_property_proxy_object_handlers.offset = XtOffsetOf(php_property_proxy_object_t, zo); php_property_proxy_object_handlers.free_obj = destroy_obj; - php_property_proxy_object_handlers.set = set_proxied_value; - php_property_proxy_object_handlers.get = get_proxied_value; - php_property_proxy_object_handlers.cast_object = cast_proxied_value; + php_property_proxy_object_handlers.get_gc = get_gc; + php_property_proxy_object_handlers.get_debug_info = get_debug_info; + php_property_proxy_object_handlers.set = set_obj; + php_property_proxy_object_handlers.get = get_obj; + php_property_proxy_object_handlers.cast_object = cast_obj; php_property_proxy_object_handlers.read_dimension = read_dimension; php_property_proxy_object_handlers.write_dimension = write_dimension; php_property_proxy_object_handlers.has_dimension = has_dimension;