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 if (n > SIZE_MAX / (sizeof *v->elts))
123 return v->capacity; /* realloc multiplication would overflow */
124 void **enlarged = realloc(v->elts, n * sizeof *v->elts);
135 v_is_empty(const vector *v)
137 return v_length(v) == 0;
141 v_at(const vector *v, size_t i)
143 if (!v || i >= v->length)
149 v_first(const vector *v)
155 v_last(const vector *v)
157 /* successfully fails when length is 0 */
158 return v_at(v, v_length(v)-1);
162 v_append(vector *v, void *e)
164 return v_insert(v, v_length(v), e);
168 v_prepend(vector *v, void *e)
170 return v_insert(v, 0, e);
174 v_remove_first(vector *v)
176 return v_remove(v, 0);
180 v_remove_last(vector *v)
182 return v_remove(v, v_length(v)-1);
186 v_remove(vector *v, size_t i)
188 if (!v || i >= v->length)
190 void *elt = v->elts[i];
191 memmove(v->elts+i, v->elts+i+1, (v->length - (i+1)) * sizeof *v->elts);
199 v_insert(vector *v, size_t i, void *elt)
201 if (!v || v_reserve_capacity(v, v->length+1) < v->length+1)
203 memmove(v->elts+i+1, v->elts+i, (v->length - i) * sizeof *v->elts);
212 v_swap(vector *v, size_t i, size_t j)
214 if (!v || i >= v->length || j >= v->length)
216 SWAP(v->elts[i], v->elts[j]);
229 v_find_index(const vector *v, const void *needle,
230 comparator *cmp, void *aux)
234 for (size_t i = 0; i < v->length; i++)
235 if (cmp(v->elts[i], needle, aux) == 0)
241 v_find_last_index(const vector *v, const void *needle,
242 comparator *cmp, void *aux)
246 for (size_t i = v->length-1; i < SIZE_MAX; i--)
247 if (cmp(v->elts[i], needle, aux) == 0)
252 /* from Bentley, https://www.youtube.com/watch?v=QvgYAQzg1z8 */
254 _quicksort(vector *v, size_t lo, size_t hi,
255 comparator *cmp, void *aux)
260 for (i = lo+1; i <= hi; i++)
261 if (cmp(v->elts[i], v->elts[lo], aux) < 0)
264 SWAP(v->elts[i], v->elts[m]);
266 SWAP(v->elts[lo], v->elts[m]);
268 if (m > 0) /* avoid wrapping size_t */
269 _quicksort(v, lo, m-1, cmp, aux);
270 _quicksort(v, m+1, hi, cmp, aux);
274 v_sort(vector *v, comparator *cmp, void *aux)
278 _quicksort(v, 0, v->length-1, cmp, aux);
287 size_t n = v_length(v);
290 for (size_t i = n-1; i >= n/2; i--)
291 SWAP(v->elts[i], v->elts[n-i-1]);