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