summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>2003-07-30 17:12:06 +0000
committerZeev Suraski <zeev@php.net>2003-07-30 17:12:06 +0000
commitc0b46739caab84c0cf1aff21c3456de335afe395 (patch)
tree3cf860096c95c4017faa3565640fc277c540ffe6
parent4839ce59527f45a83da99251be0d35e8ec7ca868 (diff)
downloadphp-git-c0b46739caab84c0cf1aff21c3456de335afe395.tar.gz
Improve array overloading - support unset($foo["bar"])
-rw-r--r--Zend/zend_compile.c4
-rw-r--r--Zend/zend_compile.h3
-rw-r--r--Zend/zend_execute.c56
-rw-r--r--Zend/zend_object_handlers.c8
-rw-r--r--Zend/zend_object_handlers.h4
5 files changed, 58 insertions, 17 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index bd01035d44..bdb0cb04dc 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2890,8 +2890,10 @@ void zend_do_unset(znode *variable TSRMLS_DC)
last_op->opcode = ZEND_UNSET_VAR;
break;
case ZEND_FETCH_DIM_UNSET:
+ last_op->opcode = ZEND_UNSET_DIM;
+ break;
case ZEND_FETCH_OBJ_UNSET:
- last_op->opcode = ZEND_UNSET_DIM_OBJ;
+ last_op->opcode = ZEND_UNSET_OBJ;
break;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 1142585ea0..aa5a9f501c 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -571,7 +571,8 @@ int zendlex(znode *zendlval TSRMLS_DC);
#define ZEND_INCLUDE_OR_EVAL 73
#define ZEND_UNSET_VAR 74
-#define ZEND_UNSET_DIM_OBJ 75
+#define ZEND_UNSET_DIM 75
+#define ZEND_UNSET_OBJ 76
#define ZEND_FE_RESET 77
#define ZEND_FE_FETCH 78
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index eaf3d98c0d..fc7e0fbcc9 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -338,6 +338,9 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode
if (opcode == ZEND_ASSIGN_OBJ) {
Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC);
} else {
+ if (!Z_OBJ_HT_P(object)->write_dimension) {
+ zend_error(E_ERROR, "Cannot use object as array");
+ }
Z_OBJ_HT_P(object)->write_dimension(object, property, value TSRMLS_CC);
}
if (property == &tmp) {
@@ -848,13 +851,17 @@ static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2,
break;
case IS_OBJECT:
if (type == BP_VAR_R) {
- zval *dim = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
- zval *overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim TSRMLS_CC);
-
- *retval = &overloaded_result;
- AI_USE_PTR(T(result->u.var).var);
- FREE_OP(Ts, op2, EG(free_op2));
- SELECTIVE_PZVAL_LOCK(**retval, result);
+ if (!Z_OBJ_HT_P(container)->read_dimension) {
+ zend_error(E_ERROR, "Cannot use object as array");
+ } else {
+ zval *dim = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R);
+ zval *overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim TSRMLS_CC);
+
+ *retval = &overloaded_result;
+ AI_USE_PTR(T(result->u.var).var);
+ FREE_OP(Ts, op2, EG(free_op2));
+ SELECTIVE_PZVAL_LOCK(**retval, result);
+ }
}
break;
default: {
@@ -3404,6 +3411,7 @@ int zend_unset_var_handler(ZEND_OPCODE_HANDLER_ARGS)
}
+
int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS)
{
zval **container = get_obj_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
@@ -3413,13 +3421,30 @@ int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS)
if (container) {
HashTable *ht;
- if ((*container)->type == IS_ARRAY) {
- ht = (*container)->value.ht;
- } else {
- ht = NULL;
- if ((*container)->type == IS_OBJECT) {
- Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
- }
+ switch (EX(opline)->opcode) {
+ case ZEND_UNSET_DIM:
+ switch (Z_TYPE_PP(container)) {
+ case IS_ARRAY:
+ ht = Z_ARRVAL_PP(container);
+ break;
+ case IS_OBJECT:
+ ht = NULL;
+ if (!Z_OBJ_HT_P(*container)->unset_dimension) {
+ zend_error(E_ERROR, "Cannot use object as array");
+ }
+ Z_OBJ_HT_P(*container)->unset_dimension(*container, offset TSRMLS_CC);
+ break;
+ default:
+ ht = NULL;
+ break;
+ }
+ break;
+ case ZEND_UNSET_OBJ:
+ ht = NULL;
+ if (Z_TYPE_PP(container) == IS_OBJECT) {
+ Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC);
+ }
+ break;
}
if (ht) {
switch (offset->type) {
@@ -4044,7 +4069,8 @@ void zend_init_opcodes_handlers()
zend_opcode_handlers[ZEND_INCLUDE_OR_EVAL] = zend_include_or_eval_handler;
zend_opcode_handlers[ZEND_UNSET_VAR] = zend_unset_var_handler;
- zend_opcode_handlers[ZEND_UNSET_DIM_OBJ] = zend_unset_dim_obj_handler;
+ zend_opcode_handlers[ZEND_UNSET_DIM] = zend_unset_dim_obj_handler;
+ zend_opcode_handlers[ZEND_UNSET_OBJ] = zend_unset_dim_obj_handler;
zend_opcode_handlers[ZEND_FE_RESET] = zend_fe_reset_handler;
zend_opcode_handlers[ZEND_FE_FETCH] = zend_fe_fetch_handler;
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 7405377aad..a5d913d409 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -452,6 +452,13 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
}
}
+
+static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
+{
+ zend_error(E_ERROR, "Cannot use object as array");
+}
+
+
static void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
{
zval ***args;
@@ -875,6 +882,7 @@ zend_object_handlers std_object_handlers = {
NULL, /* set */
zend_std_has_property, /* has_property */
zend_std_unset_property, /* unset_property */
+ zend_std_unset_dimension, /* unset_dimension */
zend_std_get_properties, /* get_properties */
zend_std_get_method, /* get_method */
NULL, /* call_method */
diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h
index 0a642b95a8..5f3d29c98f 100644
--- a/Zend/zend_object_handlers.h
+++ b/Zend/zend_object_handlers.h
@@ -59,6 +59,9 @@ typedef int (*zend_object_has_property_t)(zval *object, zval *member, int check_
/* Used to remove a property of the object */
typedef void (*zend_object_unset_property_t)(zval *object, zval *member TSRMLS_DC);
+/* Used to remove a property of the object */
+typedef void (*zend_object_unset_dimension_t)(zval *object, zval *offset TSRMLS_DC);
+
/* Used to get hash of the properties of the object, as hash of zval's */
typedef HashTable *(*zend_object_get_properties_t)(zval *object TSRMLS_DC);
@@ -99,6 +102,7 @@ typedef struct _zend_object_handlers {
zend_object_set_t set;
zend_object_has_property_t has_property;
zend_object_unset_property_t unset_property;
+ zend_object_unset_dimension_t unset_dimension;
zend_object_get_properties_t get_properties;
zend_object_get_method_t get_method;
zend_object_call_method_t call_method;