8 #define INITIAL_CAPACITY 64
11 #define CHECK(x) (void)(x)
13 #define CHECK(x) _check(x)
16 #define SWAP(x, y) do { void *swaptmp = (x); (x) = (y); (y) = swaptmp; } while (0)
28 _check(const vector *v)
31 assert(v->capacity > 0);
32 /* test that capacity is a power of two if not maxed out
33 * https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
35 if (v->capacity < SIZE_MAX)
36 assert((v->capacity & (v->capacity - 1)) == 0);
37 assert(v->length <= v->capacity);
43 vector *v = malloc(sizeof *v);
44 void **elts = malloc(INITIAL_CAPACITY * sizeof *elts);
52 .capacity = INITIAL_CAPACITY,
60 v_dtor(vector *v, dtor *elt_dtor, void *dtor_aux)
64 v->elt_dtor = elt_dtor;
65 v->dtor_aux = dtor_aux;
79 v_length(const vector *v)
81 return v ? v->length : 0;
85 v_set_length(vector *v, size_t desired)
89 if (v->elt_dtor) /* free any, if necessary */
90 for (size_t i = desired; i < v->length; i++)
91 v->elt_dtor(v->elts[i], v->dtor_aux);
92 if (v_reserve_capacity(v, desired) < desired)
94 for (size_t i = v->length; i < desired; i++)
103 v_capacity(const vector *v)
105 return v ? v->capacity : 0;
109 v_reserve_capacity(vector *v, size_t desired)
113 if (desired <= v->capacity)
115 size_t n = v->capacity;
116 /* SIZE_MAX is one less than a power of two, so if
117 * we keep looping too long we'll hit zero */
118 while (0 < n && n < desired)
122 void **enlarged = realloc(v->elts, n);
133 v_is_empty(const vector *v)
135 return v_length(v) == 0;
139 v_at(const vector *v, size_t i)
141 if (!v || i >= v->length)
147 v_first(const vector *v)
153 v_last(const vector *v)
155 /* successfully fails when length is 0 */
156 return v_at(v, v_length(v)-1);
160 v_append(vector *v, void *e)
162 return v_insert(v, v_length(v), e);
166 v_prepend(vector *v, void *e)
168 return v_insert(v, 0, e);
172 v_remove_first(vector *v)
174 return v_remove(v, 0);
178 v_remove_last(vector *v)
180 return v_remove(v, v_length(v)-1);
184 v_remove(vector *v, size_t i)
186 if (!v || i >= v->length)
188 void *elt = v->elts[i];
189 memmove(v->elts+i, v->elts+i+1, (v->length - (i+1)) * sizeof *v->elts);
197 v_insert(vector *v, size_t i, void *elt)
199 if (!v || v_reserve_capacity(v, v->length+1) < v->length+1)
201 memmove(v->elts+i+1, v->elts+i, (v->length - i) * sizeof *v->elts);
210 v_swap(vector *v, size_t i, size_t j)
212 if (!v || i >= v->length || j >= v->length)
214 SWAP(v->elts[i], v->elts[j]);
227 v_find_index(const vector *v, const void *needle,
228 comparator *cmp, void *aux)
232 for (size_t i = 0; i < v->length; i++)
233 if (cmp(v->elts[i], needle, aux) == 0)
239 v_find_last_index(const vector *v, const void *needle,
240 comparator *cmp, void *aux)
244 for (size_t i = v->length-1; i < SIZE_MAX; i--)
245 if (cmp(v->elts[i], needle, aux) == 0)
250 /* from Bentley, https://www.youtube.com/watch?v=QvgYAQzg1z8 */
252 _quicksort(vector *v, size_t lo, size_t hi,
253 comparator *cmp, void *aux)
258 for (i = lo+1; i <= hi; i++)
259 if (cmp(v->elts[i], v->elts[lo], aux) < 0)
262 SWAP(v->elts[i], v->elts[m]);
264 SWAP(v->elts[lo], v->elts[m]);
266 if (m > 0) /* avoid wrapping size_t */
267 _quicksort(v, lo, m-1, cmp, aux);
268 _quicksort(v, m+1, hi, cmp, aux);
272 v_sort(vector *v, comparator *cmp, void *aux)
276 _quicksort(v, 0, v->length-1, cmp, aux);
285 size_t n = v_length(v);
288 for (size_t i = n-1; i >= n/2; i--)
289 SWAP(v->elts[i], v->elts[n-i-1]);