From fa2a85322caf32a0e8b3d094251109df93d14d1f Mon Sep 17 00:00:00 2001 From: Francesco Date: Mon, 8 Sep 2025 23:18:30 +0200 Subject: [PATCH] feat(vector): shrink, insert, pop --- meson.build | 2 +- string/mystring.c | 4 +- test/vector/v1.c | 35 ++++++++++---- vector/myvector.c | 115 ++++++++++++++++++++++++++++++++++++++++------ vector/myvector.h | 38 +++++++++++---- 5 files changed, 158 insertions(+), 36 deletions(-) diff --git a/meson.build b/meson.build index 21e65be..3a2ecf7 100644 --- a/meson.build +++ b/meson.build @@ -2,7 +2,7 @@ project( 'testlib', 'c', version: '0.1', - default_options: ['c_std=c17'], + default_options: ['c_std=c17','warning_level=3'], ) src = files( diff --git a/string/mystring.c b/string/mystring.c index 1a3ff96..181acb2 100644 --- a/string/mystring.c +++ b/string/mystring.c @@ -355,8 +355,8 @@ void string_tolower(string_s *string) { /* Build Longest Prefix Suffix array */ static void build_lsp(int *lps, const char *substring, size_t sub_len) { - int len = 0; - int i = 1; + size_t len = 0; + size_t i = 1; while (i < sub_len) { if (substring[i] == substring[len]) { diff --git a/test/vector/v1.c b/test/vector/v1.c index 28a7657..19eda03 100644 --- a/test/vector/v1.c +++ b/test/vector/v1.c @@ -12,23 +12,38 @@ typedef struct my_elem { void test_v1() { /* Allocate a new vector */ size_t elem_size = sizeof(my_elem_s); - vector_s *v = vector_new(10, elem_size); - assert(vector_size(v) == 0); - assert(vector_cap(v) == 16); + vec_s *v = vec_new(10, elem_size); + assert(vec_size(v) == 0); + assert(vec_cap(v) == 16); /* Push an element */ my_elem_s e1 = { .age = 21, .name = "John", }; - vector_push(v, &e1); - assert(vector_size(v) == 1); + vec_push(v, &e1); + assert(vec_size(v) == 1); - /* Retrieve an element (Remember to FREE) */ - my_elem_s *e1_v = (my_elem_s *)vector_get(v, 0); - printf("name: %s, age: %d\n", e1_v->name, e1_v->age); + /* Retrieve an element (Remember to free) */ + my_elem_s *e1_v = (my_elem_s *)vec_get(v, 0); 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 */ - vector_free(v); -} \ No newline at end of file + vec_free(v); +} diff --git a/vector/myvector.c b/vector/myvector.c index a6f530a..fd7e823 100644 --- a/vector/myvector.c +++ b/vector/myvector.c @@ -20,12 +20,8 @@ static size_t next_power_two(size_t len) { return p; } -vector_s *vector_new(size_t initial_capacity, size_t element_size) { - if (initial_capacity < 0) { - return NULL; - } - - vector_s *vec = (vector_s *)malloc(sizeof(vector_s)); +vec_s *vec_new(size_t initial_capacity, size_t element_size) { + vec_s *vec = (vec_s *)malloc(sizeof(vec_s)); if (vec == NULL) { return NULL; } @@ -50,7 +46,7 @@ vector_s *vector_new(size_t initial_capacity, size_t element_size) { return vec; } -int vector_push(vector_s *vec, void *elem) { +int vec_push(vec_s *vec, void *elem) { if (vec == NULL || elem == NULL) { return -1; } @@ -62,7 +58,7 @@ int vector_push(vector_s *vec, void *elem) { if (vec->size + 1 > vec->capacity) { /* Reallocate buffer */ 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) { mtx_unlock(&vec->lock); @@ -72,7 +68,7 @@ int vector_push(vector_s *vec, void *elem) { } /* 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++; mtx_unlock(&vec->lock); @@ -80,7 +76,7 @@ int vector_push(vector_s *vec, void *elem) { return 0; } -void vector_free(vector_s *vec) { +void vec_free(vec_s *vec) { if (vec == NULL) { return; } @@ -92,7 +88,7 @@ void vector_free(vector_s *vec) { free(vec); } -size_t vector_size(vector_s *vec) { +size_t vec_size(vec_s *vec) { if (vec == NULL) { return -1; } @@ -108,7 +104,7 @@ size_t vector_size(vector_s *vec) { return size; } -size_t vector_cap(vector_s *vec) { +size_t vec_cap(vec_s *vec) { if (vec == NULL) { return -1; } @@ -124,8 +120,8 @@ size_t vector_cap(vector_s *vec) { return cap; } -void *vector_get(vector_s *vec, size_t index) { - if (vec == NULL || index < 0 || index > vec->size) { +void *vec_get(vec_s *vec, size_t index) { + if (vec == NULL || index > vec->size) { return NULL; } @@ -138,9 +134,98 @@ void *vector_get(vector_s *vec, size_t index) { 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); 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; +} diff --git a/vector/myvector.h b/vector/myvector.h index 20cb548..af8ee2a 100644 --- a/vector/myvector.h +++ b/vector/myvector.h @@ -5,21 +5,43 @@ #include #include -typedef struct vector { +typedef struct vec { void *data; size_t elem_size; size_t size; size_t capacity; mtx_t lock; -} vector_s; +} vec_s; -vector_s *vector_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); +vec_s *vec_new(size_t initial_capacity, size_t element_size); -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