as a string.
#
# Note that "Object #<id>" is no longer afallback for debugging purpose use
# var_dump, which was made for debugging. If you used this to grab the id
# of an object you can never rely on this. For object storage look at SPL's
# ObjectStorage class.
#
# Note the signature change in the cast handler:
#
# int (*cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC);
# int (*cast_t)(zval *readobj, zval *retval, int type TSRMLS_DC);
case IS_OBJECT:
{
TSRMLS_FETCH();
- if (Z_OBJ_HANDLER_P(expr, cast_object)) {
- if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
- break;
- }
+
+ if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
+ break;
}
if (Z_OBJ_HANDLER_P(expr, get)) {
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
if(Z_TYPE_P(z) != IS_OBJECT) {
- zend_make_printable_zval(z, expr_copy, use_copy);
+ zend_make_string_zval(z, expr_copy, use_copy);
FREE_ZVAL(z);
break;
}
}
- if (EG(exception)) {
- expr_copy->value.str.len = 0;
- expr_copy->value.str.val = STR_EMPTY_ALLOC();
- break;
- }
-
+ zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
+ ZVAL_EMPTY_STRING(expr_copy);
+ 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);
- break;
default:
*expr_copy = *expr;
zval_copy_ctor(expr_copy);
expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len);
break;
case IS_OBJECT:
- if (Z_OBJ_HANDLER_P(expr, cast_object)) {
- if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
- break;
- }
+ if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
+ break;
}
if (Z_OBJ_HANDLER_P(expr, get)) {
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
break;
}
}
- if (EG(exception)) {
- expr_copy->value.str.len = 0;
- expr_copy->value.str.val = STR_EMPTY_ALLOC();
- 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);
+ zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
+ ZVAL_EMPTY_STRING(expr_copy);
break;
case IS_DOUBLE:
*expr_copy = *expr;
}
switch (expr->type) {
case IS_OBJECT:
- if (Z_OBJ_HANDLER_P(expr, cast_object)) {
- if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
- break;
- }
+ if(Z_OBJ_HT_P(expr)->cast_object && Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE TSRMLS_CC) == SUCCESS) {
+ break;
}
if (Z_OBJ_HANDLER_P(expr, get)) {
zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
break;
}
}
- if (EG(exception)) {
- expr_copy->value.ustr.len = 0;
- expr_copy->value.ustr.val = USTR_MAKE("");
- break;
- }
- expr_copy->value.ustr.val = eumalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1);
- expr_copy->value.ustr.len = u_sprintf(expr_copy->value.ustr.val, "Object id #%ld", (long)expr->value.obj.handle);
+ zend_error(EG(exception) ? E_ERROR : E_RECOVERABLE_ERROR, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
+ ZVAL_EMPTY_STRING(expr_copy);
break;
default:
*expr_copy = *expr;
case IS_OBJECT: {
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
*pl = Z_STRLEN_PP(arg);
*p = Z_STRVAL_PP(arg);
break;
case IS_OBJECT: {
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_BINARY, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_BINARY TSRMLS_CC) == SUCCESS) {
*pl = Z_BINLEN_PP(arg);
*p = Z_BINVAL_PP(arg);
break;
case IS_OBJECT: {
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE TSRMLS_CC) == SUCCESS) {
*pl = Z_USTRLEN_PP(arg);
*p = Z_USTRVAL_PP(arg);
break;
case IS_OBJECT: {
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, T_arg_type, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, T_arg_type TSRMLS_CC) == SUCCESS) {
*(char**)p = Z_UNIVAL_PP(arg);
*pl = Z_UNILEN_PP(arg);
*type = Z_TYPE_PP(arg);
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
if (UG(unicode)) {
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE TSRMLS_CC) == SUCCESS) {
RETURN_AS_UNICODE(arg, p, pl, type);
break;
}
} else {
- if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING TSRMLS_CC) == SUCCESS) {
RETURN_AS_STRING(arg, p, pl, type);
break;
}
if (Z_OBJ_HT_P(op)->cast_object) {
zval tmp;
- if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL, 0 TSRMLS_CC) == SUCCESS) {
+ if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_BOOL TSRMLS_CC) == SUCCESS) {
result = Z_LVAL(tmp);
break;
}
return SUCCESS;
}
-ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
+ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC)
{
zval *retval;
zend_class_entry *ce;
-
+
switch (type) {
case IS_STRING:
case IS_UNICODE:
ce = Z_OBJCE_P(readobj);
if (ce->__tostring &&
zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval)) {
+ if (EG(exception)) {
+ zval_ptr_dtor(&retval);
+ zend_error(E_ERROR, "Method %v::__toString() must not throw an exception", ce->name);
+ return FAILURE;
+ }
if (Z_TYPE_P(retval) == (UG(unicode)?IS_UNICODE:IS_STRING)) {
- *writeobj = *retval;
- zval_copy_ctor(writeobj);
- zval_ptr_dtor(&retval);
INIT_PZVAL(writeobj);
+ ZVAL_ZVAL(writeobj, retval, 1, 1);
if (Z_TYPE_P(writeobj) != type) {
convert_to_explicit_type(writeobj, type);
}
return SUCCESS;
} else {
zval_ptr_dtor(&retval);
+ INIT_PZVAL(writeobj);
+ ZVAL_EMPTY_STRING(writeobj);
zend_error(E_RECOVERABLE_ERROR, "Method %v::__toString() must return a string value", ce->name);
+ return SUCCESS;
}
}
return FAILURE;
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 int (*zend_object_cast_t)(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC);
+
+/* Cast an object to some other type
+ */
+typedef int (*zend_object_cast_t)(zval *readobj, zval *retval, int type 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 */
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, zend_uchar type, void *property_name, int property_name_len 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, int should_free TSRMLS_DC);
+ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type TSRMLS_DC);
#define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL))
}
-#define convert_object_to_type(op, ctype, conv_func) \
+#define convert_object_to_type(op, ctype, conv_func) \
if (Z_OBJ_HT_P(op)->cast_object) { \
- if (Z_OBJ_HT_P(op)->cast_object(op, op, ctype, 1 TSRMLS_CC) == SUCCESS) { \
- op->type = ctype; \
+ zval *org; \
+ ALLOC_ZVAL(org); \
+ *org = *op; \
+ if (Z_OBJ_HT_P(op)->cast_object(org, op, ctype TSRMLS_CC) == FAILURE) { \
+ zend_error(E_RECOVERABLE_ERROR, \
+ "Object of class %v could not be converted to " # ctype, Z_OBJCE_P(org)->name); \
+ INIT_ZVAL(*op); \
} \
+ zval_dtor(org); \
} else { \
if(Z_OBJ_HT_P(op)->get) { \
zval *newop = Z_OBJ_HT_P(op)->get(op TSRMLS_CC); \
{
if (op->type == IS_OBJECT) {
if (Z_OBJ_HT_P(op)->cast_object) {
+ zval *org;
TSRMLS_FETCH();
- if (Z_OBJ_HT_P(op)->cast_object(op, op, IS_NULL, 1 TSRMLS_CC) == SUCCESS) {
+
+ ALLOC_ZVAL(org);
+ *org = *op;
+ if (Z_OBJ_HT_P(op)->cast_object(org, op, IS_NULL TSRMLS_CC) == SUCCESS) {
+ zval_dtor(org);
return;
}
+ *op = *org;
}
}