9 #define INITIAL_CAPACITY 64
12 #define CHECK(x) (void)(x)
14 #define CHECK(x) _check(x)
18 _check(const vector *v)
21 assert(v->capacity > 0);
22 /* test that capacity is a power of two if not maxed out
23 * https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
25 if (v->capacity < SIZE_MAX)
26 assert((v->capacity & (v->capacity - 1)) == 0);
27 assert(v->length <= v->capacity);
28 assert(v->length < SIZE_MAX);
32 v_new(void (*elt_dtor)(void *))
34 vector *v = malloc(sizeof *v);
35 void **elts = malloc(INITIAL_CAPACITY * sizeof *elts);
43 .capacity = INITIAL_CAPACITY,
62 v_length(const vector *v)
64 return v ? v->length : SIZE_MAX;
68 v_set_length(vector *v, size_t len)
70 if (!v || len == SIZE_MAX)
72 if (v->elt_dtor) /* free any, if necessary */
73 for (size_t i = len; i < v->length; i++)
74 v->elt_dtor(v->elts[i]);
75 if (!v_reserve_capacity(v, len))
77 for (size_t i = v->length; i < len; i++)
86 v_capacity(const vector *v)
88 return v ? v->capacity : 0;
92 v_reserve_capacity(vector *v, size_t desired)
96 if (desired <= v->capacity)
98 size_t n = v->capacity;
99 /* SIZE_MAX is one less than a power of two, so if
100 * we keep looping too long we'll hit zero */
101 while (0 < n && n < desired)
105 void **enlarged = realloc(v->elts, n);
116 v_is_empty(const vector *v)
118 return v_length(v) == 0;
122 v_at(const vector *v, size_t i)
124 if (!v || i >= v->length)
133 v_first(const vector *v)
139 v_last(const vector *v)
141 /* when length is 0, length-1 is SIZE_MAX */
142 return v_at(v, v_length(v)-1);
146 v_append(vector *v, void *e)
148 return v_insert(v, v_length(v), e);
152 v_prepend(vector *v, void *e)
154 return v_insert(v, 0, e);
158 v_remove_first(vector *v)
160 return v_remove(v, 0, 1);
164 v_remove_last(vector *v)
166 return v_remove(v, v_length(v)-1, 1);
170 v_insert(vector *v, size_t i, void *elt)
172 if (!v || !v_reserve_capacity(v, v->length+1))
174 memmove(v->elts+i+1, v->elts+i, (v->length - i) * sizeof *v->elts);
183 v_swap(vector *v, size_t i, size_t j)
185 if (!v || i >= v->length || j >= v->length)
187 void *t = v->elts[i];
188 v->elts[i] = v->elts[j];
202 v_find_index(const vector *v, const void *needle,
203 int (*cmp)(const void *, const void *))
207 for (size_t i = 0; i < v->length; i++)
208 if (cmp(v->elts[i], needle) == 0)
214 v_find_last_index(const vector *v, const void *needle,
215 int (*cmp)(const void *, const void *))
219 for (size_t i = v->length-1; i < SIZE_MAX; i--)
220 if (cmp(v->elts[i], needle) == 0)
226 v_sort(vector *v, int (*cmp)(const void *, const void *))
230 qsort(v->elts, v->length, sizeof v->elts[0], cmp);