From: Andrei Zmievski Date: Fri, 13 Oct 2006 14:52:19 +0000 (+0000) Subject: - Add an extra parameter to the cast_object handler that can be used by X-Git-Tag: RELEASE_1_0_0RC1~1287 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=83e0dbb3d294f55ed692cfa5e67ce8f615141181;p=php - Add an extra parameter to the cast_object handler that can be used by various types as needed. - Use that parameter to pass a specific converter for IS_UNICODE/IS_STRING types. --- diff --git a/Zend/zend.c b/Zend/zend.c index b260500e14..e44d1f4f3a 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -315,7 +315,7 @@ ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy) { 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(zval *expr, zval *expr_copy, int *use_cop 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(zval *expr, zval *expr_copy, int *use_copy) } 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)) { diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 3ebede95a5..29bf9d30ff 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -271,7 +271,7 @@ static int parse_arg_object_to_string(zval **arg, char **p, int *pl, int type TS { 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(zval **arg, char **p, int *pl, int type TS /* 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; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 5277a11c65..68a52e3760 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -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; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 79e62376fe..787467b761 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -118,7 +118,7 @@ static inline int i_zend_is_true(zval *op) 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; } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 9314a5a01b..79e64b2542 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1091,14 +1091,20 @@ int zend_std_object_get_class_name(zval *object, zstr *class_name, zend_uint *cl 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_tostring(zval *readobj, zval *writeobj, int ty 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 { diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index edea755dde..7202da1761 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -100,7 +100,7 @@ typedef int (*zend_object_compare_t)(zval *object1, zval *object2 TSRMLS_DC); /* 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_property(zend_class_entry *ce, zend_uch 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)) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 398dddc8dd..75617cc830 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -320,7 +320,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC) #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_converter(zval *op, UConverter *conv TSRM 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_converter(zval *op, UConverter *conv TSRML 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 *result, zval *op1, zval *op2 TSRMLS_DC) 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 *result, zval *op1, zval *op2 TSRMLS_DC) 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); } diff --git a/ext/com_dotnet/com_handlers.c b/ext/com_dotnet/com_handlers.c index fde29e500a..57bbd74527 100644 --- a/ext/com_dotnet/com_handlers.c +++ b/ext/com_dotnet/com_handlers.c @@ -486,7 +486,7 @@ static int com_objects_compare(zval *object1, zval *object2 TSRMLS_DC) 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, zval *writeobj, int type TSRMLS_DC) } 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, zval *writeobj, int type TSRMLS_DC) 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) diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 85b39a7fbc..909bdef2f3 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -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 type, char *contents TSRMLS_DC) 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 type, char *contents TSRMLS_DC) /* {{{ 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, zval *writeobj, int type TSRMLS_DC) } } - 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 TSRMLS_DC) 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 */ } diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 7b946e0ce0..9aac17aacd 100755 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -1234,7 +1234,7 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva /* }}} */ /* {{{ 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); diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index 65a0e31041..a71b9bb413 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -210,8 +210,8 @@ static zend_object_value tidy_object_new_doc(zend_class_entry * TSRMLS_DC); 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_class_entry *pce, zval *object TSRMLS_DC) 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 *in, zval *out, int type TSRMLS_DC) 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;