1 #ifndef GARRAY_H 2 #define GARRAY_H 3 4 /* $OpenBSD: garray.h,v 1.10 2019/12/22 16:53:40 espie Exp $ */ 5 /* Growable array implementation */ 6 7 /* 8 * Copyright (c) 2001 Marc Espie. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 23 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 struct growableArray { 33 GNode **a; /* Only used for gnodes right now */ 34 unsigned int size; /* Total max size */ 35 unsigned int n; /* Current number of members */ 36 }; 37 38 #define AppendList2Array(l1, l2) \ 39 do { \ 40 LstNode ln; \ 41 for (ln = Lst_First((l1)); ln != NULL; ln = Lst_Adv(ln))\ 42 Array_AtEnd((l2), Lst_Datum(ln)); \ 43 } while (0) 44 45 #ifdef STATS_GROW 46 #define MAY_INCREASE_STATS STAT_GROWARRAY++ 47 #else 48 #define MAY_INCREASE_STATS 49 #endif 50 51 #define Array_AtEnd(l, gn) \ 52 do { \ 53 if ((l)->n >= (l)->size) { \ 54 (l)->size *= 2; \ 55 (l)->a = ereallocarray((l)->a, \ 56 (l)->size, sizeof(struct GNode *)); \ 57 MAY_INCREASE_STATS; \ 58 } \ 59 (l)->a[(l)->n++] = (gn); \ 60 } while (0) 61 62 #define Array_Push(l, gn) Array_AtEnd(l, gn) 63 64 #define Array_Pop(l) \ 65 ((l)->n > 0 ? (l)->a[--(l)->n] : NULL) 66 67 #define Array_PushNew(l, gn) \ 68 do { \ 69 unsigned int i; \ 70 for (i = 0; i < (l)->n; i++) \ 71 if ((l)->a[i] == (gn)) \ 72 break; \ 73 if (i == (l)->n) \ 74 Array_Push(l, gn); \ 75 } while (0) 76 77 #define Array_Find(l, func, v) \ 78 do { \ 79 unsigned int i; \ 80 for (i = 0; i < (l)->n; i++) \ 81 if ((func)((l)->a[i], (v)) == 0)\ 82 break; \ 83 } while (0) 84 85 #define Array_FindP(l, func, v) \ 86 do { \ 87 unsigned int i; \ 88 for (i = 0; i < (l)->n; i++) \ 89 if ((func)(&((l)->a[i]), (v)) == 0) \ 90 break; \ 91 } while (0) 92 93 #define Array_ForEach(l, func, v) \ 94 do { \ 95 unsigned int i; \ 96 for (i = 0; i < (l)->n; i++) \ 97 (func)((l)->a[i], (v)); \ 98 } while (0) 99 100 #define Array_Every(l, func) \ 101 do { \ 102 unsigned int i; \ 103 for (i = 0; i < (l)->n; i++) \ 104 (func)((l)->a[i]); \ 105 } while (0) 106 107 #define Array_Init(l, sz) \ 108 do { \ 109 (l)->size = (sz); \ 110 (l)->n = 0; \ 111 (l)->a = ereallocarray(NULL, (l)->size, sizeof(GNode *)); \ 112 } while (0) 113 114 #define Array_Reset(l) \ 115 do { \ 116 (l)->n = 0; \ 117 } while (0) 118 119 #define Array_IsEmpty(l) ((l)->n == 0) 120 121 #endif 122