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