Return to spl_dllist.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / spl |
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: */