]> granicus.if.org Git - php/commitdiff
MFH:
authorMarcus Boerger <helly@php.net>
Sun, 27 Jan 2008 18:07:20 +0000 (18:07 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 27 Jan 2008 18:07:20 +0000 (18:07 +0000)
[DOC] Add ability to store associative infor with objects in SplObjectStorage
- Add second parameter to SplObjectStorage::attach()
- Add SplObjectStorage::setInfo()
- Add SplObjectStorage::getInfo()

NEWS
ext/spl/internal/splobjectstorage.inc
ext/spl/spl_observer.c
ext/spl/tests/observer_004.phpt
ext/spl/tests/observer_005.phpt
ext/spl/tests/observer_006.phpt [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index 76872801e87ab463bac56c9e060a7b107dabc8fd..aec23fe3ff4e51c2edbb13aef6f435a6dbd0ab4a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,8 @@ PHP                                                                        NEWS
   * date_timestamp_set() / DateTime::setTimestamp() to set a Unix timestamp
     without invoking the date parser. (Scott)
 
+- Added ability to store associative infor with objects in SplObjectStorage.
+  (Marcus)
 - Added ability to use Traversable objects instead of plain arrays in ext/soap.
   (Joshua Reese, Dmitry)
 - Added "?:" operator. (Marcus)
index 278e64151d50781335bf8d5a8387e6f6273b0d53..c7a56b43e19b4feeddfd06f206515009b8bb5be7 100755 (executable)
@@ -4,7 +4,7 @@
  * @ingroup SPL
  * @brief class SplObjectStorage
  * @author  Marcus Boerger
- * @date    2003 - 2005
+ * @date    2003 - 2008
  *
  * SPL - Standard PHP Library
  */
@@ -12,7 +12,7 @@
 /**
  * @brief   Object storage
  * @author  Marcus Boerger
- * @version 1.0
+ * @version 1.1
  * @since PHP 5.1.2
  *
  * This container allows to store objects uniquly without the need to compare
@@ -50,7 +50,27 @@ class SplObjectStorage implements Iterator, Countable
         */
        function current()
        {
-               return current($this->storage);
+               $element = current($this->storage);
+               return $element ? $element[0] : NULL
+       }
+       
+       /** @return get current object's associated information
+        * @since 5.3.0
+        */
+       function getInfo()
+       {
+               $element = current($this->storage);
+               return $element ? $element[1] : NULL
+       }
+       
+       /** @return set current object's associated information
+        * @since 5.3.0
+        */
+       function setInfo($inf = NULL)
+       {
+               if ($this->valid()) {
+                       $this->storage[$this->index][1] = $inf;
+               }
        }
        
        /** Forward to next element
@@ -75,9 +95,9 @@ class SplObjectStorage implements Iterator, Countable
        {
                if (is_object($obj))
                {
-                       foreach($this->storage as $object)
+                       foreach($this->storage as $element)
                        {
-                               if ($object === $obj)
+                               if ($object === $element[0])
                                {
                                        return true;
                                }
@@ -88,11 +108,11 @@ class SplObjectStorage implements Iterator, Countable
 
        /** @param $obj new object to attach to storage if not yet contained
         */
-       function attach($obj)
+       function attach($obj, $inf = NULL)
        {
                if (is_object($obj) && !$this->contains($obj))
                {
-                       $this->storage[] = $obj;
+                       $this->storage[] = array($obj, $inf);
                }
        }
 
@@ -102,9 +122,9 @@ class SplObjectStorage implements Iterator, Countable
        {
                if (is_object($obj))
                {
-                       foreach($this->storage as $idx => $object)
+                       foreach($this->storage as $idx => $element)
                        {
-                               if ($object === $obj)
+                               if ($object === $element[0])
                                {
                                        unset($this->storage[$idx]);
                                        $this->rewind();
index be09ea2cbb4b56301400f9e95ee39dd44645b9c0..d9d7dc2d09813da3b74330e5900c88676ea0ab77 100755 (executable)
@@ -75,14 +75,18 @@ PHPAPI zend_class_entry     *spl_ce_SplSubject;
 PHPAPI zend_class_entry     *spl_ce_SplObjectStorage;
 PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
 
-typedef struct _spl_SplObjectStorage {
+typedef struct _spl_SplObjectStorage { /* {{{ */
        zend_object       std;
        HashTable         storage;
        long              index;
        HashPosition      pos;
-} spl_SplObjectStorage;
+} spl_SplObjectStorage; /* }}} */
 
-/* storage is an assoc aray of [zend_object_value]=>[zval*] */
+/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
+typedef struct _spl_SplObjectStorageElement {
+       zval* obj;
+       zval* inf;
+} spl_SplObjectStorageElement; /* }}} */
 
 void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
 {
@@ -95,9 +99,10 @@ void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
        efree(object);
 } /* }}} */
 
-static void spl_object_storage_dtor(zval **element) /* {{{ */
+static void spl_object_storage_dtor(spl_SplObjectStorageElement *element) /* {{{ */
 {
-       zval_ptr_dtor(element);
+       zval_ptr_dtor(&element->obj);
+       zval_ptr_dtor(&element->inf);
 } /* }}} */
 
 static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */
@@ -124,9 +129,10 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type,
 static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{ */
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
+       spl_SplObjectStorageElement *element;
        HashTable *rv, *props;
        HashPosition pos;
-       zval *tmp, *storage, **entry;
+       zval *tmp, *storage;
        char md5str[33];
        int name_len;
        char *zname;
@@ -143,10 +149,15 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_D
        array_init(storage);
 
        zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
-       while (zend_hash_get_current_data_ex(&intern->storage, (void **)&entry, &pos) == SUCCESS) {
-               php_spl_object_hash(*entry, md5str TSRMLS_CC);
-               zval_add_ref(entry);
-               add_assoc_zval_ex(storage, md5str, 33, *entry);
+       while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
+               php_spl_object_hash(element->obj, md5str TSRMLS_CC);
+               Z_ADDREF_P(element->obj);
+               Z_ADDREF_P(element->inf);
+               MAKE_STD_ZVAL(tmp);
+               array_init(tmp);
+               add_assoc_zval_ex(tmp, "obj", sizeof("obj"), element->obj);
+               add_assoc_zval_ex(tmp, "inf", sizeof("inf"), element->inf);
+               add_assoc_zval_ex(storage, md5str, 33, tmp);
                zend_hash_move_forward_ex(&intern->storage, &pos);
        }
 
@@ -181,21 +192,53 @@ int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *obj TSRMLS_D
 #endif
 } /* }}} */
 
-void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
+spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
 {
-       if (spl_object_storage_contains(intern, obj TSRMLS_CC)) {
-               return; /* already contained */
+       spl_SplObjectStorageElement *element;
+       zend_object_value *pzvalue;     
+#if HAVE_PACKED_OBJECT_VALUE
+       pzvalue = &Z_OBJVAL_P(obj);
+#else
+       zend_object_value zvalue;
+       memset(&zvalue, 0, sizeof(zend_object_value));
+       zvalue.handle = Z_OBJ_HANDLE_P(obj);
+       zvalue.handlers = Z_OBJ_HT_P(obj);
+       pzvalue = &zvalue;
+#endif
+       if (zend_hash_find(&intern->storage, (char*)pzvalue, sizeof(zend_object_value), (void**)&element) == SUCCESS) {
+               return element;
+       } else {
+               return NULL;
+       }
+} /* }}} */
+
+
+void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj, zval *inf TSRMLS_DC) /* {{{ */
+{
+       spl_SplObjectStorageElement *pelement, element;
+       pelement = spl_object_storage_get(intern, obj TSRMLS_CC);
+       if (inf) {
+               Z_ADDREF_P(inf);
+       } else {
+               ALLOC_INIT_ZVAL(inf);
+       }
+       if (pelement) {
+               zval_ptr_dtor(&pelement->inf);
+               pelement->inf = inf;
+               return;
        }
        Z_ADDREF_P(obj);
+       element.obj = obj;
+       element.inf = inf;
 #if HAVE_PACKED_OBJECT_VALUE
-       zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &obj, sizeof(zval*), NULL);      
+       zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);    
 #else
        {
                zend_object_value zvalue;
                memset(&zvalue, 0, sizeof(zend_object_value));
                zvalue.handle = Z_OBJ_HANDLE_P(obj);
                zvalue.handlers = Z_OBJ_HT_P(obj);
-               zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &obj, sizeof(zval*), NULL);
+               zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &element, sizeof(spl_SplObjectStorageElement), NULL);
        }
 #endif
 } /* }}} */
@@ -215,18 +258,18 @@ void spl_object_storage_detach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC
 #endif
 } /* }}}*/
 
-/* {{{ proto void SplObjectStorage::attach($obj)
+/* {{{ proto void SplObjectStorage::attach($obj, $inf = NULL)
  Attaches an object to the storage if not yet contained */
 SPL_METHOD(SplObjectStorage, attach)
 {
-       zval *obj;
+       zval *obj, *inf = NULL;
 
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|z!", &obj, &inf) == FAILURE) {
                return;
        }
-       spl_object_storage_attach(intern, obj TSRMLS_CC);
+       spl_object_storage_attach(intern, obj, inf TSRMLS_CC);
 } /* }}} */
 
 /* {{{ proto void SplObjectStorage::detach($obj)
@@ -268,7 +311,7 @@ SPL_METHOD(SplObjectStorage, count)
 } /* }}} */
 
 /* {{{ proto void SplObjectStorage::rewind()
- */
Rewind to first position */
 SPL_METHOD(SplObjectStorage, rewind)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -278,7 +321,7 @@ SPL_METHOD(SplObjectStorage, rewind)
 } /* }}} */
 
 /* {{{ proto bool SplObjectStorage::valid()
- */
Returns whether current position is valid */
 SPL_METHOD(SplObjectStorage, valid)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -287,7 +330,7 @@ SPL_METHOD(SplObjectStorage, valid)
 } /* }}} */
 
 /* {{{ proto mixed SplObjectStorage::key()
- */
Returns current key */
 SPL_METHOD(SplObjectStorage, key)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -296,20 +339,53 @@ SPL_METHOD(SplObjectStorage, key)
 } /* }}} */
 
 /* {{{ proto mixed SplObjectStorage::current()
- */
Returns current element */
 SPL_METHOD(SplObjectStorage, current)
 {
-       zval **entry;
+       spl_SplObjectStorageElement *element;
+       spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       
+       if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
+               return;
+       }
+       RETVAL_ZVAL(element->obj, 1, 0);
+} /* }}} */
+
+/* {{{ proto mixed SplObjectStorage::getInfo()
+ Returns associated information to current element */
+SPL_METHOD(SplObjectStorage, getInfo)
+{
+       spl_SplObjectStorageElement *element;
+       spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       
+       if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
+               return;
+       }
+       RETVAL_ZVAL(element->inf, 1, 0);
+} /* }}} */
+
+/* {{{ proto mixed SplObjectStorage::setInfo(mixed $inf)
+ Sets associated information of current element to $inf */
+SPL_METHOD(SplObjectStorage, setInfo)
+{
+       spl_SplObjectStorageElement *element;
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
+       zval *inf;
        
-       if (zend_hash_get_current_data_ex(&intern->storage, (void**)&entry, &intern->pos) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &inf) == FAILURE) {
+               return;
+       }
+
+       if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) {
                return;
        }
-       RETVAL_ZVAL(*entry, 1, 0);
+       zval_ptr_dtor(&element->inf);
+       element->inf = inf;
+       Z_ADDREF_P(inf);
 } /* }}} */
 
 /* {{{ proto void SplObjectStorage::next()
- */
Moves position forward */
 SPL_METHOD(SplObjectStorage, next)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -319,12 +395,13 @@ SPL_METHOD(SplObjectStorage, next)
 } /* }}} */
 
 /* {{{ proto string SplObjectStorage::serialize()
- */
Serializes storage */
 SPL_METHOD(SplObjectStorage, serialize)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
-       zval **entry, members, *pmembers;
+       spl_SplObjectStorageElement *element;
+       zval members, *pmembers;
        HashPosition      pos;
        php_serialize_data_t var_hash;
        smart_str buf = {0};
@@ -339,12 +416,14 @@ SPL_METHOD(SplObjectStorage, serialize)
        zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
 
        while(zend_hash_has_more_elements_ex(&intern->storage, &pos) == SUCCESS) {
-               if (zend_hash_get_current_data_ex(&intern->storage, (void**)&entry, &pos) == FAILURE) {
+               if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &pos) == FAILURE) {
                        smart_str_free(&buf);
                        PHP_VAR_SERIALIZE_DESTROY(var_hash);
                        RETURN_NULL();
                }
-               php_var_serialize(&buf, entry, &var_hash TSRMLS_CC);
+               php_var_serialize(&buf, &element->obj, &var_hash TSRMLS_CC);
+               smart_str_appendc(&buf, ',');
+               php_var_serialize(&buf, &element->inf, &var_hash TSRMLS_CC);
                smart_str_appendc(&buf, ';');
                zend_hash_move_forward_ex(&intern->storage, &pos);
        }
@@ -369,7 +448,7 @@ SPL_METHOD(SplObjectStorage, serialize)
 } /* }}} */
 
 /* {{{ proto void SplObjectStorage::unserialize(string serialized)
- */
Unserializes storage */
 SPL_METHOD(SplObjectStorage, unserialize)
 {
        spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
@@ -378,7 +457,7 @@ SPL_METHOD(SplObjectStorage, unserialize)
        int buf_len;
        const unsigned char *p, *s;
        php_unserialize_data_t var_hash;
-       zval *pentry, *pmembers, *pcount = NULL;
+       zval *pentry, *pmembers, *pcount = NULL, *pinf;
        long count;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
@@ -419,8 +498,17 @@ SPL_METHOD(SplObjectStorage, unserialize)
                        zval_ptr_dtor(&pentry);
                        goto outexcept;
                }
-               spl_object_storage_attach(intern, pentry TSRMLS_CC);
+               ALLOC_INIT_ZVAL(pinf);
+               if (*p == ',') { /* new version has inf */
+                       ++p;
+                       if (!php_var_unserialize(&pinf, &p, s + buf_len, &var_hash TSRMLS_CC)) {
+                               zval_ptr_dtor(&pinf);
+                               goto outexcept;
+                       }
+               }
+               spl_object_storage_attach(intern, pentry, pinf TSRMLS_CC);
                zval_ptr_dtor(&pentry);
+               zval_ptr_dtor(&pinf);
        }
 
        if (*p != ';') {
@@ -461,13 +549,24 @@ ZEND_BEGIN_ARG_INFO(arginfo_Object, 0)
        ZEND_ARG_INFO(0, object)
 ZEND_END_ARG_INFO();
 
+static
+ZEND_BEGIN_ARG_INFO_EX(arginfo_attach, 0, 0, 1)
+       ZEND_ARG_INFO(0, object)
+       ZEND_ARG_INFO(0, inf)
+ZEND_END_ARG_INFO();
+
 static
 ZEND_BEGIN_ARG_INFO(arginfo_Serialized, 0)
        ZEND_ARG_INFO(0, serialized)
 ZEND_END_ARG_INFO();
 
+static
+ZEND_BEGIN_ARG_INFO(arginfo_setInfo, 0)
+       ZEND_ARG_INFO(0, info)
+ZEND_END_ARG_INFO();
+
 static const zend_function_entry spl_funcs_SplObjectStorage[] = {
-       SPL_ME(SplObjectStorage,  attach,      arginfo_Object,        0)
+       SPL_ME(SplObjectStorage,  attach,      arginfo_attach,        0)
        SPL_ME(SplObjectStorage,  detach,      arginfo_Object,        0)
        SPL_ME(SplObjectStorage,  contains,    arginfo_Object,        0)
        SPL_ME(SplObjectStorage,  count,       NULL,                  0)
@@ -478,6 +577,8 @@ static const zend_function_entry spl_funcs_SplObjectStorage[] = {
        SPL_ME(SplObjectStorage,  next,        NULL,                  0)
        SPL_ME(SplObjectStorage,  unserialize, arginfo_Serialized,    0)
        SPL_ME(SplObjectStorage,  serialize,   NULL,                  0)
+       SPL_ME(SplObjectStorage,  getInfo,     NULL,                  0)
+       SPL_ME(SplObjectStorage,  setInfo,     arginfo_setInfo,       0)
        {NULL, NULL, NULL}
 };
 
index c24f5ed777f05776aadaaf4fb46ad8d90caf8a50..cfc207395d23ea1604419100d4346e68b1a93f8f 100755 (executable)
@@ -68,14 +68,24 @@ object(MyStorage)#%d (2) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
     ["%s"]=>
-    object(TestClass)#%d (1) {
-      ["test"]=>
-      int(1)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      NULL
     }
     ["%s"]=>
-    object(TestClass)#%d (1) {
-      ["test"]=>
-      int(2)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      NULL
     }
   }
 }
@@ -90,14 +100,24 @@ object(MyStorage)#%d (2) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
     ["%s"]=>
-    object(TestClass)#%d (1) {
-      ["test"]=>
-      int(1)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      NULL
     }
     ["%s"]=>
-    object(TestClass)#%d (1) {
-      ["test"]=>
-      int(2)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      NULL
     }
   }
 }
index ae5966bfe75e498bd313ccee179442266200951c..4d4d717842bbef96c15762089a7724064426876c 100755 (executable)
@@ -110,26 +110,36 @@ object(MyStorage)#%d (5) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
     ["%s"]=>
-    object(TestClass)#%d (4) {
-      ["def"]=>
-      int(24)
-      ["pub"]=>
-      int(4)
-      ["pro":protected]=>
-      int(5)
-      ["pri":"TestClass":private]=>
-      int(6)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (4) {
+        ["def"]=>
+        int(24)
+        ["pub"]=>
+        int(4)
+        ["pro":protected]=>
+        int(5)
+        ["pri":"TestClass":private]=>
+        int(6)
+      }
+      ["inf"]=>
+      NULL
     }
     ["%s"]=>
-    object(TestClass)#%d (4) {
-      ["def"]=>
-      int(24)
-      ["pub"]=>
-      int(7)
-      ["pro":protected]=>
-      int(8)
-      ["pri":"TestClass":private]=>
-      int(9)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (4) {
+        ["def"]=>
+        int(24)
+        ["pub"]=>
+        int(7)
+        ["pro":protected]=>
+        int(8)
+        ["pri":"TestClass":private]=>
+        int(9)
+      }
+      ["inf"]=>
+      NULL
     }
   }
 }
@@ -168,26 +178,36 @@ object(MyStorage)#%d (5) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
     ["%s"]=>
-    object(TestClass)#%d (4) {
-      ["def"]=>
-      int(24)
-      ["pub"]=>
-      int(4)
-      ["pro":protected]=>
-      int(5)
-      ["pri":"TestClass":private]=>
-      int(6)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (4) {
+        ["def"]=>
+        int(24)
+        ["pub"]=>
+        int(4)
+        ["pro":protected]=>
+        int(5)
+        ["pri":"TestClass":private]=>
+        int(6)
+      }
+      ["inf"]=>
+      NULL
     }
     ["%s"]=>
-    object(TestClass)#%d (4) {
-      ["def"]=>
-      int(24)
-      ["pub"]=>
-      int(7)
-      ["pro":protected]=>
-      int(8)
-      ["pri":"TestClass":private]=>
-      int(9)
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (4) {
+        ["def"]=>
+        int(24)
+        ["pub"]=>
+        int(7)
+        ["pro":protected]=>
+        int(8)
+        ["pri":"TestClass":private]=>
+        int(9)
+      }
+      ["inf"]=>
+      NULL
     }
   }
 }
diff --git a/ext/spl/tests/observer_006.phpt b/ext/spl/tests/observer_006.phpt
new file mode 100755 (executable)
index 0000000..fc4a907
--- /dev/null
@@ -0,0 +1,312 @@
+--TEST--
+SPL: SplObjectStorage with accociatied information
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+
+class TestClass
+{
+       public $test = 25;
+       
+       public function __construct($test = 42)
+       {
+               $this->test = $test;
+       }
+}
+
+class MyStorage extends SplObjectStorage
+{
+       public $bla = 25;
+       
+       public function __construct($bla = 26)
+       {
+               $this->bla = $bla;
+       }
+}
+
+$storage = new MyStorage();
+
+foreach(array(1=>"foo",2=>42) as $key => $value)
+{
+     $storage->attach(new TestClass($key), $value);
+}
+
+var_dump(count($storage));
+
+foreach($storage as $object)
+{
+       var_dump($object->test);
+}
+
+var_dump($storage);
+
+var_dump(serialize($storage));
+echo "===UNSERIALIZE===\n";
+
+$storage2 = unserialize(serialize($storage));
+
+var_dump(count($storage2));
+
+foreach($storage2 as $object)
+{
+       var_dump($object->test);
+}
+
+var_dump($storage2);
+$storage->attach(new TestClass(3), new stdClass);
+$storage->attach(new TestClass(4), new TestClass(5));
+echo "===UNSERIALIZE2===\n";
+var_dump(unserialize(serialize($storage)));
+$storage->rewind();
+$storage->next();
+var_dump($storage->key());
+var_dump($storage->current());
+var_dump($storage->getInfo());
+$storage->setInfo("bar");
+var_dump($storage->getInfo());
+echo "===UNSERIALIZE3===\n";
+var_dump(unserialize(serialize($storage)));
+$storage->rewind();
+$storage->next();
+$storage->next();
+var_dump($storage->key());
+var_dump($storage->current());
+$storage->attach($storage->current(), "replaced");
+echo "===UNSERIALIZE4===\n";
+var_dump(unserialize(serialize($storage)));
+
+?>
+===DONE===
+<?php exit(0); ?>
+--EXPECTF--
+int(2)
+int(1)
+int(2)
+object(MyStorage)#%d (2) {
+  ["bla"]=>
+  int(26)
+  ["storage":"SplObjectStorage":private]=>
+  array(2) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      string(3) "foo"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      int(42)
+    }
+  }
+}
+string(%d) "%s"
+===UNSERIALIZE===
+int(2)
+int(1)
+int(2)
+object(MyStorage)#%d (2) {
+  ["bla"]=>
+  int(26)
+  ["storage":"SplObjectStorage":private]=>
+  array(2) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      string(3) "foo"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      int(42)
+    }
+  }
+}
+===UNSERIALIZE2===
+object(MyStorage)#%d (2) {
+  ["bla"]=>
+  int(26)
+  ["storage":"SplObjectStorage":private]=>
+  array(4) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      string(3) "foo"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      int(42)
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(3)
+      }
+      ["inf"]=>
+      object(stdClass)#%d (0) {
+      }
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(4)
+      }
+      ["inf"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(5)
+      }
+    }
+  }
+}
+int(1)
+object(TestClass)#%d (1) {
+  ["test"]=>
+  int(2)
+}
+int(42)
+string(3) "bar"
+===UNSERIALIZE3===
+object(MyStorage)#%d (2) {
+  ["bla"]=>
+  int(26)
+  ["storage":"SplObjectStorage":private]=>
+  array(4) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      string(3) "foo"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      string(3) "bar"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(3)
+      }
+      ["inf"]=>
+      object(stdClass)#%d (0) {
+      }
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(4)
+      }
+      ["inf"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(5)
+      }
+    }
+  }
+}
+int(2)
+object(TestClass)#7 (1) {
+  ["test"]=>
+  int(3)
+}
+===UNSERIALIZE4===
+object(MyStorage)#%d (2) {
+  ["bla"]=>
+  int(26)
+  ["storage":"SplObjectStorage":private]=>
+  array(4) {
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(1)
+      }
+      ["inf"]=>
+      string(3) "foo"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(2)
+      }
+      ["inf"]=>
+      string(3) "bar"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(3)
+      }
+      ["inf"]=>
+      string(8) "replaced"
+    }
+    ["%s"]=>
+    array(2) {
+      ["obj"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(4)
+      }
+      ["inf"]=>
+      object(TestClass)#%d (1) {
+        ["test"]=>
+        int(5)
+      }
+    }
+  }
+}
+===DONE===