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