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 void 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 }
32
zend_stack_push(zend_stack * stack,const void * element)33 ZEND_API int zend_stack_push(zend_stack *stack, const void *element)
34 {
35 /* We need to allocate more memory */
36 if (stack->top >= stack->max) {
37 stack->max += STACK_BLOCK_SIZE;
38 stack->elements = safe_erealloc(stack->elements, stack->size, stack->max, 0);
39 }
40 memcpy(ZEND_STACK_ELEMENT(stack, stack->top), element, stack->size);
41 return stack->top++;
42 }
43
44
zend_stack_top(const zend_stack * stack)45 ZEND_API void *zend_stack_top(const zend_stack *stack)
46 {
47 if (stack->top > 0) {
48 return ZEND_STACK_ELEMENT(stack, stack->top - 1);
49 } else {
50 return NULL;
51 }
52 }
53
54
zend_stack_del_top(zend_stack * stack)55 ZEND_API void zend_stack_del_top(zend_stack *stack)
56 {
57 --stack->top;
58 }
59
60
zend_stack_int_top(const zend_stack * stack)61 ZEND_API int zend_stack_int_top(const zend_stack *stack)
62 {
63 int *e = zend_stack_top(stack);
64 if (e) {
65 return *e;
66 } else {
67 return FAILURE;
68 }
69 }
70
71
zend_stack_is_empty(const zend_stack * stack)72 ZEND_API bool zend_stack_is_empty(const zend_stack *stack)
73 {
74 return stack->top == 0;
75 }
76
77
zend_stack_destroy(zend_stack * stack)78 ZEND_API void zend_stack_destroy(zend_stack *stack)
79 {
80 if (stack->elements) {
81 efree(stack->elements);
82 stack->elements = NULL;
83 }
84 }
85
86
zend_stack_base(const zend_stack * stack)87 ZEND_API void *zend_stack_base(const zend_stack *stack)
88 {
89 return stack->elements;
90 }
91
92
zend_stack_count(const zend_stack * stack)93 ZEND_API int zend_stack_count(const zend_stack *stack)
94 {
95 return stack->top;
96 }
97
98
zend_stack_apply(zend_stack * stack,int type,int (* apply_function)(void * element))99 ZEND_API void zend_stack_apply(zend_stack *stack, int type, int (*apply_function)(void *element))
100 {
101 int i;
102
103 switch (type) {
104 case ZEND_STACK_APPLY_TOPDOWN:
105 for (i=stack->top-1; i>=0; i--) {
106 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
107 break;
108 }
109 }
110 break;
111 case ZEND_STACK_APPLY_BOTTOMUP:
112 for (i=0; i<stack->top; i++) {
113 if (apply_function(ZEND_STACK_ELEMENT(stack, i))) {
114 break;
115 }
116 }
117 break;
118 }
119 }
120
121
zend_stack_apply_with_argument(zend_stack * stack,zend_stack_apply_direction type,int (* apply_function)(void * element,void * arg),void * arg)122 ZEND_API void zend_stack_apply_with_argument(zend_stack *stack, zend_stack_apply_direction type, int (*apply_function)(void *element, void *arg), void *arg)
123 {
124 int i;
125
126 switch (type) {
127 case ZEND_STACK_APPLY_TOPDOWN:
128 for (i=stack->top-1; i>=0; i--) {
129 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
130 break;
131 }
132 }
133 break;
134 case ZEND_STACK_APPLY_BOTTOMUP:
135 for (i=0; i<stack->top; i++) {
136 if (apply_function(ZEND_STACK_ELEMENT(stack, i), arg)) {
137 break;
138 }
139 }
140 break;
141 }
142 }
143
zend_stack_clean(zend_stack * stack,void (* func)(void *),bool free_elements)144 ZEND_API void zend_stack_clean(zend_stack *stack, void (*func)(void *), bool free_elements)
145 {
146 int i;
147
148 if (func) {
149 for (i = 0; i < stack->top; i++) {
150 func(ZEND_STACK_ELEMENT(stack, i));
151 }
152 }
153 if (free_elements) {
154 if (stack->elements) {
155 efree(stack->elements);
156 stack->elements = NULL;
157 }
158 stack->top = stack->max = 0;
159 }
160 }
161