commit 5256e868ed7f0d40ccaf480bd903ef722df4a052 from: Evan Burkey date: Sat Mar 14 06:15:10 2026 UTC add vec_pop, vec_reverse, vec_sort, vec_bsearch to vector module commit - b7a1d3fcb52c4517db8f3bd9fe6c242078e4bd24 commit + 5256e868ed7f0d40ccaf480bd903ef722df4a052 blob - aa3d3a9f05645beee2c1a4c390185747da6bcb99 blob + ba38adb6678861381669e0b59ea2d874f47eb8ad --- include/lfvector.h +++ include/lfvector.h @@ -34,6 +34,14 @@ const void *vec_min(const Vector *vec, int(*cmp)(const const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b)); +void *vec_pop(Vector *vec); + +void vec_reverse(Vector *vec); + +void vec_sort(Vector *vec, int (*cmp)(const void *a, const void *b)); + +void *vec_bsearch(Vector *vec, const void *key, int (*cmp)(const void *a, const void *b)); + int vec_cmp_int(const void *a, const void *b); int vec_cmp_char(const void *a, const void *b); blob - 86f65c6f6b4f52c38a382ae4a35ab935d0a45eb9 blob + 4fcf4f00c195c3b8f19fab2c186ffad1ee7d1aa9 --- src/vector.c +++ src/vector.c @@ -13,6 +13,8 @@ #define VEC_INIT_CAP 2 +static int (*vec_sort_cmp_fn)(const void *, const void *); + int vec_init(Vector *vec, void (*destroy)(void *data)) { return vec_init_with_capacity(vec, destroy, VEC_INIT_CAP); } @@ -178,6 +180,57 @@ const void *vec_max(const Vector *vec, int(*cmp)(const return a; } +void *vec_pop(Vector *vec) { + if (vec_len(vec) == 0) { + return NULL; + } + return vec_remove(vec, vec_len(vec) - 1); +} + +void vec_reverse(Vector *vec) { + size_t lo = 0; + size_t hi = vec_len(vec); + while (lo + 1 < hi) { + --hi; + void *tmp = vec->elements[lo]; + vec->elements[lo] = vec->elements[hi]; + vec->elements[hi] = tmp; + ++lo; + } +} + +static int vec_sort_cmp_wrapper(const void *a, const void *b) { + /* qsort passes pointers to elements; our elements are void*, so a is void** */ + const void *ea = *(const void **)a; + const void *eb = *(const void **)b; + return vec_sort_cmp_fn(ea, eb); +} + +void vec_sort(Vector *vec, int (*cmp)(const void *a, const void *b)) { + if (vec_len(vec) < 2) { + return; + } + vec_sort_cmp_fn = cmp; + qsort(vec->elements, vec_len(vec), sizeof(void *), vec_sort_cmp_wrapper); +} + +void *vec_bsearch(Vector *vec, const void *key, int (*cmp)(const void *a, const void *b)) { + size_t lo = 0; + size_t hi = vec_len(vec); + while (lo < hi) { + size_t mid = lo + (hi - lo) / 2; + int r = cmp(key, vec->elements[mid]); + if (r == 0) { + return vec->elements[mid]; + } else if (r < 0) { + hi = mid; + } else { + lo = mid + 1; + } + } + return NULL; +} + int vec_cmp_int(const void *a, const void *b) { const int x = *(int*)a; const int y = *(int*)b; blob - efca273644b392b0885d8e9f10840b81d4e34dc7 blob + 104b6f1acfc1c7a060396ba8ebc70626d3995941 --- tests/test_vector.c +++ tests/test_vector.c @@ -56,6 +56,80 @@ int main() { ASSERT_EQ(vec_len(v), 0); vec_destroy(v); + + /* vec_pop */ + vec_init(v, NULL); + int p1 = 10, p2 = 20, p3 = 30; + vec_push(v, &p1); + vec_push(v, &p2); + vec_push(v, &p3); + + int *popped = vec_pop(v); + ASSERT_EQ(*popped, 30); + ASSERT_EQ(vec_len(v), 2); + + popped = vec_pop(v); + ASSERT_EQ(*popped, 20); + + popped = vec_pop(v); + ASSERT_EQ(*popped, 10); + ASSERT_EQ(vec_len(v), 0); + + popped = vec_pop(v); + ASSERT_NULL(popped); + + vec_destroy(v); + + /* vec_reverse */ + vec_init(v, NULL); + int r1 = 1, r2 = 2, r3 = 3, r4 = 4; + vec_push(v, &r1); + vec_push(v, &r2); + vec_push(v, &r3); + vec_push(v, &r4); + + vec_reverse(v); + ASSERT_EQ(*(int *)vec_at(v, 0), 4); + ASSERT_EQ(*(int *)vec_at(v, 1), 3); + ASSERT_EQ(*(int *)vec_at(v, 2), 2); + ASSERT_EQ(*(int *)vec_at(v, 3), 1); + + /* reverse odd-length */ + vec_pop(v); + vec_reverse(v); + ASSERT_EQ(*(int *)vec_at(v, 0), 2); + ASSERT_EQ(*(int *)vec_at(v, 1), 3); + ASSERT_EQ(*(int *)vec_at(v, 2), 4); + + vec_destroy(v); + + /* vec_sort */ + vec_init(v, NULL); + int s1 = 5, s2 = 1, s3 = 3, s4 = 2, s5 = 4; + vec_push(v, &s1); + vec_push(v, &s2); + vec_push(v, &s3); + vec_push(v, &s4); + vec_push(v, &s5); + + vec_sort(v, vec_cmp_int); + ASSERT_EQ(*(int *)vec_at(v, 0), 1); + ASSERT_EQ(*(int *)vec_at(v, 1), 2); + ASSERT_EQ(*(int *)vec_at(v, 2), 3); + ASSERT_EQ(*(int *)vec_at(v, 3), 4); + ASSERT_EQ(*(int *)vec_at(v, 4), 5); + + /* vec_bsearch on sorted vector */ + int key = 3; + int *found = vec_bsearch(v, &key, vec_cmp_int); + ASSERT_NOT_NULL(found); + ASSERT_EQ(*found, 3); + + int missing = 99; + found = vec_bsearch(v, &missing, vec_cmp_int); + ASSERT_NULL(found); + + vec_destroy(v); free(v); TEST_REPORT();