Re[2]: [PHP-DEV] Re: hook cast_object handler in userspace
| From: | (Marcus B�rger) | Date: | Sat, 09 Aug 2003 21:55:50 +0000 |
| Subject: | Re[2]: [PHP-DEV] Re: hook cast_object handler in userspace | ||
| References: | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-3841@lists.php.net to get a copy of this message | ||
Hello Cristiano,
Saturday, August 9, 2003, 10:48:22 PM, you wrote:
CD> Hello Marcus,
CD> Did you think of a better interface name instead of "Printable" ?
CD> Do you think Zeev or Andi will accept this patch ?
I guess they won't like it and i would agree. I'd like to see something that
hooks into the object cast handler as i've done in the attached patch.
Besides the "to string" thing i think the cast method should return an int
value [SUCCESS,FAILURE] indicating whether the cast function could handle the
required cast operation and the fallback should be used if either no cast
function is available or FAILURE is returned.
Note: At the moment i used a solution without any interface. However an
additional check for a dedicated interface wouldn't be to bad. I'd like to
name it 'cast_string'. Also the whole thing wouldn't work on overloaded
objects with different cast functions.
--
Best regards,
Marcus mailto:helly@php.net
Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.243 diff -u -p -d -r1.243 zend.c --- Zend/zend.c 30 Jul 2003 16:13:52 -0000 1.243 +++ Zend/zend.c 9 Aug 2003 21:44:17 -0000 @@ -226,11 +226,12 @@ ZEND_API void zend_make_printable_zval(z case IS_OBJECT: if (expr->value.obj.handlers->cast_object) { TSRMLS_FETCH(); - expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC); - } else { - expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); - expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); + if (expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { + break; + } } + expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); + expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); #if 0 /* FIXME: This might break BC for some people */ expr_copy->value.str.len = sizeof("Object")-1; Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.63 diff -u -p -d -r1.63 zend_object_handlers.c --- Zend/zend_object_handlers.c 3 Aug 2003 17:40:44 -0000 1.63 +++ Zend/zend_object_handlers.c 9 Aug 2003 21:44:19 -0000 @@ -867,6 +867,30 @@ int zend_std_object_get_class_name(zval return SUCCESS; } +int zend_std_cast_object(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) +{ + zend_function *cast_method; + zval fname, *retval; + int result = FAILURE; + + switch (type) { + case IS_STRING: + ZVAL_STRING(&fname, "__to_string", 0); + if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) { + if (Z_TYPE_P(retval) != IS_STRING) { + zend_error(E_ERROR, "Method %s::__to_string must return a string value", Z_OBJCE_P(readobj)->name); + } + ZVAL_STRING(writeobj, Z_STRVAL_P(retval), 1); + zval_ptr_dtor(&retval); + result = SUCCESS; + } + break; + default: + break; + } + return result; +} + zend_object_handlers std_object_handlers = { zend_objects_store_add_ref, /* add_ref */ zend_objects_store_del_ref, /* del_ref */ @@ -891,7 +915,7 @@ zend_object_handlers std_object_handlers zend_std_object_get_class, /* get_class_entry */ zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ - NULL, /* cast_object */ + zend_std_cast_object, /* cast_object */ }; /* Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.22 diff -u -p -d -r1.22 zend_object_handlers.h --- Zend/zend_object_handlers.h 30 Jul 2003 17:12:06 -0000 1.22 +++ Zend/zend_object_handlers.h 9 Aug 2003 21:44:20 -0000 @@ -82,7 +82,7 @@ typedef zend_object_value (*zend_object_ typedef zend_class_entry *(*zend_object_get_class_entry_t)(zval *object TSRMLS_DC); typedef int (*zend_object_get_class_name_t)(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC); typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC); -typedef void (*zend_object_cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC); +typedef int (*zend_object_cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC); typedef struct _zend_object_handlers {
Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.243 diff -u -p -d -r1.243 zend.c --- Zend/zend.c 30 Jul 2003 16:13:52 -0000 1.243 +++ Zend/zend.c 9 Aug 2003 21:44:17 -0000 @@ -226,11 +226,12 @@ ZEND_API void zend_make_printable_zval(z case IS_OBJECT: if (expr->value.obj.handlers->cast_object) { TSRMLS_FETCH(); - expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC); - } else { - expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); - expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); + if (expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { + break; + } } + expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); + expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); #if 0 /* FIXME: This might break BC for some people */ expr_copy->value.str.len = sizeof("Object")-1; Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.63 diff -u -p -d -r1.63 zend_object_handlers.c --- Zend/zend_object_handlers.c 3 Aug 2003 17:40:44 -0000 1.63 +++ Zend/zend_object_handlers.c 9 Aug 2003 21:44:19 -0000 @@ -867,6 +867,30 @@ int zend_std_object_get_class_name(zval return SUCCESS; } +int zend_std_cast_object(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) +{ + zend_function *cast_method; + zval fname, *retval; + int result = FAILURE; + + switch (type) { + case IS_STRING: + ZVAL_STRING(&fname, "__to_string", 0); + if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) { + if (Z_TYPE_P(retval) != IS_STRING) { + zend_error(E_ERROR, "Method %s::__to_string must return a string value", Z_OBJCE_P(readobj)->name); + } + ZVAL_STRING(writeobj, Z_STRVAL_P(retval), 1); + zval_ptr_dtor(&retval); + result = SUCCESS; + } + break; + default: + break; + } + return result; +} + zend_object_handlers std_object_handlers = { zend_objects_store_add_ref, /* add_ref */ zend_objects_store_del_ref, /* del_ref */ @@ -891,7 +915,7 @@ zend_object_handlers std_object_handlers zend_std_object_get_class, /* get_class_entry */ zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ - NULL, /* cast_object */ + zend_std_cast_object, /* cast_object */ }; /* Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.22 diff -u -p -d -r1.22 zend_object_handlers.h --- Zend/zend_object_handlers.h 30 Jul 2003 17:12:06 -0000 1.22 +++ Zend/zend_object_handlers.h 9 Aug 2003 21:44:20 -0000 @@ -82,7 +82,7 @@ typedef zend_object_value (*zend_object_ typedef zend_class_entry *(*zend_object_get_class_entry_t)(zval *object TSRMLS_DC); typedef int (*zend_object_get_class_name_t)(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC); typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC); -typedef void (*zend_object_cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC); +typedef int (*zend_object_cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC); typedef struct _zend_object_handlers {