summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2014-04-15 18:33:38 +0200
committerNikita Popov <nikic@php.net>2014-04-15 20:32:47 +0200
commit7a1a6092f652f1c322e3a09f9fb1491775fb4072 (patch)
tree49be61d4838f50f05a0e5175f798696226891421
parent2f0a758fbbf39ff8684d167f86c708cc361db782 (diff)
downloadphp-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.c20
-rw-r--r--Zend/zend_operators.c131
-rw-r--r--Zend/zend_operators.h5
-rw-r--r--ext/date/php_date.c11
-rw-r--r--ext/dom/attr.c13
-rw-r--r--ext/dom/document.c17
-rw-r--r--ext/dom/php_dom.c58
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;
}
/* }}} */