array.h 7.3 KB

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