1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
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 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC);
340 :
341 : static void spl_dllist_object_free_storage(void *object TSRMLS_DC) /* {{{ */
342 63 : {
343 63 : spl_dllist_object *intern = (spl_dllist_object *)object;
344 63 : zval *tmp = NULL;
345 :
346 63 : zend_object_std_dtor(&intern->std TSRMLS_CC);
347 :
348 203 : while(intern->llist->count > 0) {
349 77 : tmp = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
350 77 : zval_ptr_dtor(&tmp);
351 : }
352 :
353 63 : spl_ptr_llist_destroy(intern->llist TSRMLS_CC);
354 63 : SPL_LLIST_CHECK_DELREF(intern->traverse_pointer);
355 63 : zval_ptr_dtor(&intern->retval);
356 :
357 63 : if (intern->debug_info != NULL) {
358 4 : zend_hash_destroy(intern->debug_info);
359 4 : efree(intern->debug_info);
360 : }
361 :
362 63 : efree(object);
363 63 : }
364 : /* }}} */
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 69 : } else if (parent == spl_ce_SplQueue) {
411 5 : intern->flags |= SPL_DLLIST_IT_FIX;
412 : }
413 :
414 72 : if (parent == spl_ce_SplDoublyLinkedList) {
415 63 : retval.handlers = &spl_handler_SplDoublyLinkedList;
416 63 : break;
417 : }
418 :
419 9 : parent = parent->parent;
420 9 : inherited = 1;
421 : }
422 :
423 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);
424 :
425 63 : if (!parent) { /* this must never happen */
426 0 : php_error_docref(NULL TSRMLS_CC, E_COMPILE_ERROR, "Internal compiler error, Class is not child of SplDoublyLinkedList");
427 : }
428 63 : if (inherited) {
429 9 : zend_hash_find(&class_type->function_table, "offsetget", sizeof("offsetget"), (void **) &intern->fptr_offset_get);
430 9 : if (intern->fptr_offset_get->common.scope == parent) {
431 9 : intern->fptr_offset_get = NULL;
432 : }
433 9 : zend_hash_find(&class_type->function_table, "offsetset", sizeof("offsetset"), (void **) &intern->fptr_offset_set);
434 9 : if (intern->fptr_offset_set->common.scope == parent) {
435 9 : intern->fptr_offset_set = NULL;
436 : }
437 9 : zend_hash_find(&class_type->function_table, "offsetexists", sizeof("offsetexists"), (void **) &intern->fptr_offset_has);
438 9 : if (intern->fptr_offset_has->common.scope == parent) {
439 9 : intern->fptr_offset_has = NULL;
440 : }
441 9 : zend_hash_find(&class_type->function_table, "offsetunset", sizeof("offsetunset"), (void **) &intern->fptr_offset_del);
442 9 : if (intern->fptr_offset_del->common.scope == parent) {
443 9 : intern->fptr_offset_del = NULL;
444 : }
445 9 : zend_hash_find(&class_type->function_table, "count", sizeof("count"), (void **) &intern->fptr_count);
446 9 : if (intern->fptr_count->common.scope == parent) {
447 8 : intern->fptr_count = NULL;
448 : }
449 : }
450 :
451 63 : return retval;
452 : }
453 : /* }}} */
454 :
455 : static zend_object_value spl_dllist_object_new(zend_class_entry *class_type TSRMLS_DC) /* {{{ */
456 59 : {
457 : spl_dllist_object *tmp;
458 59 : return spl_dllist_object_new_ex(class_type, &tmp, NULL, 0 TSRMLS_CC);
459 : }
460 : /* }}} */
461 :
462 : static zend_object_value spl_dllist_object_clone(zval *zobject TSRMLS_DC) /* {{{ */
463 4 : {
464 : zend_object_value new_obj_val;
465 : zend_object *old_object;
466 : zend_object *new_object;
467 4 : zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
468 : spl_dllist_object *intern;
469 :
470 4 : old_object = zend_objects_get_address(zobject TSRMLS_CC);
471 4 : new_obj_val = spl_dllist_object_new_ex(old_object->ce, &intern, zobject, 1 TSRMLS_CC);
472 4 : new_object = &intern->std;
473 :
474 4 : zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
475 :
476 4 : return new_obj_val;
477 : }
478 : /* }}} */
479 :
480 : static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
481 10 : {
482 10 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
483 :
484 10 : if (intern->fptr_count) {
485 : zval *rv;
486 1 : zend_call_method_with_0_params(&object, intern->std.ce, &intern->fptr_count, "count", &rv);
487 1 : if (rv) {
488 1 : zval_ptr_dtor(&intern->retval);
489 1 : MAKE_STD_ZVAL(intern->retval);
490 1 : ZVAL_ZVAL(intern->retval, rv, 1, 1);
491 1 : convert_to_long(intern->retval);
492 1 : *count = (long) Z_LVAL_P(intern->retval);
493 1 : return SUCCESS;
494 : }
495 0 : *count = 0;
496 0 : return FAILURE;
497 : }
498 :
499 9 : *count = spl_ptr_llist_count(intern->llist);
500 9 : return SUCCESS;
501 : }
502 : /* }}} */
503 :
504 : static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */
505 6 : {
506 6 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(obj TSRMLS_CC);
507 6 : spl_ptr_llist_element *current = intern->llist->head, *next;
508 : zval *tmp, zrv, *dllist_array;
509 : zstr pnstr;
510 : int pnlen;
511 6 : int i = 0;;
512 :
513 6 : *is_temp = 0;
514 :
515 6 : if (intern->debug_info == NULL) {
516 4 : ALLOC_HASHTABLE(intern->debug_info);
517 4 : ZEND_INIT_SYMTABLE_EX(intern->debug_info, zend_hash_num_elements(intern->std.properties) + 1, 0);
518 : }
519 :
520 6 : if (intern->debug_info->nApplyCount == 0) {
521 4 : INIT_PZVAL(&zrv);
522 4 : Z_ARRVAL(zrv) = intern->debug_info;
523 :
524 4 : zend_hash_copy(intern->debug_info, intern->std.properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
525 :
526 4 : pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "flags", sizeof("flags")-1, &pnlen TSRMLS_CC);
527 4 : add_u_assoc_long_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, intern->flags);
528 4 : efree(pnstr.v);
529 :
530 4 : ALLOC_INIT_ZVAL(dllist_array);
531 4 : array_init(dllist_array);
532 :
533 16 : while (current) {
534 8 : next = current->next;
535 :
536 8 : add_index_zval(dllist_array, i, (zval *)current->data);
537 8 : Z_ADDREF_P(current->data);
538 8 : i++;
539 :
540 8 : current = next;
541 : }
542 :
543 4 : pnstr = spl_gen_private_prop_name(spl_ce_SplDoublyLinkedList, "dllist", sizeof("dllist")-1, &pnlen TSRMLS_CC);
544 4 : add_u_assoc_zval_ex(&zrv, IS_UNICODE, pnstr, pnlen+1, dllist_array);
545 4 : efree(pnstr.v);
546 : }
547 :
548 6 : return intern->debug_info;
549 : }
550 : /* }}}} */
551 :
552 : /* {{{ proto bool SplDoublyLinkedList::push(mixed $value) U
553 : Push $value on the SplDoublyLinkedList */
554 : SPL_METHOD(SplDoublyLinkedList, push)
555 88 : {
556 : zval *value;
557 : spl_dllist_object *intern;
558 :
559 88 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
560 1 : return;
561 : }
562 :
563 87 : SEPARATE_ARG_IF_REF(value);
564 :
565 87 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
566 87 : spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
567 :
568 87 : RETURN_TRUE;
569 : }
570 : /* }}} */
571 :
572 : /* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U
573 : Unshift $value on the SplDoublyLinkedList */
574 : SPL_METHOD(SplDoublyLinkedList, unshift)
575 3 : {
576 : zval *value;
577 : spl_dllist_object *intern;
578 :
579 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) {
580 1 : return;
581 : }
582 :
583 2 : SEPARATE_ARG_IF_REF(value);
584 :
585 2 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
586 2 : spl_ptr_llist_unshift(intern->llist, value TSRMLS_CC);
587 :
588 2 : RETURN_TRUE;
589 : }
590 : /* }}} */
591 :
592 : /* {{{ proto mixed SplDoublyLinkedList::pop() U
593 : Pop an element out of the SplDoublyLinkedList */
594 : SPL_METHOD(SplDoublyLinkedList, pop)
595 18 : {
596 : zval *value;
597 : spl_dllist_object *intern;
598 :
599 18 : if (zend_parse_parameters_none() == FAILURE) {
600 2 : return;
601 : }
602 :
603 16 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
604 16 : value = (zval *)spl_ptr_llist_pop(intern->llist TSRMLS_CC);
605 :
606 16 : if (value == NULL) {
607 2 : zend_throw_exception(spl_ce_RuntimeException, "Can't pop from an empty datastructure", 0 TSRMLS_CC);
608 2 : return;
609 : }
610 :
611 14 : RETURN_ZVAL(value, 1, 1);
612 : }
613 : /* }}} */
614 :
615 : /* {{{ proto mixed SplDoublyLinkedList::shift() U
616 : Shift an element out of the SplDoublyLinkedList */
617 : SPL_METHOD(SplDoublyLinkedList, shift)
618 12 : {
619 : zval *value;
620 : spl_dllist_object *intern;
621 :
622 12 : if (zend_parse_parameters_none() == FAILURE) {
623 1 : return;
624 : }
625 :
626 11 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
627 11 : value = (zval *)spl_ptr_llist_shift(intern->llist TSRMLS_CC);
628 :
629 11 : if (value == NULL) {
630 4 : zend_throw_exception(spl_ce_RuntimeException, "Can't shift from an empty datastructure", 0 TSRMLS_CC);
631 4 : return;
632 : }
633 :
634 7 : RETURN_ZVAL(value, 1, 1);
635 : }
636 : /* }}} */
637 :
638 : /* {{{ proto mixed SplDoublyLinkedList::top() U
639 : Peek at the top element of the SplDoublyLinkedList */
640 : SPL_METHOD(SplDoublyLinkedList, top)
641 7 : {
642 : zval *value;
643 : spl_dllist_object *intern;
644 :
645 7 : if (zend_parse_parameters_none() == FAILURE) {
646 4 : return;
647 : }
648 :
649 3 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
650 3 : value = (zval *)spl_ptr_llist_last(intern->llist);
651 :
652 3 : if (value == NULL) {
653 0 : zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
654 0 : return;
655 : }
656 :
657 3 : RETURN_ZVAL(value, 1, 0);
658 : }
659 : /* }}} */
660 :
661 : /* {{{ proto mixed SplDoublyLinkedList::bottom() U
662 : Peek at the bottom element of the SplDoublyLinkedList */
663 : SPL_METHOD(SplDoublyLinkedList, bottom)
664 7 : {
665 : zval *value;
666 : spl_dllist_object *intern;
667 :
668 7 : if (zend_parse_parameters_none() == FAILURE) {
669 4 : return;
670 : }
671 :
672 3 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
673 3 : value = (zval *)spl_ptr_llist_first(intern->llist);
674 :
675 3 : if (value == NULL) {
676 0 : zend_throw_exception(spl_ce_RuntimeException, "Can't peek at an empty datastructure", 0 TSRMLS_CC);
677 0 : return;
678 : }
679 :
680 3 : RETURN_ZVAL(value, 1, 0);
681 : }
682 : /* }}} */
683 :
684 : /* {{{ proto int SplDoublyLinkedList::count() U
685 : Return the number of elements in the datastructure. */
686 : SPL_METHOD(SplDoublyLinkedList, count)
687 9 : {
688 : long count;
689 9 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
690 :
691 9 : if (zend_parse_parameters_none() == FAILURE) {
692 2 : return;
693 : }
694 :
695 7 : count = spl_ptr_llist_count(intern->llist);
696 7 : RETURN_LONG(count);
697 : }
698 : /* }}} */
699 :
700 : /* {{{ proto int SplDoublyLinkedList::isEmpty() U
701 : Return true if the SplDoublyLinkedList is empty. */
702 : SPL_METHOD(SplDoublyLinkedList, isEmpty)
703 4 : {
704 : long count;
705 :
706 4 : if (zend_parse_parameters_none() == FAILURE) {
707 2 : return;
708 : }
709 :
710 2 : spl_dllist_object_count_elements(getThis(), &count TSRMLS_CC);
711 2 : RETURN_BOOL(count==0);
712 : }
713 : /* }}} */
714 :
715 : /* {{{ proto int SplDoublyLinkedList::setIteratorMode($flags) U
716 : Set the mode of iteration */
717 : SPL_METHOD(SplDoublyLinkedList, setIteratorMode)
718 9 : {
719 : long value;
720 : spl_dllist_object *intern;
721 :
722 9 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) == FAILURE) {
723 1 : return;
724 : }
725 :
726 8 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
727 :
728 8 : if (intern->flags & SPL_DLLIST_IT_FIX
729 : && (intern->flags & SPL_DLLIST_IT_LIFO) != (value & SPL_DLLIST_IT_LIFO)) {
730 3 : zend_throw_exception(spl_ce_RuntimeException, "Iterators' LIFO/FIFO modes for SplStack/SplQueue objects are frozen", 0 TSRMLS_CC);
731 3 : return;
732 : }
733 :
734 5 : intern->flags = value & SPL_DLLIST_IT_MASK;
735 :
736 5 : RETURN_LONG(intern->flags);
737 : }
738 : /* }}} */
739 :
740 : /* {{{ proto int SplDoublyLinkedList::getIteratorMode() U
741 : Return the mode of iteration */
742 : SPL_METHOD(SplDoublyLinkedList, getIteratorMode)
743 2 : {
744 : spl_dllist_object *intern;
745 :
746 2 : if (zend_parse_parameters_none() == FAILURE) {
747 1 : return;
748 : }
749 :
750 1 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
751 :
752 1 : RETURN_LONG(intern->flags);
753 : }
754 : /* }}} */
755 :
756 : /* {{{ proto bool SplDoublyLinkedList::offsetExists(mixed $index) U
757 : Returns whether the requested $index exists. */
758 : SPL_METHOD(SplDoublyLinkedList, offsetExists)
759 4 : {
760 : zval *zindex;
761 : spl_dllist_object *intern;
762 : long index;
763 :
764 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
765 1 : return;
766 : }
767 :
768 3 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
769 3 : index = spl_offset_convert_to_long(zindex TSRMLS_CC);
770 :
771 3 : RETURN_BOOL(index >= 0 && index < intern->llist->count);
772 : } /* }}} */
773 :
774 : /* {{{ proto mixed SplDoublyLinkedList::offsetGet(mixed $index) U
775 : Returns the value at the specified $index. */
776 : SPL_METHOD(SplDoublyLinkedList, offsetGet)
777 14 : {
778 : zval *zindex, *value;
779 : long index;
780 : spl_dllist_object *intern;
781 : spl_ptr_llist_element *element;
782 :
783 14 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
784 2 : return;
785 : }
786 :
787 12 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
788 12 : index = spl_offset_convert_to_long(zindex TSRMLS_CC);
789 :
790 12 : if (index < 0 || index >= intern->llist->count) {
791 4 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
792 4 : return;
793 : }
794 :
795 8 : element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
796 :
797 8 : if (element != NULL) {
798 8 : value = (zval *)element->data;
799 8 : RETURN_ZVAL(value, 1, 0);
800 : } else {
801 0 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
802 0 : return;
803 : }
804 : } /* }}} */
805 :
806 : /* {{{ proto void SplDoublyLinkedList::offsetSet(mixed $index, mixed $newval) U
807 : Sets the value at the specified $index to $newval. */
808 : SPL_METHOD(SplDoublyLinkedList, offsetSet)
809 10 : {
810 : zval *zindex, *value;
811 : spl_dllist_object *intern;
812 :
813 10 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zindex, &value) == FAILURE) {
814 2 : return;
815 : }
816 8 : SEPARATE_ARG_IF_REF(value);
817 :
818 8 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
819 :
820 8 : if (Z_TYPE_P(zindex) == IS_NULL) {
821 : /* $obj[] = ... */
822 6 : spl_ptr_llist_push(intern->llist, value TSRMLS_CC);
823 : } else {
824 : /* $obj[$foo] = ... */
825 : long index;
826 : spl_ptr_llist_element *element;
827 :
828 2 : index = spl_offset_convert_to_long(zindex TSRMLS_CC);
829 :
830 2 : if (index < 0 || index >= intern->llist->count) {
831 1 : zval_ptr_dtor(&value);
832 1 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0 TSRMLS_CC);
833 1 : return;
834 : }
835 :
836 1 : element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
837 :
838 1 : if (element != NULL) {
839 : /* call dtor on the old element as in spl_ptr_llist_pop */
840 1 : if (intern->llist->dtor) {
841 1 : intern->llist->dtor(element TSRMLS_CC);
842 : }
843 :
844 : /* the element is replaced, delref the old one as in
845 : * SplDoublyLinkedList::pop() */
846 1 : zval_ptr_dtor((zval **)&element->data);
847 1 : element->data = value;
848 :
849 : /* new element, call ctor as in spl_ptr_llist_push */
850 1 : if (intern->llist->ctor) {
851 1 : intern->llist->ctor(element TSRMLS_CC);
852 : }
853 : } else {
854 0 : zval_ptr_dtor(&value);
855 0 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
856 0 : return;
857 : }
858 : }
859 : } /* }}} */
860 :
861 : /* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed $index) U
862 : Unsets the value at the specified $index. */
863 : SPL_METHOD(SplDoublyLinkedList, offsetUnset)
864 7 : {
865 : zval *zindex;
866 : long index;
867 : spl_dllist_object *intern;
868 : spl_ptr_llist_element *element;
869 : spl_ptr_llist *llist;
870 :
871 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zindex) == FAILURE) {
872 0 : return;
873 : }
874 :
875 7 : intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
876 7 : index = (int)spl_offset_convert_to_long(zindex TSRMLS_CC);
877 7 : llist = intern->llist;
878 :
879 7 : if (index < 0 || index >= intern->llist->count) {
880 3 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset out of range", 0 TSRMLS_CC);
881 3 : return;
882 : }
883 :
884 4 : element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);
885 :
886 4 : if (element != NULL) {
887 : /* connect the neightbors */
888 4 : if (element->prev) {
889 2 : element->prev->next = element->next;
890 : }
891 :
892 4 : if (element->next) {
893 3 : element->next->prev = element->prev;
894 : }
895 :
896 : /* take care of head/tail */
897 4 : if (element == llist->head) {
898 2 : llist->head = element->next;
899 : }
900 :
901 4 : if (element == llist->tail) {
902 1 : llist->tail = element->prev;
903 : }
904 :
905 : /* finally, delete the element */
906 4 : llist->count--;
907 :
908 4 : if(llist->dtor) {
909 4 : llist->dtor(element TSRMLS_CC);
910 : }
911 :
912 4 : zval_ptr_dtor((zval **)&element->data);
913 4 : element->data = NULL;
914 :
915 4 : SPL_LLIST_DELREF(element);
916 : } else {
917 0 : zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0 TSRMLS_CC);
918 0 : return;
919 : }
920 : } /* }}} */
921 :
922 : static void spl_dllist_it_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
923 11 : {
924 11 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
925 :
926 11 : SPL_LLIST_CHECK_DELREF(iterator->traverse_pointer);
927 :
928 11 : zend_user_it_invalidate_current(iter TSRMLS_CC);
929 11 : zval_ptr_dtor((zval**)&iterator->intern.it.data);
930 :
931 11 : efree(iterator);
932 11 : }
933 : /* }}} */
934 :
935 : 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) /* {{{ */
936 17 : {
937 17 : SPL_LLIST_CHECK_DELREF(*traverse_pointer_ptr);
938 :
939 17 : if (flags & SPL_DLLIST_IT_LIFO) {
940 3 : *traverse_position_ptr = llist->count-1;
941 3 : *traverse_pointer_ptr = llist->tail;
942 : } else {
943 14 : *traverse_position_ptr = 0;
944 14 : *traverse_pointer_ptr = llist->head;
945 : }
946 :
947 17 : SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
948 17 : }
949 : /* }}} */
950 :
951 : 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) /* {{{ */
952 44 : {
953 44 : if (*traverse_pointer_ptr) {
954 43 : spl_ptr_llist_element *old = *traverse_pointer_ptr;
955 :
956 43 : if (flags & SPL_DLLIST_IT_LIFO) {
957 10 : *traverse_pointer_ptr = old->prev;
958 10 : (*traverse_position_ptr)--;
959 :
960 10 : if (flags & SPL_DLLIST_IT_DELETE) {
961 0 : zval *prev = (zval *)spl_ptr_llist_pop(llist TSRMLS_CC);
962 :
963 0 : if (prev) {
964 0 : zval_ptr_dtor((zval **)&prev);
965 : }
966 : }
967 : } else {
968 33 : *traverse_pointer_ptr = old->next;
969 33 : if (flags & SPL_DLLIST_IT_DELETE) {
970 3 : zval *prev = (zval *)spl_ptr_llist_shift(llist TSRMLS_CC);
971 :
972 3 : if (prev) {
973 3 : zval_ptr_dtor((zval **)&prev);
974 : }
975 : } else {
976 30 : (*traverse_position_ptr)++;
977 : }
978 : }
979 :
980 43 : SPL_LLIST_DELREF(old);
981 43 : SPL_LLIST_CHECK_ADDREF(*traverse_pointer_ptr);
982 : }
983 44 : }
984 : /* }}} */
985 :
986 : static void spl_dllist_it_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
987 11 : {
988 11 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
989 11 : spl_dllist_object *object = iterator->object;
990 11 : spl_ptr_llist *llist = object->llist;
991 :
992 11 : spl_dllist_it_helper_rewind(&iterator->traverse_pointer, &iterator->traverse_position, llist, object->flags TSRMLS_CC);
993 11 : }
994 : /* }}} */
995 :
996 : static int spl_dllist_it_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
997 41 : {
998 41 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
999 41 : spl_ptr_llist_element *element = iterator->traverse_pointer;
1000 :
1001 41 : return (element != NULL ? SUCCESS : FAILURE);
1002 : }
1003 : /* }}} */
1004 :
1005 : static void spl_dllist_it_get_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
1006 30 : {
1007 30 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
1008 30 : spl_ptr_llist_element *element = iterator->traverse_pointer;
1009 :
1010 30 : if (element == NULL || element->data == NULL) {
1011 0 : *data = NULL;
1012 : } else {
1013 30 : *data = (zval **)&element->data;
1014 : }
1015 30 : }
1016 : /* }}} */
1017 :
1018 : static int spl_dllist_it_get_current_key(zend_object_iterator *iter, zstr *str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
1019 26 : {
1020 26 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
1021 :
1022 26 : *int_key = (ulong) iterator->traverse_position;
1023 26 : return HASH_KEY_IS_LONG;
1024 : }
1025 : /* }}} */
1026 :
1027 : static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
1028 30 : {
1029 30 : spl_dllist_it *iterator = (spl_dllist_it *)iter;
1030 30 : spl_dllist_object *object = iterator->object;
1031 :
1032 30 : zend_user_it_invalidate_current(iter TSRMLS_CC);
1033 :
1034 30 : spl_dllist_it_helper_move_forward(&iterator->traverse_pointer, &iterator->traverse_position, object->llist, object->flags TSRMLS_CC);
1035 30 : }
1036 : /* }}} */
1037 :
1038 : /* {{{ proto int SplDoublyLinkedList::key() U
1039 : Return current array key */
1040 : SPL_METHOD(SplDoublyLinkedList, key)
1041 0 : {
1042 0 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1043 :
1044 0 : RETURN_LONG(intern->traverse_position);
1045 : }
1046 : /* }}} */
1047 :
1048 : /* {{{ proto void SplDoublyLinkedList::prev() U
1049 : Move to next entry */
1050 : SPL_METHOD(SplDoublyLinkedList, prev)
1051 3 : {
1052 3 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1053 :
1054 3 : spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags ^ SPL_DLLIST_IT_LIFO TSRMLS_CC);
1055 3 : }
1056 : /* }}} */
1057 :
1058 : /* {{{ proto void SplDoublyLinkedList::next() U
1059 : Move to next entry */
1060 : SPL_METHOD(SplDoublyLinkedList, next)
1061 11 : {
1062 11 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1063 :
1064 11 : spl_dllist_it_helper_move_forward(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
1065 11 : }
1066 : /* }}} */
1067 :
1068 : /* {{{ proto bool SplDoublyLinkedList::valid() U
1069 : Check whether the datastructure contains more entries */
1070 : SPL_METHOD(SplDoublyLinkedList, valid)
1071 4 : {
1072 4 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1073 :
1074 4 : RETURN_BOOL(intern->traverse_pointer != NULL);
1075 : }
1076 : /* }}} */
1077 :
1078 : /* {{{ proto void SplDoublyLinkedList::rewind() U
1079 : Rewind the datastructure back to the start */
1080 : SPL_METHOD(SplDoublyLinkedList, rewind)
1081 6 : {
1082 6 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1083 :
1084 6 : spl_dllist_it_helper_rewind(&intern->traverse_pointer, &intern->traverse_position, intern->llist, intern->flags TSRMLS_CC);
1085 6 : }
1086 : /* }}} */
1087 :
1088 : /* {{{ proto mixed|NULL SplDoublyLinkedList::current() U
1089 : Return current datastructure entry */
1090 : SPL_METHOD(SplDoublyLinkedList, current)
1091 17 : {
1092 17 : spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
1093 17 : spl_ptr_llist_element *element = intern->traverse_pointer;
1094 :
1095 17 : if (element == NULL || element->data == NULL) {
1096 5 : RETURN_NULL();
1097 : } else {
1098 12 : zval *data = (zval *)element->data;
1099 12 : RETURN_ZVAL(data, 1, 0);
1100 : }
1101 : }
1102 : /* }}} */
1103 :
1104 : /* iterator handler table */
1105 : zend_object_iterator_funcs spl_dllist_it_funcs = {
1106 : spl_dllist_it_dtor,
1107 : spl_dllist_it_valid,
1108 : spl_dllist_it_get_current_data,
1109 : spl_dllist_it_get_current_key,
1110 : spl_dllist_it_move_forward,
1111 : spl_dllist_it_rewind
1112 : };
1113 :
1114 : zend_object_iterator *spl_dllist_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
1115 11 : {
1116 : spl_dllist_it *iterator;
1117 11 : spl_dllist_object *dllist_object = (spl_dllist_object*)zend_object_store_get_object(object TSRMLS_CC);
1118 :
1119 11 : if (by_ref) {
1120 0 : zend_throw_exception(spl_ce_RuntimeException, "An iterator cannot be used with foreach by reference", 0 TSRMLS_CC);
1121 0 : return NULL;
1122 : }
1123 :
1124 11 : Z_ADDREF_P(object);
1125 :
1126 11 : iterator = emalloc(sizeof(spl_dllist_it));
1127 11 : iterator->intern.it.data = (void*)object;
1128 11 : iterator->intern.it.funcs = &spl_dllist_it_funcs;
1129 11 : iterator->intern.ce = ce;
1130 11 : iterator->intern.value = NULL;
1131 11 : iterator->traverse_position = dllist_object->traverse_position;
1132 11 : iterator->traverse_pointer = dllist_object->traverse_pointer;
1133 11 : iterator->flags = dllist_object->flags & SPL_DLLIST_IT_MASK;
1134 :
1135 11 : SPL_LLIST_CHECK_ADDREF(iterator->traverse_pointer);
1136 :
1137 11 : iterator->object = dllist_object;
1138 :
1139 11 : return (zend_object_iterator*)iterator;
1140 : }
1141 : /* }}} */
1142 :
1143 : /* Function/Class/Method definitions */
1144 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_setiteratormode, 0)
1145 : ZEND_ARG_INFO(0, flags)
1146 : ZEND_END_ARG_INFO()
1147 :
1148 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_push, 0)
1149 : ZEND_ARG_INFO(0, value)
1150 : ZEND_END_ARG_INFO()
1151 :
1152 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetGet, 0, 0, 1)
1153 : ZEND_ARG_INFO(0, index)
1154 : ZEND_END_ARG_INFO()
1155 :
1156 : ZEND_BEGIN_ARG_INFO_EX(arginfo_dllist_offsetSet, 0, 0, 2)
1157 : ZEND_ARG_INFO(0, index)
1158 : ZEND_ARG_INFO(0, newval)
1159 : ZEND_END_ARG_INFO()
1160 :
1161 : ZEND_BEGIN_ARG_INFO(arginfo_dllist_void, 0)
1162 : ZEND_END_ARG_INFO()
1163 :
1164 : static const zend_function_entry spl_funcs_SplQueue[] = {
1165 : SPL_MA(SplQueue, enqueue, SplDoublyLinkedList, push, arginfo_dllist_push, ZEND_ACC_PUBLIC)
1166 : SPL_MA(SplQueue, dequeue, SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1167 : {NULL, NULL, NULL}
1168 : };
1169 :
1170 : static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
1171 : SPL_ME(SplDoublyLinkedList, pop, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1172 : SPL_ME(SplDoublyLinkedList, shift, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1173 : SPL_ME(SplDoublyLinkedList, push, arginfo_dllist_push, ZEND_ACC_PUBLIC)
1174 : SPL_ME(SplDoublyLinkedList, unshift, arginfo_dllist_push, ZEND_ACC_PUBLIC)
1175 : SPL_ME(SplDoublyLinkedList, top, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1176 : SPL_ME(SplDoublyLinkedList, bottom, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1177 : SPL_ME(SplDoublyLinkedList, count, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1178 : SPL_ME(SplDoublyLinkedList, isEmpty, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1179 : SPL_ME(SplDoublyLinkedList, setIteratorMode, arginfo_dllist_setiteratormode, ZEND_ACC_PUBLIC)
1180 : SPL_ME(SplDoublyLinkedList, getIteratorMode, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1181 : SPL_ME(SplDoublyLinkedList, offsetExists, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
1182 : SPL_ME(SplDoublyLinkedList, offsetGet, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
1183 : SPL_ME(SplDoublyLinkedList, offsetSet, arginfo_dllist_offsetSet, ZEND_ACC_PUBLIC)
1184 : SPL_ME(SplDoublyLinkedList, offsetUnset, arginfo_dllist_offsetGet, ZEND_ACC_PUBLIC)
1185 : SPL_ME(SplDoublyLinkedList, rewind, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1186 : SPL_ME(SplDoublyLinkedList, current, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1187 : SPL_ME(SplDoublyLinkedList, key, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1188 : SPL_ME(SplDoublyLinkedList, next, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1189 : SPL_ME(SplDoublyLinkedList, prev, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1190 : SPL_ME(SplDoublyLinkedList, valid, arginfo_dllist_void, ZEND_ACC_PUBLIC)
1191 : {NULL, NULL, NULL}
1192 : };
1193 : /* }}} */
1194 :
1195 : PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */
1196 17007 : {
1197 17007 : REGISTER_SPL_STD_CLASS_EX(SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplDoublyLinkedList);
1198 17007 : memcpy(&spl_handler_SplDoublyLinkedList, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1199 :
1200 17007 : spl_handler_SplDoublyLinkedList.clone_obj = spl_dllist_object_clone;
1201 17007 : spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements;
1202 17007 : spl_handler_SplDoublyLinkedList.get_debug_info = spl_dllist_object_get_debug_info;
1203 :
1204 17007 : REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_LIFO", SPL_DLLIST_IT_LIFO);
1205 17007 : REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_FIFO", 0);
1206 17007 : REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_DELETE",SPL_DLLIST_IT_DELETE);
1207 17007 : REGISTER_SPL_CLASS_CONST_LONG(SplDoublyLinkedList, "IT_MODE_KEEP", 0);
1208 :
1209 17007 : REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Iterator);
1210 17007 : REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, Countable);
1211 17007 : REGISTER_SPL_IMPLEMENTS(SplDoublyLinkedList, ArrayAccess);
1212 :
1213 17007 : spl_ce_SplDoublyLinkedList->get_iterator = spl_dllist_get_iterator;
1214 :
1215 17007 : REGISTER_SPL_SUB_CLASS_EX(SplQueue, SplDoublyLinkedList, spl_dllist_object_new, spl_funcs_SplQueue);
1216 17007 : REGISTER_SPL_SUB_CLASS_EX(SplStack, SplDoublyLinkedList, spl_dllist_object_new, NULL);
1217 :
1218 17007 : spl_ce_SplQueue->get_iterator = spl_dllist_get_iterator;
1219 17007 : spl_ce_SplStack->get_iterator = spl_dllist_get_iterator;
1220 :
1221 17007 : return SUCCESS;
1222 : }
1223 : /* }}} */
1224 : /*
1225 : * Local variables:
1226 : * tab-width: 4
1227 : * c-basic-offset: 4
1228 : * End:
1229 : * vim600: fdm=marker
1230 : * vim: noet sw=4 ts=4
1231 : */
|