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-23 Instrumented lines: 507
Code covered: 92.9 % Executed lines: 471
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       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                 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
     340                 : 
     341                 : static void spl_dllist_object_free_storage(void *object TSRMLS_DC) /* {{{ */
     342              63 : {
     343              63 :         spl_dllist_object *intern = (spl_dllist_object *)object;
     344              63 :         zval              *tmp    = NULL;
     345                 : 
     346              63 :         zend_object_std_dtor(&intern->std TSRMLS_CC);
     347                 : 
     348             203 :         while(intern->llist->count > 0) {
     349              77 :                 tmp = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
     350              77 :                 zval_ptr_dtor(&tmp);
     351                 :         }
     352                 : 
     353              63 :         spl_ptr_llist_destroy(intern->llist TSRMLS_CC);
     354              63 :         SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
     355              63 :         zval_ptr_dtor(&intern->retval);
     356                 : 
     357              63 :         if (intern->debug_info != NULL) {
     358               4 :                 zend_hash_destroy(intern->debug_info);
     359               4 :                 efree(intern->debug_info);
     360                 :         }
     361                 : 
     362              63 :         efree(object);
     363              63 : }
     364                 : /* }}} */
     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              69 :                 } else if (parent == spl_ce_SplQueue) {
     411               5 :                         intern->flags |= SPL_DLLIST_IT_FIX;
     412                 :                 }
     413                 : 
     414              72 :                 if (parent == spl_ce_SplDoublyLinkedList) {
     415              63 :                         retval.handlers = &spl_handler_SplDoublyLinkedList;
     416              63 :                         break;
     417                 :                 }
     418                 : 
     419               9 :                 parent = parent->parent;
     420               9 :                 inherited = 1;
     421                 :         }
     422                 : 
     423              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);
     424                 : 
     425              63 :         if (!parent) { /* this must never happen */
     426               0 :                 php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList");
     427                 :         }
     428              63 :         if (inherited) {
     429               9 :                 zend_hash_find(&class_type->function_table, "offsetget",    sizeof("offsetget"),    (void **) &intern->fptr_offset_get);
     430               9 :                 if (intern->fptr_offset_get->common.scope == parent) {
     431               9 :                         intern->fptr_offset_get = NULL;
     432                 :                 }
     433               9 :                 zend_hash_find(&class_type->function_table, "offsetset",    sizeof("offsetset"),    (void **) &intern->fptr_offset_set);
     434               9 :                 if (intern->fptr_offset_set->common.scope == parent) {
     435               9 :                         intern->fptr_offset_set = NULL;
     436                 :                 }
     437               9 :                 zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
     438               9 :                 if (intern->fptr_offset_has->common.scope == parent) {
     439               9 :                         intern->fptr_offset_has = NULL;
     440                 :                 }
     441               9 :                 zend_hash_find(&class_type->function_table, "offsetunset",  sizeof("offsetunset"),  (void **) &intern->fptr_offset_del);
     442               9 :                 if (intern->fptr_offset_del->common.scope == parent) {
     443               9 :                         intern->fptr_offset_del = NULL;
     444                 :                 }
     445               9 :                 zend_hash_find(&class_type->function_table, "count",        sizeof("count"),        (void **) &intern->fptr_count);
     446               9 :                 if (intern->fptr_count->common.scope == parent) {
     447               8 :                         intern->fptr_count = NULL;
     448                 :                 }
     449                 :         }
     450                 : 
     451              63 :         return retval;
     452                 : }
     453                 : /* }}} */
     454                 : 
     455                 : static zend_object_value spl_dllist_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
     456              59 : {
     457                 :         spl_dllist_object *tmp;
     458              59 :         return spl_dllist_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
     459                 : }
     460                 : /* }}} */
     461                 : 
     462                 : static zend_object_value spl_dllist_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
     463               4 : {
     464                 :         zend_object_value   new_obj_val;
     465                 :         zend_object        *old_object;
     466                 :         zend_object        *new_object;
     467               4 :         zend_object_handle  handle = Z_OBJ_HANDLE_P(zobject);
     468                 :         spl_dllist_object  *intern;
     469                 : 
     470               4 :         old_object  = zend_objects_get_address(zobject TSRMLS_CC);
     471               4 :         new_obj_val = spl_dllist_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
     472               4 :         new_object  = &intern->std;
     473                 : 
     474               4 :         zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
     475                 : 
     476               4 :         return new_obj_val;
     477                 : }
     478                 : /* }}} */
     479                 : 
     480                 : static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
     481              10 : {
     482              10 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
     483                 : 
     484              10 :         if (intern->fptr_count) {
     485                 :                 zval *rv;
     486               1 :                 zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
     487               1 :                 if (rv) {
     488               1 :                         zval_ptr_dtor(&intern->retval);
     489               1 :                         MAKE_STD_ZVAL(intern->retval);
     490               1 :                         ZVAL_ZVAL(intern->retval, rv, 1, 1);
     491               1 :                         convert_to_long(intern->retval);
     492               1 :                         *count = (long) Z_LVAL_P(intern->retval);
     493               1 :                         return SUCCESS;
     494                 :                 }
     495               0 :                 *count = 0;
     496               0 :                 return FAILURE;
     497                 :         }
     498                 : 
     499               9 :         *count = spl_ptr_llist_count(intern->llist);
     500               9 :         return SUCCESS;
     501                 : } 
     502                 : /* }}} */
     503                 : 
     504                 : static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
     505               6 : {
     506               6 :         spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
     507               6 :         spl_ptr_llist_element *current = intern->llist->head, *next;
     508                 :         zval *tmp, zrv, *dllist_array;
     509                 :         zstr pnstr;
     510                 :         int  pnlen;
     511               6 :         int  i = 0;;
     512                 : 
     513               6 :         *is_temp = 0;
     514                 : 
     515               6 :         if (intern->debug_info == NULL) {
     516               4 :                 ALLOC_HASHTABLE(intern->debug_info);
     517               4 :                 ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
     518                 :         }
     519                 : 
     520               6 :         if (intern->debug_info->nApplyCount == 0) {
     521               4 :                 INIT_PZVAL(&zrv);
     522               4 :                 Z_ARRVAL(zrv) = intern->debug_info;
     523                 : 
     524               4 :                 zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
     525                 : 
     526               4 :                 pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
     527               4 :                 add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
     528               4 :                 efree(pnstr.v);
     529                 : 
     530               4 :                 ALLOC_INIT_ZVAL(dllist_array);
     531               4 :                 array_init(dllist_array);
     532                 : 
     533              16 :                 while (current) {
     534               8 :                         next = current->next;
     535                 : 
     536               8 :                         add_index_zval(dllist_array, i, (zval *)current->data);
     537               8 :                         Z_ADDREF_P(current->data);
     538               8 :                         i++;
     539                 : 
     540               8 :                         current = next;
     541                 :                 }
     542                 : 
     543               4 :                 pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
     544               4 :                 add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, dllist_array);
     545               4 :                 efree(pnstr.v);
     546                 :         }
     547                 : 
     548               6 :         return intern->debug_info;
     549                 : }
     550                 : /* }}}} */
     551                 : 
     552                 : /* {{{ proto bool SplDoublyLinkedList::push(mixed $value) U
     553                 :            Push $value on the SplDoublyLinkedList */
     554                 : SPL_METHOD(SplDoublyLinkedList, push)
     555              88 : {
     556                 :         zval *value;
     557                 :         spl_dllist_object *intern;
     558                 : 
     559              88 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
     560               1 :                 return;
     561                 :         }
     562                 : 
     563              87 :         SEPARATE_ARG_IF_REF(value);
     564                 : 
     565              87 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     566              87 :         spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
     567                 : 
     568              87 :         RETURN_TRUE;
     569                 : } 
     570                 : /* }}} */
     571                 : 
     572                 : /* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
     573                 :            Unshift $value on the SplDoublyLinkedList */
     574                 : SPL_METHOD(SplDoublyLinkedList, unshift)
     575               3 : {
     576                 :         zval *value;
     577                 :         spl_dllist_object *intern;
     578                 : 
     579               3 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
     580               1 :                 return;
     581                 :         }
     582                 : 
     583               2 :         SEPARATE_ARG_IF_REF(value);
     584                 : 
     585               2 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     586               2 :         spl_ptr_llist_unshift(intern->llist, value TSRMLS_CC);
     587                 : 
     588               2 :         RETURN_TRUE;
     589                 : }
     590                 : /* }}} */
     591                 : 
     592                 : /* {{{ proto mixed SplDoublyLinkedList::pop() U
     593                 :            Pop an element out of the SplDoublyLinkedList */
     594                 : SPL_METHOD(SplDoublyLinkedList, pop)
     595              18 : {
     596                 :         zval *value;
     597                 :         spl_dllist_object *intern;
     598                 : 
     599              18 :         if (zend_parse_parameters_none() == FAILURE) {
     600               2 :                 return;
     601                 :         }
     602                 : 
     603              16 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     604              16 :         value = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
     605                 : 
     606              16 :         if (value == NULL) {
     607               2 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0 TSRMLS_CC);
     608               2 :                 return;
     609                 :         }
     610                 : 
     611              14 :         RETURN_ZVAL(value, 1, 1);
     612                 : } 
     613                 : /* }}} */
     614                 : 
     615                 : /* {{{ proto mixed SplDoublyLinkedList::shift() U
     616                 :            Shift an element out of the SplDoublyLinkedList */
     617                 : SPL_METHOD(SplDoublyLinkedList, shift)
     618              12 : {
     619                 :         zval *value;
     620                 :         spl_dllist_object *intern;
     621                 : 
     622              12 :         if (zend_parse_parameters_none() == FAILURE) {
     623               1 :                 return;
     624                 :         }
     625                 : 
     626              11 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     627              11 :         value  = (zval *)spl_ptr_llist_shift(intern->llist TSRMLS_CC);
     628                 : 
     629              11 :         if (value == NULL) {
     630               4 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0 TSRMLS_CC);
     631               4 :                 return;
     632                 :         }
     633                 : 
     634               7 :         RETURN_ZVAL(value, 1, 1);
     635                 : } 
     636                 : /* }}} */
     637                 : 
     638                 : /* {{{ proto mixed SplDoublyLinkedList::top() U
     639                 :            Peek at the top element of the SplDoublyLinkedList */
     640                 : SPL_METHOD(SplDoublyLinkedList, top)
     641               7 : {
     642                 :         zval *value;
     643                 :         spl_dllist_object *intern;
     644                 : 
     645               7 :         if (zend_parse_parameters_none() == FAILURE) {
     646               4 :                 return;
     647                 :         }
     648                 : 
     649               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     650               3 :         value  = (zval *)spl_ptr_llist_last(intern->llist);
     651                 : 
     652               3 :         if (value == NULL) {
     653               0 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
     654               0 :                 return;
     655                 :         }
     656                 : 
     657               3 :         RETURN_ZVAL(value, 1, 0);
     658                 : }
     659                 : /* }}} */
     660                 : 
     661                 : /* {{{ proto mixed SplDoublyLinkedList::bottom() U
     662                 :            Peek at the bottom element of the SplDoublyLinkedList */
     663                 : SPL_METHOD(SplDoublyLinkedList, bottom)
     664               7 : {
     665                 :         zval *value;
     666                 :         spl_dllist_object *intern;
     667                 : 
     668               7 :         if (zend_parse_parameters_none() == FAILURE) {
     669               4 :                 return;
     670                 :         }
     671                 : 
     672               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     673               3 :         value  = (zval *)spl_ptr_llist_first(intern->llist);
     674                 : 
     675               3 :         if (value == NULL) {
     676               0 :                 zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
     677               0 :                 return;
     678                 :         }
     679                 : 
     680               3 :         RETURN_ZVAL(value, 1, 0);
     681                 : }
     682                 : /* }}} */
     683                 : 
     684                 : /* {{{ proto int SplDoublyLinkedList::count() U
     685                 :  Return the number of elements in the datastructure. */
     686                 : SPL_METHOD(SplDoublyLinkedList, count)
     687               9 : {
     688                 :         long count;
     689               9 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     690                 : 
     691               9 :         if (zend_parse_parameters_none() == FAILURE) {
     692               2 :                 return;
     693                 :         }
     694                 : 
     695               7 :         count = spl_ptr_llist_count(intern->llist);
     696               7 :         RETURN_LONG(count);
     697                 : }
     698                 : /* }}} */
     699                 : 
     700                 : /* {{{ proto int SplDoublyLinkedList::isEmpty() U
     701                 :  Return true if the SplDoublyLinkedList is empty. */
     702                 : SPL_METHOD(SplDoublyLinkedList, isEmpty)
     703               4 : {
     704                 :         long count;
     705                 : 
     706               4 :         if (zend_parse_parameters_none() == FAILURE) {
     707               2 :                 return;
     708                 :         }
     709                 : 
     710               2 :         spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC);
     711               2 :         RETURN_BOOL(count==0);
     712                 : }
     713                 : /* }}} */
     714                 : 
     715                 : /* {{{ proto int SplDoublyLinkedList::setIteratorMode($flags) U
     716                 :  Set the mode of iteration */
     717                 : SPL_METHOD(SplDoublyLinkedList, setIteratorMode)
     718               9 : {
     719                 :         long value;
     720                 :         spl_dllist_object *intern;
     721                 : 
     722               9 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
     723               1 :                 return;
     724                 :         }
     725                 : 
     726               8 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     727                 : 
     728               8 :         if (intern->flags & SPL_DLLIST_IT_FIX
     729                 :                 && (intern->flags & SPL_DLLIST_IT_LIFO) != (value & SPL_DLLIST_IT_LIFO)) {
     730               3 :                 zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0 TSRMLS_CC);
     731               3 :                 return;
     732                 :         }
     733                 : 
     734               5 :         intern->flags = value & SPL_DLLIST_IT_MASK;
     735                 : 
     736               5 :         RETURN_LONG(intern->flags);
     737                 : }
     738                 : /* }}} */
     739                 : 
     740                 : /* {{{ proto int SplDoublyLinkedList::getIteratorMode() U
     741                 :  Return the mode of iteration */
     742                 : SPL_METHOD(SplDoublyLinkedList, getIteratorMode)
     743               2 : {
     744                 :         spl_dllist_object *intern;
     745                 : 
     746               2 :         if (zend_parse_parameters_none() == FAILURE) {
     747               1 :                 return;
     748                 :         }
     749                 : 
     750               1 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     751                 : 
     752               1 :         RETURN_LONG(intern->flags);
     753                 : }
     754                 : /* }}} */
     755                 : 
     756                 : /* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U
     757                 :  Returns whether the requested $index exists. */
     758                 : SPL_METHOD(SplDoublyLinkedList, offsetExists)
     759               4 : {
     760                 :         zval              *zindex;
     761                 :         spl_dllist_object *intern;
     762                 :         long               index;
     763                 : 
     764               4 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     765               1 :                 return;
     766                 :         }
     767                 : 
     768               3 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     769               3 :         index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
     770                 : 
     771               3 :         RETURN_BOOL(index >= 0 && index < intern->llist->count);
     772                 : } /* }}} */
     773                 : 
     774                 : /* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed $index) U
     775                 :  Returns the value at the specified $index. */
     776                 : SPL_METHOD(SplDoublyLinkedList, offsetGet)
     777              14 : {
     778                 :         zval                  *zindex, *value;
     779                 :         long                   index;
     780                 :         spl_dllist_object     *intern;
     781                 :         spl_ptr_llist_element *element;
     782                 : 
     783              14 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     784               2 :                 return;
     785                 :         }
     786                 : 
     787              12 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     788              12 :         index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
     789                 : 
     790              12 :     if (index < 0 || index >= intern->llist->count) {
     791               4 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
     792               4 :                 return;
     793                 :         }
     794                 : 
     795               8 :         element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     796                 : 
     797               8 :         if (element != NULL) {
     798               8 :                 value = (zval *)element->data;
     799               8 :                 RETURN_ZVAL(value, 1, 0);
     800                 :         } else {
     801               0 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     802               0 :                 return;
     803                 :         }
     804                 : } /* }}} */
     805                 : 
     806                 : /* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval) U
     807                 :  Sets the value at the specified $index to $newval. */
     808                 : SPL_METHOD(SplDoublyLinkedList, offsetSet)
     809              10 : {
     810                 :         zval                  *zindex, *value;
     811                 :         spl_dllist_object     *intern;
     812                 : 
     813              10 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
     814               2 :                 return;
     815                 :         }
     816               8 :         SEPARATE_ARG_IF_REF(value);
     817                 : 
     818               8 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     819                 : 
     820               8 :         if (Z_TYPE_P(zindex) == IS_NULL) {
     821                 :                 /* $obj[] = ... */
     822               6 :                 spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
     823                 :         } else {
     824                 :                 /* $obj[$foo] = ... */
     825                 :                 long                   index;
     826                 :                 spl_ptr_llist_element *element;
     827                 : 
     828               2 :                 index = spl_offset_convert_to_long(zindex TSRMLS_CC);
     829                 : 
     830               2 :                 if (index < 0 || index >= intern->llist->count) {
     831               1 :                         zval_ptr_dtor(&value);
     832               1 :                         zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
     833               1 :                         return;
     834                 :                 }
     835                 : 
     836               1 :                 element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     837                 : 
     838               1 :                 if (element != NULL) {
     839                 :                         /* call dtor on the old element as in spl_ptr_llist_pop */
     840               1 :                         if (intern->llist->dtor) {
     841               1 :                                 intern->llist->dtor(element TSRMLS_CC);
     842                 :                         }
     843                 : 
     844                 :                         /* the element is replaced, delref the old one as in
     845                 :                          * SplDoublyLinkedList::pop() */
     846               1 :                         zval_ptr_dtor((zval **)&element->data);
     847               1 :                         element->data = value;
     848                 : 
     849                 :                         /* new element, call ctor as in spl_ptr_llist_push */
     850               1 :                         if (intern->llist->ctor) {
     851               1 :                                 intern->llist->ctor(element TSRMLS_CC);
     852                 :                         }
     853                 :                 } else {
     854               0 :                         zval_ptr_dtor(&value);
     855               0 :                         zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     856               0 :                         return;
     857                 :                 }
     858                 :         }
     859                 : } /* }}} */
     860                 : 
     861                 : /* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed $index) U
     862                 :  Unsets the value at the specified $index. */
     863                 : SPL_METHOD(SplDoublyLinkedList, offsetUnset)
     864               7 : {
     865                 :         zval                  *zindex;
     866                 :         long                   index;
     867                 :         spl_dllist_object     *intern;
     868                 :         spl_ptr_llist_element *element;
     869                 :         spl_ptr_llist         *llist;
     870                 : 
     871               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
     872               0 :                 return;
     873                 :         }
     874                 : 
     875               7 :         intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
     876               7 :         index  = (int)spl_offset_convert_to_long(zindex TSRMLS_CC);
     877               7 :     llist  = intern->llist;
     878                 : 
     879               7 :     if (index < 0 || index >= intern->llist->count) {
     880               3 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
     881               3 :                 return;
     882                 :         }
     883                 : 
     884               4 :         element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
     885                 : 
     886               4 :         if (element != NULL) {
     887                 :                 /* connect the neightbors */
     888               4 :                 if (element->prev) {
     889               2 :                         element->prev->next = element->next;
     890                 :                 }
     891                 : 
     892               4 :                 if (element->next) {
     893               3 :                         element->next->prev = element->prev;
     894                 :                 }
     895                 : 
     896                 :                 /* take care of head/tail */
     897               4 :                 if (element == llist->head) {
     898               2 :                         llist->head = element->next;
     899                 :                 }
     900                 : 
     901               4 :                 if (element == llist->tail) {
     902               1 :                         llist->tail = element->prev;
     903                 :                 }
     904                 : 
     905                 :                 /* finally, delete the element */
     906               4 :                 llist->count--;
     907                 : 
     908               4 :                 if(llist->dtor) {
     909               4 :                         llist->dtor(element TSRMLS_CC);
     910                 :                 }
     911                 : 
     912               4 :                 zval_ptr_dtor((zval **)&element->data);
     913               4 :                 element->data = NULL;
     914                 : 
     915               4 :                 SPL_LLIST_DELREF(element);
     916                 :         } else {
     917               0 :                 zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
     918               0 :                 return;
     919                 :         }
     920                 : } /* }}} */
     921                 : 
     922                 : static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
     923              11 : {
     924              11 :         spl_dllist_it *iterator = (spl_dllist_it *)iter;
     925                 : 
     926              11 :         SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer);
     927                 : 
     928              11 :         zend_user_it_invalidate_current(iter TSRMLS_CC);
     929              11 :         zval_ptr_dtor((zval**)&iterator->intern.it.data);
     930                 : 
     931              11 :         efree(iterator);
     932              11 : }
     933                 : /* }}} */
     934                 : 
     935                 : 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) /* {{{ */
     936              17 : {
     937              17 :         SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr);
     938                 : 
     939              17 :         if (flags & SPL_DLLIST_IT_LIFO) {
     940               3 :                 *traverse_position_ptr = llist->count-1;
     941               3 :                 *traverse_pointer_ptr  = llist->tail;
     942                 :         } else {
     943              14 :                 *traverse_position_ptr = 0;
     944              14 :                 *traverse_pointer_ptr  = llist->head;
     945                 :         }
     946                 : 
     947              17 :         SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
     948              17 : }
     949                 : /* }}} */
     950                 : 
     951                 : 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) /* {{{ */
     952              44 : {
     953              44 :         if (*traverse_pointer_ptr) {
     954              43 :                 spl_ptr_llist_element *old = *traverse_pointer_ptr;
     955                 : 
     956              43 :                 if (flags & SPL_DLLIST_IT_LIFO) {
     957              10 :                         *traverse_pointer_ptr = old->prev;
     958              10 :                         (*traverse_position_ptr)--;
     959                 : 
     960              10 :                         if (flags & SPL_DLLIST_IT_DELETE) {
     961               0 :                                 zval *prev = (zval *)spl_ptr_llist_pop(llist TSRMLS_CC);
     962                 : 
     963               0 :                                 if (prev) {
     964               0 :                                         zval_ptr_dtor((zval **)&prev);
     965                 :                                 }
     966                 :                         }
     967                 :                 } else {
     968              33 :                         *traverse_pointer_ptr = old->next;
     969              33 :                         if (flags & SPL_DLLIST_IT_DELETE) {
     970               3 :                                 zval *prev = (zval *)spl_ptr_llist_shift(llist TSRMLS_CC);
     971                 : 
     972               3 :                                 if (prev) {
     973               3 :                                         zval_ptr_dtor((zval **)&prev);
     974                 :                                 }
     975                 :                         } else {
     976              30 :                                 (*traverse_position_ptr)++;
     977                 :                         }
     978                 :                 }
     979                 : 
     980              43 :                 SPL_LLIST_DELREF(old);
     981              43 :                 SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
     982                 :         }
     983              44 : }
     984                 : /* }}} */
     985                 : 
     986                 : static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
     987              11 : {
     988              11 :         spl_dllist_it     *iterator = (spl_dllist_it *)iter;
     989              11 :         spl_dllist_object *object   = iterator->object;
     990              11 :         spl_ptr_llist     *llist    = object->llist;
     991                 : 
     992              11 :         spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC);
     993              11 : }
     994                 : /* }}} */
     995                 : 
     996                 : static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
     997              41 : {
     998              41 :         spl_dllist_it         *iterator = (spl_dllist_it *)iter;
     999              41 :         spl_ptr_llist_element *element  = iterator->traverse_pointer;
    1000                 : 
    1001              41 :         return (element != NULL ? SUCCESS : FAILURE);
    1002                 : }
    1003                 : /* }}} */
    1004                 : 
    1005                 : static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
    1006              30 : {
    1007              30 :         spl_dllist_it         *iterator = (spl_dllist_it *)iter;
    1008              30 :         spl_ptr_llist_element *element  = iterator->traverse_pointer;
    1009                 : 
    1010              30 :         if (element == NULL || element->data == NULL) {
    1011               0 :                 *data = NULL;
    1012                 :         } else {
    1013              30 :                 *data = (zval **)&element->data;
    1014                 :         }
    1015              30 : }
    1016                 : /* }}} */
    1017                 : 
    1018                 : static int spl_dllist_it_get_current_key(zend_object_iterator *iter, zstr *str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
    1019              26 : {
    1020              26 :         spl_dllist_it *iterator = (spl_dllist_it *)iter;
    1021                 : 
    1022              26 :         *int_key = (ulong) iterator->traverse_position;
    1023              26 :         return HASH_KEY_IS_LONG;
    1024                 : }
    1025                 : /* }}} */
    1026                 : 
    1027                 : static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
    1028              30 : {
    1029              30 :         spl_dllist_it     *iterator = (spl_dllist_it *)iter;
    1030              30 :         spl_dllist_object *object   = iterator->object;
    1031                 : 
    1032              30 :         zend_user_it_invalidate_current(iter TSRMLS_CC);
    1033                 : 
    1034              30 :         spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC);
    1035              30 : }
    1036                 : /* }}} */
    1037                 : 
    1038                 : /* {{{  proto int SplDoublyLinkedList::key() U
    1039                 :    Return current array key */
    1040                 : SPL_METHOD(SplDoublyLinkedList, key)
    1041               0 : {
    1042               0 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1043                 : 
    1044               0 :         RETURN_LONG(intern->traverse_position);
    1045                 : }
    1046                 : /* }}} */
    1047                 : 
    1048                 : /* {{{ proto void SplDoublyLinkedList::prev() U
    1049                 :    Move to next entry */
    1050                 : SPL_METHOD(SplDoublyLinkedList, prev)
    1051               3 : {
    1052               3 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1053                 : 
    1054               3 :         spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO TSRMLS_CC);
    1055               3 : }
    1056                 : /* }}} */
    1057                 : 
    1058                 : /* {{{ proto void SplDoublyLinkedList::next() U
    1059                 :    Move to next entry */
    1060                 : SPL_METHOD(SplDoublyLinkedList, next)
    1061              11 : {
    1062              11 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1063                 : 
    1064              11 :         spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
    1065              11 : }
    1066                 : /* }}} */
    1067                 : 
    1068                 : /* {{{ proto bool SplDoublyLinkedList::valid() U
    1069                 :    Check whether the datastructure contains more entries */
    1070                 : SPL_METHOD(SplDoublyLinkedList, valid)
    1071               4 : {
    1072               4 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1073                 : 
    1074               4 :         RETURN_BOOL(intern->traverse_pointer != NULL);
    1075                 : }
    1076                 : /* }}} */
    1077                 : 
    1078                 : /* {{{ proto void SplDoublyLinkedList::rewind() U
    1079                 :    Rewind the datastructure back to the start */
    1080                 : SPL_METHOD(SplDoublyLinkedList, rewind)
    1081               6 : {
    1082               6 :         spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1083                 : 
    1084               6 :         spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
    1085               6 : }
    1086                 : /* }}} */
    1087                 : 
    1088                 : /* {{{ proto mixed|NULL SplDoublyLinkedList::current() U
    1089                 :    Return current datastructure entry */
    1090                 : SPL_METHOD(SplDoublyLinkedList, current)
    1091              17 : {
    1092              17 :         spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
    1093              17 :         spl_ptr_llist_element *element = intern->traverse_pointer;
    1094                 : 
    1095              17 :         if (element == NULL || element->data == NULL) {
    1096               5 :                 RETURN_NULL();
    1097                 :         } else {
    1098              12 :                 zval *data    = (zval *)element->data;
    1099              12 :                 RETURN_ZVAL(data, 1, 0);
    1100                 :         }
    1101                 : }
    1102                 : /* }}} */
    1103                 : 
    1104                 : /* iterator handler table */
    1105                 : zend_object_iterator_funcs spl_dllist_it_funcs = {
    1106                 :         spl_dllist_it_dtor,
    1107                 :         spl_dllist_it_valid,
    1108                 :         spl_dllist_it_get_current_data,
    1109                 :         spl_dllist_it_get_current_key,
    1110                 :         spl_dllist_it_move_forward,
    1111                 :         spl_dllist_it_rewind
    1112                 : };
    1113                 : 
    1114                 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
    1115              11 : {
    1116                 :         spl_dllist_it     *iterator;
    1117              11 :         spl_dllist_object *dllist_object = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
    1118                 : 
    1119              11 :         if (by_ref) {
    1120               0 :                 zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
    1121               0 :                 return NULL;
    1122                 :         }
    1123                 : 
    1124              11 :         Z_ADDREF_P(object);
    1125                 : 
    1126              11 :         iterator                     = emalloc(sizeof(spl_dllist_it));
    1127              11 :         iterator->intern.it.data     = (void*)object;
    1128              11 :         iterator->intern.it.funcs    = &spl_dllist_it_funcs;
    1129              11 :         iterator->intern.ce          = ce;
    1130              11 :         iterator->intern.value       = NULL;
    1131              11 :         iterator->traverse_position  = dllist_object->traverse_position;
    1132              11 :         iterator->traverse_pointer   = dllist_object->traverse_pointer;
    1133              11 :         iterator->flags              = dllist_object->flags & SPL_DLLIST_IT_MASK;
    1134                 : 
    1135              11 :         SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
    1136                 : 
    1137              11 :         iterator->object = dllist_object;
    1138                 : 
    1139              11 :         return (zend_object_iterator*)iterator;
    1140                 : }
    1141                 : /* }}} */
    1142                 : 
    1143                 : /*  Function/Class/Method definitions */
    1144                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_setiteratormode, 0)
    1145                 :         ZEND_ARG_INFO(0, flags)
    1146                 : ZEND_END_ARG_INFO()
    1147                 : 
    1148                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_push, 0)
    1149                 :         ZEND_ARG_INFO(0, value)
    1150                 : ZEND_END_ARG_INFO()
    1151                 : 
    1152                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetGet, 0, 0, 1)
    1153                 :         ZEND_ARG_INFO(0, index)
    1154                 : ZEND_END_ARG_INFO()
    1155                 : 
    1156                 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetSet, 0, 0, 2)
    1157                 :         ZEND_ARG_INFO(0, index)
    1158                 :         ZEND_ARG_INFO(0, newval)
    1159                 : ZEND_END_ARG_INFO()
    1160                 : 
    1161                 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0)
    1162                 : ZEND_END_ARG_INFO()
    1163                 : 
    1164                 : static const zend_function_entry spl_funcs_SplQueue[] = {
    1165                 :         SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push,  arginfo_dllist_push, ZEND_ACC_PUBLIC)
    1166                 :         SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
    1167                 :         {NULL, NULL, NULL}
    1168                 : };
    1169                 : 
    1170                 : static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
    1171                 :         SPL_ME(SplDoublyLinkedList, pop,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1172                 :         SPL_ME(SplDoublyLinkedList, shift,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1173                 :         SPL_ME(SplDoublyLinkedList, push,            arginfo_dllist_push,            ZEND_ACC_PUBLIC)
    1174                 :         SPL_ME(SplDoublyLinkedList, unshift,         arginfo_dllist_push,            ZEND_ACC_PUBLIC)
    1175                 :         SPL_ME(SplDoublyLinkedList, top,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1176                 :         SPL_ME(SplDoublyLinkedList, bottom,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1177                 :         SPL_ME(SplDoublyLinkedList, count,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1178                 :         SPL_ME(SplDoublyLinkedList, isEmpty,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1179                 :         SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC)
    1180                 :         SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1181                 :         SPL_ME(SplDoublyLinkedList, offsetExists,    arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1182                 :         SPL_ME(SplDoublyLinkedList, offsetGet,       arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1183                 :         SPL_ME(SplDoublyLinkedList, offsetSet,       arginfo_dllist_offsetSet,       ZEND_ACC_PUBLIC)
    1184                 :         SPL_ME(SplDoublyLinkedList, offsetUnset,     arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
    1185                 :         SPL_ME(SplDoublyLinkedList, rewind,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1186                 :         SPL_ME(SplDoublyLinkedList, current,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1187                 :         SPL_ME(SplDoublyLinkedList, key,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1188                 :         SPL_ME(SplDoublyLinkedList, next,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1189                 :         SPL_ME(SplDoublyLinkedList, prev,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1190                 :         SPL_ME(SplDoublyLinkedList, valid,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
    1191                 :         {NULL, NULL, NULL}
    1192                 : };
    1193                 : /* }}} */
    1194                 : 
    1195                 : PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
    1196           17007 : {
    1197           17007 :         REGISTER_SPL_STD_CLASS_EX(SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplDoublyLinkedList);
    1198           17007 :         memcpy(&spl_handler_SplDoublyLinkedList, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
    1199                 : 
    1200           17007 :         spl_handler_SplDoublyLinkedList.clone_obj      = spl_dllist_object_clone;
    1201           17007 :         spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements;
    1202           17007 :         spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info;
    1203                 : 
    1204           17007 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_LIFO",  SPL_DLLIST_IT_LIFO);
    1205           17007 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_FIFO",  0);
    1206           17007 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_DELETE",SPL_DLLIST_IT_DELETE);
    1207           17007 :         REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_KEEP",  0);
    1208                 : 
    1209           17007 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
    1210           17007 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
    1211           17007 :         REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
    1212                 : 
    1213           17007 :         spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;
    1214                 : 
    1215           17007 :         REGISTER_SPL_SUB_CLASS_EX(SplQueue,           SplDoublyLinkedList,        spl_dllist_object_new, spl_funcs_SplQueue);
    1216           17007 :         REGISTER_SPL_SUB_CLASS_EX(SplStack,           SplDoublyLinkedList,        spl_dllist_object_new, NULL);
    1217                 : 
    1218           17007 :         spl_ce_SplQueue->get_iterator = spl_dllist_get_iterator;
    1219           17007 :         spl_ce_SplStack->get_iterator = spl_dllist_get_iterator;
    1220                 : 
    1221           17007 :         return SUCCESS;
    1222                 : }
    1223                 : /* }}} */
    1224                 : /*
    1225                 :  * Local variables:
    1226                 :  * tab-width: 4
    1227                 :  * c-basic-offset: 4
    1228                 :  * End:
    1229                 :  * vim600: fdm=marker
    1230                 :  * vim: noet sw=4 ts=4
    1231                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:39 +0000 (35 hours ago)

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