8 #define INITIAL_CAPACITY 64
11 #define CHECK(x) (void)(x)
13 #define CHECK(x) _check(x)
17 _check(const vector *v)
20 assert(v->capacity > 0);
21 /* test that capacity is a power of two if not maxed out
22 * https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
24 if (v->capacity < SIZE_MAX)
25 assert((v->capacity & (v->capacity - 1)) == 0);
26 assert(v->length <= v->capacity);
30 v_new(void (*elt_dtor)(void *))
32 vector *v = malloc(sizeof *v);
33 void **elts = malloc(INITIAL_CAPACITY * sizeof *elts);
41 .capacity = INITIAL_CAPACITY,
60 v_length(const vector *v)
62 return v ? v->length : 0;
66 v_set_length(vector *v, size_t desired)
70 if (v->elt_dtor) /* free any, if necessary */
71 for (size_t i = desired; i < v->length; i++)
72 v->elt_dtor(v->elts[i]);
73 if (!v_reserve_capacity(v, desired))
75 for (size_t i = v->length; i < desired; i++)
84 v_capacity(const vector *v)
86 return v ? v->capacity : 0;
90 v_reserve_capacity(vector *v, size_t desired)
94 if (desired <= v->capacity)
96 size_t n = v->capacity;
97 /* SIZE_MAX is one less than a power of two, so if
98 * we keep looping too long we'll hit zero */
99 while (0 < n && n < desired)
103 void **enlarged = realloc(v->elts, n);
114 v_is_empty(const vector *v)
116 return v_length(v) == 0;
120 v_at(const vector *v, size_t i)
122 if (!v || i >= v->length)
128 v_first(const vector *v)
134 v_last(const vector *v)
136 /* successfully fails when length is 0 */
137 return v_at(v, v_length(v)-1);
141 v_append(vector *v, void *e)
143 return v_insert(v, v_length(v), e);
147 v_prepend(vector *v, void *e)
149 return v_insert(v, 0, e);
153 v_remove_first(vector *v)
155 return v_remove(v, 0);
159 v_remove_last(vector *v)
161 return v_remove(v, v_length(v)-1);
165 v_remove(vector *v, size_t i)
167 if (!v || i >= v->length)
169 void *elt = v->elts[i];
170 memmove(v->elts+i, v->elts+i+1, (v->length - (i+1)) * sizeof *v->elts);
178 v_insert(vector *v, size_t i, void *elt)
180 if (!v || !v_reserve_capacity(v, v->length+1))
182 memmove(v->elts+i+1, v->elts+i, (v->length - i) * sizeof *v->elts);
191 v_swap(vector *v, size_t i, size_t j)
193 if (!v || i >= v->length || j >= v->length)
195 void *t = v->elts[i];
196 v->elts[i] = v->elts[j];
210 v_find_index(const vector *v, const void *needle,
211 int (*cmp)(const void *, const void *))
215 for (size_t i = 0; i < v->length; i++)
216 if (cmp(v->elts[i], needle) == 0)
222 v_find_last_index(const vector *v, const void *needle,
223 int (*cmp)(const void *, const void *))
227 for (size_t i = v->length-1; i < SIZE_MAX; i--)
228 if (cmp(v->elts[i], needle) == 0)
234 v_sort(vector *v, int (*cmp)(const void *, const void *))
238 qsort(v->elts, v->length, sizeof v->elts[0], cmp);
247 size_t n = v_length(v);
250 for (size_t i = n-1; i >= n/2; i--)
252 void *t = v->elts[i];
253 v->elts[i] = v->elts[n-i-1];