|  | /* $Id$ */ | 
|  |  | 
|  | /* | 
|  | * Copyright (c) 2006 Nicholas Marriott <nicm@users.sourceforge.net> | 
|  | * | 
|  | * Permission to use, copy, modify, and distribute this software for any | 
|  | * purpose with or without fee is hereby granted, provided that the above | 
|  | * copyright notice and this permission notice appear in all copies. | 
|  | * | 
|  | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 
|  | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 
|  | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 
|  | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
|  | * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER | 
|  | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING | 
|  | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
|  | */ | 
|  |  | 
|  | #ifndef ARRAY_H | 
|  | #define ARRAY_H | 
|  |  | 
|  | #define ARRAY_INITIALIZER { NULL, 0, 0 } | 
|  |  | 
|  | #define ARRAY_DECL(n, c)						\ | 
|  | struct n {							\ | 
|  | c	*list;						\ | 
|  | u_int	 num;						\ | 
|  | size_t	 space;						\ | 
|  | } | 
|  |  | 
|  | #define ARRAY_ITEM(a, i) ((a)->list[i]) | 
|  | #define ARRAY_ITEMSIZE(a) (sizeof *(a)->list) | 
|  | #define ARRAY_INITIALSPACE(a) (10 * ARRAY_ITEMSIZE(a)) | 
|  |  | 
|  | #define ARRAY_ENSURE(a, n) do {						\ | 
|  | if (UINT_MAX - (n) < (a)->num)					\ | 
|  | fatalx("number too big");				\ | 
|  | if (SIZE_MAX / ((a)->num + (n)) < ARRAY_ITEMSIZE(a))		\ | 
|  | fatalx("size too big");					\ | 
|  | if ((a)->space == 0) {						\ | 
|  | (a)->space = ARRAY_INITIALSPACE(a);			\ | 
|  | (a)->list = xrealloc((a)->list, 1, (a)->space);		\ | 
|  | }								\ | 
|  | while ((a)->space <= ((a)->num + (n)) * ARRAY_ITEMSIZE(a)) {	\ | 
|  | (a)->list = xrealloc((a)->list, 2, (a)->space);		\ | 
|  | (a)->space *= 2;					\ | 
|  | }								\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_EMPTY(a) (((void *) (a)) == NULL || (a)->num == 0) | 
|  | #define ARRAY_LENGTH(a) ((a)->num) | 
|  | #define ARRAY_DATA(a) ((a)->list) | 
|  |  | 
|  | #define ARRAY_FIRST(a) ARRAY_ITEM(a, 0) | 
|  | #define ARRAY_LAST(a) ARRAY_ITEM(a, (a)->num - 1) | 
|  |  | 
|  | #define ARRAY_INIT(a) do {						\ | 
|  | (a)->num = 0;							\ | 
|  | (a)->list = NULL;		 				\ | 
|  | (a)->space = 0;							\ | 
|  | } while (0) | 
|  | #define ARRAY_CLEAR(a) do {						\ | 
|  | (a)->num = 0;							\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_SET(a, i, s) do {						\ | 
|  | (a)->list[i] = s;						\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_ADD(a, s) do {						\ | 
|  | ARRAY_ENSURE(a, 1);						\ | 
|  | (a)->list[(a)->num] = s;					\ | 
|  | (a)->num++;							\ | 
|  | } while (0) | 
|  | #define ARRAY_INSERT(a, i, s) do {					\ | 
|  | ARRAY_ENSURE(a, 1);						\ | 
|  | if ((i) < (a)->num) {						\ | 
|  | memmove((a)->list + (i) + 1, (a)->list + (i), 		\ | 
|  | ARRAY_ITEMSIZE(a) * ((a)->num - (i)));		\ | 
|  | }								\ | 
|  | (a)->list[i] = s;						\ | 
|  | (a)->num++;							\ | 
|  | } while (0) | 
|  | #define ARRAY_REMOVE(a, i) do {						\ | 
|  | if ((i) < (a)->num - 1) {					\ | 
|  | memmove((a)->list + (i), (a)->list + (i) + 1, 		\ | 
|  | ARRAY_ITEMSIZE(a) * ((a)->num - (i) - 1));		\ | 
|  | }								\ | 
|  | (a)->num--;							\ | 
|  | if ((a)->num == 0)						\ | 
|  | ARRAY_FREE(a);						\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_EXPAND(a, n) do {						\ | 
|  | ARRAY_ENSURE(a, n);						\ | 
|  | (a)->num += n;							\ | 
|  | } while (0) | 
|  | #define ARRAY_TRUNC(a, n) do {						\ | 
|  | if ((a)->num > n)						\ | 
|  | (a)->num -= n;				       		\ | 
|  | else								\ | 
|  | ARRAY_FREE(a);						\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_CONCAT(a, b) do {						\ | 
|  | ARRAY_ENSURE(a, (b)->num);					\ | 
|  | memcpy((a)->list + (a)->num, (b)->list, (b)->num * ARRAY_ITEMSIZE(a)); \ | 
|  | (a)->num += (b)->num;						\ | 
|  | } while (0) | 
|  |  | 
|  | #define ARRAY_FREE(a) do {						\ | 
|  | free((a)->list);						\ | 
|  | ARRAY_INIT(a);							\ | 
|  | } while (0) | 
|  | #define ARRAY_FREEALL(a) do {						\ | 
|  | ARRAY_FREE(a);							\ | 
|  | free(a);							\ | 
|  | } while (0) | 
|  |  | 
|  | #endif |