burkey.co /docs/libflint/vector
index vector
~/docs/libflint/vector.md
libflint

Vector

libflint·Data Structures

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 in elements
  • length: The number of real elements stored in the backing elements array
  • elements: The dynamic array of void * that holds the vector's members
  • destroy: Optional deallocation function for each stored payload. Typical usage is NULL for stack allocated data and free() for data created with malloc()

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 4

vec_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 4

vec_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 4

vec_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 2

vec_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)->length

vec_cap#

Returns the capacity of the vector

#define vec_cap(v) (v)->capacity