MULE
0.0.1
Multi-Use Library Essentials
Toggle main menu visibility
Loading...
Searching...
No Matches
arr.h
1
#pragma once
2
/**
3
* @defgroup mod_arr Arr
4
* @brief A growable array of any element type.
5
*
6
* Arr(T) is a struct with the same layout and rules as a Str, for any
7
* element type. The operations are macros, because only a macro can work
8
* for every `T`.
9
*
10
* @snippet{trimleft} test_arr.c arr
11
*
12
* - Name each array type once with a typedef: `typedef Arr(int) IntArr;`.
13
* Every spelling of `Arr(...)` is a distinct type, so use the name.
14
* - A zero-initialised array (`IntArr xs = { 0 };`) is valid, empty, and
15
* owns no memory.
16
* - The fields are `data`, `len`, `capacity` and `alloc`, where a null
17
* `alloc` means the libc heap. Index `data` directly to read and write
18
* elements, and pass it to qsort or memcpy.
19
* - Calls that may allocate return `bool`. On false the array is
20
* unchanged.
21
* - Growing may move `data`, so pointers into it do not survive arr_push(),
22
* arr_insert() or arr_reserve().
23
*
24
* @warning The macros evaluate the array argument more than once. Pass a
25
* variable or a plain pointer, never an expression with side effects.
26
* @{
27
*/
28
29
#include "base/base.h"
30
#include "mem/mem.h"
31
32
#include <assert.h>
33
#include <string.h>
34
35
/** A growable array of @p T. Declare it with a typedef before use. */
36
#define Arr(T) \
37
struct { \
38
T *data; \
39
size_t len; \
40
size_t capacity; \
41
const Allocator *alloc; \
42
}
43
44
/** @name Growing
45
* Add elements. Each call may move `data`.
46
* @{ */
47
48
/** Make room for @p n more elements without another allocation.
49
* @return False when out of memory or the size overflows. The array is
50
* then unchanged. */
51
#define arr_reserve(a, n) \
52
arr_reserve_(&(a)->data, &(a)->capacity, (a)->len, (n), sizeof *(a)->data, \
53
(a)->alloc)
54
55
/** Append @p v. @p v is evaluated after any growth and before `len`
56
* changes, so it may read the array itself, as in `arr_push(&xs,
57
* xs.data[0])` or `arr_push(&xs, xs.len)`.
58
* @return False when out of memory. The array is then unchanged. */
59
#define arr_push(a, v) \
60
(arr_reserve((a), 1) ? ((a)->data[(a)->len] = (v), (a)->len++, true) \
61
: false)
62
63
/** Insert @p v before index @p i, shifting the rest up. @p i may equal len.
64
* @return False when out of memory. The array is then unchanged.
65
* @pre `i <= len`. An assert checks it. */
66
#define arr_insert(a, i, v) \
67
(assert(arr_index_ok_((i), (a)->len)), \
68
arr_reserve((a), 1) ? (memmove((a)->data + (i) + 1, (a)->data + (i), \
69
((a)->len - (i)) * sizeof *(a)->data), \
70
(a)->data[(i)] = (v), (a)->len++, true) \
71
: false)
72
73
/** @} */
74
75
/** @name Shrinking
76
* Remove elements. None of these allocate or move `data`.
77
* @{ */
78
79
/** Remove the element at index @p i, shifting the rest down.
80
* @pre `i < len`. An assert checks it. */
81
#define arr_remove(a, i) \
82
(assert((i) < (a)->len), \
83
memmove((a)->data + (i), (a)->data + (i) + 1, \
84
((a)->len - (i) - 1) * sizeof *(a)->data), \
85
(void)(a)->len--)
86
87
/** Remove and return the last element.
88
* @pre The array is not empty. An assert checks it. */
89
#define arr_pop(a) (assert((a)->len > 0), (a)->data[--(a)->len])
90
91
/** Set the length to zero. Keeps the allocation for reuse. */
92
#define arr_clear(a) ((void)((a)->len = 0))
93
94
/** Free the elements' memory and reset to empty. Keeps `alloc`, and is safe
95
* to call twice. */
96
#define arr_free(a) \
97
(arr_free_(&(a)->data, (a)->capacity * sizeof *(a)->data, (a)->alloc), \
98
(a)->len = 0, (void)((a)->capacity = 0))
99
100
/** @} */
101
102
/** @cond */
103
/* A function, so a literal 0 index does not trip gcc's -Wtype-limits. */
104
static
inline
bool
arr_index_ok_(
size_t
i,
size_t
len) {
105
return
i <= len;
106
}
107
108
MULE_NODISCARD
bool
arr_reserve_(
void
*data_field,
size_t
*capacity,
size_t
len,
109
size_t
add,
size_t
elem,
110
const
Allocator
*alloc);
111
void
arr_free_(
void
*data_field,
size_t
bytes,
const
Allocator
*alloc);
112
/** @endcond */
113
114
/** @} */
Allocator
Where a module gets its memory.
Definition
mem.h:56
src
arr
arr.h
Generated by
1.18.0