feat(vector): shrink, insert, pop

This commit is contained in:
2025-09-08 23:18:30 +02:00
parent 39e6a2a6ab
commit fa2a85322c
5 changed files with 158 additions and 36 deletions

View File

@@ -2,7 +2,7 @@ project(
'testlib', 'testlib',
'c', 'c',
version: '0.1', version: '0.1',
default_options: ['c_std=c17'], default_options: ['c_std=c17','warning_level=3'],
) )
src = files( src = files(

View File

@@ -355,8 +355,8 @@ void string_tolower(string_s *string) {
/* Build Longest Prefix Suffix array */ /* Build Longest Prefix Suffix array */
static void build_lsp(int *lps, const char *substring, size_t sub_len) { static void build_lsp(int *lps, const char *substring, size_t sub_len) {
int len = 0; size_t len = 0;
int i = 1; size_t i = 1;
while (i < sub_len) { while (i < sub_len) {
if (substring[i] == substring[len]) { if (substring[i] == substring[len]) {

View File

@@ -12,23 +12,38 @@ typedef struct my_elem {
void test_v1() { void test_v1() {
/* Allocate a new vector */ /* Allocate a new vector */
size_t elem_size = sizeof(my_elem_s); size_t elem_size = sizeof(my_elem_s);
vector_s *v = vector_new(10, elem_size); vec_s *v = vec_new(10, elem_size);
assert(vector_size(v) == 0); assert(vec_size(v) == 0);
assert(vector_cap(v) == 16); assert(vec_cap(v) == 16);
/* Push an element */ /* Push an element */
my_elem_s e1 = { my_elem_s e1 = {
.age = 21, .age = 21,
.name = "John", .name = "John",
}; };
vector_push(v, &e1); vec_push(v, &e1);
assert(vector_size(v) == 1); assert(vec_size(v) == 1);
/* Retrieve an element (Remember to FREE) */ /* Retrieve an element (Remember to free) */
my_elem_s *e1_v = (my_elem_s *)vector_get(v, 0); my_elem_s *e1_v = (my_elem_s *)vec_get(v, 0);
printf("name: %s, age: %d\n", e1_v->name, e1_v->age);
free(e1_v); free(e1_v);
/* Pop last element (Remember to free) */
my_elem_s *pop = (my_elem_s *)vec_pop(v);
free(pop);
/* Insert an element */
vec_push(v, &e1);
vec_push(v, &e1);
vec_insert(v, 2, &e1);
my_elem_s last = {
.age = 33,
.name = "Last",
};
vec_push(v, &last);
my_elem_s *lastv = (my_elem_s *)vec_pop(v);
free(lastv);
/* Deallocate the vector */ /* Deallocate the vector */
vector_free(v); vec_free(v);
} }

View File

@@ -20,12 +20,8 @@ static size_t next_power_two(size_t len) {
return p; return p;
} }
vector_s *vector_new(size_t initial_capacity, size_t element_size) { vec_s *vec_new(size_t initial_capacity, size_t element_size) {
if (initial_capacity < 0) { vec_s *vec = (vec_s *)malloc(sizeof(vec_s));
return NULL;
}
vector_s *vec = (vector_s *)malloc(sizeof(vector_s));
if (vec == NULL) { if (vec == NULL) {
return NULL; return NULL;
} }
@@ -50,7 +46,7 @@ vector_s *vector_new(size_t initial_capacity, size_t element_size) {
return vec; return vec;
} }
int vector_push(vector_s *vec, void *elem) { int vec_push(vec_s *vec, void *elem) {
if (vec == NULL || elem == NULL) { if (vec == NULL || elem == NULL) {
return -1; return -1;
} }
@@ -62,7 +58,7 @@ int vector_push(vector_s *vec, void *elem) {
if (vec->size + 1 > vec->capacity) { if (vec->size + 1 > vec->capacity) {
/* Reallocate buffer */ /* Reallocate buffer */
vec->capacity = next_power_two(vec->size + 1); vec->capacity = next_power_two(vec->size + 1);
void *tmp = malloc(vec->capacity * vec->elem_size); void *tmp = realloc(vec->data, vec->capacity * vec->elem_size);
if (tmp == NULL) { if (tmp == NULL) {
mtx_unlock(&vec->lock); mtx_unlock(&vec->lock);
@@ -72,7 +68,7 @@ int vector_push(vector_s *vec, void *elem) {
} }
/* Add the new element */ /* Add the new element */
memcpy(vec->data + (vec->size * vec->elem_size), elem, vec->elem_size); memcpy((char *)vec->data + (vec->size * vec->elem_size), elem, vec->elem_size);
vec->size++; vec->size++;
mtx_unlock(&vec->lock); mtx_unlock(&vec->lock);
@@ -80,7 +76,7 @@ int vector_push(vector_s *vec, void *elem) {
return 0; return 0;
} }
void vector_free(vector_s *vec) { void vec_free(vec_s *vec) {
if (vec == NULL) { if (vec == NULL) {
return; return;
} }
@@ -92,7 +88,7 @@ void vector_free(vector_s *vec) {
free(vec); free(vec);
} }
size_t vector_size(vector_s *vec) { size_t vec_size(vec_s *vec) {
if (vec == NULL) { if (vec == NULL) {
return -1; return -1;
} }
@@ -108,7 +104,7 @@ size_t vector_size(vector_s *vec) {
return size; return size;
} }
size_t vector_cap(vector_s *vec) { size_t vec_cap(vec_s *vec) {
if (vec == NULL) { if (vec == NULL) {
return -1; return -1;
} }
@@ -124,8 +120,8 @@ size_t vector_cap(vector_s *vec) {
return cap; return cap;
} }
void *vector_get(vector_s *vec, size_t index) { void *vec_get(vec_s *vec, size_t index) {
if (vec == NULL || index < 0 || index > vec->size) { if (vec == NULL || index > vec->size) {
return NULL; return NULL;
} }
@@ -138,9 +134,98 @@ void *vector_get(vector_s *vec, size_t index) {
return NULL; return NULL;
} }
memcpy(elem, vec->data + (index * vec->elem_size), vec->elem_size); memcpy(elem, (char *)vec->data + (index * vec->elem_size), vec->elem_size);
mtx_unlock(&vec->lock); mtx_unlock(&vec->lock);
return elem; return elem;
} }
int vec_shrink(vec_s *vec) {
if (vec == NULL) {
return -1;
}
if (mtx_lock(&vec->lock) != thrd_success) {
return -1;
}
void *tmp = realloc(vec->data, vec->size);
if (tmp == NULL) {
mtx_unlock(&vec->lock);
return -1;
}
vec->data = tmp;
vec->capacity = vec->size;
mtx_unlock(&vec->lock);
return 0;
}
int vec_clear(vec_s *vec) {
if (vec == NULL) {
return -1;
}
if (mtx_lock(&vec->lock) != thrd_success) {
return -1;
}
memset(vec->data, 0, vec->size);
vec->size = 0;
mtx_unlock(&vec->lock);
return 0;
}
void *vec_pop(vec_s *vec) {
if (vec == NULL) {
return NULL;
}
if (vec->size == 0) {
return NULL;
}
if (mtx_lock(&vec->lock) != thrd_success) {
return NULL;
}
void *e = malloc(vec->elem_size);
vec->size--;
memcpy(e, (char *)vec->data + (vec->size * vec->elem_size), vec->elem_size);
mtx_unlock(&vec->lock);
return e;
}
int vec_insert(vec_s *vec, size_t index, void *value) {
if (vec == NULL || value == NULL) {
return -1;
}
if (index > vec->size) {
return -1;
}
if (vec->size + 1 > vec->capacity) {
/* No space, realloc */
void *tmp = realloc(vec->data, next_power_two(vec->size + 1));
if (tmp == NULL) {
return -1;
}
vec->data = tmp;
}
/* Shift memory and copy the new value */
size_t tmp_size = vec->size - index + 1;
memmove((char *)vec->data + (index * vec->elem_size), (char *)vec->data + ((index + 1) * vec->elem_size), tmp_size * vec->elem_size);
memcpy((char *)vec->data + (index * vec->elem_size), value, vec->elem_size);
return 0;
}

View File

@@ -5,21 +5,43 @@
#include <stdint.h> #include <stdint.h>
#include <threads.h> #include <threads.h>
typedef struct vector { typedef struct vec {
void *data; void *data;
size_t elem_size; size_t elem_size;
size_t size; size_t size;
size_t capacity; size_t capacity;
mtx_t lock; mtx_t lock;
} vector_s; } vec_s;
vector_s *vector_new(size_t initial_capacity, size_t element_size); vec_s *vec_new(size_t initial_capacity, size_t element_size);
int vector_push(vector_s *vec, void *elem);
size_t vector_size(vector_s *vec);
size_t vector_cap(vector_s *vec);
void *vector_get(vector_s *vec, size_t index); size_t vec_size(vec_s *vec);
void vector_free(vector_s *vec); size_t vec_cap(vec_s *vec);
int vec_shrink(vec_s *vec);
int vec_push(vec_s *vec, void *elem);
// free the returned value
void *vec_pop(vec_s *vec);
int vec_insert(vec_s *vec, size_t index, void *value);
// TODO
int vec_remove(vec_s *vec, size_t index);
// free the returned value
void *vec_get(vec_s *vec, size_t index);
// TODO
int vec_set(vec_s *vec, size_t index, void *value);
int vec_clear(vec_s *vec);
// void *vec_foreach(vec_s *, void (* fefn)(void *)) ??
// void *vec_sort(vec_s *, void (* sortfn)(void *a, void *b))
void vec_free(vec_s *vec);
#endif #endif