From 610bf5dab9c60ab7dbdeb4d2e25e6978a64c5e6b Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 10 Sep 2025 16:45:50 +0200 Subject: [PATCH] feat: add stack --- README.md | 1 + meson.build | 2 ++ stack/mystack.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ stack/mystack.h | 25 ++++++++++++++ test/stack/s1.c | 23 +++++++++++++ test/test.c | 19 ++++++---- test/vector/v1.c | 9 ++--- vector/myvector.c | 6 ++++ 8 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 stack/mystack.c create mode 100644 stack/mystack.h create mode 100644 test/stack/s1.c diff --git a/README.md b/README.md index e42828d..4877a47 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ A small, personal C library for learning and experimentation. - Thread-safe dynamic strings - Thread-safe circular queues - Thread-safe vectors +- Stack ## Usage diff --git a/meson.build b/meson.build index 0306485..58abcc0 100644 --- a/meson.build +++ b/meson.build @@ -10,6 +10,7 @@ src = files( 'queue/myqueue.c', 'string/mystring.c', 'vector/myvector.c', + 'stack/mystack.c', ) testlib = files( @@ -20,6 +21,7 @@ testlib = files( 'test/string/str2.c', 'test/string/str3.c', 'test/vector/v1.c', + 'test/stack/s1.c', ) sources = src + testlib diff --git a/stack/mystack.c b/stack/mystack.c new file mode 100644 index 0000000..6241d2e --- /dev/null +++ b/stack/mystack.c @@ -0,0 +1,88 @@ +#include "mystack.h" + +#include +#include + +stack_s *stack_new(size_t initial_capacity, size_t element_size) { + if (element_size == 0) { + return NULL; + } + + stack_s *stack = (stack_s *)malloc(sizeof(stack_s)); + if (stack == NULL) { + return NULL; + } + + if (mtx_init(&stack->lock, mtx_recursive) != thrd_success) { + free(stack); + return NULL; + } + + /* Allocate the vec data */ + stack->data = vec_new(initial_capacity, element_size); + if (stack->data == NULL) { + free(stack); + return NULL; + } + + stack->elem_size = element_size; + + return stack; +} + +void *stack_pop(stack_s *stack) { + if (stack == NULL) { + return NULL; + } + + if (mtx_lock(&stack->lock) != thrd_success) { + return NULL; + } + + void *elem = vec_pop(stack->data); + + mtx_unlock(&stack->lock); + + return elem; +} + +int stack_push(stack_s *stack, void *elem) { + if (stack == NULL || elem == NULL) { + return -1; + } + + if (mtx_lock(&stack->lock) != thrd_success) { + return -1; + } + + int ret = vec_push(stack->data, elem); + + mtx_unlock(&stack->lock); + + return ret; +} + +void *stack_top(stack_s *stack) { + if (stack == NULL) { + return NULL; + } + + if (mtx_lock(&stack->lock) != thrd_success) { + return NULL; + } + + void *elem = vec_get(stack->data, stack->data->size - 1); + + mtx_unlock(&stack->lock); + + return elem; +} + +void stack_free(stack_s *stack) { + if (stack == NULL) { + return; + } + + vec_free(stack->data); + free(stack); +} diff --git a/stack/mystack.h b/stack/mystack.h new file mode 100644 index 0000000..77aef76 --- /dev/null +++ b/stack/mystack.h @@ -0,0 +1,25 @@ +#ifndef MYCLIB_STACK_H +#define MYCLIB_STACK_H + +#include +#include + +#include "../vector/myvector.h" + +typedef struct stack { + vec_s *data; + size_t elem_size; + mtx_t lock; +} stack_s; + +stack_s *stack_new(size_t initial_capacity, size_t element_size); + +void *stack_pop(stack_s *stack); + +int stack_push(stack_s *stack, void *elem); + +void *stack_top(stack_s *stack); + +void stack_free(stack_s *stack); + +#endif diff --git a/test/stack/s1.c b/test/stack/s1.c new file mode 100644 index 0000000..a26902a --- /dev/null +++ b/test/stack/s1.c @@ -0,0 +1,23 @@ +#include +#include + +#include "../../stack/mystack.h" + +void test_s1(void) { + stack_s *stack = stack_new(32, sizeof(int)); + int num = 10; + stack_push(stack, &num); + + num = 13; + stack_push(stack, &num); + + int *rv = (int *)stack_top(stack); + assert(*rv == 13); + free(rv); + + rv = (int *)stack_pop(stack); + assert(*rv == 13); + free(rv); + + stack_free(stack); +} diff --git a/test/test.c b/test/test.c index e0f3b50..1d98e09 100644 --- a/test/test.c +++ b/test/test.c @@ -5,15 +5,17 @@ #include #include -void test_hm1(); +void test_hm1(void); -void test_q1(); +void test_q1(void); -void test_str1(); -void test_str2(); -void test_str3(); +void test_str1(void); +void test_str2(void); +void test_str3(void); -void test_v1(); +void test_v1(void); + +void test_s1(void); int main(void) { puts("==== [Running Hashmap tests] ===="); @@ -38,5 +40,10 @@ int main(void) { puts("OK!"); puts(""); + puts("==== [Running Stack tests] ===="); + test_s1(); + puts("OK!"); + puts(""); + return 0; } diff --git a/test/vector/v1.c b/test/vector/v1.c index b8f67a8..e3ff79c 100644 --- a/test/vector/v1.c +++ b/test/vector/v1.c @@ -1,5 +1,4 @@ #include -#include #include #include "../../vector/myvector.h" @@ -15,11 +14,12 @@ static void multiply(size_t index, void *elem) { e->age = e->age * 2; } -/* Another way to use foreach */ +/* Another way to use foreach static void print(size_t index, void *elem) { my_elem_s *e = (my_elem_s *)elem; printf("%s (%d)\n", e->name, e->age); } +*/ /* Compare function used to sort */ int my_cmp(const void *a, const void *b) { @@ -70,13 +70,10 @@ void test_v1() { /* Iterate for each element */ vec_foreach(v, multiply); /* Print each element */ - puts("Before sort:"); - vec_foreach(v, print); + // vec_foreach(v, print); /* Sort */ vec_sort(v, my_cmp); - puts("After sort:"); - vec_foreach(v, print); /* Deallocate the vector */ vec_free(v); diff --git a/vector/myvector.c b/vector/myvector.c index f109f84..4c0bcf4 100644 --- a/vector/myvector.c +++ b/vector/myvector.c @@ -305,7 +305,13 @@ int vec_sort(vec_s *vec, int (*cmp)(const void *a, const void *b)) { return -1; } + if (mtx_lock(&vec->lock) != thrd_success) { + return -1; + } + qsort(vec->data, vec->size, vec->elem_size, cmp); + mtx_unlock(&vec->lock); + return 0; }