/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- array_num
- array_get
- array_set
- array_add
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 #ifdef UW
34 #include <lib.h>
35 #endif
36
37 #define ARRAYS_CHECKED
38
39 #ifdef ARRAYS_CHECKED
40 #define ARRAYASSERT KASSERT
41 #else
42 #define ARRAYASSERT(x) ((void)(x))
43 #endif
44
45 /*
46 * Base array type (resizeable array of void pointers) and operations.
47 *
48 * create - allocate an array.
49 * destroy - destroy an allocated array.
50 * init - initialize an array in space externally allocated.
51 * cleanup - clean up an array in space exteranlly allocated.
52 * num - return number of elements in array.
53 * get - return element no. INDEX.
54 * set - set element no. INDEX to VAL.
55 * setsize - change size to NUM elements; may fail and return error.
56 * add - append VAL to end of array; return its index in INDEX_RET if
57 * INDEX_RET isn't null; may fail and return error.
58 * remove - excise entry INDEX and slide following entries down to
59 * close the resulting gap.
60 *
61 * Note that expanding an array with setsize doesn't initialize the new
62 * elements. (Usually the caller is about to store into them anyway.)
63 */
64
65 struct array {
66 void **v;
67 unsigned num, max;
68 };
69
70 struct array *array_create(void);
71 void array_destroy(struct array *);
72 void array_init(struct array *);
73 void array_cleanup(struct array *);
74 unsigned array_num(const struct array *);
75 void *array_get(const struct array *, unsigned index);
76 void array_set(const struct array *, unsigned index, void *val);
77 int array_setsize(struct array *, unsigned num);
78 int array_add(struct array *, void *val, unsigned *index_ret);
79 void array_remove(struct array *, unsigned index);
80
81 /*
82 * Inlining for base operations
83 */
84
85 #ifndef ARRAYINLINE
86 #define ARRAYINLINE INLINE
87 #endif
88
89 ARRAYINLINE unsigned
90 array_num(const struct array *a)
91 {
92 return a->num;
93 }
94
95 ARRAYINLINE void *
96 array_get(const struct array *a, unsigned index)
97 {
98 ARRAYASSERT(index < a->num);
99 return a->v[index];
100 }
101
102 ARRAYINLINE void
103 array_set(const struct array *a, unsigned index, void *val)
104 {
105 ARRAYASSERT(index < a->num);
106 a->v[index] = val;
107 }
108
109 ARRAYINLINE int
110 array_add(struct array *a, void *val, unsigned *index_ret)
111 {
112 unsigned index;
113 int ret;
114
115 index = a->num;
116 ret = array_setsize(a, index+1);
117 if (ret) {
118 return ret;
119 }
120 a->v[index] = val;
121 if (index_ret != NULL) {
122 *index_ret = index;
123 }
124 return 0;
125 }
126
127 /*
128 * Bits for declaring and defining typed arrays.
129 *
130 * Usage:
131 *
132 * DECLARRAY_BYTYPE(foo, bar) declares "struct foo", which is
133 * an array of pointers to "bar", plus the operations on it.
134 *
135 * DECLARRAY(foo) is equivalent to DECLARRAY_BYTYPE(fooarray, struct foo).
136 *
137 * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that
138 * they define the operations, and both take an extra argument INLINE.
139 * For C99 this should be INLINE in header files and empty in the
140 * master source file, the same as the usage of ARRAYINLINE above and
141 * in array.c.
142 *
143 * Example usage in e.g. item.h of some game:
144 *
145 * DECLARRAY_BYTYPE(stringarray, char);
146 * DECLARRAY(potion);
147 * DECLARRAY(sword);
148 *
149 * #ifndef ITEMINLINE
150 * #define ITEMINLINE INLINE
151 * #endif
152 *
153 * DEFARRAY_BYTYPE(stringarray, char, ITEMINLINE);
154 * DEFARRAY(potion, ITEMINLINE);
155 * DEFARRAY(sword, ITEMINLINE);
156 *
157 * Then item.c would do "#define ITEMINLINE" before including item.h.
158 *
159 * This creates types "struct stringarray", "struct potionarray",
160 * and "struct swordarray", with operations such as "swordarray_num".
161 *
162 * The operations on typed arrays are the same as the operations on
163 * the base array, except typed.
164 */
165
166 #define DECLARRAY_BYTYPE(ARRAY, T) \
167 struct ARRAY { \
168 struct array arr; \
169 }; \
170 \
171 struct ARRAY *ARRAY##_create(void); \
172 void ARRAY##_destroy(struct ARRAY *a); \
173 void ARRAY##_init(struct ARRAY *a); \
174 void ARRAY##_cleanup(struct ARRAY *a); \
175 unsigned ARRAY##_num(const struct ARRAY *a); \
176 T *ARRAY##_get(const struct ARRAY *a, unsigned index); \
177 void ARRAY##_set(struct ARRAY *a, unsigned index, T *val); \
178 int ARRAY##_setsize(struct ARRAY *a, unsigned num); \
179 int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
180 void ARRAY##_remove(struct ARRAY *a, unsigned index)
181
182 #define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
183 INLINE struct ARRAY * \
184 ARRAY##_create(void) \
185 { \
186 struct ARRAY *a = kmalloc(sizeof(*a)); \
187 if (a == NULL) { \
188 return NULL; \
189 } \
190 array_init(&a->arr); \
191 return a; \
192 } \
193 \
194 INLINE void \
195 ARRAY##_destroy(struct ARRAY *a) \
196 { \
197 array_cleanup(&a->arr); \
198 kfree(a); \
199 } \
200 \
201 INLINE void \
202 ARRAY##_init(struct ARRAY *a) \
203 { \
204 array_init(&a->arr); \
205 } \
206 \
207 INLINE void \
208 ARRAY##_cleanup(struct ARRAY *a) \
209 { \
210 array_cleanup(&a->arr); \
211 } \
212 \
213 INLINE unsigned \
214 ARRAY##_num(const struct ARRAY *a) \
215 { \
216 return array_num(&a->arr); \
217 } \
218 \
219 INLINE T * \
220 ARRAY##_get(const struct ARRAY *a, unsigned index) \
221 { \
222 return (T *)array_get(&a->arr, index); \
223 } \
224 \
225 INLINE void \
226 ARRAY##_set(struct ARRAY *a, unsigned index, T *val) \
227 { \
228 array_set(&a->arr, index, (void *)val); \
229 } \
230 \
231 INLINE int \
232 ARRAY##_setsize(struct ARRAY *a, unsigned num) \
233 { \
234 return array_setsize(&a->arr, num); \
235 } \
236 \
237 INLINE int \
238 ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret) \
239 { \
240 return array_add(&a->arr, (void *)val, index_ret); \
241 } \
242 \
243 INLINE void \
244 ARRAY##_remove(struct ARRAY *a, unsigned index) \
245 { \
246 return array_remove(&a->arr, index); \
247 }
248
249 #define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T)
250 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
251
252 /*
253 * This is how you declare an array of strings; it works out as
254 * an array of pointers to char.
255 */
256 DECLARRAY_BYTYPE(stringarray, char);
257 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
258
259
260 #endif /* ARRAY_H */