Annotation of embedaddon/php/ext/spl/spl_dllist.c, revision 1.1.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>