xref: /PHP-7.1/Zend/zend_stack.c (revision ccd4716e)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2018 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