Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:26042 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 46103 invoked by uid 1010); 12 Oct 2006 21:03:37 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 46087 invoked from network); 12 Oct 2006 21:03:37 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 12 Oct 2006 21:03:37 -0000 Authentication-Results: pb1.pair.com header.from=andrei@gravitonic.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=andrei@gravitonic.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain gravitonic.com from 204.11.219.139 cause and error) X-PHP-List-Original-Sender: andrei@gravitonic.com X-Host-Fingerprint: 204.11.219.139 lerdorf.com Linux 2.5 (sometimes 2.4) (4) Received: from [204.11.219.139] ([204.11.219.139:42978] helo=lerdorf.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D8/E7-22864-8ADAE254 for ; Thu, 12 Oct 2006 17:03:37 -0400 Received: from [172.27.173.217] ([66.194.95.2]) (authenticated bits=0) by lerdorf.com (8.13.8/8.13.8/Debian-2) with ESMTP id k9CL3Wgs002665 for ; Thu, 12 Oct 2006 14:03:32 -0700 Mime-Version: 1.0 (Apple Message framework v752.2) To: PHP Internals Message-ID: <638D2DBE-1C6E-46F4-B1FF-1B3E16F0E889@gravitonic.com> Content-Type: multipart/mixed; boundary=Apple-Mail-1--156306979 Date: Thu, 12 Oct 2006 16:03:23 -0500 X-Mailer: Apple Mail (2.752.2) Subject: cast_object handler patch From: andrei@gravitonic.com (Andrei Zmievski) --Apple-Mail-1--156306979 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed I discovered that using convert_to_(string|unicode)_with_converter() on objects still used runtime encoding instead of the specified converter. Turns out it's because cast_object handler has no clue about the converter passed to the macro. This patch implements a fix via adding an extra generic pointer parameter to cast_object that can be used by various types as necessary. If no one objects, I'll commit the change soon. -Andrei --Apple-Mail-1--156306979 Content-Transfer-Encoding: 7bit Content-Type: text/plain; x-unix-mode=0644; name=cast_object.diff.txt Content-Disposition: attachment; filename=cast_object.diff.txt Index: Zend/zend.c =================================================================== RCS file: /repository/ZendEngine2/zend.c,v retrieving revision 1.376 diff -p -u -r1.376 zend.c --- Zend/zend.c 5 Oct 2006 23:24:55 -0000 1.376 +++ Zend/zend.c 12 Oct 2006 20:58:02 -0000 @@ -315,7 +315,7 @@ ZEND_API void zend_make_string_zval(zval { TSRMLS_FETCH(); - if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) { + if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, NULL TSRMLS_CC) == SUCCESS) { break; } if (Z_OBJ_HANDLER_P(expr, get)) { @@ -384,7 +384,7 @@ ZEND_API void zend_make_printable_zval(z Z_STRVAL_P(expr_copy) = estrndup("Array", Z_STRLEN_P(expr_copy)); break; case IS_OBJECT: - if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) { + if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, ZEND_U_CONVERTER(UG(output_encoding_conv)) TSRMLS_CC) == SUCCESS) { break; } if (Z_OBJ_HANDLER_P(expr, get)) { @@ -436,7 +436,7 @@ ZEND_API void zend_make_unicode_zval(zva } switch (Z_TYPE_P(expr)) { case IS_OBJECT: - if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE TSRMLS_CC) == SUCCESS) { + if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, NULL TSRMLS_CC) == SUCCESS) { break; } if (Z_OBJ_HANDLER_P(expr, get)) { Index: Zend/zend_API.c =================================================================== RCS file: /repository/ZendEngine2/zend_API.c,v retrieving revision 1.409 diff -p -u -r1.409 zend_API.c --- Zend/zend_API.c 7 Oct 2006 17:34:19 -0000 1.409 +++ Zend/zend_API.c 12 Oct 2006 20:58:02 -0000 @@ -271,7 +271,7 @@ static int parse_arg_object_to_string(zv { if (Z_OBJ_HANDLER_PP(arg, cast_object)) { SEPARATE_ZVAL_IF_NOT_REF(arg); - if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, type TSRMLS_CC) == SUCCESS) { + if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, type, NULL TSRMLS_CC) == SUCCESS) { *pl = Z_STRLEN_PP(arg); *p = Z_STRVAL_PP(arg); return SUCCESS; @@ -280,7 +280,7 @@ static int parse_arg_object_to_string(zv /* Standard PHP objects */ if (Z_OBJ_HT_PP(arg) == &std_object_handlers || !Z_OBJ_HANDLER_PP(arg, cast_object)) { SEPARATE_ZVAL_IF_NOT_REF(arg); - if (zend_std_cast_object_tostring(*arg, *arg, type TSRMLS_CC) == SUCCESS) { + if (zend_std_cast_object_tostring(*arg, *arg, type, NULL TSRMLS_CC) == SUCCESS) { *pl = Z_STRLEN_PP(arg); *p = Z_STRVAL_PP(arg); return SUCCESS; Index: Zend/zend_builtin_functions.c =================================================================== RCS file: /repository/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.329 diff -p -u -r1.329 zend_builtin_functions.c --- Zend/zend_builtin_functions.c 6 Oct 2006 17:11:17 -0000 1.329 +++ Zend/zend_builtin_functions.c 12 Oct 2006 20:58:02 -0000 @@ -532,7 +532,7 @@ repeat: goto repeat; } else if (Z_OBJ_HT_PP(val)->cast_object) { ALLOC_INIT_ZVAL(val_free); - if (Z_OBJ_HT_PP(val)->cast_object(*val, val_free, UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC) == SUCCESS) { + if (Z_OBJ_HT_PP(val)->cast_object(*val, val_free, UG(unicode)?IS_UNICODE:IS_STRING, NULL TSRMLS_CC) == SUCCESS) { val = &val_free; break; } Index: Zend/zend_execute.h =================================================================== RCS file: /repository/ZendEngine2/zend_execute.h,v retrieving revision 1.101 diff -p -u -r1.101 zend_execute.h --- Zend/zend_execute.h 18 Jul 2006 17:52:44 -0000 1.101 +++ Zend/zend_execute.h 12 Oct 2006 20:58:02 -0000 @@ -118,7 +118,7 @@ static inline int i_zend_is_true(zval *o if (Z_OBJ_HT_P(op)->cast_object) { zval tmp; - if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) { + if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL, NULL TSRMLS_CC) == SUCCESS) { result = Z_LVAL(tmp); break; } Index: Zend/zend_object_handlers.c =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.176 diff -p -u -r1.176 zend_object_handlers.c --- Zend/zend_object_handlers.c 12 Sep 2006 11:01:31 -0000 1.176 +++ Zend/zend_object_handlers.c 12 Oct 2006 20:58:02 -0000 @@ -1091,14 +1091,20 @@ int zend_std_object_get_class_name(zval return SUCCESS; } -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC) +ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC) { zval *retval; zend_class_entry *ce; + UConverter *conv; switch (type) { case IS_STRING: case IS_UNICODE: + if (extra) { + conv = (UConverter *) extra; + } else { + conv = ZEND_U_CONVERTER(UG(runtime_encoding_conv)); + } ce = Z_OBJCE_P(readobj); if (ce->__tostring && (zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval) || EG(exception))) { @@ -1113,7 +1119,11 @@ ZEND_API int zend_std_cast_object_tostri INIT_PZVAL(writeobj); ZVAL_ZVAL(writeobj, retval, 1, 1); if (Z_TYPE_P(writeobj) != type) { - convert_to_explicit_type(writeobj, type); + if (type == IS_UNICODE) { + convert_to_unicode_with_converter(writeobj, conv); + } else { + convert_to_string_with_converter(writeobj, conv); + } } return SUCCESS; } else { Index: Zend/zend_object_handlers.h =================================================================== RCS file: /repository/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.59 diff -p -u -r1.59 zend_object_handlers.h --- Zend/zend_object_handlers.h 24 Jul 2006 17:51:41 -0000 1.59 +++ Zend/zend_object_handlers.h 12 Oct 2006 20:58:02 -0000 @@ -100,7 +100,7 @@ typedef int (*zend_object_compare_t)(zva /* Cast an object to some other type */ -typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type TSRMLS_DC); +typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type, void *extra TSRMLS_DC); /* updates *count to hold the number of elements present and returns SUCCESS. * Returns FAILURE if the object does not have any sense of overloaded dimensions */ @@ -143,7 +143,7 @@ ZEND_API zend_bool zend_std_unset_static ZEND_API union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC); ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce, zval *member, int silent TSRMLS_DC); -ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC); +ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC); #define IS_ZEND_STD_OBJECT(z) (Z_TYPE(z) == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) Index: Zend/zend_operators.c =================================================================== RCS file: /repository/ZendEngine2/zend_operators.c,v retrieving revision 1.257 diff -p -u -r1.257 zend_operators.c --- Zend/zend_operators.c 3 Oct 2006 17:54:32 -0000 1.257 +++ Zend/zend_operators.c 12 Oct 2006 20:58:03 -0000 @@ -320,7 +320,7 @@ ZEND_API void convert_scalar_to_number(z #define convert_object_to_type(op, ctype, conv_func) \ if (Z_OBJ_HT_P(op)->cast_object) { \ zval dst; \ - if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype TSRMLS_CC) == FAILURE) { \ + if (Z_OBJ_HT_P(op)->cast_object(op, &dst, ctype, NULL TSRMLS_CC) == FAILURE) { \ zend_error(E_RECOVERABLE_ERROR, \ "Object of class %v could not be converted to %s", Z_OBJCE_P(op)->name, \ zend_get_type_by_const(ctype)); \ @@ -493,7 +493,7 @@ ZEND_API void convert_to_null(zval *op) ALLOC_ZVAL(org); *org = *op; - if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) { + if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL, NULL TSRMLS_CC) == SUCCESS) { zval_dtor(org); return; } @@ -875,7 +875,29 @@ ZEND_API void _convert_to_unicode_with_c Z_USTRLEN_P(op) = sizeof("Array")-1; break; case IS_OBJECT: { - convert_object_to_type(op, IS_UNICODE, convert_to_unicode); + if (Z_OBJ_HT_P(op)->cast_object) { + zval dst; + if (Z_OBJ_HT_P(op)->cast_object(op, &dst, IS_UNICODE, conv TSRMLS_CC) == FAILURE) { + zend_error(E_RECOVERABLE_ERROR, + "Object of class %v could not be converted to %s", Z_OBJCE_P(op)->name, + zend_get_type_by_const(IS_UNICODE)); + } else { + zval_dtor(op); + Z_TYPE_P(op) = IS_UNICODE; + op->value = dst.value; + } + } else { + if(Z_OBJ_HT_P(op)->get) { + zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); + if(Z_TYPE_P(newop) != IS_OBJECT) { + /* for safety - avoid loop */ + zval_dtor(op); + *op = *newop; + FREE_ZVAL(newop); + convert_to_string_with_converter(op, conv); + } + } + } if (Z_TYPE_P(op) == IS_UNICODE) { return; @@ -958,7 +980,29 @@ ZEND_API void _convert_to_string_with_co case IS_OBJECT: { TSRMLS_FETCH(); - convert_object_to_type(op, IS_STRING, convert_to_string); + if (Z_OBJ_HT_P(op)->cast_object) { + zval dst; + if (Z_OBJ_HT_P(op)->cast_object(op, &dst, IS_STRING, conv TSRMLS_CC) == FAILURE) { + zend_error(E_RECOVERABLE_ERROR, + "Object of class %v could not be converted to %s", Z_OBJCE_P(op)->name, + zend_get_type_by_const(IS_STRING)); + } else { + zval_dtor(op); + Z_TYPE_P(op) = IS_STRING; + op->value = dst.value; + } + } else { + if(Z_OBJ_HT_P(op)->get) { + zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); + if(Z_TYPE_P(newop) != IS_OBJECT) { + /* for safety - avoid loop */ + zval_dtor(op); + *op = *newop; + FREE_ZVAL(newop); + convert_to_string_with_converter(op, conv); + } + } + } if (Z_TYPE_P(op) == IS_STRING) { return; @@ -1775,7 +1819,7 @@ ZEND_API int compare_function(zval *resu op1 = op1_free = Z_OBJ_HT_P(op1)->get(op1 TSRMLS_CC); } else if (!op2_obj && Z_OBJ_HT_P(op1)->cast_object) { ALLOC_INIT_ZVAL(op1_free); - if (Z_OBJ_HT_P(op1)->cast_object(op1, op1_free, Z_TYPE_P(op2) TSRMLS_CC) == FAILURE) { + if (Z_OBJ_HT_P(op1)->cast_object(op1, op1_free, Z_TYPE_P(op2), NULL TSRMLS_CC) == FAILURE) { op2_free = NULL; ZVAL_LONG(result, 1); COMPARE_RETURN_AND_FREE(SUCCESS); @@ -1799,7 +1843,7 @@ ZEND_API int compare_function(zval *resu op2 = op2_free = Z_OBJ_HT_P(op2)->get(op2 TSRMLS_CC); } else if (!op1_obj && Z_OBJ_HT_P(op2)->cast_object) { ALLOC_INIT_ZVAL(op2_free); - if (Z_OBJ_HT_P(op2)->cast_object(op2, op2_free, Z_TYPE_P(op1) TSRMLS_CC) == FAILURE) { + if (Z_OBJ_HT_P(op2)->cast_object(op2, op2_free, Z_TYPE_P(op1), NULL TSRMLS_CC) == FAILURE) { ZVAL_LONG(result, -1); COMPARE_RETURN_AND_FREE(SUCCESS); } Index: ext/com_dotnet/com_handlers.c =================================================================== RCS file: /repository/php-src/ext/com_dotnet/com_handlers.c,v retrieving revision 1.38 diff -p -u -r1.38 com_handlers.c --- ext/com_dotnet/com_handlers.c 6 Oct 2006 12:24:11 -0000 1.38 +++ ext/com_dotnet/com_handlers.c 12 Oct 2006 20:58:03 -0000 @@ -486,7 +486,7 @@ static int com_objects_compare(zval *obj return ret; } -static int com_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC) +static int com_object_cast(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC) { php_com_dotnet_object *obj; VARIANT v; @@ -530,6 +530,7 @@ static int com_object_cast(zval *readobj } if (SUCCEEDED(res)) { + /* FIXME use 'extra' here for IS_STRING/IS_UNICODE */ php_com_zval_from_variant(writeobj, &v, obj->code_page TSRMLS_CC); } @@ -539,7 +540,7 @@ static int com_object_cast(zval *readobj return SUCCESS; } - return zend_std_cast_object_tostring(readobj, writeobj, type TSRMLS_CC); + return zend_std_cast_object_tostring(readobj, writeobj, type, extra TSRMLS_CC); } static int com_object_count(zval *object, long *count TSRMLS_DC) Index: ext/simplexml/simplexml.c =================================================================== RCS file: /repository/php-src/ext/simplexml/simplexml.c,v retrieving revision 1.220 diff -p -u -r1.220 simplexml.c --- ext/simplexml/simplexml.c 19 Sep 2006 10:38:30 -0000 1.220 +++ ext/simplexml/simplexml.c 12 Oct 2006 20:58:03 -0000 @@ -1608,8 +1608,18 @@ SXE_METHOD(addAttribute) /* {{{ cast_object() */ -static int cast_object(zval *object, int type, char *contents TSRMLS_DC) +static int cast_object(zval *object, int type, char *contents, void *extra TSRMLS_DC) { + UConverter *conv; + + if (type == IS_STRING || type == IS_UNICODE) { + if (extra) { + conv = (UConverter *) extra; + } else { + conv = ZEND_U_CONVERTER(UG(runtime_encoding_conv)); + } + } + if (contents) { ZVAL_XML_STRING(object, contents, ZSTR_DUPLICATE); } else { @@ -1620,10 +1630,10 @@ static int cast_object(zval *object, int switch (type) { case IS_STRING: - convert_to_string(object); + convert_to_string_with_converter(object, conv); break; case IS_UNICODE: - convert_to_unicode(object); + convert_to_unicode_with_converter(object, conv); break; case IS_BOOL: convert_to_boolean(object); @@ -1643,7 +1653,7 @@ static int cast_object(zval *object, int /* {{{ sxe_object_cast() */ -static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC) +static int sxe_object_cast(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC) { php_sxe_object *sxe; xmlChar *contents = NULL; @@ -1678,7 +1688,7 @@ static int sxe_object_cast(zval *readobj } } - rv = cast_object(writeobj, type, (char *)contents TSRMLS_CC); + rv = cast_object(writeobj, type, (char *)contents, extra TSRMLS_CC); if (contents) { xmlFree(contents); @@ -1722,7 +1732,7 @@ static zval *sxe_get_value(zval *z TSRML MAKE_STD_ZVAL(retval); - if (sxe_object_cast(z, retval, UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC)==FAILURE) { + if (sxe_object_cast(z, retval, UG(unicode)?IS_UNICODE:IS_STRING, NULL TSRMLS_CC)==FAILURE) { zend_error(E_ERROR, "Unable to cast node to string"); /* FIXME: Should not be fatal */ } Index: ext/spl/spl_directory.c =================================================================== RCS file: /repository/php-src/ext/spl/spl_directory.c,v retrieving revision 1.100 diff -p -u -r1.100 spl_directory.c --- ext/spl/spl_directory.c 29 Sep 2006 13:22:43 -0000 1.100 +++ ext/spl/spl_directory.c 12 Oct 2006 20:58:03 -0000 @@ -1234,7 +1234,7 @@ zend_object_iterator *spl_filesystem_tre /* }}} */ /* {{{ spl_filesystem_object_cast */ -static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC) +static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type, void *extra TSRMLS_DC) { spl_filesystem_object *intern = (spl_filesystem_object*)zend_object_store_get_object(readobj TSRMLS_CC); Index: ext/tidy/tidy.c =================================================================== RCS file: /repository/php-src/ext/tidy/tidy.c,v retrieving revision 1.103 diff -p -u -r1.103 tidy.c --- ext/tidy/tidy.c 8 Oct 2006 13:34:24 -0000 1.103 +++ ext/tidy/tidy.c 12 Oct 2006 20:58:03 -0000 @@ -210,8 +210,8 @@ static zend_object_value tidy_object_new static zend_class_entry *tidy_get_ce_node(zval * TSRMLS_DC); static zend_class_entry *tidy_get_ce_doc(zval * TSRMLS_DC); static zval * tidy_instanciate(zend_class_entry *, zval * TSRMLS_DC); -static int tidy_doc_cast_handler(zval *, zval *, int TSRMLS_DC); -static int tidy_node_cast_handler(zval *, zval *, int TSRMLS_DC); +static int tidy_doc_cast_handler(zval *, zval *, int, void * TSRMLS_DC); +static int tidy_node_cast_handler(zval *, zval *, int, void * TSRMLS_DC); static void tidy_doc_update_properties(PHPTidyObj * TSRMLS_DC); static void tidy_add_default_properties(PHPTidyObj *, tidy_obj_type TSRMLS_DC); static void *php_tidy_get_opt_val(PHPTidyDoc *, TidyOption, TidyOptionType * TSRMLS_DC); @@ -659,7 +659,7 @@ static zval * tidy_instanciate(zend_clas return object; } -static int tidy_doc_cast_handler(zval *in, zval *out, int type TSRMLS_DC) +static int tidy_doc_cast_handler(zval *in, zval *out, int type, void *extra TSRMLS_DC) { TidyBuffer output = {0}; PHPTidyObj *obj; @@ -691,7 +691,7 @@ static int tidy_doc_cast_handler(zval *i return SUCCESS; } -static int tidy_node_cast_handler(zval *in, zval *out, int type TSRMLS_DC) +static int tidy_node_cast_handler(zval *in, zval *out, int type, void *extra TSRMLS_DC) { TidyBuffer buf = {0}; PHPTidyObj *obj; --Apple-Mail-1--156306979 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed --Apple-Mail-1--156306979--