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