os161-1.99
 All Data Structures
array.h
00001 /*-
00002  * Copyright (c) 2009 The NetBSD Foundation, Inc.
00003  * All rights reserved.
00004  *
00005  * This code is derived from software contributed to The NetBSD Foundation
00006  * by David A. Holland.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00019  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00020  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
00021  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #ifndef _ARRAY_H_
00031 #define _ARRAY_H_
00032 
00033 #ifdef UW
00034 #include <lib.h>
00035 #endif
00036 
00037 #define ARRAYS_CHECKED
00038 
00039 #ifdef ARRAYS_CHECKED
00040 #define ARRAYASSERT KASSERT
00041 #else
00042 #define ARRAYASSERT(x) ((void)(x))
00043 #endif
00044 
00045 /*
00046  * Base array type (resizeable array of void pointers) and operations.
00047  *
00048  * create - allocate an array.
00049  * destroy - destroy an allocated array.
00050  * init - initialize an array in space externally allocated.
00051  * cleanup - clean up an array in space exteranlly allocated.
00052  * num - return number of elements in array.
00053  * get - return element no. INDEX.
00054  * set - set element no. INDEX to VAL.
00055  * setsize - change size to NUM elements; may fail and return error.
00056  * add - append VAL to end of array; return its index in INDEX_RET if
00057  *       INDEX_RET isn't null; may fail and return error.
00058  * remove - excise entry INDEX and slide following entries down to
00059  *       close the resulting gap.
00060  *
00061  * Note that expanding an array with setsize doesn't initialize the new
00062  * elements. (Usually the caller is about to store into them anyway.)
00063  */
00064 
00065 struct array {
00066         void **v;
00067         unsigned num, max;
00068 };
00069 
00070 struct array *array_create(void);
00071 void array_destroy(struct array *);
00072 void array_init(struct array *);
00073 void array_cleanup(struct array *);
00074 unsigned array_num(const struct array *);
00075 void *array_get(const struct array *, unsigned index);
00076 void array_set(const struct array *, unsigned index, void *val);
00077 int array_setsize(struct array *, unsigned num);
00078 int array_add(struct array *, void *val, unsigned *index_ret);
00079 void array_remove(struct array *, unsigned index);
00080 
00081 /*
00082  * Inlining for base operations
00083  */
00084 
00085 #ifndef ARRAYINLINE
00086 #define ARRAYINLINE INLINE
00087 #endif
00088 
00089 ARRAYINLINE unsigned
00090 array_num(const struct array *a)
00091 {
00092         return a->num;
00093 }
00094 
00095 ARRAYINLINE void *
00096 array_get(const struct array *a, unsigned index)
00097 {
00098         ARRAYASSERT(index < a->num);
00099         return a->v[index];
00100 }
00101 
00102 ARRAYINLINE void
00103 array_set(const struct array *a, unsigned index, void *val)
00104 {
00105         ARRAYASSERT(index < a->num);
00106         a->v[index] = val;
00107 }
00108 
00109 ARRAYINLINE int
00110 array_add(struct array *a, void *val, unsigned *index_ret)
00111 {
00112         unsigned index;
00113         int ret;
00114 
00115         index = a->num;
00116         ret = array_setsize(a, index+1);
00117         if (ret) {
00118                 return ret;
00119         }
00120         a->v[index] = val;
00121         if (index_ret != NULL) {
00122                 *index_ret = index;
00123         }
00124         return 0;
00125 }
00126 
00127 /*
00128  * Bits for declaring and defining typed arrays.
00129  *
00130  * Usage:
00131  *
00132  * DECLARRAY_BYTYPE(foo, bar) declares "struct foo", which is
00133  * an array of pointers to "bar", plus the operations on it.
00134  *
00135  * DECLARRAY(foo) is equivalent to DECLARRAY_BYTYPE(fooarray, struct foo).
00136  *
00137  * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that
00138  * they define the operations, and both take an extra argument INLINE.
00139  * For C99 this should be INLINE in header files and empty in the
00140  * master source file, the same as the usage of ARRAYINLINE above and
00141  * in array.c.
00142  *
00143  * Example usage in e.g. item.h of some game:
00144  * 
00145  * DECLARRAY_BYTYPE(stringarray, char);
00146  * DECLARRAY(potion);
00147  * DECLARRAY(sword);
00148  *
00149  * #ifndef ITEMINLINE
00150  * #define ITEMINLINE INLINE
00151  * #endif
00152  *
00153  * DEFARRAY_BYTYPE(stringarray, char, ITEMINLINE);
00154  * DEFARRAY(potion, ITEMINLINE);
00155  * DEFARRAY(sword, ITEMINLINE);
00156  *
00157  * Then item.c would do "#define ITEMINLINE" before including item.h.
00158  *
00159  * This creates types "struct stringarray", "struct potionarray",
00160  * and "struct swordarray", with operations such as "swordarray_num".
00161  *
00162  * The operations on typed arrays are the same as the operations on
00163  * the base array, except typed.
00164  */
00165 
00166 #define DECLARRAY_BYTYPE(ARRAY, T) \
00167         struct ARRAY {                                          \
00168                 struct array arr;                               \
00169         };                                                      \
00170                                                                 \
00171         struct ARRAY *ARRAY##_create(void);                     \
00172         void ARRAY##_destroy(struct ARRAY *a);                  \
00173         void ARRAY##_init(struct ARRAY *a);                     \
00174         void ARRAY##_cleanup(struct ARRAY *a);                  \
00175         unsigned ARRAY##_num(const struct ARRAY *a);            \
00176         T *ARRAY##_get(const struct ARRAY *a, unsigned index);  \
00177         void ARRAY##_set(struct ARRAY *a, unsigned index, T *val); \
00178         int ARRAY##_setsize(struct ARRAY *a, unsigned num);     \
00179         int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \
00180         void ARRAY##_remove(struct ARRAY *a, unsigned index)
00181 
00182 #define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \
00183         INLINE struct ARRAY *                                   \
00184         ARRAY##_create(void)                                    \
00185         {                                                       \
00186                 struct ARRAY *a = kmalloc(sizeof(*a));          \
00187                 if (a == NULL) {                                \
00188                         return NULL;                            \
00189                 }                                               \
00190                 array_init(&a->arr);                            \
00191                 return a;                                       \
00192         }                                                       \
00193                                                                 \
00194         INLINE void                                             \
00195         ARRAY##_destroy(struct ARRAY *a)                        \
00196         {                                                       \
00197                 array_cleanup(&a->arr);                         \
00198                 kfree(a);                                       \
00199         }                                                       \
00200                                                                 \
00201         INLINE void                                             \
00202         ARRAY##_init(struct ARRAY *a)                           \
00203         {                                                       \
00204                 array_init(&a->arr);                            \
00205         }                                                       \
00206                                                                 \
00207         INLINE void                                             \
00208         ARRAY##_cleanup(struct ARRAY *a)                        \
00209         {                                                       \
00210                 array_cleanup(&a->arr);                         \
00211         }                                                       \
00212                                                                 \
00213         INLINE unsigned                                         \
00214         ARRAY##_num(const struct ARRAY *a)                      \
00215         {                                                       \
00216                 return array_num(&a->arr);                      \
00217         }                                                       \
00218                                                                 \
00219         INLINE T *                                              \
00220         ARRAY##_get(const struct ARRAY *a, unsigned index)      \
00221         {                                                       \
00222                 return (T *)array_get(&a->arr, index);          \
00223         }                                                       \
00224                                                                 \
00225         INLINE void                                             \
00226         ARRAY##_set(struct ARRAY *a, unsigned index, T *val)    \
00227         {                                                       \
00228                 array_set(&a->arr, index, (void *)val);         \
00229         }                                                       \
00230                                                                 \
00231         INLINE int                                              \
00232         ARRAY##_setsize(struct ARRAY *a, unsigned num)          \
00233         {                                                       \
00234                 return array_setsize(&a->arr, num);             \
00235         }                                                       \
00236                                                                 \
00237         INLINE int                                              \
00238         ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret) \
00239         {                                                       \
00240                 return array_add(&a->arr, (void *)val, index_ret); \
00241         }                                                       \
00242                                                                 \
00243         INLINE void                                             \
00244         ARRAY##_remove(struct ARRAY *a, unsigned index)         \
00245         {                                                       \
00246                 return array_remove(&a->arr, index);            \
00247         }
00248 
00249 #define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T)
00250 #define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE)
00251 
00252 /*
00253  * This is how you declare an array of strings; it works out as
00254  * an array of pointers to char.
00255  */
00256 DECLARRAY_BYTYPE(stringarray, char);
00257 DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE);
00258 
00259 
00260 #endif /* ARRAY_H */
 All Data Structures