PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - spl - spl_dllist.c
Test: PHP Code Coverage
Date: 2009-11-21 Instrumented lines: 509
Code covered: 92.9 % Executed lines: 473
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject 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: Etienne Kneuss <colder@php.net>                             |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : 
      19                 : /* $Id: spl_dllist.c 287266 2009-08-13 22:07:05Z colder $ */
      20                 : 
      21                 : #ifdef HAVE_CONFIG_H
      22                 : # include "config.h"
      23                 : #endif
      24                 : 
      25                 : #include "php.h"
      26                 : #include "zend_exceptions.h"
      27                 : #include "zend_hash.h"
      28                 : 
      29                 : #include "php_spl.h"
      30                 : #include "spl_functions.h"
      31                 : #include "spl_engine.h"
      32                 : #include "spl_iterators.h"
      33                 : #include "spl_dllist.h"
      34                 : #include "spl_exceptions.h"
      35                 : 
      36                 : zend_object_handlers spl_handler_SplDoublyLinkedList;
      37                 : PHPAPI zend_class_entry  *spl_ce_SplDoublyLinkedList;
      38                 : PHPAPI zend_class_entry  *spl_ce_SplQueue;
      39                 : PHPAPI zend_class_entry  *spl_ce_SplStack;
      40                 : 
      41                 : #define SPL_LLIST_DELREF(elem) if(!--(elem)->rc) { \
      42                 :         efree(elem); \
      43                 :         elem = NULL; \
      44                 : }
      45                 : 
      46                 : #define SPL_LLIST_CHECK_DELREF(elem) if((elem) && !--(elem)->rc) { \
      47                 :         efree(elem); \
      48                 :         elem = NULL; \
      49                 : }
      50                 : 
      51                 : #define SPL_LLIST_ADDREF(elem) (elem)->rc++
      52                 : #define SPL_LLIST_CHECK_ADDREF(elem) if(elem) (elem)->rc++
      53                 : 
      54                 : #define SPL_DLLIST_IT_DELETE 0x00000001 /* Delete flag makes the iterator delete the current element on next */
      55                 : #define SPL_DLLIST_IT_LIFO   0x00000002 /* LIFO flag makes the iterator traverse the structure as a LastInFirstOut */
      56                 : #define SPL_DLLIST_IT_MASK   0x00000003 /* Mask to isolate flags related to iterators */
      57                 : #define SPL_DLLIST_IT_FIX    0x00000004 /* Backward/Forward bit is fixed */
      58                 : 
      59                 : #ifdef accept
      60                 : #undef accept
      61                 : #endif
      62                 : 
      63                 : typedef struct _spl_ptr_llist_element {
      64                 :         struct _spl_ptr_llist_element *prev;
      65                 :         struct _spl_ptr_llist_element *next;
      66                 :         int                            rc;
      67                 :         void                          *data;
      68                 : } spl_ptr_llist_element;
      69                 : 
      70                 : typedef void (*spl_ptr_llist_dtor_func)(spl_ptr_llist_element * TSRMLS_DC);
      71                 : typedef void (*spl_ptr_llist_ctor_func)(spl_ptr_llist_element * TSRMLS_DC);
      72                 : 
      73                 : typedef struct _spl_ptr_llist {
      74                 :         spl_ptr_llist_element   *head;
      75                 :         spl_ptr_llist_element   *tail;
      76                 :         spl_ptr_llist_dtor_func  dtor;
      77                 :         spl_ptr_llist_ctor_func  ctor;
      78                 :         int count;
      79                 : } spl_ptr_llist;
      80                 : 
      81                 : typedef struct _spl_dllist_object spl_dllist_object;
      82                 : typedef struct _spl_dllist_it spl_dllist_it;
      83                 : 
      84                 : struct _spl_dllist_object {
      85                 :         zend_object            std;
      86                 :         spl_ptr_llist         *llist;
      87                 :         int                    traverse_position;
      88                 :         spl_ptr_llist_element *traverse_pointer;
      89                 :         zval                  *retval;
      90                 :         int                    flags;
      91                 :         zend_function         *fptr_offset_get;
      92                 :         zend_function         *fptr_offset_set;
      93                 :         zend_function         *fptr_offset_has;
      94                 :         zend_function         *fptr_offset_del;
      95                 :         zend_function         *fptr_count;
      96                 :         zend_class_entry      *ce_get_iterator;
      97                 :         HashTable             *debug_info;
      98                 : };
      99                 : 
     100                 : /* define an overloaded iterator structure */
     101                 : struct _spl_dllist_it {
     102                 :         zend_user_iterator     intern;
     103                 :         int                    traverse_position;
     104                 :         spl_ptr_llist_element *traverse_pointer;
     105                 :         int                    flags;
     106                 :         spl_dllist_object     *object;
     107                 : };
     108                 : 
     109                 : /* {{{  spl_ptr_llist */
     110             106 : static void spl_ptr_llist_zval_dtor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */
     111             106 :         if (elem->data) {
     112             106 :                 zval_ptr_dtor((zval **)&elem->data);
     113                 :         }
     114             106 : }
     115                 : /* }}} */
     116                 : 
     117             116 : static void spl_ptr_llist_zval_ctor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */
     118             116 :         Z_ADDREF_P((zval *)elem->data);
     119             116 : }
     120                 : /* }}} */
     121                 : 
     122                 : static spl_ptr_llist *spl_ptr_llist_init(spl_ptr_llist_ctor_func ctor, spl_ptr_llist_dtor_func dtor) /* {{{ */
     123              63 : {
     124              63 :         spl_ptr_llist *llist = emalloc(sizeof(spl_ptr_llist));
     125                 : 
     126              63 :         llist->head  = NULL;
     127              63 :         llist->tail  = NULL;
     128              63 :         llist->count = 0;
     129              63 :         llist->dtor  = dtor;
     130              63 :         llist->ctor  = ctor;
     131                 : 
     132              63 :         return llist;
     133                 : }
     134                 : /* }}} */
     135                 : 
     136                 : static long spl_ptr_llist_count(spl_ptr_llist *llist) /* {{{ */
     137              16 : {
     138              16 :         return (long)llist->count;
     139                 : }
     140                 : /* }}} */
     141                 : 
     142                 : static void spl_ptr_llist_destroy(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
     143              63 : {
     144              63 :         spl_ptr_llist_element   *current = llist->head, *next;
     145              63 :         spl_ptr_llist_dtor_func  dtor    = llist->dtor;
     146                 : 
     147             126 :         while (current) {
     148               0 :                 next = current->next;
     149               0 :                 if(current && dtor) {
     150               0 :                         dtor(current TSRMLS_CC);
     151                 :                 }
     152               0 :                 SPL_LLIST_DELREF(current);
     153               0 :                 current = next;
     154                 :         }
     155                 : 
     156              63 :         efree(llist);
     157              63 : }
     158                 : /* }}} */
     159                 : 
     160                 : static spl_ptr_llist_element *spl_ptr_llist_offset(spl_ptr_llist *llist, long offset, int backward) /* {{{ */
     161              13 : {
     162                 : 
     163                 :         spl_ptr_llist_element *current;
     164              13 :         int pos = 0;
     165                 : 
     166              13 :         if (backward) {
     167               0 :                 current = llist->tail;
     168                 :         } else {
     169              13 :                 current = llist->head;
     170                 :         }
     171                 : 
     172              44 :         while (current && pos < offset) {
     173              18 :                 pos++;
     174              18 :                 if (backward) {
     175               0 :                         current = current->prev;
     176                 :                 } else {
     177              18 :                         current = current->next;
     178                 :                 }
     179                 :         }
     180                 : 
     181              13 :         return current;
     182                 : }
     183                 : /* }}} */
     184                 : 
     185                 : static void spl_ptr_llist_unshift(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */
     186               2 : {
     187               2 :         spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));
     188                 : 
     189               2 :         elem->data = data;
     190               2 :         elem->rc   = 1;
     191               2 :         elem->prev = NULL;
     192               2 :         elem->next = llist->head;
     193                 : 
     194               2 :         if (llist->head) {
     195               1 :                 llist->head->prev = elem;
     196                 :         } else {
     197               1 :                 llist->tail = elem;
     198                 :         }
     199                 : 
     200               2 :         llist->head = elem;
     201               2 :         llist->count++;
     202                 : 
     203               2 :         if (llist->ctor) {
     204               2 :                 llist->ctor(elem TSRMLS_CC);
     205                 :         }
     206               2 : }
     207                 : /* }}} */
     208                 : 
     209                 : static void spl_ptr_llist_push(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */
     210             103 : {
     211             103 :         spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));
     212                 : 
     213             103 :         elem->data = data;
     214             103 :         elem->rc   = 1;
     215             103 :         elem->prev = llist->tail;
     216             103 :         elem->next = NULL;
     217                 : 
     218             103 :         if (llist->tail) {
     219              60 :                 llist->tail->next = elem;
     220                 :         } else {
     221              43 :                 llist->head = elem;
     222                 :         }
     223                 : 
     224             103 :         llist->tail = elem;
     225             103 :         llist->count++;
     226                 : 
     227             103 :         if (llist->ctor) {
     228             103 :                 llist->ctor(elem TSRMLS_CC);
     229                 :         }
     230             103 : }
     231                 : /* }}} */
     232                 : 
     233                 : static void *spl_ptr_llist_pop(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
     234              93 : {
     235                 :         void                     *data;
     236              93 :         spl_ptr_llist_element    *tail = llist->tail;
     237                 : 
     238              93 :         if (tail == NULL) {
     239               2 :                 return NULL;
     240                 :         }
     241                 : 
     242              91 :         if (tail->prev) {
     243              50 :                 tail->prev->next = NULL;
     244                 :         } else {
     245              41 :                 llist->head = NULL;
     246                 :         }
     247                 : 
     248              91 :         llist->tail = tail->prev;
     249              91 :         llist->count--;
     250              91 :         data = tail->data;
     251                 : 
     252              91 :         if (llist->dtor) {
     253              91 :                 llist->dtor(tail TSRMLS_CC);
     254                 :         }
     255                 : 
     256              91 :         tail->data = NULL;
     257                 : 
     258              91 :         SPL_LLIST_DELREF(tail);
     259                 : 
     260              91 :         return data;
     261                 : }
     262                 : /* }}} */
     263                 : 
     264                 : static void *spl_ptr_llist_last(spl_ptr_llist *llist) /* {{{ */
     265               3 : {
     266               3 :         spl_ptr_llist_element *tail = llist->tail;
     267                 : 
     268               3 :         if (tail == NULL) {
     269               0 :                 return NULL;
     270                 :         } else {
     271               3 :                 return tail->data;
     272                 :         }
     273                 : }
     274                 : /* }}} */
     275                 : 
     276                 : static void *spl_ptr_llist_first(spl_ptr_llist *llist) /* {{{ */
     277               3 : {
     278               3 :         spl_ptr_llist_element *head = llist->head;
     279                 : 
     280               3 :         if (head == NULL) {
     281               0 :                 return NULL;
     282                 :         } else {
     283               3 :                 return head->data;
     284                 :         }
     285                 : }
     286                 : /* }}} */
     287                 : 
     288                 : static void *spl_ptr_llist_shift(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
     289              14 : {
     290                 :         void                    *data;
     291              14 :         spl_ptr_llist_element   *head = llist->head;
     292                 : 
     293              14 :         if (head == NULL) {
     294               4 :                 return NULL;
     295                 :         }
     296                 : 
     297              10 :         if (head->next) {
     298               7 :                 head->next->prev = NULL;
     299                 :         } else {
     300               3 :                 llist->tail = NULL;
     301                 :         }
     302                 : 
     303              10 :         llist->head = head->next;
     304              10 :         llist->count--;
     305              10 :         data = head->data;
     306                 : 
     307              10 :         if (llist->dtor) {
     308              10 :                 llist->dtor(head TSRMLS_CC);
     309                 :         }
     310              10 :         head->data = NULL;
     311                 : 
     312              10 :         SPL_LLIST_DELREF(head);
     313                 : 
     314              10 :         return data;
     315                 : }
     316                 : /* }}} */
     317                 : 
     318                 : static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to TSRMLS_DC) /* {{{ */
     319               4 : {
     320               4 :         spl_ptr_llist_element   *current = from->head, *next;
     321               4 :         spl_ptr_llist_ctor_func  ctor    = from->ctor;
     322                 : 
     323              18 :         while (current) {
     324              10 :                 next = current->next;
     325                 : 
     326              10 :                 if (ctor) {
     327              10 :                         ctor(current TSRMLS_CC);
     328                 :                 }
     329                 : 
     330              10 :                 spl_ptr_llist_push(to, current->data TSRMLS_CC);
     331              10 :                 current = next;
     332                 :         }
     333                 : 
     334               4 : }
     335                 : /* }}} */
     336                 : 
     337                 : /* }}} */
     338                 : 
     339                 : static void spl_dllist_object_free_storage(void *object TSRMLS_DC) /* {{{ */
     340              63 : {
     341              63 :         spl_dllist_object *intern = (spl_dllist_object *)object;
     342              63 :         zval              *tmp    = NULL;
     343                 : 
     344              63 :         zend_object_std_dtor(&intern->std TSRMLS_CC);
     345                 : 
     346             203 :         while(intern->llist->count > 0) {
     347              77 :                 tmp = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
     348              77 :                 zval_ptr_dtor(&tmp);
     349                 :         }
     350                 : 
     351              63 :         spl_ptr_llist_destroy(intern->llist TSRMLS_CC);
     352              63 :         SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
     353              63 :         zval_ptr_dtor(&intern->retval);
     354                 : 
     355              63 :         if (intern->debug_info != NULL) {
     356               4 :                 zend_hash_destroy(intern->debug_info);
     357               4 :                 efree(intern->debug_info);
     358                 :         }
     359                 : 
     360              63 :         efree(object);
     361              63 : }
     362                 : /* }}} */
     363                 : 
     364                 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
     365                 : 
     366                 : static zend_object_value spl_dllist_object_new_ex(zend_class_entry *class_type, spl_dllist_object **obj, zval *orig, int clone_orig TSRMLS_DC) /* {{{ */
     367              63 : {
     368                 :         zend_object_value  retval;
     369                 :         spl_dllist_object *intern;
     370                 :         zval              *tmp;
     371              63 :         zend_class_entry  *parent = class_type;
     372              63 :         int                inherited = 0;
     373                 : 
     374              63 :         intern = ecalloc(1, sizeof(spl_dllist_object));
     375              63 :         *obj = intern;
     376              63 :         ALLOC_INIT_ZVAL(intern->retval);
     377                 : 
     378              63 :         zend_object_std_init(&intern->std, class_type TSRMLS_CC);
     379              63 :         zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     380                 : 
     381              63 :         intern->flags = 0;
     382              63 :         intern->traverse_position = 0;
     383              63 :         intern->debug_info = NULL;
     384                 : 
     385              63 :         if (orig) {
     386               4 :                 spl_dllist_object *other = (spl_dllist_object*)zend_object_store_get_object(orig TSRMLS_CC);
     387               4 :                 intern->ce_get_iterator = other->ce_get_iterator;
     388                 : 
     389               4 :                 if (clone_orig) {
     390               4 :                         intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(other->llist->ctor, other->llist->dtor);
     391               4 :                         spl_ptr_llist_copy(other->llist, intern->llist TSRMLS_CC);
     392               4 :                         intern->traverse_pointer  = intern->llist->head;
     393               4 :                         SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
     394                 :                 } else {
     395               0 :                         intern->llist = other->llist;
     396               0 :                         intern->traverse_pointer  = intern->llist->head;
     397               0 :                         SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
     398                 :                 }
     399                 : 
     400               4 :                 intern->flags = other->flags;
     401                 :         } else {
     402              59 :                 intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(spl_ptr_llist_zval_ctor, spl_ptr_llist_zval_dtor);
     403              59 :                 intern->traverse_pointer  = intern->llist->head;
     404              59 :                 SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
     405                 :         }
     406                 : 
     407             135 :         while (parent) {
     408              72 :                 if (parent == spl_ce_SplStack) {
     409               3 :                         intern->flags |= (SPL_DLLIST_IT_FIX | SPL_DLLIST_IT_LIFO);
     410               3 :                         retval.handlers = &spl_handler_SplDoublyLinkedList;
     411              69 :                 } else if (parent == spl_ce_SplQueue) {
     412               5 :                         intern->flags |= SPL_DLLIST_IT_FIX;
     413               5 :                         retval.handlers = &spl_handler_SplDoublyLinkedList;
     414                 :                 }
     415                 : 
     416              72 :                 if (parent == spl_ce_SplDoublyLinkedList) {
     417              63 :                         retval.handlers = &spl_handler_SplDoublyLinkedList;
     418              63 :                         break;
     419                 :                 }
     420                 : 
     421               9 :                 parent = parent->parent;
     422               9 :                 inherited = 1;
     423                 :         }
     424                 : 
     425              63 :         retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_dllist_object_free_storage, NULL TSRMLS_CC);
     426                 : 
     427              63 :         if (!parent) { /* this must never happen */
     428               0 :                 php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList");
     429                 :         }
     430              63 :         if (inherited) {
     431               9 :                 zend_hash_find(&class_type->function_table, "offsetget",    sizeof("offsetget"),    (void **) &intern->fptr_offset_get);
     432               9 :                 if (intern->fptr_offset_get->common.scope == parent) {
     433               9 :                         intern->fptr_offset_get = NULL;
     434                 :                 }
     435               9 :                 zend_hash_find(&class_type->function_table, "offsetset",    sizeof("offsetset"),    (void **) &intern->fptr_offset_set);
     436               9 :                 if (intern->fptr_offset_set->common.scope == parent) {
     437               9 :                         intern->fptr_offset_set = NULL;
     438                 :                 }
     439               9 :                 zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
     440               9 :                 if (intern->fptr_offset_has->common.scope == parent) {
     441               9 :                         intern->fptr_offset_has = NULL;
     442                 :                 }
     443               9 :                 zend_hash_find(&class_type->function_table, "offsetunset",  sizeof("offsetunset"),  (void **) &intern->fptr_offset_del);
     444               9 :                 if (intern->fptr_offset_del->common.scope == parent) {
     445               9 :                         intern->fptr_offset_del = NULL;
     446                 :                 }
     447               9 :                 zend_hash_find(&class_type->function_table, "count",        sizeof("count"),        (void **) &intern->fptr_count);
     448               9 :                 if (intern->fptr_count->common.scope == parent) {
     449               8 :                         intern->fptr_count = NULL;
     450                 :                 }
     451                 :         }
     452                 : 
     453              63 :         return retval;
     454                 : }
     455                 : /* }}} */
     456                 : 
     457                 : static zend_object_value spl_dllist_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     458              59 : {
     459                 :         spl_dllist_object *tmp;
     460              59 :         return spl_dllist_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
     461                 : }
     462                 : /* }}} */
     463                 : 
     464                 : static zend_object_value spl_dllist_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
     465               4 : {
     466                 :         zend_object_value   new_obj_val;
     467                 :         zend_object        *old_object;
     468                 :         zend_object        *new_object;
     469               4 :         zend_object_handle  handle = Z_OBJ_HANDLE_P(zobject);
     470                 :         spl_dllist_object  *intern;
     471                 : 
     472               4 :         old_object  = zend_objects_get_address(zobject TSRMLS_CC);
     473               4 :         new_obj_val = spl_dllist_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
     474               4 :         new_object  = &intern->std;
     475                 : 
     476               4 :         zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
     477                 : 
     478               4 :         return new_obj_val;
     479                 : }
     480                 : /* }}} */
     481                 : 
     482                 : static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
     483              10 : {
     484              10 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
     485                 : 
     486              10 :         if (intern->fptr_count) {
     487                 :                 zval *rv;
     488               1 :                 zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
     489               1 :                 if (rv) {
     490               1 :                         zval_ptr_dtor(&intern->retval);
     491               1 :                         MAKE_STD_ZVAL(intern->retval);
     492               1 :                         ZVAL_ZVAL(intern->retval, rv, 1, 1);
     493               1 :                         convert_to_long(intern->retval);
     494               1 :                         *count = (long) Z_LVAL_P(intern->retval);
     495               1 :                         return SUCCESS;
     496                 :                 }
     497               0 :                 *count = 0;
     498               0 :                 return FAILURE;
     499                 :         }
     500                 : 
     501               9 :         *count = spl_ptr_llist_count(intern->llist);
     502               9 :         return SUCCESS;
     503                 : } 
     504                 : /* }}} */
     505                 : 
     506                 : static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
     507               6 : {
     508               6 :         spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
     509               6 :         spl_ptr_llist_element *current = intern->llist->head, *next;
     510                 :         zval *tmp, zrv, *dllist_array;
     511                 :         char *pnstr;
     512                 :         int  pnlen;
     513               6 :         int  i = 0;
     514                 : 
     515               6 :         *is_temp = 0;
     516                 : 
     517               6 :         if (intern->debug_info == NULL) {
     518               4 :                 ALLOC_HASHTABLE(intern->debug_info);
     519               4 :                 zend_hash_init(intern->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
     520                 :         }
     521                 : 
     522               6 :         if (intern->debug_info->nApplyCount == 0) {
     523               4 :                 INIT_PZVAL(&zrv);
     524               4 :                 Z_ARRVAL(zrv) = intern->debug_info;
     525                 : 
     526               4 :                 zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     527                 : 
     528               4 :                 pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
     529               4 :                 add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
     530               4 :                 efree(pnstr);
     531                 : 
     532               4 :                 ALLOC_INIT_ZVAL(dllist_array);
     533               4 :                 array_init(dllist_array);
     534                 : 
     535              16 :                 while (current) {
     536               8 :                         next = current->next;
     537                 : 
     538               8 :                         add_index_zval(dllist_array, i, (zval *)current->data);
     539               8 :                         Z_ADDREF_P(current->data);
     540               8 :                         i++;
     541                 : 
     542               8 :                         current = next;
     543                 :                 }
     544                 : 
     545               4 :                 pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
     546               4 :                 add_assoc_zval_ex(&zrv, pnstr, pnlen+1, dllist_array);
     547               4 :                 efree(pnstr);
     548                 :         }
     549                 : 
     550               6 :         return intern->debug_info;
     551                 : }
     552                 : /* }}}} */
     553                 : 
     554                 : /* {{{ proto bool SplDoublyLinkedList::push(mixed $value) U
     555                 :            Push $value on the SplDoublyLinkedList */
     556                 : SPL_METHOD(SplDoublyLinkedList, push)
     557              88 : {
     558                 :         zval *value;
     559                 :         spl_dllist_object *intern;
     560                 : 
     561              88 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
     562               1 :                 return;
     563                 :         }
     564                 : 
     565              87 :         SEPARATE_ARG_IF_REF(value);
     566                 : 
     567              87 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     568              87 :         spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
     569                 : 
     570              87 :         RETURN_TRUE;
     571                 : } 
     572                 : /* }}} */
     573                 : 
     574                 : /* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
     575                 :            Unshift $value on the SplDoublyLinkedList */
     576                 : SPL_METHOD(SplDoublyLinkedList, unshift)
     577               3 : {
     578                 :         zval *value;
     579                 :         spl_dllist_object *intern;
     580                 : 
     581               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
     582               1 :                 return;
     583                 :         }
     584                 : 
     585               2 :         SEPARATE_ARG_IF_REF(value);
     586                 : 
     587               2 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     588               2 :         spl_ptr_llist_unshift(intern->llist, value TSRMLS_CC);
     589                 : 
     590               2 :         RETURN_TRUE;
     591                 : }
     592                 : /* }}} */
     593                 : 
     594                 : /* {{{ proto mixed SplDoublyLinkedList::pop() U
     595                 :            Pop an element out of the SplDoublyLinkedList */
     596                 : SPL_METHOD(SplDoublyLinkedList, pop)
     597              18 : {
     598                 :         zval *value;
     599                 :         spl_dllist_object *intern;
     600                 : 
     601              18 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     602               2 :                 return;
     603                 :         }
     604                 : 
     605              16 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     606              16 :         value = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
     607                 : 
     608              16 :         if (value == NULL) {
     609               2 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0 TSRMLS_CC);
     610               2 :                 return;
     611                 :         }
     612                 : 
     613              14 :         RETURN_ZVAL(value, 1, 1);
     614                 : } 
     615                 : /* }}} */
     616                 : 
     617                 : /* {{{ proto mixed SplDoublyLinkedList::shift() U
     618                 :            Shift an element out of the SplDoublyLinkedList */
     619                 : SPL_METHOD(SplDoublyLinkedList, shift)
     620              12 : {
     621                 :         zval *value;
     622                 :         spl_dllist_object *intern;
     623                 : 
     624              12 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     625               1 :                 return;
     626                 :         }
     627                 : 
     628              11 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     629              11 :         value  = (zval *)spl_ptr_llist_shift(intern->llist TSRMLS_CC);
     630                 : 
     631              11 :         if (value == NULL) {
     632               4 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0 TSRMLS_CC);
     633               4 :                 return;
     634                 :         }
     635                 : 
     636               7 :         RETURN_ZVAL(value, 1, 1);
     637                 : } 
     638                 : /* }}} */
     639                 : 
     640                 : /* {{{ proto mixed SplDoublyLinkedList::top() U
     641                 :            Peek at the top element of the SplDoublyLinkedList */
     642                 : SPL_METHOD(SplDoublyLinkedList, top)
     643               7 : {
     644                 :         zval *value;
     645                 :         spl_dllist_object *intern;
     646                 : 
     647               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     648               4 :                 return;
     649                 :         }
     650                 : 
     651               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     652               3 :         value  = (zval *)spl_ptr_llist_last(intern->llist);
     653                 : 
     654               3 :         if (value == NULL) {
     655               0 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
     656               0 :                 return;
     657                 :         }
     658                 : 
     659               3 :         RETURN_ZVAL(value, 1, 0);
     660                 : }
     661                 : /* }}} */
     662                 : 
     663                 : /* {{{ proto mixed SplDoublyLinkedList::bottom() U
     664                 :            Peek at the bottom element of the SplDoublyLinkedList */
     665                 : SPL_METHOD(SplDoublyLinkedList, bottom)
     666               7 : {
     667                 :         zval *value;
     668                 :         spl_dllist_object *intern;
     669                 : 
     670               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     671               4 :                 return;
     672                 :         }
     673                 : 
     674               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     675               3 :         value  = (zval *)spl_ptr_llist_first(intern->llist);
     676                 : 
     677               3 :         if (value == NULL) {
     678               0 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
     679               0 :                 return;
     680                 :         }
     681                 : 
     682               3 :         RETURN_ZVAL(value, 1, 0);
     683                 : }
     684                 : /* }}} */
     685                 : 
     686                 : /* {{{ proto int SplDoublyLinkedList::count() U
     687                 :  Return the number of elements in the datastructure. */
     688                 : SPL_METHOD(SplDoublyLinkedList, count)
     689               9 : {
     690                 :         long count;
     691               9 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     692                 : 
     693               9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     694               2 :                 return;
     695                 :         }
     696                 : 
     697               7 :         count = spl_ptr_llist_count(intern->llist);
     698               7 :         RETURN_LONG(count);
     699                 : }
     700                 : /* }}} */
     701                 : 
     702                 : /* {{{ proto int SplDoublyLinkedList::isEmpty() U
     703                 :  Return true if the SplDoublyLinkedList is empty. */
     704                 : SPL_METHOD(SplDoublyLinkedList, isEmpty)
     705               4 : {
     706                 :         long count;
     707                 : 
     708               4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     709               2 :                 return;
     710                 :         }
     711                 : 
     712               2 :         spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC);
     713               2 :         RETURN_BOOL(count==0);
     714                 : }
     715                 : /* }}} */
     716                 : 
     717                 : /* {{{ proto int SplDoublyLinkedList::setIteratorMode($flags) U
     718                 :  Set the mode of iteration */
     719                 : SPL_METHOD(SplDoublyLinkedList, setIteratorMode)
     720               9 : {
     721                 :         long value;
     722                 :         spl_dllist_object *intern;
     723                 : 
     724               9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
     725               1 :                 return;
     726                 :         }
     727                 : 
     728               8 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     729                 : 
     730               8 :         if (intern->flags & SPL_DLLIST_IT_FIX
     731                 :                 && (intern->flags & SPL_DLLIST_IT_LIFO) != (value & SPL_DLLIST_IT_LIFO)) {
     732               3 :                 zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0 TSRMLS_CC);
     733               3 :                 return;
     734                 :         }
     735                 : 
     736               5 :         intern->flags = value & SPL_DLLIST_IT_MASK;
     737                 : 
     738               5 :         RETURN_LONG(intern->flags);
     739                 : }
     740                 : /* }}} */
     741                 : 
     742                 : /* {{{ proto int SplDoublyLinkedList::getIteratorMode() U
     743                 :  Return the mode of iteration */
     744                 : SPL_METHOD(SplDoublyLinkedList, getIteratorMode)
     745               2 : {
     746                 :         spl_dllist_object *intern;
     747                 : 
     748               2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
     749               1 :                 return;
     750                 :         }
     751                 : 
     752               1 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     753                 : 
     754               1 :         RETURN_LONG(intern->flags);
     755                 : }
     756                 : /* }}} */
     757                 : 
     758                 : /* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U
     759                 :  Returns whether the requested $index exists. */
     760                 : SPL_METHOD(SplDoublyLinkedList, offsetExists)
     761               4 : {
     762                 :         zval              *zindex;
     763                 :         spl_dllist_object *intern;
     764                 :         long               index;
     765                 : 
     766               4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     767               1 :                 return;
     768                 :         }
     769                 : 
     770               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     771               3 :         index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
     772                 : 
     773               3 :         RETURN_BOOL(index >= 0 && index < intern->llist->count);
     774                 : } /* }}} */
     775                 : 
     776                 : /* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed $index) U
     777                 :  Returns the value at the specified $index. */
     778                 : SPL_METHOD(SplDoublyLinkedList, offsetGet)
     779              14 : {
     780                 :         zval                  *zindex, *value;
     781                 :         long                   index;
     782                 :         spl_dllist_object     *intern;
     783                 :         spl_ptr_llist_element *element;
     784                 : 
     785              14 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     786               2 :                 return;
     787                 :         }
     788                 : 
     789              12 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     790              12 :         index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
     791                 : 
     792              12 :     if (index < 0 || index >= intern->llist->count) {
     793               4 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
     794               4 :                 return;
     795                 :         }
     796                 : 
     797               8 :         element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     798                 : 
     799               8 :         if (element != NULL) {
     800               8 :                 value = (zval *)element->data;
     801               8 :                 RETURN_ZVAL(value, 1, 0);
     802                 :         } else {
     803               0 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     804               0 :                 return;
     805                 :         }
     806                 : } /* }}} */
     807                 : 
     808                 : /* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval) U
     809                 :  Sets the value at the specified $index to $newval. */
     810                 : SPL_METHOD(SplDoublyLinkedList, offsetSet)
     811              10 : {
     812                 :         zval                  *zindex, *value;
     813                 :         spl_dllist_object     *intern;
     814                 : 
     815              10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
     816               2 :                 return;
     817                 :         }
     818               8 :         SEPARATE_ARG_IF_REF(value);
     819                 : 
     820               8 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     821                 : 
     822               8 :         if (Z_TYPE_P(zindex) == IS_NULL) {
     823                 :                 /* $obj[] = ... */
     824               6 :                 spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
     825                 :         } else {
     826                 :                 /* $obj[$foo] = ... */
     827                 :                 long                   index;
     828                 :                 spl_ptr_llist_element *element;
     829                 : 
     830               2 :                 index = spl_offset_convert_to_long(zindex TSRMLS_CC);
     831                 : 
     832               2 :                 if (index < 0 || index >= intern->llist->count) {
     833               1 :                         zval_ptr_dtor(&value);
     834               1 :                         zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
     835               1 :                         return;
     836                 :                 }
     837                 : 
     838               1 :                 element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     839                 : 
     840               1 :                 if (element != NULL) {
     841                 :                         /* call dtor on the old element as in spl_ptr_llist_pop */
     842               1 :                         if (intern->llist->dtor) {
     843               1 :                                 intern->llist->dtor(element TSRMLS_CC);
     844                 :                         }
     845                 : 
     846                 :                         /* the element is replaced, delref the old one as in
     847                 :                          * SplDoublyLinkedList::pop() */
     848               1 :                         zval_ptr_dtor((zval **)&element->data);
     849               1 :                         element->data = value;
     850                 : 
     851                 :                         /* new element, call ctor as in spl_ptr_llist_push */
     852               1 :                         if (intern->llist->ctor) {
     853               1 :                                 intern->llist->ctor(element TSRMLS_CC);
     854                 :                         }
     855                 :                 } else {
     856               0 :                         zval_ptr_dtor(&value);
     857               0 :                         zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     858               0 :                         return;
     859                 :                 }
     860                 :         }
     861                 : } /* }}} */
     862                 : 
     863                 : /* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed $index) U
     864                 :  Unsets the value at the specified $index. */
     865                 : SPL_METHOD(SplDoublyLinkedList, offsetUnset)
     866               7 : {
     867                 :         zval                  *zindex;
     868                 :         long                   index;
     869                 :         spl_dllist_object     *intern;
     870                 :         spl_ptr_llist_element *element;
     871                 :         spl_ptr_llist         *llist;
     872                 : 
     873               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     874               0 :                 return;
     875                 :         }
     876                 : 
     877               7 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     878               7 :         index  = (int)spl_offset_convert_to_long(zindex TSRMLS_CC);
     879               7 :     llist  = intern->llist;
     880                 : 
     881               7 :     if (index < 0 || index >= intern->llist->count) {
     882               3 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
     883               3 :                 return;
     884                 :         }
     885                 : 
     886               4 :         element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     887                 : 
     888               4 :         if (element != NULL) {
     889                 :                 /* connect the neightbors */
     890               4 :                 if (element->prev) {
     891               2 :                         element->prev->next = element->next;
     892                 :                 }
     893                 : 
     894               4 :                 if (element->next) {
     895               3 :                         element->next->prev = element->prev;
     896                 :                 }
     897                 : 
     898                 :                 /* take care of head/tail */
     899               4 :                 if (element == llist->head) {
     900               2 :                         llist->head = element->next;
     901                 :                 }
     902                 : 
     903               4 :                 if (element == llist->tail) {
     904               1 :                         llist->tail = element->prev;
     905                 :                 }
     906                 : 
     907                 :                 /* finally, delete the element */
     908               4 :                 llist->count--;
     909                 : 
     910               4 :                 if(llist->dtor) {
     911               4 :                         llist->dtor(element TSRMLS_CC);
     912                 :                 }
     913                 : 
     914               4 :                 zval_ptr_dtor((zval **)&element->data);
     915               4 :                 element->data = NULL;
     916                 : 
     917               4 :                 SPL_LLIST_DELREF(element);
     918                 :         } else {
     919               0 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     920               0 :                 return;
     921                 :         }
     922                 : } /* }}} */
     923                 : 
     924                 : static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
     925              11 : {
     926              11 :         spl_dllist_it *iterator = (spl_dllist_it *)iter;
     927                 : 
     928              11 :         SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer);
     929                 : 
     930              11 :         zend_user_it_invalidate_current(iter TSRMLS_CC);
     931              11 :         zval_ptr_dtor((zval**)&iterator->intern.it.data);
     932                 : 
     933              11 :         efree(iterator);
     934              11 : }
     935                 : /* }}} */
     936                 : 
     937                 : static void spl_dllist_it_helper_rewind(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */
     938              17 : {
     939              17 :         SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr);
     940                 : 
     941              17 :         if (flags & SPL_DLLIST_IT_LIFO) {
     942               3 :                 *traverse_position_ptr = llist->count-1;
     943               3 :                 *traverse_pointer_ptr  = llist->tail;
     944                 :         } else {
     945              14 :                 *traverse_position_ptr = 0;
     946              14 :                 *traverse_pointer_ptr  = llist->head;
     947                 :         }
     948                 : 
     949              17 :         SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
     950              17 : }
     951                 : /* }}} */
     952                 : 
     953                 : static void spl_dllist_it_helper_move_forward(spl_ptr_llist_element **traverse_pointer_ptr, int *traverse_position_ptr, spl_ptr_llist *llist, int flags TSRMLS_DC) /* {{{ */
     954              44 : {
     955              44 :         if (*traverse_pointer_ptr) {
     956              43 :                 spl_ptr_llist_element *old = *traverse_pointer_ptr;
     957                 : 
     958              43 :                 if (flags & SPL_DLLIST_IT_LIFO) {
     959              10 :                         *traverse_pointer_ptr = old->prev;
     960              10 :                         (*traverse_position_ptr)--;
     961                 : 
     962              10 :                         if (flags & SPL_DLLIST_IT_DELETE) {
     963               0 :                                 zval *prev = (zval *)spl_ptr_llist_pop(llist TSRMLS_CC);
     964                 : 
     965               0 :                                 if (prev) {
     966               0 :                                         zval_ptr_dtor((zval **)&prev);
     967                 :                                 }
     968                 :                         }
     969                 :                 } else {
     970              33 :                         *traverse_pointer_ptr = old->next;
     971                 : 
     972              33 :                         if (flags & SPL_DLLIST_IT_DELETE) {
     973               3 :                                 zval *prev = (zval *)spl_ptr_llist_shift(llist TSRMLS_CC);
     974                 : 
     975               3 :                                 if (prev) {
     976               3 :                                         zval_ptr_dtor((zval **)&prev);
     977                 :                                 }
     978                 :                         } else {
     979              30 :                                 (*traverse_position_ptr)++;
     980                 :                         }
     981                 :                 }
     982                 : 
     983              43 :                 SPL_LLIST_DELREF(old);
     984              43 :                 SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
     985                 :         }
     986              44 : }
     987                 : /* }}} */
     988                 : 
     989                 : static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
     990              11 : {
     991              11 :         spl_dllist_it     *iterator = (spl_dllist_it *)iter;
     992              11 :         spl_dllist_object *object   = iterator->object;
     993              11 :         spl_ptr_llist     *llist    = object->llist;
     994                 : 
     995              11 :         spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC);
     996              11 : }
     997                 : /* }}} */
     998                 : 
     999                 : static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
    1000              41 : {
    1001              41 :         spl_dllist_it         *iterator = (spl_dllist_it *)iter;
    1002              41 :         spl_ptr_llist_element *element  = iterator->traverse_pointer;
    1003                 : 
    1004              41 :         return (element != NULL ? SUCCESS : FAILURE);
    1005                 : }
    1006                 : /* }}} */
    1007                 : 
    1008                 : static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
    1009              30 : {
    1010              30 :         spl_dllist_it         *iterator = (spl_dllist_it *)iter;
    1011              30 :         spl_ptr_llist_element *element  = iterator->traverse_pointer;
    1012                 : 
    1013              30 :         if (element == NULL || element->data == NULL) {
    1014               0 :                 *data = NULL;
    1015                 :         } else {
    1016              30 :                 *data = (zval **)&element->data;
    1017                 :         }
    1018              30 : }
    1019                 : /* }}} */
    1020                 : 
    1021                 : static int spl_dllist_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
    1022              26 : {
    1023              26 :         spl_dllist_it *iterator = (spl_dllist_it *)iter;
    1024                 : 
    1025              26 :         *int_key = (ulong) iterator->traverse_position;
    1026              26 :         return HASH_KEY_IS_LONG;
    1027                 : }
    1028                 : /* }}} */
    1029                 : 
    1030                 : static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
    1031              30 : {
    1032              30 :         spl_dllist_it     *iterator = (spl_dllist_it *)iter;
    1033              30 :         spl_dllist_object *object   = iterator->object;
    1034                 : 
    1035              30 :         zend_user_it_invalidate_current(iter TSRMLS_CC);
    1036                 : 
    1037              30 :         spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC);
    1038              30 : }
    1039                 : /* }}} */
    1040                 : 
    1041                 : /* {{{  proto int SplDoublyLinkedList::key() U
    1042                 :    Return current array key */
    1043                 : SPL_METHOD(SplDoublyLinkedList, key)
    1044               0 : {
    1045               0 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1046                 : 
    1047               0 :         RETURN_LONG(intern->traverse_position);
    1048                 : }
    1049                 : /* }}} */
    1050                 : 
    1051                 : /* {{{ proto void SplDoublyLinkedList::prev() U
    1052                 :    Move to next entry */
    1053                 : SPL_METHOD(SplDoublyLinkedList, prev)
    1054               3 : {
    1055               3 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1056                 : 
    1057               3 :         spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO TSRMLS_CC);
    1058               3 : }
    1059                 : /* }}} */
    1060                 : 
    1061                 : /* {{{ proto void SplDoublyLinkedList::next() U
    1062                 :    Move to next entry */
    1063                 : SPL_METHOD(SplDoublyLinkedList, next)
    1064              11 : {
    1065              11 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1066                 : 
    1067              11 :         spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
    1068              11 : }
    1069                 : /* }}} */
    1070                 : 
    1071                 : /* {{{ proto bool SplDoublyLinkedList::valid() U
    1072                 :    Check whether the datastructure contains more entries */
    1073                 : SPL_METHOD(SplDoublyLinkedList, valid)
    1074               4 : {
    1075               4 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1076                 : 
    1077               4 :         RETURN_BOOL(intern->traverse_pointer != NULL);
    1078                 : }
    1079                 : /* }}} */
    1080                 : 
    1081                 : /* {{{ proto void SplDoublyLinkedList::rewind() U
    1082                 :    Rewind the datastructure back to the start */
    1083                 : SPL_METHOD(SplDoublyLinkedList, rewind)
    1084               6 : {
    1085               6 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1086                 : 
    1087               6 :         spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
    1088               6 : }
    1089                 : /* }}} */
    1090                 : 
    1091                 : /* {{{ proto mixed|NULL SplDoublyLinkedList::current() U
    1092                 :    Return current datastructure entry */
    1093                 : SPL_METHOD(SplDoublyLinkedList, current)
    1094              17 : {
    1095              17 :         spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1096              17 :         spl_ptr_llist_element *element = intern->traverse_pointer;
    1097                 : 
    1098              17 :         if (element == NULL || element->data == NULL) {
    1099               5 :                 RETURN_NULL();
    1100                 :         } else {
    1101              12 :                 zval *data    = (zval *)element->data;
    1102              12 :                 RETURN_ZVAL(data, 1, 0);
    1103                 :         }
    1104                 : }
    1105                 : /* }}} */
    1106                 : 
    1107                 : /* iterator handler table */
    1108                 : zend_object_iterator_funcs spl_dllist_it_funcs = {
    1109                 :         spl_dllist_it_dtor,
    1110                 :         spl_dllist_it_valid,
    1111                 :         spl_dllist_it_get_current_data,
    1112                 :         spl_dllist_it_get_current_key,
    1113                 :         spl_dllist_it_move_forward,
    1114                 :         spl_dllist_it_rewind
    1115                 : };
    1116                 : 
    1117                 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
    1118              11 : {
    1119                 :         spl_dllist_it     *iterator;
    1120              11 :         spl_dllist_object *dllist_object = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
    1121                 : 
    1122              11 :         if (by_ref) {
    1123               0 :                 zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
    1124               0 :                 return NULL;
    1125                 :         }
    1126                 : 
    1127              11 :         Z_ADDREF_P(object);
    1128                 : 
    1129              11 :         iterator                     = emalloc(sizeof(spl_dllist_it));
    1130              11 :         iterator->intern.it.data     = (void*)object;
    1131              11 :         iterator->intern.it.funcs    = &spl_dllist_it_funcs;
    1132              11 :         iterator->intern.ce          = ce;
    1133              11 :         iterator->intern.value       = NULL;
    1134              11 :         iterator->traverse_position  = dllist_object->traverse_position;
    1135              11 :         iterator->traverse_pointer   = dllist_object->traverse_pointer;
    1136              11 :         iterator->flags              = dllist_object->flags & SPL_DLLIST_IT_MASK;
    1137              11 :         iterator->object             = dllist_object;
    1138                 : 
    1139              11 :         SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
    1140                 : 
    1141                 : 
    1142              11 :         return (zend_object_iterator*)iterator;
    1143                 : }
    1144                 : /* }}} */
    1145                 : 
    1146                 : /*  Function/Class/Method definitions */
    1147                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_setiteratormode, 0)
    1148                 :         ZEND_ARG_INFO(0, flags)
    1149                 : ZEND_END_ARG_INFO()
    1150                 : 
    1151                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_push, 0)
    1152                 :         ZEND_ARG_INFO(0, value)
    1153                 : ZEND_END_ARG_INFO()
    1154                 : 
    1155                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetGet, 0, 0, 1)
    1156                 :         ZEND_ARG_INFO(0, index)
    1157                 : ZEND_END_ARG_INFO()
    1158                 : 
    1159                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetSet, 0, 0, 2)
    1160                 :         ZEND_ARG_INFO(0, index)
    1161                 :         ZEND_ARG_INFO(0, newval)
    1162                 : ZEND_END_ARG_INFO()
    1163                 : 
    1164                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0)
    1165                 : ZEND_END_ARG_INFO()
    1166                 : 
    1167                 : static const zend_function_entry spl_funcs_SplQueue[] = {
    1168                 :         SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push,  arginfo_dllist_push, ZEND_ACC_PUBLIC)
    1169                 :         SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
    1170                 :         {NULL, NULL, NULL}
    1171                 : };
    1172                 : 
    1173                 : static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
    1174                 :         SPL_ME(SplDoublyLinkedList, pop,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1175                 :         SPL_ME(SplDoublyLinkedList, shift,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1176                 :         SPL_ME(SplDoublyLinkedList, push,            arginfo_dllist_push,            ZEND_ACC_PUBLIC)
    1177                 :         SPL_ME(SplDoublyLinkedList, unshift,         arginfo_dllist_push,            ZEND_ACC_PUBLIC)
    1178                 :         SPL_ME(SplDoublyLinkedList, top,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1179                 :         SPL_ME(SplDoublyLinkedList, bottom,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1180                 :         SPL_ME(SplDoublyLinkedList, count,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1181                 :         SPL_ME(SplDoublyLinkedList, isEmpty,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1182                 :         SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC)
    1183                 :         SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1184                 :         SPL_ME(SplDoublyLinkedList, offsetExists,    arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1185                 :         SPL_ME(SplDoublyLinkedList, offsetGet,       arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1186                 :         SPL_ME(SplDoublyLinkedList, offsetSet,       arginfo_dllist_offsetSet,       ZEND_ACC_PUBLIC)
    1187                 :         SPL_ME(SplDoublyLinkedList, offsetUnset,     arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1188                 :         SPL_ME(SplDoublyLinkedList, rewind,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1189                 :         SPL_ME(SplDoublyLinkedList, current,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1190                 :         SPL_ME(SplDoublyLinkedList, key,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1191                 :         SPL_ME(SplDoublyLinkedList, next,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1192                 :         SPL_ME(SplDoublyLinkedList, prev,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1193                 :         SPL_ME(SplDoublyLinkedList, valid,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1194                 :         {NULL, NULL, NULL}
    1195                 : };
    1196                 : /* }}} */
    1197                 : 
    1198                 : PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
    1199           17633 : {
    1200           17633 :         REGISTER_SPL_STD_CLASS_EX(SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplDoublyLinkedList);
    1201           17633 :         memcpy(&spl_handler_SplDoublyLinkedList, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    1202                 : 
    1203           17633 :         spl_handler_SplDoublyLinkedList.clone_obj      = spl_dllist_object_clone;
    1204           17633 :         spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements;
    1205           17633 :         spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info;
    1206                 : 
    1207           17633 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_LIFO",  SPL_DLLIST_IT_LIFO);
    1208           17633 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_FIFO",  0);
    1209           17633 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_DELETE",SPL_DLLIST_IT_DELETE);
    1210           17633 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_KEEP",  0);
    1211                 : 
    1212           17633 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
    1213           17633 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
    1214           17633 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
    1215                 : 
    1216           17633 :         spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;
    1217                 : 
    1218           17633 :         REGISTER_SPL_SUB_CLASS_EX(SplQueue,           SplDoublyLinkedList,        spl_dllist_object_new, spl_funcs_SplQueue);
    1219           17633 :         REGISTER_SPL_SUB_CLASS_EX(SplStack,           SplDoublyLinkedList,        spl_dllist_object_new, NULL);
    1220                 : 
    1221           17633 :         spl_ce_SplQueue->get_iterator = spl_dllist_get_iterator;
    1222           17633 :         spl_ce_SplStack->get_iterator = spl_dllist_get_iterator;
    1223                 : 
    1224           17633 :         return SUCCESS;
    1225                 : }
    1226                 : /* }}} */
    1227                 : /*
    1228                 :  * Local variables:
    1229                 :  * tab-width: 4
    1230                 :  * c-basic-offset: 4
    1231                 :  * End:
    1232                 :  * vim600: fdm=marker
    1233                 :  * vim: noet sw=4 ts=4
    1234                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Sat, 21 Nov 2009 12:27:09 +0000 (3 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.