Mercurial > ~dholland > hg > tradcpp > index.cgi
changeset 1:411b28d78483
standard arrays (nearly)
author | David A. Holland |
---|---|
date | Sun, 19 Dec 2010 16:47:59 -0500 |
parents | 67fa1db0651c |
children | 9c1cecba517c |
files | array.c array.h inlinedefs.h |
diffstat | 3 files changed, 402 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/array.c Sun Dec 19 16:47:59 2010 -0500 @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David A. Holland. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <string.h> + +#define ARRAYINLINE +#include "array.h" + +struct array * +array_create(void) +{ + struct array *a; + + a = malloc(sizeof(*a)); + if (a != NULL) { + array_init(a); + } + return a; +} + +void +array_destroy(struct array *a) +{ + array_cleanup(a); + free(a); +} + +void +array_init(struct array *a) +{ + a->num = a->max = 0; + a->v = NULL; +} + +void +array_cleanup(struct array *a) +{ + arrayassert(a->num == 0); + free(a->v); +#ifdef ARRAYS_CHECKED + a->v = NULL; +#endif +} + +int +array_setsize(struct array *a, unsigned num) +{ + unsigned newmax; + void **newptr; + + if (num > a->max) { + newmax = a->max; + while (num > newmax) { + newmax = newmax ? newmax*2 : 4; + } + newptr = realloc(a->v, newmax*sizeof(*a->v)); + if (newptr == NULL) { + return -1; + } + a->v = newptr; + a->max = newmax; + } + a->num = num; + return 0; +} + +int +array_insert(struct array *a, unsigned index_) +{ + unsigned movers; + + arrayassert(a->num <= a->max); + arrayassert(index_ < a->num); + + movers = a->num - index_; + + if (array_setsize(a, a->num + 1)) { + return -1; + } + + memmove(a->v + index_+1, a->v + index_, movers*sizeof(*a->v)); + return 0; +} + +void +array_remove(struct array *a, unsigned index_) +{ + unsigned movers; + + arrayassert(a->num <= a->max); + arrayassert(index_ < a->num); + + movers = a->num - (index_ + 1); + memmove(a->v + index_, a->v + index_+1, movers*sizeof(*a->v)); + a->num--; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/array.h Sun Dec 19 16:47:59 2010 -0500 @@ -0,0 +1,239 @@ +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by David A. Holland. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ARRAY_H +#define ARRAY_H + +#define ARRAYS_CHECKED + +#ifdef ARRAYS_CHECKED +#include <assert.h> +#define arrayassert assert +#else +#define arrayassert(x) ((void)(x)) +#endif + +//////////////////////////////////////////////////////////// +// type and base operations + +struct array { + void **v; + unsigned num, max; +}; + +struct array *array_create(void); +void array_destroy(struct array *); +void array_init(struct array *); +void array_cleanup(struct array *); +unsigned array_num(const struct array *); +void *array_get(const struct array *, unsigned index_); +void array_set(const struct array *, unsigned index_, void *val); +int array_setsize(struct array *, unsigned num); +int array_add(struct array *, void *val, unsigned *index_ret); +int array_insert(struct array *a, unsigned index_); +void array_remove(struct array *a, unsigned index_); + +//////////////////////////////////////////////////////////// +// inlining for base operations + +#ifndef ARRAYINLINE +#define ARRAYINLINE __c99inline +#endif + +ARRAYINLINE unsigned +array_num(const struct array *a) +{ + return a->num; +} + +ARRAYINLINE void * +array_get(const struct array *a, unsigned index_) +{ + arrayassert(index_ < a->num); + return a->v[index_]; +} + +ARRAYINLINE void +array_set(const struct array *a, unsigned index_, void *val) +{ + arrayassert(index_ < a->num); + a->v[index_] = val; +} + +ARRAYINLINE int +array_add(struct array *a, void *val, unsigned *index_ret) +{ + unsigned index_ = a->num; + if (array_setsize(a, index_+1)) { + return -1; + } + a->v[index_] = val; + if (index_ret != NULL) { + *index_ret = index_; + } + return 0; +} + +//////////////////////////////////////////////////////////// +// bits for declaring and defining typed arrays + +/* + * Usage: + * + * DECLARRAY_BYTYPE(foo, bar) declares "struct foo", which is + * an array of pointers to "bar", plus the operations on it. + * + * DECLARRAY(foo) is equivalent to DECLARRAY_BYTYPE(fooarray, struct foo). + * + * DEFARRAY_BYTYPE and DEFARRAY are the same as DECLARRAY except that + * they define the operations, and both take an extra argument INLINE. + * For C99 this should be INLINE in header files and empty in the + * master source file, the same as the usage of ARRAYINLINE above and + * in array.c. + * + * Example usage in e.g. item.h of some game: + * + * DECLARRAY_BYTYPE(stringarray, char); + * DECLARRAY(potion); + * DECLARRAY(sword); + * + * #ifndef ITEMINLINE + * #define ITEMINLINE INLINE + * #endif + * + * DEFARRAY_BYTYPE(stringarray, char, ITEMINLINE); + * DEFARRAY(potion, ITEMINLINE); + * DEFARRAY(sword, ITEMINLINE); + * + * Then item.c would do "#define ITEMINLINE" before including item.h. + */ + +#define DECLARRAY_BYTYPE(ARRAY, T) \ + struct ARRAY { \ + struct array arr; \ + }; \ + \ + struct ARRAY *ARRAY##_create(void); \ + void ARRAY##_destroy(struct ARRAY *a); \ + void ARRAY##_init(struct ARRAY *a); \ + void ARRAY##_cleanup(struct ARRAY *a); \ + unsigned ARRAY##_num(const struct ARRAY *a); \ + T *ARRAY##_get(const struct ARRAY *a, unsigned index_); \ + void ARRAY##_set(struct ARRAY *a, unsigned index_, T *val); \ + int ARRAY##_setsize(struct ARRAY *a, unsigned num); \ + int ARRAY##_add(struct ARRAY *a, T *val, unsigned *index_ret); \ + int ARRAY##_insert(struct ARRAY *a, unsigned index_); \ + void ARRAY##_remove(struct ARRAY *a, unsigned index_) + + +#define DEFARRAY_BYTYPE(ARRAY, T, INLINE) \ + INLINE void \ + ARRAY##_init(struct ARRAY *a) \ + { \ + array_init(&a->arr); \ + } \ + \ + INLINE void \ + ARRAY##_cleanup(struct ARRAY *a) \ + { \ + array_cleanup(&a->arr); \ + } \ + \ + INLINE struct \ + ARRAY *ARRAY##_create(void) \ + { \ + struct ARRAY *a; \ + \ + a = malloc(sizeof(*a)); \ + if (a == NULL) { \ + return NULL; \ + } \ + ARRAY##_init(a); \ + return a; \ + } \ + \ + INLINE void \ + ARRAY##_destroy(struct ARRAY *a) \ + { \ + ARRAY##_cleanup(a); \ + free(a); \ + } \ + \ + INLINE unsigned \ + ARRAY##_num(const struct ARRAY *a) \ + { \ + return array_num(&a->arr); \ + } \ + \ + INLINE T * \ + ARRAY##_get(const struct ARRAY *a, unsigned index_) \ + { \ + return (T *)array_get(&a->arr, index_); \ + } \ + \ + INLINE void \ + ARRAY##_set(struct ARRAY *a, unsigned index_, T *val) \ + { \ + array_set(&a->arr, index_, (void *)val); \ + } \ + \ + INLINE int \ + ARRAY##_setsize(struct ARRAY *a, unsigned num) \ + { \ + return array_setsize(&a->arr, num); \ + } \ + \ + INLINE int \ + ARRAY##_add(struct ARRAY *a, T *val, unsigned *ret) \ + { \ + return array_add(&a->arr, (void *)val, ret); \ + } \ + \ + INLINE int \ + ARRAY##_insert(struct ARRAY *a, unsigned index_) \ + { \ + return array_insert(&a->arr, index_); \ + } \ + \ + INLINE void \ + ARRAY##_remove(struct ARRAY *a, unsigned index_) \ + { \ + return array_remove(&a->arr, index_); \ + } + +#define DECLARRAY(T) DECLARRAY_BYTYPE(T##array, struct T) +#define DEFARRAY(T, INLINE) DEFARRAY_BYTYPE(T##array, struct T, INLINE) + +//////////////////////////////////////////////////////////// +// basic array types + +DECLARRAY_BYTYPE(stringarray, char); +DEFARRAY_BYTYPE(stringarray, char, ARRAYINLINE); + +#endif /* ARRAY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inlinedefs.h Sun Dec 19 16:47:59 2010 -0500 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2009 David A. Holland. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Author nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__) +/* gcc's non-C99 inline semantics */ +#define __c99inline extern inline +#elif defined(__STDC__) && __STDC_VERSION__ >= 199901L +/* C99 */ +#define __c99inline inline +#else +/* something else; static inline is safest */ +#define __c99inline static inline +#endif +