Mercurial > ~dholland > hg > tradcpp > index.cgi
annotate array.h @ 46:eaa154ded584
Test recursive macros.
author | David A. Holland |
---|---|
date | Sat, 30 Mar 2013 22:35:06 -0400 |
parents | 337110e7240a |
children | 2e25e55dba6b |
rev | line source |
---|---|
1 | 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 | |
6 | 33 #include "inlinedefs.h" // XXX |
2 | 34 #include "utils.h" |
35 | |
1 | 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 //////////////////////////////////////////////////////////// | |
46 // type and base operations | |
47 | |
48 struct array { | |
49 void **v; | |
50 unsigned num, max; | |
51 }; | |
52 | |
53 struct array *array_create(void); | |
54 void array_destroy(struct array *); | |
55 void array_init(struct array *); | |
56 void array_cleanup(struct array *); | |
57 unsigned array_num(const struct array *); | |
58 void *array_get(const struct array *, unsigned index_); | |
59 void array_set(const struct array *, unsigned index_, void *val); | |
2 | 60 void array_setsize(struct array *, unsigned num); |
61 void array_add(struct array *, void *val, unsigned *index_ret); | |
62 void array_insert(struct array *a, unsigned index_); | |
1 | 63 void array_remove(struct array *a, unsigned index_); |
64 | |
65 //////////////////////////////////////////////////////////// | |
66 // inlining for base operations | |
67 | |
68 #ifndef ARRAYINLINE | |
69 #define ARRAYINLINE __c99inline | |
70 #endif | |
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 | |
2 | 92 ARRAYINLINE void |
1 | 93 array_add(struct array *a, void *val, unsigned *index_ret) |
94 { | |
95 unsigned index_ = a->num; | |
2 | 96 array_setsize(a, index_+1); |
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) declares "struct foo", which is | |
110 * an array of pointers to "bar", plus the operations on it. | |
111 * | |
112 * DECLARRAY(foo) is equivalent to DECLARRAY_BYTYPE(fooarray, struct foo). | |
113 * | |
114 * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that | |
115 * they define the operations, and both take an extra argument INLINE. | |
116 * For C99 this should be INLINE in header files and empty in the | |
117 * master source file, the same as the usage of ARRAYINLINE above and | |
118 * in array.c. | |
119 * | |
120 * Example usage in e.g. item.h of some game: | |
121 * | |
122 * DECLARRAY_BYTYPE(stringarray, char); | |
123 * DECLARRAY(potion); | |
124 * DECLARRAY(sword); | |
125 * | |
126 * #ifndef ITEMINLINE | |
127 * #define ITEMINLINE INLINE | |
128 * #endif | |
129 * | |
130 * DEFARRAY_BYTYPE(stringarray, char, ITEMINLINE); | |
131 * DEFARRAY(potion, ITEMINLINE); | |
132 * DEFARRAY(sword, ITEMINLINE); | |
133 * | |
134 * Then item.c would do "#define ITEMINLINE" before including item.h. | |
135 */ | |
136 | |
137 #define DECLARRAY_BYTYPE(ARRAY, T) \ | |
138 struct ARRAY { \ | |
139 struct array arr; \ | |
140 }; \ | |
141 \ | |
142 struct ARRAY *ARRAY##_create(void); \ | |
143 void ARRAY##_destroy(struct ARRAY *a); \ | |
144 void ARRAY##_init(struct ARRAY *a); \ | |
145 void ARRAY##_cleanup(struct ARRAY *a); \ | |
146 unsigned ARRAY##_num(const struct ARRAY *a); \ | |
147 T *ARRAY##_get(const struct ARRAY *a, unsigned index_); \ | |
148 void ARRAY##_set(struct ARRAY *a, unsigned index_, T *val); \ | |
2 | 149 void ARRAY##_setsize(struct ARRAY *a, unsigned num); \ |
150 void ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \ | |
151 void ARRAY##_insert(struct ARRAY *a, unsigned index_); \ | |
1 | 152 void ARRAY##_remove(struct ARRAY *a, unsigned index_) |
153 | |
154 | |
155 #define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \ | |
156 INLINE void \ | |
157 ARRAY##_init(struct ARRAY *a) \ | |
158 { \ | |
159 array_init(&a->arr); \ | |
160 } \ | |
161 \ | |
162 INLINE void \ | |
163 ARRAY##_cleanup(struct ARRAY *a) \ | |
164 { \ | |
165 array_cleanup(&a->arr); \ | |
166 } \ | |
167 \ | |
168 INLINE struct \ | |
169 ARRAY *ARRAY##_create(void) \ | |
170 { \ | |
171 struct ARRAY *a; \ | |
172 \ | |
2 | 173 a = domalloc(sizeof(*a)); \ |
1 | 174 ARRAY##_init(a); \ |
175 return a; \ | |
176 } \ | |
177 \ | |
178 INLINE void \ | |
179 ARRAY##_destroy(struct ARRAY *a) \ | |
180 { \ | |
181 ARRAY##_cleanup(a); \ | |
39
337110e7240a
Pass the size to free; it makes debug checking easier.
David A. Holland
parents:
38
diff
changeset
|
182 dofree(a, sizeof(*a)); \ |
1 | 183 } \ |
184 \ | |
185 INLINE unsigned \ | |
186 ARRAY##_num(const struct ARRAY *a) \ | |
187 { \ | |
188 return array_num(&a->arr); \ | |
189 } \ | |
190 \ | |
191 INLINE T * \ | |
192 ARRAY##_get(const struct ARRAY *a, unsigned index_) \ | |
193 { \ | |
194 return (T *)array_get(&a->arr, index_); \ | |
195 } \ | |
196 \ | |
197 INLINE void \ | |
198 ARRAY##_set(struct ARRAY *a, unsigned index_, T *val) \ | |
199 { \ | |
200 array_set(&a->arr, index_, (void *)val); \ | |
201 } \ | |
202 \ | |
2 | 203 INLINE void \ |
1 | 204 ARRAY##_setsize(struct ARRAY *a, unsigned num) \ |
205 { \ | |
2 | 206 array_setsize(&a->arr, num); \ |
1 | 207 } \ |
208 \ | |
2 | 209 INLINE void \ |
1 | 210 ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret) \ |
211 { \ | |
2 | 212 array_add(&a->arr, (void *)val, ret); \ |
1 | 213 } \ |
214 \ | |
2 | 215 INLINE void \ |
1 | 216 ARRAY##_insert(struct ARRAY *a, unsigned index_) \ |
217 { \ | |
2 | 218 array_insert(&a->arr, index_); \ |
1 | 219 } \ |
220 \ | |
221 INLINE void \ | |
222 ARRAY##_remove(struct ARRAY *a, unsigned index_) \ | |
223 { \ | |
2 | 224 array_remove(&a->arr, index_); \ |
1 | 225 } |
226 | |
227 #define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T) | |
228 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE) | |
229 | |
9 | 230 #define DESTROYALL_ARRAY(T, INLINE) \ |
231 void T##array_destroyall(struct T##array *arr); \ | |
232 \ | |
233 INLINE void \ | |
234 T##array_destroyall(struct T##array *arr) \ | |
235 { \ | |
236 unsigned i, num; \ | |
237 struct T *t; \ | |
238 \ | |
239 num = T##array_num(arr); \ | |
240 for (i=0; i<num; i++) { \ | |
241 t = T##array_get(arr, i); \ | |
242 T##_destroy(t); \ | |
243 } \ | |
244 T##array_setsize(arr, 0); \ | |
245 } | |
246 | |
247 | |
1 | 248 //////////////////////////////////////////////////////////// |
249 // basic array types | |
250 | |
251 DECLARRAY_BYTYPE(stringarray, char); | |
252 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE); | |
253 | |
254 #endif /* ARRAY_H */ |