1*0a6a1f1dSLionel Sambuc /*- 2*0a6a1f1dSLionel Sambuc * Copyright (c) 2012 Alistair Crooks <agc@NetBSD.org> 3*0a6a1f1dSLionel Sambuc * All rights reserved. 4*0a6a1f1dSLionel Sambuc * 5*0a6a1f1dSLionel Sambuc * Redistribution and use in source and binary forms, with or without 6*0a6a1f1dSLionel Sambuc * modification, are permitted provided that the following conditions 7*0a6a1f1dSLionel Sambuc * are met: 8*0a6a1f1dSLionel Sambuc * 1. Redistributions of source code must retain the above copyright 9*0a6a1f1dSLionel Sambuc * notice, this list of conditions and the following disclaimer. 10*0a6a1f1dSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright 11*0a6a1f1dSLionel Sambuc * notice, this list of conditions and the following disclaimer in the 12*0a6a1f1dSLionel Sambuc * documentation and/or other materials provided with the distribution. 13*0a6a1f1dSLionel Sambuc * 14*0a6a1f1dSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15*0a6a1f1dSLionel Sambuc * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*0a6a1f1dSLionel Sambuc * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*0a6a1f1dSLionel Sambuc * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18*0a6a1f1dSLionel Sambuc * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*0a6a1f1dSLionel Sambuc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*0a6a1f1dSLionel Sambuc * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*0a6a1f1dSLionel Sambuc * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*0a6a1f1dSLionel Sambuc * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*0a6a1f1dSLionel Sambuc * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*0a6a1f1dSLionel Sambuc */ 25*0a6a1f1dSLionel Sambuc #ifndef ARRAY_H_ 26*0a6a1f1dSLionel Sambuc #define ARRAY_H_ 20120921 27*0a6a1f1dSLionel Sambuc 28*0a6a1f1dSLionel Sambuc #ifndef PGPV_ARRAY 29*0a6a1f1dSLionel Sambuc /* creates 2 unsigned vars called "name"c and "name"size in current scope */ 30*0a6a1f1dSLionel Sambuc /* also creates an array called "name"s in current scope */ 31*0a6a1f1dSLionel Sambuc #define PGPV_ARRAY(type, name) \ 32*0a6a1f1dSLionel Sambuc unsigned name##c; unsigned name##vsize; type *name##s 33*0a6a1f1dSLionel Sambuc #endif 34*0a6a1f1dSLionel Sambuc 35*0a6a1f1dSLionel Sambuc /* if this isn't part of a struct, need to specifically initialise things */ 36*0a6a1f1dSLionel Sambuc #define ARRAY_INIT(name) do { \ 37*0a6a1f1dSLionel Sambuc name##c = name##vsize = 0; \ 38*0a6a1f1dSLionel Sambuc name##s = NULL; \ 39*0a6a1f1dSLionel Sambuc } while(/*CONSTCOND*/0) 40*0a6a1f1dSLionel Sambuc 41*0a6a1f1dSLionel Sambuc /* check the array is big enough - if not, expand it by explicit amount */ 42*0a6a1f1dSLionel Sambuc /* this is clunky, but there are bugs a-lurking */ 43*0a6a1f1dSLionel Sambuc #define ARRAY_EXPAND_SIZED(name, mult, add) do { \ 44*0a6a1f1dSLionel Sambuc if (name##c == name##vsize) { \ 45*0a6a1f1dSLionel Sambuc void *_v; \ 46*0a6a1f1dSLionel Sambuc char *_cv = NULL; \ 47*0a6a1f1dSLionel Sambuc unsigned _ents; \ 48*0a6a1f1dSLionel Sambuc _ents = (name##vsize * (mult)) + (add); \ 49*0a6a1f1dSLionel Sambuc _cv = _v = realloc(name##s, _ents * sizeof(*name##s)); \ 50*0a6a1f1dSLionel Sambuc if (_v == NULL) { \ 51*0a6a1f1dSLionel Sambuc fprintf(stderr, "ARRAY_EXPAND - bad realloc\n"); \ 52*0a6a1f1dSLionel Sambuc } else { \ 53*0a6a1f1dSLionel Sambuc memset(&_cv[name##vsize * sizeof(*name##s)], \ 54*0a6a1f1dSLionel Sambuc 0x0, (_ents - name##vsize) * sizeof(*name##s)); \ 55*0a6a1f1dSLionel Sambuc name##s = _v; \ 56*0a6a1f1dSLionel Sambuc name##vsize = _ents; \ 57*0a6a1f1dSLionel Sambuc } \ 58*0a6a1f1dSLionel Sambuc } \ 59*0a6a1f1dSLionel Sambuc } while(/*CONSTCOND*/0) 60*0a6a1f1dSLionel Sambuc 61*0a6a1f1dSLionel Sambuc /* check the array is big enough - if not, expand it (size * 2) + 10 */ 62*0a6a1f1dSLionel Sambuc #define ARRAY_EXPAND(name) ARRAY_EXPAND_SIZED(name, 2, 10) 63*0a6a1f1dSLionel Sambuc 64*0a6a1f1dSLionel Sambuc #define ARRAY_ELEMENT(name, num) name##s[num] 65*0a6a1f1dSLionel Sambuc #define ARRAY_LAST(name) name##s[name##c - 1] 66*0a6a1f1dSLionel Sambuc #define ARRAY_COUNT(name) name##c 67*0a6a1f1dSLionel Sambuc #define ARRAY_SIZE(name) name##vsize 68*0a6a1f1dSLionel Sambuc #define ARRAY_ARRAY(name) name##s 69*0a6a1f1dSLionel Sambuc 70*0a6a1f1dSLionel Sambuc #define ARRAY_APPEND(name, newel) do { \ 71*0a6a1f1dSLionel Sambuc ARRAY_EXPAND(name); \ 72*0a6a1f1dSLionel Sambuc ARRAY_COUNT(name) += 1; \ 73*0a6a1f1dSLionel Sambuc ARRAY_LAST(name) = newel; \ 74*0a6a1f1dSLionel Sambuc } while(/*CONSTCOND*/0) 75*0a6a1f1dSLionel Sambuc 76*0a6a1f1dSLionel Sambuc #define ARRAY_DELETE(name, num) do { \ 77*0a6a1f1dSLionel Sambuc ARRAY_COUNT(name) -= 1; \ 78*0a6a1f1dSLionel Sambuc memmove(&ARRAY_ELEMENT(name, num), &ARRAY_ELEMENT(name, num + 1), \ 79*0a6a1f1dSLionel Sambuc (ARRAY_COUNT(name) - (num)) * sizeof(ARRAY_ELEMENT(name, 0))); \ 80*0a6a1f1dSLionel Sambuc } while(/*CONSTCOND*/0) 81*0a6a1f1dSLionel Sambuc 82*0a6a1f1dSLionel Sambuc #endif 83