1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2017 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@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include "zend.h"
23 #include "zend_stack.h"
24
25 #define ZEND_STACK_ELEMENT(stack, n) ((void *)((char *) (stack)->elements + (stack)->size * (n)))
26
zend_stack_init(zend_stack * stack,int size)27 ZEND_API int zend_stack_init(zend_stack *stack, int size)
28 {
29 stack->size = size;
30 stack->top = 0;
31 stack->max = 0;
32 stack->elements = NULL;
33 return SUCCESS;
34 }
35
zend_stack_push(zend_stack * stack,const void * element)36 ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
37 {
38 /* We need to allocate more memory */
39 if (stack->top >= stack->max) {
40 stack->max += STACK_BLOCK_SIZE;
41 stack->elements = safe_erealloc(stack->elements, stack->size, stack->max, 0);
42 }
43 memcpy(ZEND_STACK_ELEMENT(stack, stack->top), element, stack->size);
44 return stack->top++;
45 }
46
47
zend_stack_top(const zend_stack * stack)48 ZEND_API void *zend_stack_top(const zend_stack *stack)
49 {
50 if (stack->top > 0) {
51 return ZEND_STACK_ELEMENT(stack, stack->top - 1);
52 } else {
53 return NULL;
54 }
55 }
56
57
zend_stack_del_top(zend_stack * stack)58 ZEND_API int zend_stack_del_top(zend_stack *stack)
59 {
60 --stack->top;
61 return SUCCESS;
62 }
63
64
zend_stack_int_top(const zend_stack * stack)65 ZEND_API int zend_stack_int_top(const zend_stack *stack)
66 {
67 int *e = zend_stack_top(stack);
68 if (e) {
69 return *e;
70 } else {
71 return FAILURE;
72 }
73 }
74
75
zend_stack_is_empty(const zend_stack * stack)76 ZEND_API int zend_stack_is_empty(const zend_stack *stack)
77 {
78 return stack->top == 0;
79 }
80
81
zend_stack_destroy(zend_stack * stack)82 ZEND_API int zend_stack_destroy(zend_stack *stack)
83 {
84 if (stack->elements) {
85 efree(stack->elements);
86 stack->elements = NULL;
87 }
88
89 return SUCCESS;
90 }
91
92
zend_stack_base(const zend_stack * stack)93 ZEND_API void *zend_stack_base(const zend_stack *stack)
94 {
95 return stack->elements;
96 }
97
98
zend_stack_count(const zend_stack * stack)99 ZEND_API int zend_stack_count(const zend_stack *stack)
100 {
101 return stack->top;
102 }
103
104
zend_stack_apply(zend_stack * stack,int type,int (* apply_function)(void * element))105 ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))
106 {
107 int i;
108
109 switch (type) {
110 case ZEND_STACK_APPLY_TOPDOWN:
111 for (i=stack->top-1; i>=0; i--) {
112 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
113 break;
114 }
115 }
116 break;
117 case ZEND_STACK_APPLY_BOTTOMUP:
118 for (i=0; i<stack->top; i++) {
119 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
120 break;
121 }
122 }
123 break;
124 }
125 }
126
127
zend_stack_apply_with_argument(zend_stack * stack,int type,int (* apply_function)(void * element,void * arg),void * arg)128 ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, int type, int (*apply_function)(void *element, void *arg), void *arg)
129 {
130 int i;
131
132 switch (type) {
133 case ZEND_STACK_APPLY_TOPDOWN:
134 for (i=stack->top-1; i>=0; i--) {
135 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
136 break;
137 }
138 }
139 break;
140 case ZEND_STACK_APPLY_BOTTOMUP:
141 for (i=0; i<stack->top; i++) {
142 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
143 break;
144 }
145 }
146 break;
147 }
148 }
149
zend_stack_clean(zend_stack * stack,void (* func)(void *),zend_bool free_elements)150 ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), zend_bool free_elements)
151 {
152 int i;
153
154 if (func) {
155 for (i = 0; i < stack->top; i++) {
156 func(ZEND_STACK_ELEMENT(stack, i));
157 }
158 }
159 if (free_elements) {
160 if (stack->elements) {
161 efree(stack->elements);
162 stack->elements = NULL;
163 }
164 stack->top = stack->max = 0;
165 }
166 }
167
168 /*
169 * Local variables:
170 * tab-width: 4
171 * c-basic-offset: 4
172 * indent-tabs-mode: t
173 * End:
174 */
175