1 /****************************************************************************
2  * bfs                                                                      *
3  * Copyright (C) 2019-2022 Tavian Barnes <tavianator@tavianator.com>        *
4  *                                                                          *
5  * Permission to use, copy, modify, and/or distribute this software for any *
6  * purpose with or without fee is hereby granted.                           *
7  *                                                                          *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF         *
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR  *
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES   *
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN    *
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF  *
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.           *
15  ****************************************************************************/
16 
17 /**
18  * A dynamic array library.
19  *
20  * darrays are represented by a simple pointer to the array element type, like
21  * any other array.  Behind the scenes, the capacity and current length of the
22  * array are stored along with it.  NULL is a valid way to initialize an empty
23  * darray:
24  *
25  *     int *darray = NULL;
26  *
27  * To append an element to a darray, use the DARRAY_PUSH macro:
28  *
29  *     int e = 42;
30  *     if (DARRAY_PUSH(&darray, &e) != 0) {
31  *             // Report the error...
32  *     }
33  *
34  * The length can be retrieved by darray_length().  Iterating over the array
35  * works like normal arrays:
36  *
37  *     for (size_t i = 0; i < darray_length(darray); ++i) {
38  *             printf("%d\n", darray[i]);
39  *     }
40  *
41  * To free a darray, use darray_free():
42  *
43  *     darray_free(darray);
44  */
45 
46 #ifndef BFS_DARRAY_H
47 #define BFS_DARRAY_H
48 
49 #include <stddef.h>
50 
51 /**
52  * Get the length of a darray.
53  *
54  * @param da
55  *         The array in question.
56  * @return
57  *         The length of the array.
58  */
59 size_t darray_length(const void *da);
60 
61 /**
62  * @internal Use DARRAY_PUSH().
63  *
64  * Push an element into a darray.
65  *
66  * @param da
67  *         The array to append to.
68  * @param item
69  *         The item to append.
70  * @param size
71  *         The size of the item.
72  * @return
73  *         The (new) location of the array.
74  */
75 void *darray_push(void *da, const void *item, size_t size);
76 
77 /**
78  * @internal Use DARRAY_PUSH().
79  *
80  * Check if the last darray_push() call failed.
81  *
82  * @param da
83  *         The darray to check.
84  * @return
85  *         0 on success, -1 on failure.
86  */
87 int darray_check(void *da);
88 
89 /**
90  * @internal Use DARRAY_POP().
91  *
92  * Pop an element from an array.
93  *
94  * @param da
95  *         The array in question.
96  * @return
97  *         The (new) length of the array.
98  */
99 size_t darray_pop(void *da);
100 
101 /**
102  * Free a darray.
103  *
104  * @param da
105  *         The darray to free.
106  */
107 void darray_free(void *da);
108 
109 /**
110  * Push an item into a darray.
111  *
112  * @param da
113  *         The array to append to.
114  * @param item
115  *         A pointer to the item to append.
116  * @return
117  *         0 on success, -1 on failure.
118  */
119 #define DARRAY_PUSH(da, item) \
120 	(darray_check(*(da) = darray_push(*(da), (item), sizeof(**(da) = *(item)))))
121 
122 /**
123  * Pop an item from a darray.
124  *
125  * @param da
126  *         The array to pop from.
127  * @return
128  *         The popped item.
129  */
130 #define DARRAY_POP(da) \
131 	((da)[darray_pop((da))])
132 
133 #endif // BFS_DARRAY_H
134