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)
23 void (*elt_dtor)(void *);
27 _check(const vector *v)
30 assert(v->capacity > 0);
31 /* test that capacity is a power of two if not maxed out
32 * https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
34 if (v->capacity < SIZE_MAX)
35 assert((v->capacity & (v->capacity - 1)) == 0);
36 assert(v->length <= v->capacity);
40 v_new(void (*elt_dtor)(void *))
42 vector *v = malloc(sizeof *v);
43 void **elts = malloc(INITIAL_CAPACITY * sizeof *elts);
51 .capacity = INITIAL_CAPACITY,
70 v_length(const vector *v)
72 return v ? v->length : 0;
76 v_set_length(vector *v, size_t desired)
80 if (v->elt_dtor) /* free any, if necessary */
81 for (size_t i = desired; i < v->length; i++)
82 v->elt_dtor(v->elts[i]);
83 if (v_reserve_capacity(v, desired) < desired)
85 for (size_t i = v->length; i < desired; i++)
94 v_capacity(const vector *v)
96 return v ? v->capacity : 0;
100 v_reserve_capacity(vector *v, size_t desired)
104 if (desired <= v->capacity)
106 size_t n = v->capacity;
107 /* SIZE_MAX is one less than a power of two, so if
108 * we keep looping too long we'll hit zero */
109 while (0 < n && n < desired)
113 void **enlarged = realloc(v->elts, n);
124 v_is_empty(const vector *v)
126 return v_length(v) == 0;
130 v_at(const vector *v, size_t i)
132 if (!v || i >= v->length)
138 v_first(const vector *v)
144 v_last(const vector *v)
146 /* successfully fails when length is 0 */
147 return v_at(v, v_length(v)-1);
151 v_append(vector *v, void *e)
153 return v_insert(v, v_length(v), e);
157 v_prepend(vector *v, void *e)
159 return v_insert(v, 0, e);
163 v_remove_first(vector *v)
165 return v_remove(v, 0);
169 v_remove_last(vector *v)
171 return v_remove(v, v_length(v)-1);
175 v_remove(vector *v, size_t i)
177 if (!v || i >= v->length)
179 void *elt = v->elts[i];
180 memmove(v->elts+i, v->elts+i+1, (v->length - (i+1)) * sizeof *v->elts);
188 v_insert(vector *v, size_t i, void *elt)
190 if (!v || v_reserve_capacity(v, v->length+1) < v->length+1)
192 memmove(v->elts+i+1, v->elts+i, (v->length - i) * sizeof *v->elts);
201 v_swap(vector *v, size_t i, size_t j)
203 if (!v || i >= v->length || j >= v->length)
205 SWAP(v->elts[i], v->elts[j]);
218 v_find_index(const vector *v, const void *needle,
219 comparator *cmp, void *aux)
223 for (size_t i = 0; i < v->length; i++)
224 if (cmp(v->elts[i], needle, aux) == 0)
230 v_find_last_index(const vector *v, const void *needle,
231 comparator *cmp, void *aux)
235 for (size_t i = v->length-1; i < SIZE_MAX; i--)
236 if (cmp(v->elts[i], needle, aux) == 0)
241 /* from Bentley, https://www.youtube.com/watch?v=QvgYAQzg1z8 */
243 _quicksort(vector *v, size_t lo, size_t hi,
244 comparator *cmp, void *aux)
249 for (i = lo+1; i <= hi; i++)
250 if (cmp(v->elts[i], v->elts[lo], aux) < 0)
253 SWAP(v->elts[i], v->elts[m]);
255 SWAP(v->elts[lo], v->elts[m]);
257 if (m > 0) /* avoid wrapping size_t */
258 _quicksort(v, lo, m-1, cmp, aux);
259 _quicksort(v, m+1, hi, cmp, aux);
263 v_sort(vector *v, comparator *cmp, void *aux)
267 _quicksort(v, 0, v->length-1, cmp, aux);
276 size_t n = v_length(v);
279 for (size_t i = n-1; i >= n/2; i--)
281 void *t = v->elts[i];
282 v->elts[i] = v->elts[n-i-1];