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