-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathstack.c
189 lines (154 loc) · 6.87 KB
/
stack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/* stack.c implements a generic stack as specified in stack.h
*
* written nml 2004-07-12
*
*/
#include "firstinclude.h"
#include "stack.h"
#include <stdlib.h> /* for malloc and free */
union stack_node {
void *d_ptr;
unsigned long int d_luint;
double d_dbl;
};
struct stack {
unsigned int size;
unsigned int capacity;
union stack_node *stack;
};
struct stack *stack_new(unsigned int sizehint) {
struct stack *stk;
if ((stk = malloc(sizeof(*stk)))) {
stk->size = stk->capacity = 0;
stk->stack = NULL;
if (!sizehint
|| (stk->stack = malloc(sizeof(*stk->stack) * sizehint))) {
stk->capacity = sizehint;
}
}
return stk;
}
void stack_delete(struct stack *stk) {
if (stk->stack) {
free(stk->stack);
}
free(stk);
}
unsigned int stack_size(struct stack *stk) {
return stk->size;
}
/* push template */
#define STACK_PUSH(stk, data, type) \
do { \
/* check for enough stack space */ \
if ((stk)->size >= (stk)->capacity) { \
void *ptr; \
\
if ((ptr = realloc((stk)->stack, \
sizeof(*(stk)->stack) * ((stk)->capacity * 2 + 1)))) { \
\
(stk)->stack = ptr; \
(stk)->capacity = (stk)->capacity * 2 + 1; \
} else { \
return STACK_ENOMEM; \
} \
} \
\
(stk)->stack[(stk)->size++].d_##type = (data); \
return STACK_OK; \
} while (0)
/* pop template */
#define STACK_POP(stk, pointer, type) \
do { \
if ((stk)->size) { \
*(pointer) = (stk)->stack[--(stk)->size].d_##type; \
return STACK_OK; \
} else { \
return STACK_ENOENT; \
} \
} while (0)
/* peek template */
#define STACK_PEEK(stk, pointer, type) \
do { \
if ((stk)->size) { \
*(pointer) = (stk)->stack[(stk)->size - 1].d_##type; \
return STACK_OK; \
} else { \
return STACK_ENOENT; \
} \
} while (0)
/* foreach template */
#define STACK_FOREACH(stk, opaque, fn, type) \
do { \
unsigned int i; \
\
for (i = 0; i < (stk)->size; i++) { \
(fn)((opaque), &(stk)->stack[i].d_##type); \
} \
\
return STACK_OK; \
} while (0)
/* fetch template */
#define STACK_FETCH(stk, index, pointer, type) \
do { \
if ((index) < (stk)->size) { \
*(pointer) = (stk)->stack[index].d_##type; \
return STACK_OK; \
} else { \
return STACK_ENOENT; \
} \
} while (0)
/* luint functions */
enum stack_ret stack_luint_push(struct stack *stk, unsigned long int ptr) {
STACK_PUSH(stk, ptr, luint);
}
enum stack_ret stack_luint_pop(struct stack *stk, unsigned long int *ptr) {
STACK_POP(stk, ptr, luint);
}
enum stack_ret stack_luint_peek(struct stack *stk, unsigned long int *ptr) {
STACK_PEEK(stk, ptr, luint);
}
enum stack_ret stack_luint_foreach(struct stack *stk, void *opaque,
void (*fn)(void *opaque, unsigned long int *data)) {
STACK_FOREACH(stk, opaque, fn, luint);
}
enum stack_ret stack_luint_fetch(struct stack *stk, unsigned int index,
unsigned long int *ptr) {
STACK_FETCH(stk, index, ptr, luint);
}
/* ptr functions */
enum stack_ret stack_ptr_push(struct stack *stk, void *ptr) {
STACK_PUSH(stk, ptr, ptr);
}
enum stack_ret stack_ptr_pop(struct stack *stk, void **ptr) {
STACK_POP(stk, ptr, ptr);
}
enum stack_ret stack_ptr_peek(struct stack *stk, void **ptr) {
STACK_PEEK(stk, ptr, ptr);
}
enum stack_ret stack_ptr_foreach(struct stack *stk, void *opaque,
void (*fn)(void *opaque, void **data)) {
STACK_FOREACH(stk, opaque, fn, ptr);
}
enum stack_ret stack_ptr_fetch(struct stack *stk, unsigned int index,
void **ptr) {
STACK_FETCH(stk, index, ptr, ptr);
}
/* dbl functions */
enum stack_ret stack_dbl_push(struct stack *stk, double ptr) {
STACK_PUSH(stk, ptr, dbl);
}
enum stack_ret stack_dbl_pop(struct stack *stk, double *ptr) {
STACK_POP(stk, ptr, dbl);
}
enum stack_ret stack_dbl_peek(struct stack *stk, double *ptr) {
STACK_PEEK(stk, ptr, dbl);
}
enum stack_ret stack_dbl_foreach(struct stack *stk, void *opaque,
void (*fn)(void *opaque, double *data)) {
STACK_FOREACH(stk, opaque, fn, dbl);
}
enum stack_ret stack_dbl_fetch(struct stack *stk, unsigned int index,
double *ptr) {
STACK_FETCH(stk, index, ptr, dbl);
}