commit - b7a1d3fcb52c4517db8f3bd9fe6c242078e4bd24
commit + 5256e868ed7f0d40ccaf480bd903ef722df4a052
blob - aa3d3a9f05645beee2c1a4c390185747da6bcb99
blob + ba38adb6678861381669e0b59ea2d874f47eb8ad
--- include/lfvector.h
+++ include/lfvector.h
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
#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);
}
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
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();