xref: /openbsd/libexec/tradcpp/array.h (revision cecf84d4)
1 /*-
2  * Copyright (c) 2009 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by David A. Holland.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef ARRAY_H
31 #define ARRAY_H
32 
33 #include "inlinedefs.h" // XXX
34 #include "utils.h"
35 
36 #define ARRAYS_CHECKED
37 
38 #ifdef ARRAYS_CHECKED
39 #include <assert.h>
40 #define arrayassert assert
41 #else
42 #define arrayassert(x) ((void)(x))
43 #endif
44 
45 #ifndef ARRAYINLINE
46 #define ARRAYINLINE C99INLINE
47 #endif
48 
49 ////////////////////////////////////////////////////////////
50 // type and base operations
51 
52 struct array {
53 	void **v;
54 	unsigned num, max;
55 };
56 
57 struct array *array_create(void);
58 void array_destroy(struct array *);
59 void array_init(struct array *);
60 void array_cleanup(struct array *);
61 ARRAYINLINE unsigned array_num(const struct array *);
62 ARRAYINLINE void *array_get(const struct array *, unsigned index_);
63 ARRAYINLINE void array_set(const struct array *, unsigned index_, void *val);
64 void array_setsize(struct array *, unsigned num);
65 ARRAYINLINE void array_add(struct array *, void *val, unsigned *index_ret);
66 void array_insert(struct array *a, unsigned index_);
67 void array_remove(struct array *a, unsigned index_);
68 
69 ////////////////////////////////////////////////////////////
70 // inlining for base operations
71 
72 ARRAYINLINE unsigned
73 array_num(const struct array *a)
74 {
75 	return a->num;
76 }
77 
78 ARRAYINLINE void *
79 array_get(const struct array *a, unsigned index_)
80 {
81 	arrayassert(index_ < a->num);
82 	return a->v[index_];
83 }
84 
85 ARRAYINLINE void
86 array_set(const struct array *a, unsigned index_, void *val)
87 {
88 	arrayassert(index_ < a->num);
89 	a->v[index_] = val;
90 }
91 
92 ARRAYINLINE void
93 array_add(struct array *a, void *val, unsigned *index_ret)
94 {
95 	unsigned index_ = a->num;
96 	array_setsize(a, index_+1);
97 	a->v[index_] = val;
98 	if (index_ret != NULL) {
99 		*index_ret = index_;
100 	}
101 }
102 
103 ////////////////////////////////////////////////////////////
104 // bits for declaring and defining typed arrays
105 
106 /*
107  * Usage:
108  *
109  * DECLARRAY_BYTYPE(foo, bar, INLINE) declares "struct foo", which is
110  * an array of pointers to "bar", plus the operations on it.
111  *
112  * DECLARRAY(foo, INLINE) is equivalent to
113  * DECLARRAY_BYTYPE(fooarray, struct foo, INLINE).
114  *
115  * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that
116  * they define the operations.
117  *
118  * The argument INLINE can be used as follows:
119  *
120  * 1. For no inlining:
121  *    In foo.h:
122  *           DECLARRAY(foo, );
123  *    In foo.c:
124  *           DEFARRAY(foo, );
125  *
126  * 2. To be file-static:
127  *    In foo.c:
128  *           DECLARRAY(foo, static);
129  *           DEFARRAY(foo, static);
130  *
131  * 3. To inline using C99:
132  *    In foo.h:
133  *           DECLARRAY(foo, inline);
134  *           DEFARRAY(foo, inline);
135  *
136  * 4. To inline with old gcc:
137  *    In foo.h:
138  *           #ifndef FOO_INLINE
139  *           #define FOO_INLINE extern inline
140  *           #endif
141  *           DECLARRAY(foo, );
142  *           DEFARRAY(foo, FOO_INLINE);
143  *    In foo.c:
144  *           #define FOO_INLINE
145  *           #include "foo.h"
146  *
147  * 5. To inline such that it works both with old gcc and C99:
148  *    In foo.h:
149  *           #ifndef FOO_INLINE
150  *           #define FOO_INLINE extern inline
151  *           #endif
152  *           DECLARRAY(foo, FOO_INLINE);
153  *           DEFARRAY(foo, FOO_INLINE);
154  *    In foo.c:
155  *           #define FOO_INLINE
156  *           #include "foo.h"
157  *
158  * The mechanism in case (4) ensures that an externally linkable
159  * definition exists.
160  */
161 
162 #define DECLARRAY_BYTYPE(ARRAY, T, INLINE) \
163 	struct ARRAY {							\
164 		struct array arr;					\
165 	};								\
166 									\
167 	INLINE struct ARRAY *ARRAY##_create(void);			\
168 	INLINE void ARRAY##_destroy(struct ARRAY *a);			\
169 	INLINE void ARRAY##_init(struct ARRAY *a);			\
170 	INLINE void ARRAY##_cleanup(struct ARRAY *a);			\
171 	INLINE unsigned ARRAY##_num(const struct ARRAY *a);		\
172 	INLINE T *ARRAY##_get(const struct ARRAY *a, unsigned index_);	\
173 	INLINE void ARRAY##_set(struct ARRAY *a, unsigned index_, T *val); \
174 	INLINE void ARRAY##_setsize(struct ARRAY *a, unsigned num);	\
175 	INLINE void ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret);\
176 	INLINE void ARRAY##_insert(struct ARRAY *a, unsigned index_);	\
177 	INLINE void ARRAY##_remove(struct ARRAY *a, unsigned index_)
178 
179 
180 #define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
181 	INLINE void						\
182 	ARRAY##_init(struct ARRAY *a)				\
183 	{							\
184 		array_init(&a->arr);				\
185 	}							\
186 								\
187 	INLINE void						\
188 	ARRAY##_cleanup(struct ARRAY *a)			\
189 	{							\
190 		array_cleanup(&a->arr);				\
191 	}							\
192 								\
193 	INLINE struct						\
194 	ARRAY *ARRAY##_create(void)				\
195 	{							\
196 		struct ARRAY *a;				\
197 								\
198 		a = domalloc(sizeof(*a));			\
199 		ARRAY##_init(a);				\
200 		return a;					\
201 	}							\
202 								\
203 	INLINE void						\
204 	ARRAY##_destroy(struct ARRAY *a)			\
205 	{							\
206 		ARRAY##_cleanup(a);				\
207 		dofree(a, sizeof(*a));				\
208 	}							\
209 								\
210 	INLINE unsigned						\
211 	ARRAY##_num(const struct ARRAY *a)			\
212 	{							\
213 		return array_num(&a->arr);			\
214 	}							\
215 								\
216 	INLINE T *						\
217 	ARRAY##_get(const struct ARRAY *a, unsigned index_)	\
218 	{				 			\
219 		return (T *)array_get(&a->arr, index_);		\
220 	}							\
221 								\
222 	INLINE void						\
223 	ARRAY##_set(struct ARRAY *a, unsigned index_, T *val)	\
224 	{				 			\
225 		array_set(&a->arr, index_, (void *)val);	\
226 	}							\
227 								\
228 	INLINE void						\
229 	ARRAY##_setsize(struct ARRAY *a, unsigned num)		\
230 	{				 			\
231 		array_setsize(&a->arr, num);			\
232 	}							\
233 								\
234 	INLINE void						\
235 	ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret)	\
236 	{				 			\
237 		array_add(&a->arr, (void *)val, ret);		\
238 	}							\
239 								\
240 	INLINE void						\
241 	ARRAY##_insert(struct ARRAY *a, unsigned index_)	\
242 	{				 			\
243 		array_insert(&a->arr, index_);			\
244 	}							\
245 								\
246 	INLINE void						\
247 	ARRAY##_remove(struct ARRAY *a, unsigned index_)	\
248 	{				 			\
249 		array_remove(&a->arr, index_);			\
250 	}
251 
252 #define DECLARRAY(T, INLINE) DECLARRAY_BYTYPE(T##array, struct T, INLINE)
253 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
254 
255 #define DESTROYALL_ARRAY(T, INLINE) \
256 	void T##array_destroyall(struct T##array *arr);	\
257 							\
258 	INLINE void					\
259 	T##array_destroyall(struct T##array *arr)	\
260 	{						\
261 		unsigned i, num;			\
262 		struct T *t;				\
263 							\
264 		num = T##array_num(arr);		\
265 		for (i=0; i<num; i++) {			\
266 			t = T##array_get(arr, i);	\
267 			T##_destroy(t);			\
268 		}					\
269 		T##array_setsize(arr, 0);		\
270 	}
271 
272 
273 ////////////////////////////////////////////////////////////
274 // basic array types
275 
276 DECLARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
277 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
278 
279 #endif /* ARRAY_H */
280