helly           Mon Nov 24 15:57:55 2003 EDT

  Added files:                 
    /php-src/tests/classes      array_access_001.phpt array_access_002.phpt 
                                array_access_003.phpt array_access_004.phpt 

  Modified files:              
    /ZendEngine2        zend_execute.c zend_interfaces.c zend_interfaces.h 
                        zend_operators.c zend_operators.h 
                        zend_object_handlers.c 
  Log:
  Add new interface ArrayAccess to use objects as Arrays
  
  
Index: ZendEngine2/zend_execute.c
diff -u ZendEngine2/zend_execute.c:1.552 ZendEngine2/zend_execute.c:1.553
--- ZendEngine2/zend_execute.c:1.552    Mon Nov 24 13:13:29 2003
+++ ZendEngine2/zend_execute.c  Mon Nov 24 15:57:53 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_execute.c,v 1.552 2003/11/24 18:13:29 andi Exp $ */
+/* $Id: zend_execute.c,v 1.553 2003/11/24 20:57:53 helly Exp $ */
 
 #define ZEND_INTENSIVE_DEBUGGING 0
 
@@ -920,13 +920,17 @@
                        }
                        break;
                case IS_OBJECT:
-                       if (type == BP_VAR_R) {
+                       if (type == BP_VAR_R || type == BP_VAR_RW) {
                                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);
                                         
+                                       if (type == BP_VAR_RW && 
!overloaded_result->is_ref) {
+                                               zend_error(E_ERROR, "Objects used as 
arrays in post/pre increment/decrement must return values by reference");
+                                       }
+
                                        *retval = &overloaded_result;
                                        AI_USE_PTR(T(result->u.var).var);
                                        FREE_OP(Ts, op2, EG(free_op2));
Index: ZendEngine2/zend_interfaces.c
diff -u ZendEngine2/zend_interfaces.c:1.8 ZendEngine2/zend_interfaces.c:1.9
--- ZendEngine2/zend_interfaces.c:1.8   Mon Nov 17 19:18:48 2003
+++ ZendEngine2/zend_interfaces.c       Mon Nov 24 15:57:53 2003
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_interfaces.c,v 1.8 2003/11/18 00:18:48 helly Exp $ */
+/* $Id: zend_interfaces.c,v 1.9 2003/11/24 20:57:53 helly Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -25,6 +25,7 @@
 zend_class_entry *zend_ce_traversable;
 zend_class_entry *zend_ce_aggregate;
 zend_class_entry *zend_ce_iterator;
+zend_class_entry *zend_ce_arrayaccess;
 
 /* {{{ zend_call_method 
  Only returns the returned zval if retval_ptr != NULL */
@@ -344,6 +345,13 @@
 }
 /* }}} */
 
+/* {{{ zend_implement_arrayaccess */
+static int zend_implement_arrayaccess(zend_class_entry *interface, zend_class_entry 
*class_type TSRMLS_DC)
+{
+       return SUCCESS;
+}
+/* }}}*/
+
 /* {{{ function tables */
 zend_function_entry zend_funcs_aggregate[] = {
        ZEND_ABSTRACT_ME(iterator, getIterator, NULL)
@@ -360,6 +368,26 @@
 };
 
 zend_function_entry *zend_funcs_traversable    = NULL;
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_arrayaccess_offset, 0) 
+       ZEND_ARG_INFO(0, offset)
+ZEND_END_ARG_INFO();
+
+static
+ZEND_BEGIN_ARG_INFO(arginfo_arrayaccess_offset_value, 0) 
+       ZEND_ARG_INFO(0, offset)
+       ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO();
+
+zend_function_entry zend_funcs_arrayaccess[] = {
+       ZEND_ABSTRACT_ME(arrayaccess, offsetExists, arginfo_arrayaccess_offset)
+       ZEND_ABSTRACT_ME(arrayaccess, offsetGet,    arginfo_arrayaccess_offset)
+       ZEND_ABSTRACT_ME(arrayaccess, offsetSet,    arginfo_arrayaccess_offset_value)
+       ZEND_ABSTRACT_ME(arrayaccess, offsetUnset,  arginfo_arrayaccess_offset)
+       {NULL, NULL, NULL}
+};
+
 /* }}} */
 
 #define REGISTER_ITERATOR_INTERFACE(class_name, class_name_str) \
@@ -383,6 +411,8 @@
 
        REGISTER_ITERATOR_INTERFACE(iterator, Iterator);
        REGISTER_ITERATOR_IMPLEMENT(iterator, traversable);
+       
+       REGISTER_ITERATOR_INTERFACE(arrayaccess, ArrayAccess);
 }
 /* }}} */
 
Index: ZendEngine2/zend_interfaces.h
diff -u ZendEngine2/zend_interfaces.h:1.2 ZendEngine2/zend_interfaces.h:1.3
--- ZendEngine2/zend_interfaces.h:1.2   Fri Nov  7 04:33:06 2003
+++ ZendEngine2/zend_interfaces.h       Mon Nov 24 15:57:53 2003
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_interfaces.h,v 1.2 2003/11/07 09:33:06 helly Exp $ */
+/* $Id: zend_interfaces.h,v 1.3 2003/11/24 20:57:53 helly Exp $ */
 
 #include "zend.h"
 #include "zend_API.h"
@@ -24,6 +24,7 @@
 ZEND_API zend_class_entry *zend_ce_traversable;
 ZEND_API zend_class_entry *zend_ce_aggregate;
 ZEND_API zend_class_entry *zend_ce_iterator;
+ZEND_API zend_class_entry *zend_ce_arrayaccess;
 
 ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, 
zend_function **fn_proxy, char *function_name, int function_name_len, zval 
**retval_ptr_ptr, int param_count, zval* arg1, zval* arg2 TSRMLS_DC);
 
Index: ZendEngine2/zend_operators.c
diff -u ZendEngine2/zend_operators.c:1.167 ZendEngine2/zend_operators.c:1.168
--- ZendEngine2/zend_operators.c:1.167  Thu Nov 13 15:53:55 2003
+++ ZendEngine2/zend_operators.c        Mon Nov 24 15:57:53 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_operators.c,v 1.167 2003/11/13 20:53:55 moriyoshi Exp $ */
+/* $Id: zend_operators.c,v 1.168 2003/11/24 20:57:53 helly Exp $ */
 
 #include <ctype.h>
 
@@ -1410,7 +1410,7 @@
 }
 
 
-ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, 
zend_class_entry *ce TSRMLS_DC)
+ZEND_API zend_bool instanceof_function_ex(zend_class_entry *instance_ce, 
zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC)
 {
        zend_uint i;
 
@@ -1419,16 +1419,23 @@
                        return 1;
                }
        }
-       while (instance_ce) {
-               if (instance_ce == ce) {
-                       return 1;
+       if (!interfaces_only) {
+               while (instance_ce) {
+                       if (instance_ce == ce) {
+                               return 1;
+                       }
+                       instance_ce = instance_ce->parent;
                }
-               instance_ce = instance_ce->parent;
        }
 
        return 0;
 }
 
+ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, 
zend_class_entry *ce TSRMLS_DC)
+{
+       return instanceof_function_ex(instance_ce, ce, 0 TSRMLS_CC);
+}
+
 #define LOWER_CASE 1
 #define UPPER_CASE 2
 #define NUMERIC 3
Index: ZendEngine2/zend_operators.h
diff -u ZendEngine2/zend_operators.h:1.81 ZendEngine2/zend_operators.h:1.82
--- ZendEngine2/zend_operators.h:1.81   Wed Oct 29 12:45:56 2003
+++ ZendEngine2/zend_operators.h        Mon Nov 24 15:57:54 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_operators.h,v 1.81 2003/10/29 17:45:56 moriyoshi Exp $ */
+/* $Id: zend_operators.h,v 1.82 2003/11/24 20:57:54 helly Exp $ */
 
 #ifndef ZEND_OPERATORS_H
 #define ZEND_OPERATORS_H
@@ -59,6 +59,7 @@
 ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC);
 ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 
TSRMLS_DC);
 
+ZEND_API zend_bool instanceof_function_ex(zend_class_entry *instance_ce, 
zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC);
 ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, 
zend_class_entry *ce TSRMLS_DC);
 
 static inline zend_bool is_numeric_string(char *str, int length, long *lval, double 
*dval, zend_bool allow_errors)
Index: ZendEngine2/zend_object_handlers.c
diff -u ZendEngine2/zend_object_handlers.c:1.76 ZendEngine2/zend_object_handlers.c:1.77
--- ZendEngine2/zend_object_handlers.c:1.76     Mon Nov 10 15:44:50 2003
+++ ZendEngine2/zend_object_handlers.c  Mon Nov 24 15:57:54 2003
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_object_handlers.c,v 1.76 2003/11/10 20:44:50 helly Exp $ */
+/* $Id: zend_object_handlers.c,v 1.77 2003/11/24 20:57:54 helly Exp $ */
 
 #include "zend.h"
 #include "zend_globals.h"
@@ -26,6 +26,7 @@
 #include "zend_objects.h"
 #include "zend_objects_API.h"
 #include "zend_object_handlers.h"
+#include "zend_interfaces.h"
 
 #define DEBUG_OBJECT_HANDLERS 0
 
@@ -352,44 +353,49 @@
 
 zval *zend_std_read_dimension(zval *object, zval *offset TSRMLS_DC)
 {
-#if 1
-       zend_error(E_ERROR, "Cannot use object as array");
-#else
-       zend_printf("Fetching from object:  ");
-       zend_print_zval(object, 0);
-
-       zend_printf("\n the offset:  ");
-       zend_print_zval(offset, 0);
-
-       zend_printf("\n");
-#endif
-       return EG(uninitialized_zval_ptr);
+       zend_class_entry *ce = Z_OBJCE_P(object);
+       zval *retval;
+       
+       if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               zend_call_method_with_1_params(&object, ce, NULL, "offsetget", 
&retval, offset);
+               if (retval->refcount > 0) { /* Should always  be  the case */
+                       retval->refcount--;
+               }
+               return retval;
+       } else {
+               zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+               return 0;
+       }
 }
 
 
 static void zend_std_write_dimension(zval *object, zval *offset, zval *value 
TSRMLS_DC)
 {
-#if 1
-       zend_error(E_ERROR, "Cannot use object as array");
-#else
-       zend_printf("Assigning to object:  ");
-       zend_print_zval(object, 0);
-
-       zend_printf("\n with offset:  ");
-       zend_print_zval(offset, 0);
-
-       zend_printf("\n the value:  ");
-       zend_print_zval(value, 0);
-
-       zend_printf("\n");
-#endif
+       zend_class_entry *ce = Z_OBJCE_P(object);
+       
+       if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, 
offset, value);
+       } else {
+               zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+       }
 }
 
 
 static int zend_std_has_dimension(zval *object, zval *offset, int check_empty 
TSRMLS_DC)
 {
-       zend_error(E_ERROR, "Cannot use object as array");
-       return 0;
+       zend_class_entry *ce = Z_OBJCE_P(object);
+       zval *retval;
+       int result;
+       
+       if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               zend_call_method_with_1_params(&object, ce, NULL, "offsetexists", 
&retval, offset);
+               result = i_zend_is_true(retval);
+               zval_ptr_dtor(&retval);
+               return result;
+       } else {
+               zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+               return 0;
+       }
 }
 
 
@@ -463,7 +469,15 @@
 
 static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
 {
-       zend_error(E_ERROR, "Cannot use object as array");
+       zend_class_entry *ce = Z_OBJCE_P(object);
+       zval *retval;
+       
+       if (instanceof_function_ex(ce, zend_ce_arrayaccess, 1 TSRMLS_CC)) {
+               zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", 
&retval, offset);
+               zval_ptr_dtor(&retval);
+       } else {
+               zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+       }
 }
 
 

Index: php-src/tests/classes/array_access_001.phpt
+++ php-src/tests/classes/array_access_001.phpt
--TEST--
ZE2 ArrayAccess
--SKIPIF--
<?php
        if (!class_exists('ArrayAccess')) die('skip ArrayAccess not present');
?>
--FILE--
<?php
class Object implements ArrayAccess {

        public $a = array('1st', 1, 2=>'3rd', '4th'=>4);

        function offsetExists($index) {
                echo __METHOD__ . "($index)\n";
                return array_key_exists($index, $this->a);
        }
        function offsetGet($index) {
                echo __METHOD__ . "($index)\n";
                return $this->a[$index];
        }
        function offsetSet($index, $newval) {
                echo __METHOD__ . "($index,$newval)\n";
                return $this->a[$index] = $newval;
        }
        function offsetUnset($index) {
                echo __METHOD__ . "($index)\n";
                unset($this->a[$index]);
        }
}

$obj = new Object;

var_dump($obj->a);

echo "===EMPTY===\n";
var_dump(empty($obj[0]));
var_dump(empty($obj[1]));
var_dump(empty($obj[2]));
var_dump(empty($obj['4th']));
var_dump(empty($obj['5th']));
var_dump(empty($obj[6]));

echo "===isset===\n";
var_dump(isset($obj[0]));
var_dump(isset($obj[1]));
var_dump(isset($obj[2]));
var_dump(isset($obj['4th']));
var_dump(isset($obj['5th']));
var_dump(isset($obj[6]));

echo "===offsetGet===\n";
var_dump($obj[0]);
var_dump($obj[1]);
var_dump($obj[2]);
var_dump($obj['4th']);
var_dump($obj['5th']);
var_dump($obj[6]);

echo "===offsetSet===\n";
echo "WRITE 1\n";
$obj[1] = 'Changed 1';
var_dump($obj[1]);
echo "WRITE 2\n";
$obj['4th'] = 'Changed 4th';
var_dump($obj['4th']);
echo "WRITE 3\n";
$obj['5th'] = 'Added 5th';
var_dump($obj['5th']);
echo "WRITE 4\n";
$obj[6] = 'Added 6';
var_dump($obj[6]);

var_dump($obj[0]);
var_dump($obj[2]);

$x = $obj[6] = 'changed 6';
var_dump($obj[6]);
var_dump($x);

echo "===unset===\n";
var_dump($obj->a);
unset($obj[2]);
unset($obj['4th']);
unset($obj[7]);
unset($obj['8th']);
var_dump($obj->a);

?>
===DONE===
--EXPECTF--
array(4) {
  [0]=>
  string(3) "1st"
  [1]=>
  int(1)
  [2]=>
  string(3) "3rd"
  ["4th"]=>
  int(4)
}
===EMPTY===
object::offsetExists(0)
bool(false)
object::offsetExists(1)
bool(false)
object::offsetExists(2)
bool(false)
object::offsetExists(4th)
bool(false)
object::offsetExists(5th)
bool(true)
object::offsetExists(6)
bool(true)
===isset===
object::offsetExists(0)
bool(true)
object::offsetExists(1)
bool(true)
object::offsetExists(2)
bool(true)
object::offsetExists(4th)
bool(true)
object::offsetExists(5th)
bool(false)
object::offsetExists(6)
bool(false)
===offsetGet===
object::offsetGet(0)
string(3) "1st"
object::offsetGet(1)
int(1)
object::offsetGet(2)
string(3) "3rd"
object::offsetGet(4th)
int(4)
object::offsetGet(5th)

Notice: Undefined index:  5th in %sarray_access_001.php on line %d
NULL
object::offsetGet(6)

Notice: Undefined offset:  6 in %sarray_access_001.php on line %d
NULL
===offsetSet===
WRITE 1
object::offsetSet(1,Changed 1)
object::offsetGet(1)
string(9) "Changed 1"
WRITE 2
object::offsetSet(4th,Changed 4th)
object::offsetGet(4th)
string(11) "Changed 4th"
WRITE 3
object::offsetSet(5th,Added 5th)
object::offsetGet(5th)
string(9) "Added 5th"
WRITE 4
object::offsetSet(6,Added 6)
object::offsetGet(6)
string(7) "Added 6"
object::offsetGet(0)
string(3) "1st"
object::offsetGet(2)
string(3) "3rd"
object::offsetSet(6,changed 6)
object::offsetGet(6)
string(9) "changed 6"
string(9) "changed 6"
===unset===
array(6) {
  [0]=>
  string(3) "1st"
  [1]=>
  string(9) "Changed 1"
  [2]=>
  string(3) "3rd"
  ["4th"]=>
  string(11) "Changed 4th"
  ["5th"]=>
  string(9) "Added 5th"
  [6]=>
  string(9) "changed 6"
}
object::offsetUnset(2)
object::offsetUnset(4th)
object::offsetUnset(7)
object::offsetUnset(8th)
array(4) {
  [0]=>
  string(3) "1st"
  [1]=>
  string(9) "Changed 1"
  ["5th"]=>
  string(9) "Added 5th"
  [6]=>
  string(9) "changed 6"
}
===DONE===

Index: php-src/tests/classes/array_access_002.phpt
+++ php-src/tests/classes/array_access_002.phpt
--TEST--
ZE2 ArrayAccess::offsetSet without return
--SKIPIF--
<?php
        if (!class_exists('ArrayAccess')) die('skip ArrayAccess not present');
?>
--FILE--
<?php
class Object implements ArrayAccess {

        public $a = array('1st', 1, 2=>'3rd', '4th'=>4);

        function offsetExists($index) {
                echo __METHOD__ . "($index)\n";
                return array_key_exists($index, $this->a);
        }
        function offsetGet($index) {
                echo __METHOD__ . "($index)\n";
                return $this->a[$index];
        }
        function offsetSet($index, $newval) {
                echo __METHOD__ . "($index,$newval)\n";
                /*return*/ $this->a[$index] = $newval;
        }
        function offsetUnset($index) {
                echo __METHOD__ . "($index)\n";
                unset($this->a[$index]);
        }
}

$obj = new Object;

var_dump($obj->a);

echo "===EMPTY===\n";
var_dump(empty($obj[0]));
var_dump(empty($obj[1]));
var_dump(empty($obj[2]));
var_dump(empty($obj['4th']));
var_dump(empty($obj['5th']));
var_dump(empty($obj[6]));

echo "===isset===\n";
var_dump(isset($obj[0]));
var_dump(isset($obj[1]));
var_dump(isset($obj[2]));
var_dump(isset($obj['4th']));
var_dump(isset($obj['5th']));
var_dump(isset($obj[6]));

echo "===offsetGet===\n";
var_dump($obj[0]);
var_dump($obj[1]);
var_dump($obj[2]);
var_dump($obj['4th']);
var_dump($obj['5th']);
var_dump($obj[6]);

echo "===offsetSet===\n";
echo "WRITE 1\n";
$obj[1] = 'Changed 1';
var_dump($obj[1]);
echo "WRITE 2\n";
$obj['4th'] = 'Changed 4th';
var_dump($obj['4th']);
echo "WRITE 3\n";
$obj['5th'] = 'Added 5th';
var_dump($obj['5th']);
echo "WRITE 4\n";
$obj[6] = 'Added 6';
var_dump($obj[6]);

var_dump($obj[0]);
var_dump($obj[2]);

$x = $obj[6] = 'changed 6';
var_dump($obj[6]);
var_dump($x);

echo "===unset===\n";
var_dump($obj->a);
unset($obj[2]);
unset($obj['4th']);
unset($obj[7]);
unset($obj['8th']);
var_dump($obj->a);

?>
===DONE===
--EXPECTF--
array(4) {
  [0]=>
  string(3) "1st"
  [1]=>
  int(1)
  [2]=>
  string(3) "3rd"
  ["4th"]=>
  int(4)
}
===EMPTY===
object::offsetExists(0)
bool(false)
object::offsetExists(1)
bool(false)
object::offsetExists(2)
bool(false)
object::offsetExists(4th)
bool(false)
object::offsetExists(5th)
bool(true)
object::offsetExists(6)
bool(true)
===isset===
object::offsetExists(0)
bool(true)
object::offsetExists(1)
bool(true)
object::offsetExists(2)
bool(true)
object::offsetExists(4th)
bool(true)
object::offsetExists(5th)
bool(false)
object::offsetExists(6)
bool(false)
===offsetGet===
object::offsetGet(0)
string(3) "1st"
object::offsetGet(1)
int(1)
object::offsetGet(2)
string(3) "3rd"
object::offsetGet(4th)
int(4)
object::offsetGet(5th)

Notice: Undefined index:  5th in %sarray_access_002.php on line %d
NULL
object::offsetGet(6)

Notice: Undefined offset:  6 in %sarray_access_002.php on line %d
NULL
===offsetSet===
WRITE 1
object::offsetSet(1,Changed 1)
object::offsetGet(1)
string(9) "Changed 1"
WRITE 2
object::offsetSet(4th,Changed 4th)
object::offsetGet(4th)
string(11) "Changed 4th"
WRITE 3
object::offsetSet(5th,Added 5th)
object::offsetGet(5th)
string(9) "Added 5th"
WRITE 4
object::offsetSet(6,Added 6)
object::offsetGet(6)
string(7) "Added 6"
object::offsetGet(0)
string(3) "1st"
object::offsetGet(2)
string(3) "3rd"
object::offsetSet(6,changed 6)
object::offsetGet(6)
string(9) "changed 6"
string(9) "changed 6"
===unset===
array(6) {
  [0]=>
  string(3) "1st"
  [1]=>
  string(9) "Changed 1"
  [2]=>
  string(3) "3rd"
  ["4th"]=>
  string(11) "Changed 4th"
  ["5th"]=>
  string(9) "Added 5th"
  [6]=>
  string(9) "changed 6"
}
object::offsetUnset(2)
object::offsetUnset(4th)
object::offsetUnset(7)
object::offsetUnset(8th)
array(4) {
  [0]=>
  string(3) "1st"
  [1]=>
  string(9) "Changed 1"
  ["5th"]=>
  string(9) "Added 5th"
  [6]=>
  string(9) "changed 6"
}
===DONE===

Index: php-src/tests/classes/array_access_003.phpt
+++ php-src/tests/classes/array_access_003.phpt
--TEST--
ZE2 ArrayAccess::offsetGet ambiguties
--SKIPIF--
<?php
        if (!class_exists('ArrayAccess')) die('skip ArrayAccess not present');
?>
--FILE--
<?php
class Object implements ArrayAccess {

        public $a = array('1st', 1, 2=>'3rd', '4th'=>4);

        function offsetExists($index) {
                echo __METHOD__ . "($index)\n";
                return array_key_exists($index, $this->a);
        }
        function &offsetGet($index) {
                echo __METHOD__ . "($index)\n";
                switch($index) {
                case 1:
                        $a = 'foo';
                        return $a . 'Bar';
                case 2:
                        static $a=1;
                        return $a;
                }
                return $this->a[$index];
        }
        function offsetSet($index, $newval) {
                echo __METHOD__ . "($index,$newval)\n";
                if ($index==3) {
                        $this->cnt = $newval;
                }
                return $this->a[$index] = $newval;
        }
        function offsetUnset($index) {
                echo __METHOD__ . "($index)\n";
                unset($this->a[$index]);
        }
}

$obj = new Object;

var_dump($obj[1]);
var_dump($obj[2]);
$obj[2]++;
var_dump($obj[2]);

?>
===DONE===
--EXPECTF--
object::offsetGet(1)
string(6) "fooBar"
object::offsetGet(2)
int(1)
object::offsetGet(2)
object::offsetGet(2)
int(2)
===DONE===

Index: php-src/tests/classes/array_access_004.phpt
+++ php-src/tests/classes/array_access_004.phpt
--TEST--
ZE2 ArrayAccess::offsetGet ambiguties
--SKIPIF--
<?php
        if (!class_exists('ArrayAccess')) die('skip ArrayAccess not present');
?>
--FILE--
<?php
class Object implements ArrayAccess {

        public $a = array('1st', 1, 2=>'3rd', '4th'=>4);

        function offsetExists($index) {
                echo __METHOD__ . "($index)\n";
                return array_key_exists($index, $this->a);
        }
        function offsetGet($index) {
                echo __METHOD__ . "($index)\n";
                switch($index) {
                case 1:
                        $a = 'foo';
                        return $a . 'Bar';
                case 2:
                        static $a=1;
                        return $a;
                }
                return $this->a[$index];
        }
        function offsetSet($index, $newval) {
                echo __METHOD__ . "($index,$newval)\n";
                if ($index==3) {
                        $this->cnt = $newval;
                }
                return $this->a[$index] = $newval;
        }
        function offsetUnset($index) {
                echo __METHOD__ . "($index)\n";
                unset($this->a[$index]);
        }
}

$obj = new Object;

var_dump($obj[1]);
var_dump($obj[2]);
$obj[2]++;
var_dump($obj[2]);

?>
===DONE===
--EXPECTF--
object::offsetGet(1)
string(6) "fooBar"
object::offsetGet(2)
int(1)
object::offsetGet(2)

Fatal error: Objects used as arrays in post/pre increment/decrement must return values 
by reference in %sarray_access_004.php on line %d

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to