Vector
A dynamic array of void * values.
Usage
Initialize a Vector with an optional payload destructor. Pass NULL for stack allocated data. The vector stores pointers without copying the payloads.
Vector vec;
if (vec_init(&vec, NULL) == 0) {
int value = 42;
if (vec_push(&vec, &value) == 0) {
int *stored = vec_safe_at(&vec, 0);
/* stored points to value. */
(void)stored;
}
vec_destroy(&vec);
}
vec_destroy frees the backing array and calls the destructor on remaining payloads. The Vector handle is yours to free if you allocated it. Removing or popping a payload transfers it to the caller without running the destructor.
Structs
Vector
Vector struct
typedef struct Vector {
size_t capacity;
size_t length;
void **elements;
void (*destroy)(void *data);
} Vector;
Members:
capacity: The number of pointer slots allocated inelementslength: The number of real elements stored in the backingelementsarrayelements: The dynamic array ofvoid *that holds the vector's membersdestroy: Optional deallocation function for each stored payload. Typical usage isNULLfor stack allocated data andfree()for data created withmalloc()
Functions
vec_init
Initialize the vector with a default capacity of 2. Call vec_destroy() when finished. Returns 0 on success, -1 on error.
int vec_init(Vector *vec, void (*destroy)(void *data));vec_init_with_capacity
Initialize the vector with a user-specified capacity. capacity == 0 is allowed: elements is NULL and the first insert grows from the default capacity. Failed init leaves a destroyable empty vector (capacity == 0, elements == NULL). Returns 0 on success, -1 on error.
int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t cap);vec_destroy
Frees the underlying array inside a Vector. If destroy was provided when creating the vector, then it is called against each element in the array before the array is freed. Does not destroy the vector itself, that is left up to the user. Zeros the handle so a second vec_destroy is a no-op.
void vec_destroy(Vector *vec);
/* Usage */
vec_destroy(vec);
free(vec);vec_clear
Destroys all elements in the vector (calling destroy on each if provided) and sets length to 0. Capacity and the backing array are kept. Returns 0 on success, -1 on error.
int vec_clear(Vector *vec);vec_grow_to
Grows the capacity of the vector to new_cap. Returns -1 if new_cap is less than the current capacity. Returns 0 without reallocating when new_cap equals the current capacity. Returns -1 on allocation failure, overflow, or a NULL vector. Failure leaves the vector unchanged.
int vec_grow_to(Vector *vec, const size_t new_cap);vec_reserve
Ensure the vector can hold at least n elements. Returns 0 when n is already within capacity or growth succeeds, -1 on a NULL vector, overflow, or allocation failure. Failure leaves the vector unchanged.
int vec_reserve(Vector *vec, size_t n);vec_insert
Insert data into the vector at a specified index. The index may range from 0 through the current length, inclusive. Elements at that index and beyond move up to make room. Returns 0 on success, -1 on invalid arguments or allocation failure.
int vec_insert(Vector *vec, void *data, size_t index);
/* Usage */
// vec: 1 2 3 4
int i = 99;
vec_insert(vec, &i, 2);
// vec: 1 2 99 3 4vec_push
Insert data at the end of the vector. Returns 0 on success, -1 on error.
int vec_push(Vector *vec, void *data);
/* Usage */
// vec: 1 2 3
int i = 4;
vec_push(vec, &i); /* Keep i alive while stored; use a NULL destructor. */
// vec: 1 2 3 4vec_safe_at
Gets the stored data at a specified index. Uses safety checks to make sure index is not out of bounds. Returns NULL if the index is out of bounds or the stored payload is NULL. The vector must be non-NULL.
void *vec_safe_at(Vector *vec, size_t index);vec_remove
Removes an element from the array and returns the pointer, then shifts later elements down to close the gap. Does not call the destructor or change capacity. Returns NULL if the index is not valid or the removed payload is NULL.
void *vec_remove(Vector *vec, size_t index);
/* Usage */
// vec: 1 2 3 4
int *t = NULL;
t = (int*)vec_remove(vec, 2);
assert(*t == 3);
// vec: 1 2 4vec_shrink
Shrinks capacity to the current length. An empty vector releases its backing array. Returns 0 on success, -1 on allocation failure.
int vec_shrink(Vector *vec);vec_min
Finds the smallest value in the vector and returns a void pointer to the underlying data. Returns NULL if the vector is empty. Requires a comparison function to compare the data in the vector. The comparator receives payload pointers directly and must return a positive value if a > b, a negative value if a < b, or 0 if equal. See the supplied comparison functions below for reference.
const void *vec_min(const Vector *vec, int(*cmp)(const void *a, const void *b));vec_max
Finds the largest value in the vector and returns a void pointer to the underlying data. Returns NULL if the vector is empty. Requires a comparison function to compare the data in the vector. The comparator receives payload pointers directly and must return a positive value if a > b, a negative value if a < b, or 0 if equal. See the supplied comparison functions below for reference.
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));vec_pop
Removes and returns the last element of the vector. Does not call the destructor. Returns NULL if the vector is empty or the removed payload is NULL.
void *vec_pop(Vector *vec);
/* Usage */
// vec: 1 2 3
int *t = (int *)vec_pop(vec);
assert(*t == 3);
// vec: 1 2vec_reverse
Reverses the order of elements in the vector in-place. O(n) time, O(1) space.
void vec_reverse(Vector *vec);vec_sort
Sorts the vector in-place using qsort_r. The comparator receives payload pointers directly, not pointers to array slots. Concurrent mutation of the same vector is not supported. Requires a comparator function that returns a negative value if a < b, 0 if a == b, or a positive value if a > b. See the supplied comparison functions below for reference.
void vec_sort(Vector *vec, int (*cmp)(const void *a, const void *b));
/* Usage */
vec_sort(vec, vec_cmp_int);vec_bsearch
Binary search on a sorted vector. Returns a pointer to the matching element's data, or NULL if not found. The vector must be sorted by the same comparator before calling this function.
void *vec_bsearch(Vector *vec, const void *key, int (*cmp)(const void *a, const void *b));
/* Usage */
vec_sort(vec, vec_cmp_int);
int key = 3;
int *found = (int *)vec_bsearch(vec, &key, vec_cmp_int);Comparison Functions
Comparison functions to compare data in a vector. The supplied functions return 1 if a > b, -1 if a < b, or 0 if equal. Custom comparators may return any positive or negative value.
int vec_cmp_int(const void *a, const void *b);
int vec_cmp_char(const void *a, const void *b);Macros
vec_at
Grabs the element at index i without safety checks for better performance. Use with caution
#define vec_at(v, i) (v)->elements[(i)]vec_len
Returns the length of the vector
#define vec_len(v) (v)->lengthvec_cap
Returns the capacity of the vector
#define vec_cap(v) (v)->capacity