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
|
2
|
33 #include "utils.h"
|
|
34
|
1
|
35 #define ARRAYS_CHECKED
|
|
36
|
|
37 #ifdef ARRAYS_CHECKED
|
|
38 #include <assert.h>
|
|
39 #define arrayassert assert
|
|
40 #else
|
|
41 #define arrayassert(x) ((void)(x))
|
|
42 #endif
|
|
43
|
|
44 ////////////////////////////////////////////////////////////
|
|
45 // type and base operations
|
|
46
|
|
47 struct array {
|
|
48 void **v;
|
|
49 unsigned num, max;
|
|
50 };
|
|
51
|
|
52 struct array *array_create(void);
|
|
53 void array_destroy(struct array *);
|
|
54 void array_init(struct array *);
|
|
55 void array_cleanup(struct array *);
|
|
56 unsigned array_num(const struct array *);
|
|
57 void *array_get(const struct array *, unsigned index_);
|
|
58 void array_set(const struct array *, unsigned index_, void *val);
|
2
|
59 void array_setsize(struct array *, unsigned num);
|
|
60 void array_add(struct array *, void *val, unsigned *index_ret);
|
|
61 void array_insert(struct array *a, unsigned index_);
|
1
|
62 void array_remove(struct array *a, unsigned index_);
|
|
63
|
|
64 ////////////////////////////////////////////////////////////
|
|
65 // inlining for base operations
|
|
66
|
|
67 #ifndef ARRAYINLINE
|
|
68 #define ARRAYINLINE __c99inline
|
|
69 #endif
|
|
70
|
|
71 ARRAYINLINE unsigned
|
|
72 array_num(const struct array *a)
|
|
73 {
|
|
74 return a->num;
|
|
75 }
|
|
76
|
|
77 ARRAYINLINE void *
|
|
78 array_get(const struct array *a, unsigned index_)
|
|
79 {
|
|
80 arrayassert(index_ < a->num);
|
|
81 return a->v[index_];
|
|
82 }
|
|
83
|
|
84 ARRAYINLINE void
|
|
85 array_set(const struct array *a, unsigned index_, void *val)
|
|
86 {
|
|
87 arrayassert(index_ < a->num);
|
|
88 a->v[index_] = val;
|
|
89 }
|
|
90
|
2
|
91 ARRAYINLINE void
|
1
|
92 array_add(struct array *a, void *val, unsigned *index_ret)
|
|
93 {
|
|
94 unsigned index_ = a->num;
|
2
|
95 array_setsize(a, index_+1);
|
1
|
96 a->v[index_] = val;
|
|
97 if (index_ret != NULL) {
|
|
98 *index_ret = index_;
|
|
99 }
|
|
100 }
|
|
101
|
|
102 ////////////////////////////////////////////////////////////
|
|
103 // bits for declaring and defining typed arrays
|
|
104
|
|
105 /*
|
|
106 * Usage:
|
|
107 *
|
|
108 * DECLARRAY_BYTYPE(foo, bar) declares "struct foo", which is
|
|
109 * an array of pointers to "bar", plus the operations on it.
|
|
110 *
|
|
111 * DECLARRAY(foo) is equivalent to DECLARRAY_BYTYPE(fooarray, struct foo).
|
|
112 *
|
|
113 * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that
|
|
114 * they define the operations, and both take an extra argument INLINE.
|
|
115 * For C99 this should be INLINE in header files and empty in the
|
|
116 * master source file, the same as the usage of ARRAYINLINE above and
|
|
117 * in array.c.
|
|
118 *
|
|
119 * Example usage in e.g. item.h of some game:
|
|
120 *
|
|
121 * DECLARRAY_BYTYPE(stringarray, char);
|
|
122 * DECLARRAY(potion);
|
|
123 * DECLARRAY(sword);
|
|
124 *
|
|
125 * #ifndef ITEMINLINE
|
|
126 * #define ITEMINLINE INLINE
|
|
127 * #endif
|
|
128 *
|
|
129 * DEFARRAY_BYTYPE(stringarray, char, ITEMINLINE);
|
|
130 * DEFARRAY(potion, ITEMINLINE);
|
|
131 * DEFARRAY(sword, ITEMINLINE);
|
|
132 *
|
|
133 * Then item.c would do "#define ITEMINLINE" before including item.h.
|
|
134 */
|
|
135
|
|
136 #define DECLARRAY_BYTYPE(ARRAY, T) \
|
|
137 struct ARRAY { \
|
|
138 struct array arr; \
|
|
139 }; \
|
|
140 \
|
|
141 struct ARRAY *ARRAY##_create(void); \
|
|
142 void ARRAY##_destroy(struct ARRAY *a); \
|
|
143 void ARRAY##_init(struct ARRAY *a); \
|
|
144 void ARRAY##_cleanup(struct ARRAY *a); \
|
|
145 unsigned ARRAY##_num(const struct ARRAY *a); \
|
|
146 T *ARRAY##_get(const struct ARRAY *a, unsigned index_); \
|
|
147 void ARRAY##_set(struct ARRAY *a, unsigned index_, T *val); \
|
2
|
148 void ARRAY##_setsize(struct ARRAY *a, unsigned num); \
|
|
149 void ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
|
|
150 void ARRAY##_insert(struct ARRAY *a, unsigned index_); \
|
1
|
151 void ARRAY##_remove(struct ARRAY *a, unsigned index_)
|
|
152
|
|
153
|
|
154 #define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
|
|
155 INLINE void \
|
|
156 ARRAY##_init(struct ARRAY *a) \
|
|
157 { \
|
|
158 array_init(&a->arr); \
|
|
159 } \
|
|
160 \
|
|
161 INLINE void \
|
|
162 ARRAY##_cleanup(struct ARRAY *a) \
|
|
163 { \
|
|
164 array_cleanup(&a->arr); \
|
|
165 } \
|
|
166 \
|
|
167 INLINE struct \
|
|
168 ARRAY *ARRAY##_create(void) \
|
|
169 { \
|
|
170 struct ARRAY *a; \
|
|
171 \
|
2
|
172 a = domalloc(sizeof(*a)); \
|
1
|
173 ARRAY##_init(a); \
|
|
174 return a; \
|
|
175 } \
|
|
176 \
|
|
177 INLINE void \
|
|
178 ARRAY##_destroy(struct ARRAY *a) \
|
|
179 { \
|
|
180 ARRAY##_cleanup(a); \
|
|
181 free(a); \
|
|
182 } \
|
|
183 \
|
|
184 INLINE unsigned \
|
|
185 ARRAY##_num(const struct ARRAY *a) \
|
|
186 { \
|
|
187 return array_num(&a->arr); \
|
|
188 } \
|
|
189 \
|
|
190 INLINE T * \
|
|
191 ARRAY##_get(const struct ARRAY *a, unsigned index_) \
|
|
192 { \
|
|
193 return (T *)array_get(&a->arr, index_); \
|
|
194 } \
|
|
195 \
|
|
196 INLINE void \
|
|
197 ARRAY##_set(struct ARRAY *a, unsigned index_, T *val) \
|
|
198 { \
|
|
199 array_set(&a->arr, index_, (void *)val); \
|
|
200 } \
|
|
201 \
|
2
|
202 INLINE void \
|
1
|
203 ARRAY##_setsize(struct ARRAY *a, unsigned num) \
|
|
204 { \
|
2
|
205 array_setsize(&a->arr, num); \
|
1
|
206 } \
|
|
207 \
|
2
|
208 INLINE void \
|
1
|
209 ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret) \
|
|
210 { \
|
2
|
211 array_add(&a->arr, (void *)val, ret); \
|
1
|
212 } \
|
|
213 \
|
2
|
214 INLINE void \
|
1
|
215 ARRAY##_insert(struct ARRAY *a, unsigned index_) \
|
|
216 { \
|
2
|
217 array_insert(&a->arr, index_); \
|
1
|
218 } \
|
|
219 \
|
|
220 INLINE void \
|
|
221 ARRAY##_remove(struct ARRAY *a, unsigned index_) \
|
|
222 { \
|
2
|
223 array_remove(&a->arr, index_); \
|
1
|
224 }
|
|
225
|
|
226 #define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T)
|
|
227 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
|
|
228
|
|
229 ////////////////////////////////////////////////////////////
|
|
230 // basic array types
|
|
231
|
|
232 DECLARRAY_BYTYPE(stringarray, char);
|
|
233 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
|
|
234
|
|
235 #endif /* ARRAY_H */
|