1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2013 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$ */
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 */
spl_ptr_llist_zval_dtor(spl_ptr_llist_element * elem TSRMLS_DC)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
spl_ptr_llist_zval_ctor(spl_ptr_llist_element * elem TSRMLS_DC)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
spl_ptr_llist_init(spl_ptr_llist_ctor_func ctor,spl_ptr_llist_dtor_func dtor)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
spl_ptr_llist_count(spl_ptr_llist * llist)136 static long spl_ptr_llist_count(spl_ptr_llist *llist) /* {{{ */
137 {
138 return (long)llist->count;
139 }
140 /* }}} */
141
spl_ptr_llist_destroy(spl_ptr_llist * llist TSRMLS_DC)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
spl_ptr_llist_offset(spl_ptr_llist * llist,long offset,int backward)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
spl_ptr_llist_unshift(spl_ptr_llist * llist,void * data TSRMLS_DC)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
spl_ptr_llist_push(spl_ptr_llist * llist,void * data TSRMLS_DC)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
spl_ptr_llist_pop(spl_ptr_llist * llist TSRMLS_DC)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
spl_ptr_llist_last(spl_ptr_llist * llist)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
spl_ptr_llist_first(spl_ptr_llist * llist)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
spl_ptr_llist_shift(spl_ptr_llist * llist TSRMLS_DC)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
spl_ptr_llist_copy(spl_ptr_llist * from,spl_ptr_llist * to TSRMLS_DC)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
spl_dllist_object_free_storage(void * object TSRMLS_DC)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
spl_dllist_object_new_ex(zend_class_entry * class_type,spl_dllist_object ** obj,zval * orig,int clone_orig TSRMLS_DC)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_property_ctor, (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
spl_dllist_object_new(zend_class_entry * class_type TSRMLS_DC)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
spl_dllist_object_clone(zval * zobject TSRMLS_DC)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
spl_dllist_object_count_elements(zval * object,long * count TSRMLS_DC)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
spl_dllist_object_get_debug_info(zval * obj,int * is_temp TSRMLS_DC)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 */
SPL_METHOD(SplDoublyLinkedList,push)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 */
SPL_METHOD(SplDoublyLinkedList,unshift)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 */
SPL_METHOD(SplDoublyLinkedList,pop)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 */
SPL_METHOD(SplDoublyLinkedList,shift)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 */
SPL_METHOD(SplDoublyLinkedList,top)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 */
SPL_METHOD(SplDoublyLinkedList,bottom)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. */
SPL_METHOD(SplDoublyLinkedList,count)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. */
SPL_METHOD(SplDoublyLinkedList,isEmpty)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 */
SPL_METHOD(SplDoublyLinkedList,setIteratorMode)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 */
SPL_METHOD(SplDoublyLinkedList,getIteratorMode)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. */
SPL_METHOD(SplDoublyLinkedList,offsetExists)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. */
SPL_METHOD(SplDoublyLinkedList,offsetGet)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. */
SPL_METHOD(SplDoublyLinkedList,offsetSet)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. */
SPL_METHOD(SplDoublyLinkedList,offsetUnset)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 = 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
spl_dllist_it_dtor(zend_object_iterator * iter TSRMLS_DC)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
spl_dllist_it_helper_rewind(spl_ptr_llist_element ** traverse_pointer_ptr,int * traverse_position_ptr,spl_ptr_llist * llist,int flags TSRMLS_DC)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
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)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
spl_dllist_it_rewind(zend_object_iterator * iter TSRMLS_DC)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
spl_dllist_it_valid(zend_object_iterator * iter TSRMLS_DC)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
spl_dllist_it_get_current_data(zend_object_iterator * iter,zval *** data TSRMLS_DC)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
spl_dllist_it_get_current_key(zend_object_iterator * iter,char ** str_key,uint * str_key_len,ulong * int_key TSRMLS_DC)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
spl_dllist_it_move_forward(zend_object_iterator * iter TSRMLS_DC)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 */
SPL_METHOD(SplDoublyLinkedList,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 */
SPL_METHOD(SplDoublyLinkedList,prev)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 */
SPL_METHOD(SplDoublyLinkedList,next)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 */
SPL_METHOD(SplDoublyLinkedList,valid)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 */
SPL_METHOD(SplDoublyLinkedList,rewind)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 */
SPL_METHOD(SplDoublyLinkedList,current)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
spl_dllist_get_iterator(zend_class_entry * ce,zval * object,int by_ref TSRMLS_DC)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
PHP_MINIT_FUNCTION(spl_dllist)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 */
1259