LTP GCOV extension - code coverage report
Current view: directory - ext/spl - spl_observer.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 144
Code covered: 6.2 % Executed lines: 9
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is SplSubject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Marcus Boerger <helly@php.net>                              |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: spl_observer.c,v 1.2.2.6.2.3 2007/02/08 22:14:25 helly Exp $ */
      20                 : 
      21                 : #ifdef HAVE_CONFIG_H
      22                 : # include "config.h"
      23                 : #endif
      24                 : 
      25                 : #include "php.h"
      26                 : #include "php_ini.h"
      27                 : #include "ext/standard/info.h"
      28                 : #include "ext/standard/php_var.h"
      29                 : #include "ext/standard/php_smart_str.h"
      30                 : #include "zend_interfaces.h"
      31                 : #include "zend_exceptions.h"
      32                 : 
      33                 : #include "php_spl.h"
      34                 : #include "spl_functions.h"
      35                 : #include "spl_engine.h"
      36                 : #include "spl_observer.h"
      37                 : #include "spl_iterators.h"
      38                 : #include "spl_array.h"
      39                 : #include "spl_exceptions.h"
      40                 : 
      41                 : SPL_METHOD(SplObserver, update);
      42                 : SPL_METHOD(SplSubject, attach);
      43                 : SPL_METHOD(SplSubject, detach);
      44                 : SPL_METHOD(SplSubject, notify);
      45                 : 
      46                 : static
      47                 : ZEND_BEGIN_ARG_INFO(arginfo_SplObserver_update, 0)
      48                 :         ZEND_ARG_OBJ_INFO(0, SplSubject, SplSubject, 0)
      49                 : ZEND_END_ARG_INFO();
      50                 : 
      51                 : static zend_function_entry spl_funcs_SplObserver[] = {
      52                 :         SPL_ABSTRACT_ME(SplObserver, update,   arginfo_SplObserver_update)
      53                 :         {NULL, NULL, NULL}
      54                 : };
      55                 : 
      56                 : static
      57                 : ZEND_BEGIN_ARG_INFO(arginfo_SplSubject_attach, 0)
      58                 :         ZEND_ARG_OBJ_INFO(0, SplObserver, SplObserver, 0)
      59                 : ZEND_END_ARG_INFO();
      60                 : 
      61                 : /*static
      62                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_SplSubject_notify, 0, 0, 1)
      63                 :         ZEND_ARG_OBJ_INFO(0, ignore, SplObserver, 1)
      64                 : ZEND_END_ARG_INFO();*/
      65                 : 
      66                 : static zend_function_entry spl_funcs_SplSubject[] = {
      67                 :         SPL_ABSTRACT_ME(SplSubject,  attach,   arginfo_SplSubject_attach)
      68                 :         SPL_ABSTRACT_ME(SplSubject,  detach,   arginfo_SplSubject_attach)
      69                 :         SPL_ABSTRACT_ME(SplSubject,  notify,   NULL)
      70                 :         {NULL, NULL, NULL}
      71                 : };
      72                 : 
      73                 : PHPAPI zend_class_entry     *spl_ce_SplObserver;
      74                 : PHPAPI zend_class_entry     *spl_ce_SplSubject;
      75                 : PHPAPI zend_class_entry     *spl_ce_SplObjectStorage;
      76                 : PHPAPI zend_object_handlers spl_handler_SplObjectStorage;
      77                 : 
      78                 : typedef struct _spl_SplObjectStorage {
      79                 :         zend_object       std;
      80                 :         HashTable         storage;
      81                 :         long              index;
      82                 :         HashPosition      pos;
      83                 : } spl_SplObjectStorage;
      84                 : 
      85                 : /* storage is an assoc aray of [zend_object_value]=>[zval*] */
      86                 : 
      87                 : void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
      88               0 : {
      89               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object;
      90                 : 
      91               0 :         zend_object_std_dtor(&intern->std TSRMLS_CC);
      92                 :         
      93               0 :         zend_hash_destroy(&intern->storage);
      94                 : 
      95               0 :         efree(object);
      96               0 : } /* }}} */
      97                 : 
      98                 : static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type, spl_SplObjectStorage **obj, zval *orig TSRMLS_DC) /* {{{ */
      99               0 : {
     100                 :         zend_object_value retval;
     101                 :         spl_SplObjectStorage *intern;
     102                 :         zval *tmp;
     103                 : 
     104               0 :         intern = emalloc(sizeof(spl_SplObjectStorage));
     105               0 :         memset(intern, 0, sizeof(spl_SplObjectStorage));
     106               0 :         *obj = intern;
     107                 : 
     108               0 :         zend_object_std_init(&intern->std, class_type TSRMLS_CC);
     109               0 :         zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     110                 : 
     111               0 :         zend_hash_init(&intern->storage, 0, NULL, ZVAL_PTR_DTOR, 0);
     112                 : 
     113               0 :         retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage, NULL TSRMLS_CC);
     114               0 :         retval.handlers = &spl_handler_SplObjectStorage;
     115               0 :         return retval;
     116                 : }
     117                 : /* }}} */
     118                 : 
     119                 : /* {{{ spl_array_object_new */
     120                 : static zend_object_value spl_SplObjectStorage_new(zend_class_entry *class_type TSRMLS_DC)
     121               0 : {
     122                 :         spl_SplObjectStorage *tmp;
     123               0 :         return spl_object_storage_new_ex(class_type, &tmp, NULL TSRMLS_CC);
     124                 : }
     125                 : /* }}} */
     126                 : 
     127                 : void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *obj TSRMLS_DC) /* {{{ */
     128               0 : {
     129                 : #if HAVE_PACKED_OBJECT_VALUE
     130               0 :         zend_hash_update(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value), &obj, sizeof(zval*), NULL);       
     131                 : #else
     132                 :         {
     133                 :                 zend_object_value zvalue;
     134                 :                 memset(&zvalue, 0, sizeof(zend_object_value));
     135                 :                 zvalue.handle = Z_OBJ_HANDLE_P(obj);
     136                 :                 zvalue.handlers = Z_OBJ_HT_P(obj);
     137                 :                 zend_hash_update(&intern->storage, (char*)&zvalue, sizeof(zend_object_value), &obj, sizeof(zval*), NULL);
     138                 :         }
     139                 : #endif
     140                 : 
     141               0 :         obj->refcount++;
     142               0 : } /* }}} */
     143                 : 
     144                 : /* {{{ proto void SplObjectStorage::attach($obj)
     145                 :  Attaches an object to the storage if not yet contained */
     146                 : SPL_METHOD(SplObjectStorage, attach)
     147               0 : {
     148                 :         zval *obj;
     149                 : 
     150               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     151                 : 
     152               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
     153               0 :                 return;
     154                 :         }
     155               0 :         spl_object_storage_attach(intern, obj TSRMLS_CC);
     156                 : } /* }}} */
     157                 : 
     158                 : /* {{{ proto void SplObjectStorage::detach($obj)
     159                 :  Detaches an object from the storage */
     160                 : SPL_METHOD(SplObjectStorage, detach)
     161               0 : {
     162                 :         zval *obj;
     163               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     164                 : 
     165               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
     166               0 :                 return;
     167                 :         }
     168                 : 
     169                 : #if HAVE_PACKED_OBJECT_VALUE
     170               0 :         zend_hash_del(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value));
     171                 : #else
     172                 :         {
     173                 :                 zend_object_value zvalue;
     174                 :                 memset(&zvalue, 0, sizeof(zend_object_value));
     175                 :                 zvalue.handle = Z_OBJ_HANDLE_P(obj);
     176                 :                 zvalue.handlers = Z_OBJ_HT_P(obj);
     177                 :                 zend_hash_del(&intern->storage, (char*)&zvalue, sizeof(zend_object_value));
     178                 :         }
     179                 : #endif
     180                 : 
     181               0 :         zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
     182               0 :         intern->index = 0;
     183                 : } /* }}} */
     184                 : 
     185                 : /* {{{ proto bool SplObjectStorage::contains($obj)
     186                 :  Determine whethe an object is contained in the storage */
     187                 : SPL_METHOD(SplObjectStorage, contains)
     188               0 : {
     189                 :         zval *obj;
     190               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     191                 : 
     192               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
     193               0 :                 return;
     194                 :         }
     195                 : 
     196                 : #if HAVE_PACKED_OBJECT_VALUE
     197               0 :         RETURN_BOOL(zend_hash_exists(&intern->storage, (char*)&Z_OBJVAL_P(obj), sizeof(zend_object_value)));
     198                 : #else
     199                 :         {
     200                 :                 zend_object_value zvalue;
     201                 :                 memset(&zvalue, 0, sizeof(zend_object_value));
     202                 :                 zvalue.handle = Z_OBJ_HANDLE_P(obj);
     203                 :                 zvalue.handlers = Z_OBJ_HT_P(obj);
     204                 :                 RETURN_BOOL(zend_hash_exists(&intern->storage, (char*)&zvalue, sizeof(zend_object_value)));
     205                 :         }
     206                 : #endif
     207                 : } /* }}} */
     208                 : 
     209                 : /* {{{ proto int SplObjectStorage::count()
     210                 :  Determine number of objects in storage */
     211                 : SPL_METHOD(SplObjectStorage, count)
     212               0 : {
     213               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     214                 :         
     215               0 :         RETURN_LONG(zend_hash_num_elements(&intern->storage));
     216                 : } /* }}} */
     217                 : 
     218                 : /* {{{ proto void SplObjectStorage::rewind()
     219                 :  */
     220                 : SPL_METHOD(SplObjectStorage, rewind)
     221               0 : {
     222               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     223                 :         
     224               0 :         zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos);
     225               0 :         intern->index = 0;
     226               0 : } /* }}} */
     227                 : 
     228                 : /* {{{ proto bool SplObjectStorage::valid()
     229                 :  */
     230                 : SPL_METHOD(SplObjectStorage, valid)
     231               0 : {
     232               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     233                 :         
     234               0 :         RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, &intern->pos) == SUCCESS);
     235                 : } /* }}} */
     236                 : 
     237                 : /* {{{ proto mixed SplObjectStorage::key()
     238                 :  */
     239                 : SPL_METHOD(SplObjectStorage, key)
     240               0 : {
     241               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     242                 :         
     243               0 :         RETURN_LONG(intern->index);
     244                 : } /* }}} */
     245                 : 
     246                 : /* {{{ proto mixed SplObjectStorage::current()
     247                 :  */
     248                 : SPL_METHOD(SplObjectStorage, current)
     249               0 : {
     250                 :         zval **entry;
     251               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     252                 :         
     253               0 :         if (zend_hash_get_current_data_ex(&intern->storage, (void**)&entry, &intern->pos) == FAILURE) {
     254               0 :                 return;
     255                 :         }
     256               0 :         RETVAL_ZVAL(*entry, 1, 0);
     257                 : } /* }}} */
     258                 : 
     259                 : /* {{{ proto void SplObjectStorage::next()
     260                 :  */
     261                 : SPL_METHOD(SplObjectStorage, next)
     262               0 : {
     263               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     264                 :         
     265               0 :         zend_hash_move_forward_ex(&intern->storage, &intern->pos);
     266               0 :         intern->index++;
     267               0 : } /* }}} */
     268                 : 
     269                 : /* {{{ proto string SplObjectStorage::serialize()
     270                 :  */
     271                 : SPL_METHOD(SplObjectStorage, serialize)
     272               0 : {
     273               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     274                 : 
     275                 :         zval **entry, members, *pmembers;
     276                 :         HashPosition      pos;
     277                 :         php_serialize_data_t var_hash;
     278               0 :         smart_str buf = {0};
     279                 : 
     280               0 :         PHP_VAR_SERIALIZE_INIT(var_hash);
     281                 : 
     282                 :         /* storage */
     283               0 :         smart_str_appendl(&buf, "x:i:", 4);
     284               0 :         smart_str_append_long(&buf, zend_hash_num_elements(&intern->storage));
     285               0 :         smart_str_appendc(&buf, ';');
     286                 : 
     287               0 :         zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
     288                 : 
     289               0 :         while(zend_hash_has_more_elements_ex(&intern->storage, &pos) == SUCCESS) {
     290               0 :                 if (zend_hash_get_current_data_ex(&intern->storage, (void**)&entry, &pos) == FAILURE) {
     291               0 :                         smart_str_free(&buf);
     292               0 :                         PHP_VAR_SERIALIZE_DESTROY(var_hash);
     293               0 :                         RETURN_NULL();
     294                 :                 }
     295               0 :                 php_var_serialize(&buf, entry, &var_hash TSRMLS_CC);
     296               0 :                 smart_str_appendc(&buf, ';');
     297               0 :                 zend_hash_move_forward_ex(&intern->storage, &pos);
     298                 :         }
     299                 : 
     300                 :         /* members */
     301               0 :         smart_str_appendl(&buf, "m:", 2);
     302               0 :         INIT_PZVAL(&members);
     303               0 :         Z_ARRVAL(members) = intern->std.properties;
     304               0 :         Z_TYPE(members) = IS_ARRAY;
     305               0 :         pmembers = &members;
     306               0 :         php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
     307                 : 
     308                 :         /* done */
     309               0 :         PHP_VAR_SERIALIZE_DESTROY(var_hash);
     310                 : 
     311               0 :         if (buf.c) {
     312               0 :                 RETURN_STRINGL(buf.c, buf.len, 0);
     313                 :         } else {
     314               0 :                 RETURN_NULL();
     315                 :         }
     316                 :         
     317                 : } /* }}} */
     318                 : 
     319                 : /* {{{ proto void SplObjectStorage::unserialize(string serialized)
     320                 :  */
     321                 : SPL_METHOD(SplObjectStorage, unserialize)
     322               0 : {
     323               0 :         spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC);
     324                 : 
     325                 :         char *buf;
     326                 :         int buf_len;
     327                 :         const unsigned char *p, *s;
     328                 :         php_unserialize_data_t var_hash;
     329               0 :         zval *pentry, *pmembers, *pcount = NULL;
     330                 :         long count;
     331                 :         
     332               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) {
     333               0 :                 return;
     334                 :         }
     335                 : 
     336               0 :         if (buf_len == 0) {
     337               0 :                 zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Empty serialized string cannot be empty");
     338               0 :                 return;
     339                 :         }
     340                 : 
     341                 :         /* storage */
     342               0 :         s = p = (const unsigned char*)buf;
     343               0 :         PHP_VAR_UNSERIALIZE_INIT(var_hash);
     344                 : 
     345               0 :         if (*p!= 'x' || *++p != ':') {
     346                 :                 goto outexcept;
     347                 :         }
     348               0 :         ++p;
     349                 : 
     350               0 :         ALLOC_INIT_ZVAL(pcount);
     351               0 :         if (!php_var_unserialize(&pcount, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pcount) != IS_LONG) {
     352               0 :                 zval_ptr_dtor(&pcount);
     353               0 :                 goto outexcept;
     354                 :         }
     355                 : 
     356               0 :         --p; /* for ';' */
     357               0 :         count = Z_LVAL_P(pcount);
     358               0 :         zval_ptr_dtor(&pcount);
     359                 :                 
     360               0 :         while(count-- > 0) {
     361               0 :                 if (*p != ';') {
     362               0 :                         goto outexcept;
     363                 :                 }
     364               0 :                 ++p;
     365               0 :                 ALLOC_INIT_ZVAL(pentry);
     366               0 :                 if (!php_var_unserialize(&pentry, &p, s + buf_len, &var_hash TSRMLS_CC)) {
     367               0 :                         zval_ptr_dtor(&pentry);
     368               0 :                         goto outexcept;
     369                 :                 }
     370               0 :                 spl_object_storage_attach(intern, pentry TSRMLS_CC);
     371               0 :                 zval_ptr_dtor(&pentry);
     372                 :         }
     373                 : 
     374               0 :         if (*p != ';') {
     375               0 :                 goto outexcept;
     376                 :         }
     377               0 :         ++p;
     378                 : 
     379                 :         /* members */
     380               0 :         if (*p!= 'm' || *++p != ':') {
     381                 :                 goto outexcept;
     382                 :         }
     383               0 :         ++p;
     384                 : 
     385               0 :         ALLOC_INIT_ZVAL(pmembers);
     386               0 :         if (!php_var_unserialize(&pmembers, &p, s + buf_len, &var_hash TSRMLS_CC)) {
     387               0 :                 zval_ptr_dtor(&pmembers);
     388               0 :                 goto outexcept;
     389                 :         }
     390                 : 
     391                 :         /* copy members */
     392               0 :         zend_hash_copy(intern->std.properties, Z_ARRVAL_P(pmembers), (copy_ctor_func_t) zval_add_ref, (void *) NULL, sizeof(zval *));
     393               0 :         zval_ptr_dtor(&pmembers);
     394                 : 
     395                 :         /* done reading $serialized */
     396                 : 
     397               0 :         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
     398               0 :         return;
     399                 : 
     400               0 : outexcept:
     401               0 :         PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
     402               0 :         zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len);
     403               0 :         return;
     404                 : 
     405                 : } /* }}} */
     406                 : 
     407                 : static
     408                 : ZEND_BEGIN_ARG_INFO(arginfo_Object, 0)
     409                 :         ZEND_ARG_INFO(0, object)
     410                 : ZEND_END_ARG_INFO();
     411                 : 
     412                 : static
     413                 : ZEND_BEGIN_ARG_INFO(arginfo_Serialized, 0)
     414                 :         ZEND_ARG_INFO(0, serialized)
     415                 : ZEND_END_ARG_INFO();
     416                 : 
     417                 : static zend_function_entry spl_funcs_SplObjectStorage[] = {
     418                 :         SPL_ME(SplObjectStorage,  attach,      arginfo_Object,        0)
     419                 :         SPL_ME(SplObjectStorage,  detach,      arginfo_Object,        0)
     420                 :         SPL_ME(SplObjectStorage,  contains,    arginfo_Object,        0)
     421                 :         SPL_ME(SplObjectStorage,  count,       NULL,                  0)
     422                 :         SPL_ME(SplObjectStorage,  rewind,      NULL,                  0)
     423                 :         SPL_ME(SplObjectStorage,  valid,       NULL,                  0)
     424                 :         SPL_ME(SplObjectStorage,  key,         NULL,                  0)
     425                 :         SPL_ME(SplObjectStorage,  current,     NULL,                  0)
     426                 :         SPL_ME(SplObjectStorage,  next,        NULL,                  0)
     427                 :         SPL_ME(SplObjectStorage,  unserialize, arginfo_Serialized,    0)
     428                 :         SPL_ME(SplObjectStorage,  serialize,   NULL,                  0)
     429                 :         {NULL, NULL, NULL}
     430                 : };
     431                 : 
     432                 : /* {{{ PHP_MINIT_FUNCTION(spl_observer) */
     433                 : PHP_MINIT_FUNCTION(spl_observer)
     434             220 : {
     435             220 :         REGISTER_SPL_INTERFACE(SplObserver);
     436             220 :         REGISTER_SPL_INTERFACE(SplSubject);
     437                 : 
     438             220 :         REGISTER_SPL_STD_CLASS_EX(SplObjectStorage, spl_SplObjectStorage_new, spl_funcs_SplObjectStorage);
     439             220 :         memcpy(&spl_handler_SplObjectStorage, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
     440                 : 
     441             220 :         REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Countable);
     442             220 :         REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Iterator);
     443             220 :         REGISTER_SPL_IMPLEMENTS(SplObjectStorage, Serializable);
     444                 : 
     445             220 :         return SUCCESS;
     446                 : }
     447                 : /* }}} */
     448                 : 
     449                 : /*
     450                 :  * Local variables:
     451                 :  * tab-width: 4
     452                 :  * c-basic-offset: 4
     453                 :  * End:
     454                 :  * vim600: fdm=marker
     455                 :  * vim: noet sw=4 ts=4
     456                 :  */

Generated by: LTP GCOV extension version 1.5