cvs: php4 /ext/overload overload.c
| From: | Andrei Zmievski | Date: | Sun, 09 Dec 2001 04:28:24 +0000 |
| Subject: | cvs: php4 /ext/overload overload.c | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-8528@lists.php.net to get a copy of this message | ||
andrei Sat Dec 8 23:28:24 2001 EDT
Modified files:
/php4/ext/overload overload.c
Log:
- Only destroy the current object if it was received from the __get() handler.
- Changed the way method arguments are passed to __call() handler. They are
now encapsulated inside of an array, which makes it easier to pass them
to call_user_func_array().
Index: php4/ext/overload/overload.c
diff -u php4/ext/overload/overload.c:1.7 php4/ext/overload/overload.c:1.8
--- php4/ext/overload/overload.c:1.7 Fri Dec 7 17:03:19 2001
+++ php4/ext/overload/overload.c Sat Dec 8 23:28:23 2001
@@ -130,6 +130,14 @@
(ce).handle_property_set = NULL; \
(ce).handle_function_call = NULL;
+/*
+ * In all three handlers, we save the original CE of the object, and replace it
+ * with a temporary one that has all handlers turned off. This is to avoid
+ * recursive calls to our handlers. We can't simply set a handler to NULL on the
+ * original CE, as that would disable overloading on other objects of the same
+ * class. After invoking the callback we restore the object's CE.
+ */
+
/* {{{ int call_get_handler() */
static int call_get_handler(zval *object, zval *prop_name, zval **prop_value TSRMLS_DC)
{
@@ -141,13 +149,6 @@
zval *retval = NULL;
oo_class_data oo_data;
- /*
- * Save original CE of the object, and make it use a temporary one
- * that has all handlers turned off. This is to avoid recursive
- * calls to overload_property_get. We can't just change
- * handle_property_get to NULL on the original CE, as that would
- * disable overloading on other objects of the same class.
- */
temp_ce = *Z_OBJCE_P(object);
DISABLE_HANDLERS(temp_ce);
orig_ce = Z_OBJCE_P(object);
@@ -167,7 +168,6 @@
&retval,
2, args,
0, NULL TSRMLS_CC);
- /* Restore object's original CE. */
Z_OBJCE_P(object) = orig_ce;
if (call_result == FAILURE || !retval) {
@@ -210,13 +210,6 @@
zval *retval = NULL;
oo_class_data oo_data;
- /*
- * Save original CE of the object, and make it use a temporary one
- * that has all handlers turned off. This is to avoid recursive
- * calls to overload_property_set. We can't just change
- * handle_property_set to NULL on the original CE, as that would
- * disable overloading on other objects of the same class.
- */
temp_ce = *Z_OBJCE_P(object);
DISABLE_HANDLERS(temp_ce);
orig_ce = Z_OBJCE_P(object);
@@ -238,7 +231,6 @@
&retval,
2, args,
0, NULL TSRMLS_CC);
- /* Restore object's original CE. */
Z_OBJCE_P(object) = orig_ce;
if (call_result == FAILURE || !retval) {
@@ -297,7 +289,8 @@
/* Trying to access a property on a non-object. */
if (Z_TYPE(object) != IS_OBJECT) {
CLEANUP_OO_CHAIN();
- zval_dtor(&object);
+ if (got_prop)
+ zval_dtor(&object);
return result;
}
@@ -316,14 +309,16 @@
} else {
php_error(E_NOTICE, "Undefined property: %s",
Z_STRVAL(overloaded_property->element));
CLEANUP_OO_CHAIN();
- zval_dtor(&object);
+ if (got_prop)
+ zval_dtor(&object);
return result;
}
} else if (Z_TYPE_P(overloaded_property) == OE_IS_ARRAY) {
/* Trying to access index on a non-array. */
if (Z_TYPE(object) != IS_ARRAY) {
CLEANUP_OO_CHAIN();
- zval_dtor(&object);
+ if (got_prop)
+ zval_dtor(&object);
return result;
}
@@ -333,7 +328,8 @@
Z_STRLEN(overloaded_property->element)+1,
(void **)&real_prop) == FAILURE) {
CLEANUP_OO_CHAIN();
- zval_dtor(&object);
+ if (got_prop)
+ zval_dtor(&object);
return result;
}
} else if (Z_TYPE(overloaded_property->element) == IS_LONG) {
@@ -341,7 +337,8 @@
Z_LVAL(overloaded_property->element),
(void **)&real_prop) == FAILURE) {
CLEANUP_OO_CHAIN();
- zval_dtor(&object);
+ if (got_prop)
+ zval_dtor(&object);
return result;
}
}
@@ -433,9 +430,8 @@
{
zval ***args;
zval *retval = NULL;
- int call_result, arg_offset = 1;
+ int call_result;
zend_bool use_call_handler = 1;
- zend_class_entry temp_ce, *orig_ce;
zval *object = property_reference->object;
zval call_handler, method_name, *method_name_ptr = &method_name;
zend_overloaded_element *method = (zend_overloaded_element
*)property_reference->elements_list->tail->data;
@@ -444,18 +440,22 @@
Z_STRVAL(method->element),
Z_STRLEN(method->element) + 1)) {
use_call_handler = 0;
- arg_offset = 0;
}
- args = (zval ***)emalloc((ZEND_NUM_ARGS() + arg_offset) * sizeof(zval **));
+ args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **));
- if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), &args[arg_offset]) == FAILURE) {
+ if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
efree(args);
php_error(E_WARNING, "unable to obtain arguments");
return;
}
if (use_call_handler) {
+ zval **handler_args[2];
+ zval *arg_array;
+ zend_class_entry temp_ce, *orig_ce;
+ int i;
+
temp_ce = *Z_OBJCE_P(object);
DISABLE_HANDLERS(temp_ce);
orig_ce = Z_OBJCE_P(object);
@@ -463,32 +463,46 @@
ZVAL_STRINGL(&call_handler, CALL_HANDLER, sizeof(CALL_HANDLER)-1, 0);
ZVAL_STRINGL(&method_name, Z_STRVAL(method->element), Z_STRLEN(method->element), 0);
+ INIT_PZVAL(&call_handler);
INIT_PZVAL(method_name_ptr);
- args[0] = &method_name_ptr;
- } else {
- ZVAL_STRINGL(&call_handler, Z_STRVAL(method->element), Z_STRLEN(method->element), 0);
- }
- INIT_PZVAL(&call_handler);
-
- call_result = call_user_function_ex(NULL,
- &object,
- &call_handler,
- &retval,
- ZEND_NUM_ARGS() + arg_offset, args,
- 0, NULL TSRMLS_CC);
- if (use_call_handler) {
- /* Restore object's original CE. */
+ MAKE_STD_ZVAL(arg_array);
+ array_init(arg_array);
+ for (i = 0; i < ZEND_NUM_ARGS(); i++) {
+ zval_add_ref(args[i]);
+ add_next_index_zval(arg_array, *args[i]);
+ }
+
+ handler_args[0] = &method_name_ptr;
+ handler_args[1] = &arg_array;
+ call_result = call_user_function_ex(NULL,
+ &object,
+ &call_handler,
+ &retval,
+ 2, handler_args,
+ 0, NULL TSRMLS_CC);
Z_OBJCE_P(object) = orig_ce;
- }
+ zval_ptr_dtor(&arg_array);
- if (call_result == FAILURE || !retval) {
- efree(args);
- if (use_call_handler)
- php_error(E_WARNING, "unable to call %s::__call() handler", orig_ce->name);
- else
- php_error(E_WARNING, "unable to call %s::%s() method", orig_ce->name,
Z_STRVAL(method->element));
- return;
+ if (call_result == FAILURE || !retval) {
+ efree(args);
+ php_error(E_WARNING, "unable to call %s::__call() handler",
Z_OBJCE_P(object)->name);
+ return;
+ }
+ } else {
+ ZVAL_STRINGL(&call_handler, Z_STRVAL(method->element), Z_STRLEN(method->element), 0);
+ call_result = call_user_function_ex(NULL,
+ &object,
+ &call_handler,
+ &retval,
+ ZEND_NUM_ARGS(), args,
+ 0, NULL TSRMLS_CC);
+
+ if (call_result == FAILURE || !retval) {
+ efree(args);
+ php_error(E_WARNING, "unable to call %s::%s() method", Z_OBJCE_P(object)->name,
Z_STRVAL(method->element));
+ return;
+ }
}
*return_value = *retval;