]> granicus.if.org Git - php/commitdiff
Improve array overloading - support unset($foo["bar"])
authorZeev Suraski <zeev@php.net>
Wed, 30 Jul 2003 17:12:06 +0000 (17:12 +0000)
committerZeev Suraski <zeev@php.net>
Wed, 30 Jul 2003 17:12:06 +0000 (17:12 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_object_handlers.c
Zend/zend_object_handlers.h

index bd01035d4414b6e0c99b7ba4135b702b4570f6ad..bdb0cb04dc389b3c2b1e140d3798cbce57524c8a 100644 (file)
@@ -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;
 
        }
index 1142585ea048f855cfaef6c3dc62ba476d50cf77..aa5a9f501cd8d4f5af664fc3dfcc0fec237167a9 100644 (file)
@@ -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
index eaf3d98c0d7c66bc69d2ce1c3d31253c1b0ad7c5..fc7e0fbcc98d802de86d056d36853b958c50f347 100644 (file)
@@ -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;
index 7405377aad0ae0e5ac85a0abe91b4078580fa74f..a5d913d409997482032b030817a26f214c4e9fcc 100644 (file)
@@ -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 */
index 0a642b95a887b4de4d303fa3572e034f7f34f82c..5f3d29c98f9504698a03c1d8408b529c7a31ad52 100644 (file)
@@ -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;