1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 +----------------------------------------------------------------------+
18 */
19
20 #include "zend.h"
21 #include "zend_stack.h"
22
23 #define ZEND_STACK_ELEMENT(stack, n) ((void *)((char *) (stack)->elements + (stack)->size * (n)))
24
zend_stack_init(zend_stack * stack,int size)25 ZEND_API int zend_stack_init(zend_stack *stack, int size)
26 {
27 stack->size = size;
28 stack->top = 0;
29 stack->max = 0;
30 stack->elements = NULL;
31 return SUCCESS;
32 }
33
zend_stack_push(zend_stack * stack,const void * element)34 ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
35 {
36 /* We need to allocate more memory */
37 if (stack->top >= stack->max) {
38 stack->max += STACK_BLOCK_SIZE;
39 stack->elements = safe_erealloc(stack->elements, stack->size, stack->max, 0);
40 }
41 memcpy(ZEND_STACK_ELEMENT(stack, stack->top), element, stack->size);
42 return stack->top++;
43 }
44
45
zend_stack_top(const zend_stack * stack)46 ZEND_API void *zend_stack_top(const zend_stack *stack)
47 {
48 if (stack->top > 0) {
49 return ZEND_STACK_ELEMENT(stack, stack->top - 1);
50 } else {
51 return NULL;
52 }
53 }
54
55
zend_stack_del_top(zend_stack * stack)56 ZEND_API int zend_stack_del_top(zend_stack *stack)
57 {
58 --stack->top;
59 return SUCCESS;
60 }
61
62
zend_stack_int_top(const zend_stack * stack)63 ZEND_API int zend_stack_int_top(const zend_stack *stack)
64 {
65 int *e = zend_stack_top(stack);
66 if (e) {
67 return *e;
68 } else {
69 return FAILURE;
70 }
71 }
72
73
zend_stack_is_empty(const zend_stack * stack)74 ZEND_API int zend_stack_is_empty(const zend_stack *stack)
75 {
76 return stack->top == 0;
77 }
78
79
zend_stack_destroy(zend_stack * stack)80 ZEND_API int zend_stack_destroy(zend_stack *stack)
81 {
82 if (stack->elements) {
83 efree(stack->elements);
84 stack->elements = NULL;
85 }
86
87 return SUCCESS;
88 }
89
90
zend_stack_base(const zend_stack * stack)91 ZEND_API void *zend_stack_base(const zend_stack *stack)
92 {
93 return stack->elements;
94 }
95
96
zend_stack_count(const zend_stack * stack)97 ZEND_API int zend_stack_count(const zend_stack *stack)
98 {
99 return stack->top;
100 }
101
102
zend_stack_apply(zend_stack * stack,int type,int (* apply_function)(void * element))103 ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))
104 {
105 int i;
106
107 switch (type) {
108 case ZEND_STACK_APPLY_TOPDOWN:
109 for (i=stack->top-1; i>=0; i--) {
110 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
111 break;
112 }
113 }
114 break;
115 case ZEND_STACK_APPLY_BOTTOMUP:
116 for (i=0; i<stack->top; i++) {
117 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
118 break;
119 }
120 }
121 break;
122 }
123 }
124
125
zend_stack_apply_with_argument(zend_stack * stack,int type,int (* apply_function)(void * element,void * arg),void * arg)126 ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
127 {
128 int i;
129
130 switch (type) {
131 case ZEND_STACK_APPLY_TOPDOWN:
132 for (i=stack->top-1; i>=0; i--) {
133 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
134 break;
135 }
136 }
137 break;
138 case ZEND_STACK_APPLY_BOTTOMUP:
139 for (i=0; i<stack->top; i++) {
140 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
141 break;
142 }
143 }
144 break;
145 }
146 }
147
zend_stack_clean(zend_stack * stack,void (* func)(void *),zend_bool free_elements)148 ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), zend_bool free_elements)
149 {
150 int i;
151
152 if (func) {
153 for (i = 0; i < stack->top; i++) {
154 func(ZEND_STACK_ELEMENT(stack, i));
155 }
156 }
157 if (free_elements) {
158 if (stack->elements) {
159 efree(stack->elements);
160 stack->elements = NULL;
161 }
162 stack->top = stack->max = 0;
163 }
164 }
165