root/usr.bin/make/garray.h
#ifndef GARRAY_H
#define GARRAY_H

/* $OpenBSD: garray.h,v 1.10 2019/12/22 16:53:40 espie Exp $ */
/* Growable array implementation */

/*
 * Copyright (c) 2001 Marc Espie.
 *
 * 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 OPENBSD PROJECT 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 OPENBSD
 * PROJECT 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.
 */

struct growableArray {
        GNode        **a;       /* Only used for gnodes right now */
        unsigned int size;      /* Total max size */
        unsigned int n;         /* Current number of members */
};

#define AppendList2Array(l1, l2)                                \
do {                                                            \
        LstNode ln;                                             \
        for (ln = Lst_First((l1)); ln != NULL; ln = Lst_Adv(ln))\
                Array_AtEnd((l2), Lst_Datum(ln));               \
} while (0)

#ifdef STATS_GROW
#define MAY_INCREASE_STATS      STAT_GROWARRAY++
#else
#define MAY_INCREASE_STATS
#endif

#define Array_AtEnd(l, gn)                              \
do {                                                    \
        if ((l)->n >= (l)->size) {                      \
                (l)->size *= 2;                         \
                (l)->a = ereallocarray((l)->a,          \
                    (l)->size, sizeof(struct GNode *)); \
                MAY_INCREASE_STATS;                     \
        }                                               \
        (l)->a[(l)->n++] = (gn);                        \
} while (0)

#define Array_Push(l, gn)       Array_AtEnd(l, gn)

#define Array_Pop(l) \
        ((l)->n > 0 ?  (l)->a[--(l)->n] : NULL)

#define Array_PushNew(l, gn) \
do {                                            \
        unsigned int i;                         \
        for (i = 0; i < (l)->n; i++)            \
                if ((l)->a[i] == (gn))          \
                    break;                      \
        if (i == (l)->n)                        \
                Array_Push(l, gn);              \
} while (0)

#define Array_Find(l, func, v)                  \
do {                                            \
        unsigned int i;                         \
        for (i = 0; i < (l)->n; i++)            \
                if ((func)((l)->a[i], (v)) == 0)\
                        break;                  \
} while (0)

#define Array_FindP(l, func, v)                         \
do {                                                    \
        unsigned int i;                                 \
        for (i = 0; i < (l)->n; i++)                    \
                if ((func)(&((l)->a[i]), (v)) == 0)     \
                        break;                          \
} while (0)

#define Array_ForEach(l, func, v)               \
do {                                            \
        unsigned int i;                         \
        for (i = 0; i < (l)->n; i++)            \
                (func)((l)->a[i], (v));         \
} while (0)

#define Array_Every(l, func)                    \
do {                                            \
        unsigned int i;                         \
        for (i = 0; i < (l)->n; i++)            \
                (func)((l)->a[i]);              \
} while (0)

#define Array_Init(l, sz)                               \
do {                                                    \
        (l)->size = (sz);                               \
        (l)->n = 0;                                     \
        (l)->a = ereallocarray(NULL, (l)->size, sizeof(GNode *));       \
} while (0)

#define Array_Reset(l)          \
do {                            \
        (l)->n = 0;             \
} while (0)

#define Array_IsEmpty(l)        ((l)->n == 0)

#endif