diff options
author | Nikita Popov <nikic@php.net> | 2014-04-15 18:33:38 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2014-04-15 20:32:47 +0200 |
commit | 7a1a6092f652f1c322e3a09f9fb1491775fb4072 (patch) | |
tree | 49be61d4838f50f05a0e5175f798696226891421 | |
parent | 2f0a758fbbf39ff8684d167f86c708cc361db782 (diff) | |
download | php-git-7a1a6092f652f1c322e3a09f9fb1491775fb4072.tar.gz |
Add functions for extracting long/double/string from zval
These function get the long / double / string value of a zval with
usual cast semantics, but without actually modifying the zval.
Didn't go on a killing spree for convert_to_* yet...
-rw-r--r-- | Zend/zend_closures.c | 20 | ||||
-rw-r--r-- | Zend/zend_operators.c | 131 | ||||
-rw-r--r-- | Zend/zend_operators.h | 5 | ||||
-rw-r--r-- | ext/date/php_date.c | 11 | ||||
-rw-r--r-- | ext/dom/attr.c | 13 | ||||
-rw-r--r-- | ext/dom/document.c | 17 | ||||
-rw-r--r-- | ext/dom/php_dom.c | 58 |
7 files changed, 160 insertions, 95 deletions
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 548dc06b93..1b1d6ef6ed 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -90,28 +90,16 @@ ZEND_METHOD(Closure, bind) } else if (Z_TYPE_P(scope_arg) == IS_NULL) { ce = NULL; } else { - zend_string *class_name; - zval tmp_zval; - - ZVAL_UNDEF(&tmp_zval); - if (Z_TYPE_P(scope_arg) == IS_STRING) { - class_name = Z_STR_P(scope_arg); - } else { - ZVAL_DUP(&tmp_zval, scope_arg); - convert_to_string(&tmp_zval); - class_name = Z_STR(tmp_zval); - } - + zend_string *class_name = zval_get_string(scope_arg TSRMLS_CC); if ((class_name->len == sizeof("static") - 1) && (memcmp("static", class_name->val, sizeof("static") - 1) == 0)) { ce = closure->func.common.scope; - } - else if ((ce = zend_lookup_class_ex(class_name, NULL, 1 TSRMLS_CC)) == NULL) { + } else if ((ce = zend_lookup_class_ex(class_name, NULL, 1 TSRMLS_CC)) == NULL) { zend_error(E_WARNING, "Class '%s' not found", class_name->val); - zval_dtor(&tmp_zval); + STR_RELEASE(class_name); RETURN_NULL(); } - zval_dtor(&tmp_zval); + STR_RELEASE(class_name); } } else { /* scope argument not given; do not change the scope by default */ ce = closure->func.common.scope; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1460eb3670..47e2562da8 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -819,6 +819,137 @@ ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */ } /* }}} */ +ZEND_API long zval_get_long(zval *op TSRMLS_DC) /* {{{ */ +{ + switch (Z_TYPE_P(op)) { + case IS_NULL: + return 0; + case IS_RESOURCE: + return Z_RES_HANDLE_P(op); + case IS_BOOL: + case IS_LONG: + return Z_LVAL_P(op); + case IS_DOUBLE: + return zend_dval_to_lval(Z_DVAL_P(op)); + case IS_STRING: + return strtol(Z_STRVAL_P(op), NULL, 10); + case IS_ARRAY: + return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0; + case IS_OBJECT: + { + zval tmp; + ZVAL_DUP(&tmp, op); + convert_object_to_type(&tmp, IS_LONG, convert_to_long); + if (Z_TYPE(tmp) == IS_LONG) { + return Z_LVAL(tmp); + } else { + zend_error(E_NOTICE, "Object of class %s could not be converted to int", Z_OBJCE_P(op)->name->val); + zval_dtor(&tmp); + return 1; + } + } + default: + zend_error(E_WARNING, "Cannot convert to ordinal value"); + return 0; + } +} +/* }}} */ + +ZEND_API double zval_get_double(zval *op TSRMLS_DC) /* {{{ */ +{ + switch (Z_TYPE_P(op)) { + case IS_NULL: + return 0.0; + case IS_RESOURCE: + return (double) Z_RES_HANDLE_P(op); + case IS_BOOL: + case IS_LONG: + return (double) Z_LVAL_P(op); + case IS_DOUBLE: + return Z_DVAL_P(op); + case IS_STRING: + return zend_strtod(Z_STRVAL_P(op), NULL); + case IS_ARRAY: + return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1.0 : 0.0; + case IS_OBJECT: + { + zval tmp; + ZVAL_DUP(&tmp, op); + convert_object_to_type(op, IS_DOUBLE, convert_to_double); + + if (Z_TYPE(tmp) == IS_DOUBLE) { + return Z_DVAL(tmp); + } else { + zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name->val); + + zval_dtor(&tmp); + return 1.0; + } + } + default: + zend_error(E_WARNING, "Cannot convert to real value (type=%d)", Z_TYPE_P(op)); + return 0.0; + } +} +/* }}} */ + +ZEND_API zend_string *zval_get_string(zval *op TSRMLS_DC) /* {{{ */ +{ + switch (Z_TYPE_P(op)) { + case IS_NULL: + return STR_EMPTY_ALLOC(); + case IS_STRING: + return STR_COPY(Z_STR_P(op)); + case IS_BOOL: + if (Z_LVAL_P(op)) { + return STR_INIT("1", 1, 0); + } else { + return STR_EMPTY_ALLOC(); + } + case IS_RESOURCE: { + char *str; + int len = zend_spprintf(&str, 0, "Resource id #%ld", Z_RES_HANDLE_P(op)); + zend_string *retval = STR_INIT(str, len, 0); + efree(str); + return retval; + } + case IS_LONG: { + char *str; + int len = zend_spprintf(&str, 0, "%ld", Z_LVAL_P(op)); + zend_string *retval = STR_INIT(str, len, 0); + efree(str); + return retval; + } + case IS_DOUBLE: { + char *str; + int len = zend_spprintf(&str, 0, "%.*G", (int) EG(precision), Z_DVAL_P(op)); + zend_string *retval = STR_INIT(str, len, 0); + efree(str); + return retval; + } + case IS_ARRAY: + zend_error(E_NOTICE, "Array to string conversion"); + return STR_INIT("Array", sizeof("Array")-1, 0); + case IS_OBJECT: { + zval tmp; + ZVAL_DUP(&tmp, op); + convert_object_to_type(op, IS_STRING, convert_to_string); + + if (Z_TYPE(tmp) == IS_STRING) { + return Z_STR(tmp); + } else { + zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name->val); + zval_dtor(&tmp); + return STR_INIT("Object", sizeof("Object")-1, 0); + } + } + default: + //??? original code returns bool(0) + return STR_EMPTY_ALLOC(); + } +} +/* }}} */ + ZEND_API int add_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{{ */ { zval op1_copy, op2_copy; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 17d60a9b04..c062cd5e19 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -336,6 +336,11 @@ ZEND_API void convert_to_object(zval *op); ZEND_API void multi_convert_to_long_ex(int argc, ...); ZEND_API void multi_convert_to_double_ex(int argc, ...); ZEND_API void multi_convert_to_string_ex(int argc, ...); + +ZEND_API long zval_get_long(zval *op TSRMLS_DC); +ZEND_API double zval_get_double(zval *op TSRMLS_DC); +ZEND_API zend_string *zval_get_string(zval *op TSRMLS_DC); + ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2); ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2); #define convert_to_cstring(op) if (Z_TYPE_P(op) != IS_STRING) { _convert_to_cstring((op) ZEND_FILE_LINE_CC); } diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 8009897b9a..a336321c61 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4045,16 +4045,7 @@ void date_interval_write_property(zval *object, zval *member, zval *value, const #define SET_VALUE_FROM_STRUCT(n,m) \ if (strcmp(Z_STRVAL_P(member), m) == 0) { \ - if (Z_TYPE_P(value) != IS_LONG) { \ - tmp_value = *value; \ - zval_copy_ctor(&tmp_value); \ - convert_to_long(&tmp_value); \ - value = &tmp_value; \ - } \ - obj->diff->n = Z_LVAL_P(value); \ - if (value == &tmp_value) { \ - zval_dtor(value); \ - } \ + obj->diff->n = zval_get_long(value TSRMLS_CC); \ break; \ } diff --git a/ext/dom/attr.c b/ext/dom/attr.c index c5fdcfeeae..e436f180d7 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -161,7 +161,7 @@ int dom_attr_value_read(dom_object *obj, zval *retval TSRMLS_DC) int dom_attr_value_write(dom_object *obj, zval *newval TSRMLS_DC) { - zval value_copy; + zend_string *str; xmlAttrPtr attrp = (xmlAttrPtr) dom_object_get_node(obj); if (attrp == NULL) { @@ -173,18 +173,11 @@ int dom_attr_value_write(dom_object *obj, zval *newval TSRMLS_DC) node_list_unlink(attrp->children TSRMLS_CC); } - if (Z_TYPE_P(newval) != IS_STRING) { - ZVAL_DUP(&value_copy, newval); - newval = &value_copy; - convert_to_string(newval); - } + str = zval_get_string(newval TSRMLS_CC); xmlNodeSetContentLen((xmlNodePtr) attrp, Z_STRVAL_P(newval), Z_STRLEN_P(newval) + 1); - if (newval == &value_copy) { - zval_dtor(newval); - } - + STR_RELEASE(str); return SUCCESS; } diff --git a/ext/dom/document.c b/ext/dom/document.c index 4029d97db9..73ca6a95b3 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -330,7 +330,7 @@ int dom_document_encoding_read(dom_object *obj, zval **retval TSRMLS_DC) int dom_document_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) { xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj); - zval value_copy; + zend_string *str; xmlCharEncodingHandlerPtr handler; if (docp == NULL) { @@ -338,15 +338,7 @@ int dom_document_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) return FAILURE; } - // TODO: Stopped here - if (newval->type != IS_STRING) { - if(Z_REFCOUNT_P(newval) > 1) { - value_copy = *newval; - zval_copy_ctor(&value_copy); - newval = &value_copy; - } - convert_to_string(newval); - } + str = zval_get_string(newval TSMLRS_CC); handler = xmlFindCharEncodingHandler(Z_STRVAL_P(newval)); @@ -360,10 +352,7 @@ int dom_document_encoding_write(dom_object *obj, zval *newval TSRMLS_DC) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Document Encoding"); } - if (newval == &value_copy) { - zval_dtor(newval); - } - + STR_RELEASE(str); return SUCCESS; } diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index d3aed667e3..ab5a7d7844 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -305,23 +305,15 @@ static void dom_register_prop_handler(HashTable *prop_handler, char *name, dom_r static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ { dom_object *obj = Z_DOMOBJ_P(object); - zval tmp_member; + zend_string *member_str = zval_get_string(member TSRMLS_CC); zval *retval = NULL; - if (Z_TYPE_P(member) != IS_STRING) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); - member = &tmp_member; - } - - if (!obj->prop_handler || !zend_hash_exists(obj->prop_handler, Z_STR_P(member))) { + if (!obj->prop_handler || !zend_hash_exists(obj->prop_handler, member_str)) { zend_object_handlers *std_hnd = zend_get_std_object_handlers(); retval = std_hnd->get_property_ptr_ptr(object, member, type, key TSRMLS_CC); } - if (member == &tmp_member) { - zval_dtor(member); - } + STR_RELEASE(member_str); return retval; } /* }}} */ @@ -330,18 +322,12 @@ static zval *dom_get_property_ptr_ptr(zval *object, zval *member, int type, cons zval *dom_read_property(zval *object, zval *member, int type, const zend_literal *key, zval *rv TSRMLS_DC) { dom_object *obj = Z_DOMOBJ_P(object); - zval tmp_member; + zend_string *member_str = zval_get_string(member TSRMLS_CC); zval *retval; dom_prop_handler *hnd = NULL; - if (Z_TYPE_P(member) != IS_STRING) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); - member = &tmp_member; - } - if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, member_str); } else if (instanceof_function(obj->std.ce, dom_node_class_entry TSRMLS_CC)) { php_error(E_WARNING, "Couldn't fetch %s. Node no longer exists", obj->std.ce->name->val); } @@ -358,9 +344,7 @@ zval *dom_read_property(zval *object, zval *member, int type, const zend_literal retval = std_hnd->read_property(object, member, type, key, rv TSRMLS_CC); } - if (member == &tmp_member) { - zval_dtor(member); - } + STR_RELEASE(member_str); return retval; } /* }}} */ @@ -369,17 +353,11 @@ zval *dom_read_property(zval *object, zval *member, int type, const zend_literal void dom_write_property(zval *object, zval *member, zval *value, const zend_literal *key TSRMLS_DC) { dom_object *obj = Z_DOMOBJ_P(object); - zval tmp_member; + zend_string *member_str = zval_get_string(member TSRMLS_CC); dom_prop_handler *hnd = NULL; - if (Z_TYPE_P(member) != IS_STRING) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); - member = &tmp_member; - } - if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, member_str); } if (hnd) { hnd->write_func(obj, value TSRMLS_CC); @@ -388,9 +366,7 @@ void dom_write_property(zval *object, zval *member, zval *value, const zend_lite std_hnd->write_property(object, member, value, key TSRMLS_CC); } - if (member == &tmp_member) { - zval_dtor(member); - } + STR_RELEASE(member_str); } /* }}} */ @@ -398,18 +374,12 @@ void dom_write_property(zval *object, zval *member, zval *value, const zend_lite static int dom_property_exists(zval *object, zval *member, int check_empty, const zend_literal *key TSRMLS_DC) { dom_object *obj = Z_DOMOBJ_P(object); - zval tmp_member; + zend_string *member_str = zval_get_string(member TSRMLS_CC); dom_prop_handler *hnd = NULL; - int retval=0; - - if (Z_TYPE_P(member) != IS_STRING) { - ZVAL_DUP(&tmp_member, member); - convert_to_string(&tmp_member); - member = &tmp_member; - } + int retval = 0; if (obj->prop_handler != NULL) { - hnd = zend_hash_find_ptr(obj->prop_handler, Z_STR_P(member)); + hnd = zend_hash_find_ptr(obj->prop_handler, member_str); } if (hnd) { zval tmp; @@ -429,9 +399,7 @@ static int dom_property_exists(zval *object, zval *member, int check_empty, cons retval = std_hnd->has_property(object, member, check_empty, key TSRMLS_CC); } - if (member == &tmp_member) { - zval_dtor(member); - } + STR_RELEASE(member_str); return retval; } /* }}} */ |