1 /* $Id$ */ 2 3 /* 4 * Copyright (c) 2006 Nicholas Marriott <nicholas.marriott@gmail.com> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef ARRAY_H 20 #define ARRAY_H 21 22 #define ARRAY_INITIALIZER { NULL, 0, 0 } 23 24 #define ARRAY_DECL(n, c) \ 25 struct n { \ 26 c *list; \ 27 u_int num; \ 28 size_t space; \ 29 } 30 31 #define ARRAY_ITEM(a, i) ((a)->list[i]) 32 #define ARRAY_ITEMSIZE(a) (sizeof *(a)->list) 33 #define ARRAY_INITIALSPACE(a) (10 * ARRAY_ITEMSIZE(a)) 34 35 #define ARRAY_ENSURE(a, n) do { \ 36 if (UINT_MAX - (n) < (a)->num) \ 37 fatalx("number too big"); \ 38 if (SIZE_MAX / ((a)->num + (n)) < ARRAY_ITEMSIZE(a)) \ 39 fatalx("size too big"); \ 40 if ((a)->space == 0) { \ 41 (a)->space = ARRAY_INITIALSPACE(a); \ 42 (a)->list = xrealloc((a)->list, 1, (a)->space); \ 43 } \ 44 while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) { \ 45 (a)->list = xrealloc((a)->list, 2, (a)->space); \ 46 (a)->space *= 2; \ 47 } \ 48 } while (0) 49 50 #define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0) 51 #define ARRAY_LENGTH(a) ((a)->num) 52 #define ARRAY_DATA(a) ((a)->list) 53 54 #define ARRAY_FIRST(a) ARRAY_ITEM(a, 0) 55 #define ARRAY_LAST(a) ARRAY_ITEM(a, (a)->num - 1) 56 57 #define ARRAY_INIT(a) do { \ 58 (a)->num = 0; \ 59 (a)->list = NULL; \ 60 (a)->space = 0; \ 61 } while (0) 62 #define ARRAY_CLEAR(a) do { \ 63 (a)->num = 0; \ 64 } while (0) 65 66 #define ARRAY_SET(a, i, s) do { \ 67 (a)->list[i] = s; \ 68 } while (0) 69 70 #define ARRAY_ADD(a, s) do { \ 71 ARRAY_ENSURE(a, 1); \ 72 (a)->list[(a)->num] = s; \ 73 (a)->num++; \ 74 } while (0) 75 #define ARRAY_INSERT(a, i, s) do { \ 76 ARRAY_ENSURE(a, 1); \ 77 if ((i) < (a)->num) { \ 78 memmove((a)->list + (i) + 1, (a)->list + (i), \ 79 ARRAY_ITEMSIZE(a) * ((a)->num - (i))); \ 80 } \ 81 (a)->list[i] = s; \ 82 (a)->num++; \ 83 } while (0) 84 #define ARRAY_REMOVE(a, i) do { \ 85 if ((i) < (a)->num - 1) { \ 86 memmove((a)->list + (i), (a)->list + (i) + 1, \ 87 ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1)); \ 88 } \ 89 (a)->num--; \ 90 if ((a)->num == 0) \ 91 ARRAY_FREE(a); \ 92 } while (0) 93 94 #define ARRAY_EXPAND(a, n) do { \ 95 ARRAY_ENSURE(a, n); \ 96 (a)->num += n; \ 97 } while (0) 98 #define ARRAY_TRUNC(a, n) do { \ 99 if ((a)->num > n) \ 100 (a)->num -= n; \ 101 else \ 102 ARRAY_FREE(a); \ 103 } while (0) 104 105 #define ARRAY_CONCAT(a, b) do { \ 106 ARRAY_ENSURE(a, (b)->num); \ 107 memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)); \ 108 (a)->num += (b)->num; \ 109 } while (0) 110 111 #define ARRAY_FREE(a) do { \ 112 if ((a)->list != NULL) \ 113 xfree((a)->list); \ 114 ARRAY_INIT(a); \ 115 } while (0) 116 #define ARRAY_FREEALL(a) do { \ 117 ARRAY_FREE(a); \ 118 xfree(a); \ 119 } while (0) 120 121 #endif 122