xref: /dragonfly/games/sail/array.h (revision 58645856)
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 #define ARRAYS_CHECKED
34 
35 #ifdef ARRAYS_CHECKED
36 #include <assert.h>
37 #define arrayassert assert
38 #else
39 #define arrayassert(x) ((void)(x))
40 #endif
41 
42 ////////////////////////////////////////////////////////////
43 // type and base operations
44 
45 struct array {
46 	void **v;
47 	unsigned num, max;
48 };
49 
50 struct array *array_create(void);
51 void array_destroy(struct array *);
52 void array_init(struct array *);
53 void array_cleanup(struct array *);
54 unsigned array_num(const struct array *);
55 void *array_get(const struct array *, unsigned index_);
56 void array_set(const struct array *, unsigned index_, void *val);
57 int array_setsize(struct array *, unsigned num);
58 int array_add(struct array *, void *val, unsigned *index_ret);
59 int array_insert(struct array *a, unsigned index_);
60 void array_remove(struct array *a, unsigned index_);
61 
62 ////////////////////////////////////////////////////////////
63 // inlining for base operations
64 
65 #ifndef ARRAYINLINE
66 #define ARRAYINLINE extern __attribute__((__gnu_inline__)) __inline
67 #endif
68 
69 ARRAYINLINE unsigned
70 array_num(const struct array *a)
71 {
72 	return a->num;
73 }
74 
75 ARRAYINLINE void *
76 array_get(const struct array *a, unsigned index_)
77 {
78 	arrayassert(index_ < a->num);
79 	return a->v[index_];
80 }
81 
82 ARRAYINLINE void
83 array_set(const struct array *a, unsigned index_, void *val)
84 {
85 	arrayassert(index_ < a->num);
86 	a->v[index_] = val;
87 }
88 
89 ARRAYINLINE int
90 array_add(struct array *a, void *val, unsigned *index_ret)
91 {
92 	unsigned index_ = a->num;
93 	if (array_setsize(a, index_+1)) {
94 		return -1;
95 	}
96 	a->v[index_] = val;
97 	if (index_ret != NULL) {
98 		*index_ret = index_;
99 	}
100 	return 0;
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); \
149 	int ARRAY##_setsize(struct ARRAY *a, unsigned num);	\
150 	int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
151 	int ARRAY##_insert(struct ARRAY *a, unsigned index_);	\
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 								\
173 		a  = malloc(sizeof(*a));			\
174 		if (a == NULL) {				\
175 			return NULL;				\
176 		}						\
177 		ARRAY##_init(a);				\
178 		return a;					\
179 	}							\
180 								\
181 	INLINE void						\
182 	ARRAY##_destroy(struct ARRAY *a)			\
183 	{							\
184 		ARRAY##_cleanup(a);				\
185 		free(a);					\
186 	}							\
187 								\
188 	INLINE unsigned						\
189 	ARRAY##_num(const struct ARRAY *a)			\
190 	{							\
191 		return array_num(&a->arr);			\
192 	}							\
193 								\
194 	INLINE T *						\
195 	ARRAY##_get(const struct ARRAY *a, unsigned index_)	\
196 	{				 			\
197 		return (T *)array_get(&a->arr, index_);		\
198 	}							\
199 								\
200 	INLINE void						\
201 	ARRAY##_set(struct ARRAY *a, unsigned index_, T *val)	\
202 	{				 			\
203 		array_set(&a->arr, index_, (void *)val);	\
204 	}							\
205 								\
206 	INLINE int						\
207 	ARRAY##_setsize(struct ARRAY *a, unsigned num)		\
208 	{				 			\
209 		return array_setsize(&a->arr, num);		\
210 	}							\
211 								\
212 	INLINE int						\
213 	ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret)	\
214 	{				 			\
215 		return array_add(&a->arr, (void *)val, ret);	\
216 	}							\
217 								\
218 	INLINE int						\
219 	ARRAY##_insert(struct ARRAY *a, unsigned index_)	\
220 	{				 			\
221 		return array_insert(&a->arr, index_);		\
222 	}							\
223 								\
224 	INLINE void						\
225 	ARRAY##_remove(struct ARRAY *a, unsigned index_)	\
226 	{				 			\
227 		return array_remove(&a->arr, index_);		\
228 	}
229 
230 #define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T)
231 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
232 
233 ////////////////////////////////////////////////////////////
234 // basic array types
235 
236 DECLARRAY_BYTYPE(stringarray, char);
237 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
238 
239 #endif /* ARRAY_H */
240