]> granicus.if.org Git - php/commitdiff
Add functions for extracting long/double/string from zval
authorNikita Popov <nikic@php.net>
Tue, 15 Apr 2014 16:33:38 +0000 (18:33 +0200)
committerNikita Popov <nikic@php.net>
Tue, 15 Apr 2014 18:32:47 +0000 (20:32 +0200)
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...

Zend/zend_closures.c
Zend/zend_operators.c
Zend/zend_operators.h
ext/date/php_date.c
ext/dom/attr.c
ext/dom/document.c
ext/dom/php_dom.c

index 548dc06b932d8d21ce9d52f3a5f409cf2d74bb3d..1b1d6ef6edb5ffeebefccf2a075ddf1eb885822a 100644 (file)
@@ -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;
index 1460eb367099eb0318e4cebbe01cd097f2bdd643..47e2562da82e77184bf9d89ece57b6079a3bbbd9 100644 (file)
@@ -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;
index 17d60a9b0411ee4973433e314258557b5cb718e4..c062cd5e19ed4667c47302ce8173c59c09911118 100644 (file)
@@ -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); }
index 8009897b9a9448b9fdbb265db2e6a8fe85fc6f9f..a336321c61127c5658379a47e76d98c6caa8fa4e 100644 (file)
@@ -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;                                                            \
        }
 
index c5fdcfeeae66cfaafbf9aaf4565918ce834cb1e1..e436f180d7c0c4e5a6a8b5c3e1015222099d5ba1 100644 (file)
@@ -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;
 }
 
index 4029d97db9e2c70f1f27366f731a2fadcdd44df2..73ca6a95b3b262fa4712c5eb6a56f1051a78c9df 100644 (file)
@@ -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;
 }
 
index d3aed667e38018737bb9290a474aba8ea123a049..ab5a7d7844b50e87dc038f115b8a1b62827e4e62 100644 (file)
@@ -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;
 }
 /* }}} */