Back to index

php5  5.3.10
spl_dllist.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Etienne Kneuss <colder@php.net>                             |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: spl_dllist.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00021 #ifdef HAVE_CONFIG_H
00022 # include "config.h"
00023 #endif
00024 
00025 #include "php.h"
00026 #include "zend_exceptions.h"
00027 #include "zend_hash.h"
00028 
00029 #include "php_spl.h"
00030 #include "spl_functions.h"
00031 #include "spl_engine.h"
00032 #include "spl_iterators.h"
00033 #include "spl_dllist.h"
00034 #include "spl_exceptions.h"
00035 
00036 zend_object_handlers spl_handler_SplDoublyLinkedList;
00037 PHPAPI zend_class_entry  *spl_ce_SplDoublyLinkedList;
00038 PHPAPI zend_class_entry  *spl_ce_SplQueue;
00039 PHPAPI zend_class_entry  *spl_ce_SplStack;
00040 
00041 #define SPL_LLIST_DELREF(elem) if(!--(elem)->rc) { \
00042        efree(elem); \
00043        elem = NULL; \
00044 }
00045 
00046 #define SPL_LLIST_CHECK_DELREF(elem) if((elem) && !--(elem)->rc) { \
00047        efree(elem); \
00048        elem = NULL; \
00049 }
00050 
00051 #define SPL_LLIST_ADDREF(elem) (elem)->rc++
00052 #define SPL_LLIST_CHECK_ADDREF(elem) if(elem) (elem)->rc++
00053 
00054 #define SPL_DLLIST_IT_DELETE 0x00000001 /* Delete flag makes the iterator delete the current element on next */
00055 #define SPL_DLLIST_IT_LIFO   0x00000002 /* LIFO flag makes the iterator traverse the structure as a LastInFirstOut */
00056 #define SPL_DLLIST_IT_MASK   0x00000003 /* Mask to isolate flags related to iterators */
00057 #define SPL_DLLIST_IT_FIX    0x00000004 /* Backward/Forward bit is fixed */
00058 
00059 #ifdef accept
00060 #undef accept
00061 #endif
00062 
00063 typedef struct _spl_ptr_llist_element {
00064        struct _spl_ptr_llist_element *prev;
00065        struct _spl_ptr_llist_element *next;
00066        int                            rc;
00067        void                          *data;
00068 } spl_ptr_llist_element;
00069 
00070 typedef void (*spl_ptr_llist_dtor_func)(spl_ptr_llist_element * TSRMLS_DC);
00071 typedef void (*spl_ptr_llist_ctor_func)(spl_ptr_llist_element * TSRMLS_DC);
00072 
00073 typedef struct _spl_ptr_llist {
00074        spl_ptr_llist_element   *head;
00075        spl_ptr_llist_element   *tail;
00076        spl_ptr_llist_dtor_func  dtor;
00077        spl_ptr_llist_ctor_func  ctor;
00078        int count;
00079 } spl_ptr_llist;
00080 
00081 typedef struct _spl_dllist_object spl_dllist_object;
00082 typedef struct _spl_dllist_it spl_dllist_it;
00083 
00084 struct _spl_dllist_object {
00085        zend_object            std;
00086        spl_ptr_llist         *llist;
00087        int                    traverse_position;
00088        spl_ptr_llist_element *traverse_pointer;
00089        zval                  *retval;
00090        int                    flags;
00091        zend_function         *fptr_offset_get;
00092        zend_function         *fptr_offset_set;
00093        zend_function         *fptr_offset_has;
00094        zend_function         *fptr_offset_del;
00095        zend_function         *fptr_count;
00096        zend_class_entry      *ce_get_iterator;
00097        HashTable             *debug_info;
00098 };
00099 
00100 /* define an overloaded iterator structure */
00101 struct _spl_dllist_it {
00102        zend_user_iterator     intern;
00103        int                    traverse_position;
00104        spl_ptr_llist_element *traverse_pointer;
00105        int                    flags;
00106        spl_dllist_object     *object;
00107 };
00108 
00109 /* {{{  spl_ptr_llist */
00110 static void spl_ptr_llist_zval_dtor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */
00111        if (elem->data) {
00112               zval_ptr_dtor((zval **)&elem->data);
00113        }
00114 }
00115 /* }}} */
00116 
00117 static void spl_ptr_llist_zval_ctor(spl_ptr_llist_element *elem TSRMLS_DC) { /* {{{ */
00118        Z_ADDREF_P((zval *)elem->data);
00119 }
00120 /* }}} */
00121 
00122 static spl_ptr_llist *spl_ptr_llist_init(spl_ptr_llist_ctor_func ctor, spl_ptr_llist_dtor_func dtor) /* {{{ */
00123 {
00124        spl_ptr_llist *llist = emalloc(sizeof(spl_ptr_llist));
00125 
00126        llist->head  = NULL;
00127        llist->tail  = NULL;
00128        llist->count = 0;
00129        llist->dtor  = dtor;
00130        llist->ctor  = ctor;
00131 
00132        return llist;
00133 }
00134 /* }}} */
00135 
00136 static long spl_ptr_llist_count(spl_ptr_llist *llist) /* {{{ */
00137 {
00138        return (long)llist->count;
00139 }
00140 /* }}} */
00141 
00142 static void spl_ptr_llist_destroy(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
00143 {
00144        spl_ptr_llist_element   *current = llist->head, *next;
00145        spl_ptr_llist_dtor_func  dtor    = llist->dtor;
00146 
00147        while (current) {
00148               next = current->next;
00149               if(current && dtor) {
00150                      dtor(current TSRMLS_CC);
00151               }
00152               SPL_LLIST_DELREF(current);
00153               current = next;
00154        }
00155 
00156        efree(llist);
00157 }
00158 /* }}} */
00159 
00160 static spl_ptr_llist_element *spl_ptr_llist_offset(spl_ptr_llist *llist, long offset, int backward) /* {{{ */
00161 {
00162 
00163        spl_ptr_llist_element *current;
00164        int pos = 0;
00165 
00166        if (backward) {
00167               current = llist->tail;
00168        } else {
00169               current = llist->head;
00170        }
00171 
00172        while (current && pos < offset) {
00173               pos++;
00174               if (backward) {
00175                      current = current->prev;
00176               } else {
00177                      current = current->next;
00178               }
00179        }
00180 
00181        return current;
00182 }
00183 /* }}} */
00184 
00185 static void spl_ptr_llist_unshift(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */
00186 {
00187        spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));
00188 
00189        elem->data = data;
00190        elem->rc   = 1;
00191        elem->prev = NULL;
00192        elem->next = llist->head;
00193 
00194        if (llist->head) {
00195               llist->head->prev = elem;
00196        } else {
00197               llist->tail = elem;
00198        }
00199 
00200        llist->head = elem;
00201        llist->count++;
00202 
00203        if (llist->ctor) {
00204               llist->ctor(elem TSRMLS_CC);
00205        }
00206 }
00207 /* }}} */
00208 
00209 static void spl_ptr_llist_push(spl_ptr_llist *llist, void *data TSRMLS_DC) /* {{{ */
00210 {
00211        spl_ptr_llist_element *elem = emalloc(sizeof(spl_ptr_llist_element));
00212 
00213        elem->data = data;
00214        elem->rc   = 1;
00215        elem->prev = llist->tail;
00216        elem->next = NULL;
00217 
00218        if (llist->tail) {
00219               llist->tail->next = elem;
00220        } else {
00221               llist->head = elem;
00222        }
00223 
00224        llist->tail = elem;
00225        llist->count++;
00226 
00227        if (llist->ctor) {
00228               llist->ctor(elem TSRMLS_CC);
00229        }
00230 }
00231 /* }}} */
00232 
00233 static void *spl_ptr_llist_pop(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
00234 {
00235        void                     *data;
00236        spl_ptr_llist_element    *tail = llist->tail;
00237 
00238        if (tail == NULL) {
00239               return NULL;
00240        }
00241 
00242        if (tail->prev) {
00243               tail->prev->next = NULL;
00244        } else {
00245               llist->head = NULL;
00246        }
00247 
00248        llist->tail = tail->prev;
00249        llist->count--;
00250        data = tail->data;
00251 
00252        if (llist->dtor) {
00253               llist->dtor(tail TSRMLS_CC);
00254        }
00255 
00256        tail->data = NULL;
00257 
00258        SPL_LLIST_DELREF(tail);
00259 
00260        return data;
00261 }
00262 /* }}} */
00263 
00264 static void *spl_ptr_llist_last(spl_ptr_llist *llist) /* {{{ */
00265 {
00266        spl_ptr_llist_element *tail = llist->tail;
00267 
00268        if (tail == NULL) {
00269               return NULL;
00270        } else {
00271               return tail->data;
00272        }
00273 }
00274 /* }}} */
00275 
00276 static void *spl_ptr_llist_first(spl_ptr_llist *llist) /* {{{ */
00277 {
00278        spl_ptr_llist_element *head = llist->head;
00279 
00280        if (head == NULL) {
00281               return NULL;
00282        } else {
00283               return head->data;
00284        }
00285 }
00286 /* }}} */
00287 
00288 static void *spl_ptr_llist_shift(spl_ptr_llist *llist TSRMLS_DC) /* {{{ */
00289 {
00290        void                    *data;
00291        spl_ptr_llist_element   *head = llist->head;
00292 
00293        if (head == NULL) {
00294               return NULL;
00295        }
00296 
00297        if (head->next) {
00298               head->next->prev = NULL;
00299        } else {
00300               llist->tail = NULL;
00301        }
00302 
00303        llist->head = head->next;
00304        llist->count--;
00305        data = head->data;
00306 
00307        if (llist->dtor) {
00308               llist->dtor(head TSRMLS_CC);
00309        }
00310        head->data = NULL;
00311 
00312        SPL_LLIST_DELREF(head);
00313 
00314        return data;
00315 }
00316 /* }}} */
00317 
00318 static void spl_ptr_llist_copy(spl_ptr_llist *from, spl_ptr_llist *to TSRMLS_DC) /* {{{ */
00319 {
00320        spl_ptr_llist_element   *current = from->head, *next;
00321        spl_ptr_llist_ctor_func  ctor    = from->ctor;
00322 
00323        while (current) {
00324               next = current->next;
00325 
00326               if (ctor) {
00327                      ctor(current TSRMLS_CC);
00328               }
00329 
00330               spl_ptr_llist_push(to, current->data TSRMLS_CC);
00331               current = next;
00332        }
00333 
00334 }
00335 /* }}} */
00336 
00337 /* }}} */
00338 
00339 static void spl_dllist_object_free_storage(void *object TSRMLS_DC) /* {{{ */
00340 {
00341        spl_dllist_object *intern = (spl_dllist_object *)object;
00342        zval              *tmp    = NULL;
00343 
00344        zend_object_std_dtor(&intern->std TSRMLS_CC);
00345 
00346        while(intern->llist->count > 0) {
00347               tmp = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
00348               zval_ptr_dtor(&tmp);
00349        }
00350 
00351        spl_ptr_llist_destroy(intern->llist TSRMLS_CC);
00352        SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
00353        zval_ptr_dtor(&intern->retval);
00354 
00355        if (intern->debug_info != NULL) {
00356               zend_hash_destroy(intern->debug_info);
00357               efree(intern->debug_info);
00358        }
00359 
00360        efree(object);
00361 }
00362 /* }}} */
00363 
00364 zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
00365 
00366 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) /* {{{ */
00367 {
00368        zend_object_value  retval;
00369        spl_dllist_object *intern;
00370        zval              *tmp;
00371        zend_class_entry  *parent = class_type;
00372        int                inherited = 0;
00373 
00374        intern = ecalloc(1, sizeof(spl_dllist_object));
00375        *obj = intern;
00376        ALLOC_INIT_ZVAL(intern->retval);
00377 
00378        zend_object_std_init(&intern->std, class_type TSRMLS_CC);
00379        zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00380 
00381        intern->flags = 0;
00382        intern->traverse_position = 0;
00383        intern->debug_info = NULL;
00384 
00385        if (orig) {
00386               spl_dllist_object *other = (spl_dllist_object*)zend_object_store_get_object(orig TSRMLS_CC);
00387               intern->ce_get_iterator = other->ce_get_iterator;
00388 
00389               if (clone_orig) {
00390                      intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(other->llist->ctor, other->llist->dtor);
00391                      spl_ptr_llist_copy(other->llist, intern->llist TSRMLS_CC);
00392                      intern->traverse_pointer  = intern->llist->head;
00393                      SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
00394               } else {
00395                      intern->llist = other->llist;
00396                      intern->traverse_pointer  = intern->llist->head;
00397                      SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
00398               }
00399 
00400               intern->flags = other->flags;
00401        } else {
00402               intern->llist = (spl_ptr_llist *)spl_ptr_llist_init(spl_ptr_llist_zval_ctor, spl_ptr_llist_zval_dtor);
00403               intern->traverse_pointer  = intern->llist->head;
00404               SPL_LLIST_CHECK_ADDREF(intern->traverse_pointer);
00405        }
00406 
00407        while (parent) {
00408               if (parent == spl_ce_SplStack) {
00409                      intern->flags |= (SPL_DLLIST_IT_FIX | SPL_DLLIST_IT_LIFO);
00410                      retval.handlers = &spl_handler_SplDoublyLinkedList;
00411               } else if (parent == spl_ce_SplQueue) {
00412                      intern->flags |= SPL_DLLIST_IT_FIX;
00413                      retval.handlers = &spl_handler_SplDoublyLinkedList;
00414               }
00415 
00416               if (parent == spl_ce_SplDoublyLinkedList) {
00417                      retval.handlers = &spl_handler_SplDoublyLinkedList;
00418                      break;
00419               }
00420 
00421               parent = parent->parent;
00422               inherited = 1;
00423        }
00424 
00425        retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, spl_dllist_object_free_storage, NULL TSRMLS_CC);
00426 
00427        if (!parent) { /* this must never happen */
00428               php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList");
00429        }
00430        if (inherited) {
00431               zend_hash_find(&class_type->function_table, "offsetget",    sizeof("offsetget"),    (void **) &intern->fptr_offset_get);
00432               if (intern->fptr_offset_get->common.scope == parent) {
00433                      intern->fptr_offset_get = NULL;
00434               }
00435               zend_hash_find(&class_type->function_table, "offsetset",    sizeof("offsetset"),    (void **) &intern->fptr_offset_set);
00436               if (intern->fptr_offset_set->common.scope == parent) {
00437                      intern->fptr_offset_set = NULL;
00438               }
00439               zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
00440               if (intern->fptr_offset_has->common.scope == parent) {
00441                      intern->fptr_offset_has = NULL;
00442               }
00443               zend_hash_find(&class_type->function_table, "offsetunset",  sizeof("offsetunset"),  (void **) &intern->fptr_offset_del);
00444               if (intern->fptr_offset_del->common.scope == parent) {
00445                      intern->fptr_offset_del = NULL;
00446               }
00447               zend_hash_find(&class_type->function_table, "count",        sizeof("count"),        (void **) &intern->fptr_count);
00448               if (intern->fptr_count->common.scope == parent) {
00449                      intern->fptr_count = NULL;
00450               }
00451        }
00452 
00453        return retval;
00454 }
00455 /* }}} */
00456 
00457 static zend_object_value spl_dllist_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
00458 {
00459        spl_dllist_object *tmp;
00460        return spl_dllist_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
00461 }
00462 /* }}} */
00463 
00464 static zend_object_value spl_dllist_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
00465 {
00466        zend_object_value   new_obj_val;
00467        zend_object        *old_object;
00468        zend_object        *new_object;
00469        zend_object_handle  handle = Z_OBJ_HANDLE_P(zobject);
00470        spl_dllist_object  *intern;
00471 
00472        old_object  = zend_objects_get_address(zobject TSRMLS_CC);
00473        new_obj_val = spl_dllist_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
00474        new_object  = &intern->std;
00475 
00476        zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
00477 
00478        return new_obj_val;
00479 }
00480 /* }}} */
00481 
00482 static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
00483 {
00484        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
00485 
00486        if (intern->fptr_count) {
00487               zval *rv;
00488               zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
00489               if (rv) {
00490                      zval_ptr_dtor(&intern->retval);
00491                      MAKE_STD_ZVAL(intern->retval);
00492                      ZVAL_ZVAL(intern->retval, rv, 1, 1);
00493                      convert_to_long(intern->retval);
00494                      *count = (long) Z_LVAL_P(intern->retval);
00495                      return SUCCESS;
00496               }
00497               *count = 0;
00498               return FAILURE;
00499        }
00500 
00501        *count = spl_ptr_llist_count(intern->llist);
00502        return SUCCESS;
00503 } 
00504 /* }}} */
00505 
00506 static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
00507 {
00508        spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
00509        spl_ptr_llist_element *current = intern->llist->head, *next;
00510        zval *tmp, zrv, *dllist_array;
00511        char *pnstr;
00512        int  pnlen;
00513        int  i = 0;
00514 
00515        *is_temp = 0;
00516 
00517        if (intern->debug_info == NULL) {
00518               ALLOC_HASHTABLE(intern->debug_info);
00519               zend_hash_init(intern->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0);
00520        }
00521 
00522        if (intern->debug_info->nApplyCount == 0) {
00523               INIT_PZVAL(&zrv);
00524               Z_ARRVAL(zrv) = intern->debug_info;
00525 
00526               zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
00527 
00528               pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
00529               add_assoc_long_ex(&zrv, pnstr, pnlen+1, intern->flags);
00530               efree(pnstr);
00531 
00532               ALLOC_INIT_ZVAL(dllist_array);
00533               array_init(dllist_array);
00534 
00535               while (current) {
00536                      next = current->next;
00537 
00538                      add_index_zval(dllist_array, i, (zval *)current->data);
00539                      Z_ADDREF_P(current->data);
00540                      i++;
00541 
00542                      current = next;
00543               }
00544 
00545               pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
00546               add_assoc_zval_ex(&zrv, pnstr, pnlen+1, dllist_array);
00547               efree(pnstr);
00548        }
00549 
00550        return intern->debug_info;
00551 }
00552 /* }}}} */
00553 
00554 /* {{{ proto bool SplDoublyLinkedList::push(mixed $value) U
00555           Push $value on the SplDoublyLinkedList */
00556 SPL_METHOD(SplDoublyLinkedList, push)
00557 {
00558        zval *value;
00559        spl_dllist_object *intern;
00560 
00561        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
00562               return;
00563        }
00564 
00565        SEPARATE_ARG_IF_REF(value);
00566 
00567        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00568        spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
00569 
00570        RETURN_TRUE;
00571 } 
00572 /* }}} */
00573 
00574 /* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
00575           Unshift $value on the SplDoublyLinkedList */
00576 SPL_METHOD(SplDoublyLinkedList, unshift)
00577 {
00578        zval *value;
00579        spl_dllist_object *intern;
00580 
00581        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
00582               return;
00583        }
00584 
00585        SEPARATE_ARG_IF_REF(value);
00586 
00587        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00588        spl_ptr_llist_unshift(intern->llist, value TSRMLS_CC);
00589 
00590        RETURN_TRUE;
00591 }
00592 /* }}} */
00593 
00594 /* {{{ proto mixed SplDoublyLinkedList::pop() U
00595           Pop an element out of the SplDoublyLinkedList */
00596 SPL_METHOD(SplDoublyLinkedList, pop)
00597 {
00598        zval *value;
00599        spl_dllist_object *intern;
00600 
00601        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00602               return;
00603        }
00604 
00605        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00606        value = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
00607 
00608        if (value == NULL) {
00609               zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0 TSRMLS_CC);
00610               return;
00611        }
00612 
00613        RETURN_ZVAL(value, 1, 1);
00614 } 
00615 /* }}} */
00616 
00617 /* {{{ proto mixed SplDoublyLinkedList::shift() U
00618           Shift an element out of the SplDoublyLinkedList */
00619 SPL_METHOD(SplDoublyLinkedList, shift)
00620 {
00621        zval *value;
00622        spl_dllist_object *intern;
00623 
00624        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00625               return;
00626        }
00627 
00628        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00629        value  = (zval *)spl_ptr_llist_shift(intern->llist TSRMLS_CC);
00630 
00631        if (value == NULL) {
00632               zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0 TSRMLS_CC);
00633               return;
00634        }
00635 
00636        RETURN_ZVAL(value, 1, 1);
00637 } 
00638 /* }}} */
00639 
00640 /* {{{ proto mixed SplDoublyLinkedList::top() U
00641           Peek at the top element of the SplDoublyLinkedList */
00642 SPL_METHOD(SplDoublyLinkedList, top)
00643 {
00644        zval *value;
00645        spl_dllist_object *intern;
00646 
00647        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00648               return;
00649        }
00650 
00651        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00652        value  = (zval *)spl_ptr_llist_last(intern->llist);
00653 
00654        if (value == NULL) {
00655               zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
00656               return;
00657        }
00658 
00659        RETURN_ZVAL(value, 1, 0);
00660 }
00661 /* }}} */
00662 
00663 /* {{{ proto mixed SplDoublyLinkedList::bottom() U
00664           Peek at the bottom element of the SplDoublyLinkedList */
00665 SPL_METHOD(SplDoublyLinkedList, bottom)
00666 {
00667        zval *value;
00668        spl_dllist_object *intern;
00669 
00670        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00671               return;
00672        }
00673 
00674        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00675        value  = (zval *)spl_ptr_llist_first(intern->llist);
00676 
00677        if (value == NULL) {
00678               zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
00679               return;
00680        }
00681 
00682        RETURN_ZVAL(value, 1, 0);
00683 }
00684 /* }}} */
00685 
00686 /* {{{ proto int SplDoublyLinkedList::count() U
00687  Return the number of elements in the datastructure. */
00688 SPL_METHOD(SplDoublyLinkedList, count)
00689 {
00690        long count;
00691        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00692 
00693        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00694               return;
00695        }
00696 
00697        count = spl_ptr_llist_count(intern->llist);
00698        RETURN_LONG(count);
00699 }
00700 /* }}} */
00701 
00702 /* {{{ proto int SplDoublyLinkedList::isEmpty() U
00703  Return true if the SplDoublyLinkedList is empty. */
00704 SPL_METHOD(SplDoublyLinkedList, isEmpty)
00705 {
00706        long count;
00707 
00708        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00709               return;
00710        }
00711 
00712        spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC);
00713        RETURN_BOOL(count==0);
00714 }
00715 /* }}} */
00716 
00717 /* {{{ proto int SplDoublyLinkedList::setIteratorMode($flags) U
00718  Set the mode of iteration */
00719 SPL_METHOD(SplDoublyLinkedList, setIteratorMode)
00720 {
00721        long value;
00722        spl_dllist_object *intern;
00723 
00724        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
00725               return;
00726        }
00727 
00728        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00729 
00730        if (intern->flags & SPL_DLLIST_IT_FIX
00731               && (intern->flags & SPL_DLLIST_IT_LIFO) != (value & SPL_DLLIST_IT_LIFO)) {
00732               zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0 TSRMLS_CC);
00733               return;
00734        }
00735 
00736        intern->flags = value & SPL_DLLIST_IT_MASK;
00737 
00738        RETURN_LONG(intern->flags);
00739 }
00740 /* }}} */
00741 
00742 /* {{{ proto int SplDoublyLinkedList::getIteratorMode() U
00743  Return the mode of iteration */
00744 SPL_METHOD(SplDoublyLinkedList, getIteratorMode)
00745 {
00746        spl_dllist_object *intern;
00747 
00748        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
00749               return;
00750        }
00751 
00752        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00753 
00754        RETURN_LONG(intern->flags);
00755 }
00756 /* }}} */
00757 
00758 /* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U
00759  Returns whether the requested $index exists. */
00760 SPL_METHOD(SplDoublyLinkedList, offsetExists)
00761 {
00762        zval              *zindex;
00763        spl_dllist_object *intern;
00764        long               index;
00765 
00766        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
00767               return;
00768        }
00769 
00770        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00771        index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
00772 
00773        RETURN_BOOL(index >= 0 && index < intern->llist->count);
00774 } /* }}} */
00775 
00776 /* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed $index) U
00777  Returns the value at the specified $index. */
00778 SPL_METHOD(SplDoublyLinkedList, offsetGet)
00779 {
00780        zval                  *zindex, *value;
00781        long                   index;
00782        spl_dllist_object     *intern;
00783        spl_ptr_llist_element *element;
00784 
00785        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
00786               return;
00787        }
00788 
00789        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00790        index  = spl_offset_convert_to_long(zindex TSRMLS_CC);
00791 
00792     if (index < 0 || index >= intern->llist->count) {
00793               zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
00794               return;
00795        }
00796 
00797        element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
00798 
00799        if (element != NULL) {
00800               value = (zval *)element->data;
00801               RETURN_ZVAL(value, 1, 0);
00802        } else {
00803               zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
00804               return;
00805        }
00806 } /* }}} */
00807 
00808 /* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval) U
00809  Sets the value at the specified $index to $newval. */
00810 SPL_METHOD(SplDoublyLinkedList, offsetSet)
00811 {
00812        zval                  *zindex, *value;
00813        spl_dllist_object     *intern;
00814 
00815        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
00816               return;
00817        }
00818        SEPARATE_ARG_IF_REF(value);
00819 
00820        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00821 
00822        if (Z_TYPE_P(zindex) == IS_NULL) {
00823               /* $obj[] = ... */
00824               spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
00825        } else {
00826               /* $obj[$foo] = ... */
00827               long                   index;
00828               spl_ptr_llist_element *element;
00829 
00830               index = spl_offset_convert_to_long(zindex TSRMLS_CC);
00831 
00832               if (index < 0 || index >= intern->llist->count) {
00833                      zval_ptr_dtor(&value);
00834                      zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
00835                      return;
00836               }
00837 
00838               element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
00839 
00840               if (element != NULL) {
00841                      /* call dtor on the old element as in spl_ptr_llist_pop */
00842                      if (intern->llist->dtor) {
00843                             intern->llist->dtor(element TSRMLS_CC);
00844                      }
00845 
00846                      /* the element is replaced, delref the old one as in
00847                       * SplDoublyLinkedList::pop() */
00848                      zval_ptr_dtor((zval **)&element->data);
00849                      element->data = value;
00850 
00851                      /* new element, call ctor as in spl_ptr_llist_push */
00852                      if (intern->llist->ctor) {
00853                             intern->llist->ctor(element TSRMLS_CC);
00854                      }
00855               } else {
00856                      zval_ptr_dtor(&value);
00857                      zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
00858                      return;
00859               }
00860        }
00861 } /* }}} */
00862 
00863 /* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed $index) U
00864  Unsets the value at the specified $index. */
00865 SPL_METHOD(SplDoublyLinkedList, offsetUnset)
00866 {
00867        zval                  *zindex;
00868        long                   index;
00869        spl_dllist_object     *intern;
00870        spl_ptr_llist_element *element;
00871        spl_ptr_llist         *llist;
00872 
00873        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
00874               return;
00875        }
00876 
00877        intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
00878        index  = (int)spl_offset_convert_to_long(zindex TSRMLS_CC);
00879     llist  = intern->llist;
00880 
00881     if (index < 0 || index >= intern->llist->count) {
00882               zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
00883               return;
00884        }
00885 
00886        element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
00887 
00888        if (element != NULL) {
00889               /* connect the neightbors */
00890               if (element->prev) {
00891                      element->prev->next = element->next;
00892               }
00893 
00894               if (element->next) {
00895                      element->next->prev = element->prev;
00896               }
00897 
00898               /* take care of head/tail */
00899               if (element == llist->head) {
00900                      llist->head = element->next;
00901               }
00902 
00903               if (element == llist->tail) {
00904                      llist->tail = element->prev;
00905               }
00906 
00907               /* finally, delete the element */
00908               llist->count--;
00909 
00910               if(llist->dtor) {
00911                      llist->dtor(element TSRMLS_CC);
00912               }
00913 
00914               zval_ptr_dtor((zval **)&element->data);
00915               element->data = NULL;
00916 
00917               SPL_LLIST_DELREF(element);
00918        } else {
00919               zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
00920               return;
00921        }
00922 } /* }}} */
00923 
00924 static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00925 {
00926        spl_dllist_it *iterator = (spl_dllist_it *)iter;
00927 
00928        SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer);
00929 
00930        zend_user_it_invalidate_current(iter TSRMLS_CC);
00931        zval_ptr_dtor((zval**)&iterator->intern.it.data);
00932 
00933        efree(iterator);
00934 }
00935 /* }}} */
00936 
00937 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) /* {{{ */
00938 {
00939        SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr);
00940 
00941        if (flags & SPL_DLLIST_IT_LIFO) {
00942               *traverse_position_ptr = llist->count-1;
00943               *traverse_pointer_ptr  = llist->tail;
00944        } else {
00945               *traverse_position_ptr = 0;
00946               *traverse_pointer_ptr  = llist->head;
00947        }
00948 
00949        SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
00950 }
00951 /* }}} */
00952 
00953 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) /* {{{ */
00954 {
00955        if (*traverse_pointer_ptr) {
00956               spl_ptr_llist_element *old = *traverse_pointer_ptr;
00957 
00958               if (flags & SPL_DLLIST_IT_LIFO) {
00959                      *traverse_pointer_ptr = old->prev;
00960                      (*traverse_position_ptr)--;
00961 
00962                      if (flags & SPL_DLLIST_IT_DELETE) {
00963                             zval *prev = (zval *)spl_ptr_llist_pop(llist TSRMLS_CC);
00964 
00965                             if (prev) {
00966                                    zval_ptr_dtor((zval **)&prev);
00967                             }
00968                      }
00969               } else {
00970                      *traverse_pointer_ptr = old->next;
00971 
00972                      if (flags & SPL_DLLIST_IT_DELETE) {
00973                             zval *prev = (zval *)spl_ptr_llist_shift(llist TSRMLS_CC);
00974 
00975                             if (prev) {
00976                                    zval_ptr_dtor((zval **)&prev);
00977                             }
00978                      } else {
00979                             (*traverse_position_ptr)++;
00980                      }
00981               }
00982 
00983               SPL_LLIST_DELREF(old);
00984               SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
00985        }
00986 }
00987 /* }}} */
00988 
00989 static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
00990 {
00991        spl_dllist_it     *iterator = (spl_dllist_it *)iter;
00992        spl_dllist_object *object   = iterator->object;
00993        spl_ptr_llist     *llist    = object->llist;
00994 
00995        spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC);
00996 }
00997 /* }}} */
00998 
00999 static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
01000 {
01001        spl_dllist_it         *iterator = (spl_dllist_it *)iter;
01002        spl_ptr_llist_element *element  = iterator->traverse_pointer;
01003 
01004        return (element != NULL ? SUCCESS : FAILURE);
01005 }
01006 /* }}} */
01007 
01008 static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
01009 {
01010        spl_dllist_it         *iterator = (spl_dllist_it *)iter;
01011        spl_ptr_llist_element *element  = iterator->traverse_pointer;
01012 
01013        if (element == NULL || element->data == NULL) {
01014               *data = NULL;
01015        } else {
01016               *data = (zval **)&element->data;
01017        }
01018 }
01019 /* }}} */
01020 
01021 static int spl_dllist_it_get_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
01022 {
01023        spl_dllist_it *iterator = (spl_dllist_it *)iter;
01024 
01025        *int_key = (ulong) iterator->traverse_position;
01026        return HASH_KEY_IS_LONG;
01027 }
01028 /* }}} */
01029 
01030 static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
01031 {
01032        spl_dllist_it     *iterator = (spl_dllist_it *)iter;
01033        spl_dllist_object *object   = iterator->object;
01034 
01035        zend_user_it_invalidate_current(iter TSRMLS_CC);
01036 
01037        spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC);
01038 }
01039 /* }}} */
01040 
01041 /* {{{  proto int SplDoublyLinkedList::key() U
01042    Return current array key */
01043 SPL_METHOD(SplDoublyLinkedList, key)
01044 {
01045        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01046        
01047        if (zend_parse_parameters_none() == FAILURE) {
01048               return;
01049        }
01050 
01051        RETURN_LONG(intern->traverse_position);
01052 }
01053 /* }}} */
01054 
01055 /* {{{ proto void SplDoublyLinkedList::prev() U
01056    Move to next entry */
01057 SPL_METHOD(SplDoublyLinkedList, prev)
01058 {
01059        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01060        
01061        if (zend_parse_parameters_none() == FAILURE) {
01062               return;
01063        }
01064 
01065        spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO TSRMLS_CC);
01066 }
01067 /* }}} */
01068 
01069 /* {{{ proto void SplDoublyLinkedList::next() U
01070    Move to next entry */
01071 SPL_METHOD(SplDoublyLinkedList, next)
01072 {
01073        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01074        
01075        if (zend_parse_parameters_none() == FAILURE) {
01076               return;
01077        }
01078 
01079        spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
01080 }
01081 /* }}} */
01082 
01083 /* {{{ proto bool SplDoublyLinkedList::valid() U
01084    Check whether the datastructure contains more entries */
01085 SPL_METHOD(SplDoublyLinkedList, valid)
01086 {
01087        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01088        
01089        if (zend_parse_parameters_none() == FAILURE) {
01090               return;
01091        }
01092 
01093        RETURN_BOOL(intern->traverse_pointer != NULL);
01094 }
01095 /* }}} */
01096 
01097 /* {{{ proto void SplDoublyLinkedList::rewind() U
01098    Rewind the datastructure back to the start */
01099 SPL_METHOD(SplDoublyLinkedList, rewind)
01100 {
01101        spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01102        
01103        if (zend_parse_parameters_none() == FAILURE) {
01104               return;
01105        }
01106 
01107        spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
01108 }
01109 /* }}} */
01110 
01111 /* {{{ proto mixed|NULL SplDoublyLinkedList::current() U
01112    Return current datastructure entry */
01113 SPL_METHOD(SplDoublyLinkedList, current)
01114 {
01115        spl_dllist_object     *intern  = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
01116        spl_ptr_llist_element *element = intern->traverse_pointer;
01117        
01118        if (zend_parse_parameters_none() == FAILURE) {
01119               return;
01120        }
01121 
01122        if (element == NULL || element->data == NULL) {
01123               RETURN_NULL();
01124        } else {
01125               zval *data    = (zval *)element->data;
01126               RETURN_ZVAL(data, 1, 0);
01127        }
01128 }
01129 /* }}} */
01130 
01131 /* iterator handler table */
01132 zend_object_iterator_funcs spl_dllist_it_funcs = {
01133        spl_dllist_it_dtor,
01134        spl_dllist_it_valid,
01135        spl_dllist_it_get_current_data,
01136        spl_dllist_it_get_current_key,
01137        spl_dllist_it_move_forward,
01138        spl_dllist_it_rewind
01139 };
01140 
01141 zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
01142 {
01143        spl_dllist_it     *iterator;
01144        spl_dllist_object *dllist_object = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
01145 
01146        if (by_ref) {
01147               zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
01148               return NULL;
01149        }
01150 
01151        Z_ADDREF_P(object);
01152 
01153        iterator                     = emalloc(sizeof(spl_dllist_it));
01154        iterator->intern.it.data     = (void*)object;
01155        iterator->intern.it.funcs    = &spl_dllist_it_funcs;
01156        iterator->intern.ce          = ce;
01157        iterator->intern.value       = NULL;
01158        iterator->traverse_position  = dllist_object->traverse_position;
01159        iterator->traverse_pointer   = dllist_object->traverse_pointer;
01160        iterator->flags              = dllist_object->flags & SPL_DLLIST_IT_MASK;
01161        iterator->object             = dllist_object;
01162 
01163        SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
01164 
01165 
01166        return (zend_object_iterator*)iterator;
01167 }
01168 /* }}} */
01169 
01170 /*  Function/Class/Method definitions */
01171 ZEND_BEGIN_ARG_INFO(arginfo_dllist_setiteratormode, 0)
01172        ZEND_ARG_INFO(0, flags)
01173 ZEND_END_ARG_INFO()
01174 
01175 ZEND_BEGIN_ARG_INFO(arginfo_dllist_push, 0)
01176        ZEND_ARG_INFO(0, value)
01177 ZEND_END_ARG_INFO()
01178 
01179 ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetGet, 0, 0, 1)
01180        ZEND_ARG_INFO(0, index)
01181 ZEND_END_ARG_INFO()
01182 
01183 ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetSet, 0, 0, 2)
01184        ZEND_ARG_INFO(0, index)
01185        ZEND_ARG_INFO(0, newval)
01186 ZEND_END_ARG_INFO()
01187 
01188 ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0)
01189 ZEND_END_ARG_INFO()
01190 
01191 static const zend_function_entry spl_funcs_SplQueue[] = {
01192        SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push,  arginfo_dllist_push, ZEND_ACC_PUBLIC)
01193        SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
01194        PHP_FE_END
01195 };
01196 
01197 static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
01198        SPL_ME(SplDoublyLinkedList, pop,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01199        SPL_ME(SplDoublyLinkedList, shift,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01200        SPL_ME(SplDoublyLinkedList, push,            arginfo_dllist_push,            ZEND_ACC_PUBLIC)
01201        SPL_ME(SplDoublyLinkedList, unshift,         arginfo_dllist_push,            ZEND_ACC_PUBLIC)
01202        SPL_ME(SplDoublyLinkedList, top,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01203        SPL_ME(SplDoublyLinkedList, bottom,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01204        SPL_ME(SplDoublyLinkedList, count,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01205        SPL_ME(SplDoublyLinkedList, isEmpty,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01206        SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC)
01207        SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01208        SPL_ME(SplDoublyLinkedList, offsetExists,    arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
01209        SPL_ME(SplDoublyLinkedList, offsetGet,       arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
01210        SPL_ME(SplDoublyLinkedList, offsetSet,       arginfo_dllist_offsetSet,       ZEND_ACC_PUBLIC)
01211        SPL_ME(SplDoublyLinkedList, offsetUnset,     arginfo_dllist_offsetGet,       ZEND_ACC_PUBLIC)
01212        SPL_ME(SplDoublyLinkedList, rewind,          arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01213        SPL_ME(SplDoublyLinkedList, current,         arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01214        SPL_ME(SplDoublyLinkedList, key,             arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01215        SPL_ME(SplDoublyLinkedList, next,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01216        SPL_ME(SplDoublyLinkedList, prev,            arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01217        SPL_ME(SplDoublyLinkedList, valid,           arginfo_dllist_void,            ZEND_ACC_PUBLIC)
01218        PHP_FE_END
01219 };
01220 /* }}} */
01221 
01222 PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
01223 {
01224        REGISTER_SPL_STD_CLASS_EX(SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplDoublyLinkedList);
01225        memcpy(&spl_handler_SplDoublyLinkedList, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
01226 
01227        spl_handler_SplDoublyLinkedList.clone_obj      = spl_dllist_object_clone;
01228        spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements;
01229        spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info;
01230 
01231        REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_LIFO",  SPL_DLLIST_IT_LIFO);
01232        REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_FIFO",  0);
01233        REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_DELETE",SPL_DLLIST_IT_DELETE);
01234        REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_KEEP",  0);
01235 
01236        REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
01237        REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
01238        REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
01239 
01240        spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;
01241 
01242        REGISTER_SPL_SUB_CLASS_EX(SplQueue,           SplDoublyLinkedList,        spl_dllist_object_new, spl_funcs_SplQueue);
01243        REGISTER_SPL_SUB_CLASS_EX(SplStack,           SplDoublyLinkedList,        spl_dllist_object_new, NULL);
01244 
01245        spl_ce_SplQueue->get_iterator = spl_dllist_get_iterator;
01246        spl_ce_SplStack->get_iterator = spl_dllist_get_iterator;
01247 
01248        return SUCCESS;
01249 }
01250 /* }}} */
01251 /*
01252  * Local variables:
01253  * tab-width: 4
01254  * c-basic-offset: 4
01255  * End:
01256  * vim600: fdm=marker
01257  * vim: noet sw=4 ts=4
01258  */