From a9f5b9c3c6084c6ef8f8c5d7c5a72ec6d66ea407 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 11 Jan 2026 23:46:23 +0000 Subject: [PATCH] Add queue implementation --- src/base/queue/queue.c | 20 ++++++++++ src/base/queue/queue.h | 81 +++++++++++++++++++++++++++++++++++++++ src/base/wapp_base.c | 1 + src/base/wapp_base.h | 3 +- tests/queue/test_queue.c | 63 ++++++++++++++++++++++++++++++ tests/queue/test_queue.cc | 61 +++++++++++++++++++++++++++++ tests/queue/test_queue.h | 11 ++++++ tests/wapptest.c | 3 ++ tests/wapptest.cc | 3 ++ 9 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 src/base/queue/queue.c create mode 100644 src/base/queue/queue.h create mode 100644 tests/queue/test_queue.c create mode 100644 tests/queue/test_queue.cc create mode 100644 tests/queue/test_queue.h diff --git a/src/base/queue/queue.c b/src/base/queue/queue.c new file mode 100644 index 0000000..557bfb1 --- /dev/null +++ b/src/base/queue/queue.c @@ -0,0 +1,20 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#include "queue.h" +#include "../array/array.h" +#include "../../common/assert/assert.h" +#include + +void _queue_pop_front(GenericQueue *queue, void *output, u64 item_size) { + wapp_debug_assert(queue != NULL && output != NULL, "`queue` and `output` should not be NULL"); + wapp_runtime_assert(item_size == wapp_array_item_size(queue->items), "Invalid type"); + + memcpy(output, queue->items, item_size); + + u64 new_count = wapp_array_count(queue->items) - 1; + for (u64 i = 0; i < new_count; ++i) { + _array_set(queue->items, i, _array_get(queue->items, i + 1, item_size), item_size); + } + + wapp_array_set_count(queue->items, new_count); +} diff --git a/src/base/queue/queue.h b/src/base/queue/queue.h new file mode 100644 index 0000000..5dc189e --- /dev/null +++ b/src/base/queue/queue.h @@ -0,0 +1,81 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef QUEUE_H +#define QUEUE_H + +#include "../array/array.h" +#include "../../common/aliases/aliases.h" +#include "../../common/platform/platform.h" + +#ifdef WAPP_PLATFORM_CPP +BEGIN_C_LINKAGE +#endif // !WAPP_PLATFORM_CPP + +typedef struct { + GenericArray items; +} GenericQueue; + +// NOTE (Abdelrahman): GenericQueue typedefs for readability +typedef GenericQueue VoidPtrQueue; +typedef GenericQueue C8Queue; +typedef GenericQueue C16Queue; +typedef GenericQueue C32Queue; +typedef GenericQueue U8Queue; +typedef GenericQueue U16Queue; +typedef GenericQueue U32Queue; +typedef GenericQueue U64Queue; +typedef GenericQueue B8Queue; +typedef GenericQueue I8Queue; +typedef GenericQueue I16Queue; +typedef GenericQueue I32Queue; +typedef GenericQueue I64Queue; +typedef GenericQueue F32Queue; +typedef GenericQueue F64Queue; +typedef GenericQueue F128Queue; +typedef GenericQueue UptrQueue; +typedef GenericQueue IptrQueue; +typedef GenericQueue Str8Queue; + +#ifdef WAPP_PLATFORM_CPP +#define wapp_queue(TYPE, CAPACITY) ([&]() { \ + wapp_persist GenericArray arr = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_NONE); \ + wapp_persist GenericQueue queue = {arr}; \ + \ + return queue; \ +}()) +#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ([&]() { \ + wapp_persist GenericQueue queue = { \ + wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_NONE) \ + }; \ + \ + return queue; \ +}()) +#else +#define wapp_queue(TYPE, CAPACITY) ((GenericQueue){ \ + .items = wapp_array_with_capacity(TYPE, CAPACITY, ARRAY_INIT_NONE) \ +}) +#define wapp_queue_alloc(TYPE, ALLOCATOR_PTR, CAPACITY) ((GenericQueue){ \ + .items = wapp_array_alloc_capacity(TYPE, ALLOCATOR_PTR, CAPACITY, ARRAY_INIT_NONE) \ +}) +#endif // !WAPP_PLATFORM_CPP + +#define wapp_queue_count(QUEUE_PTR) (wapp_array_count((QUEUE_PTR)->items)) +#define wapp_queue_capacity(QUEUE_PTR) (wapp_array_capacity((QUEUE_PTR)->items)) +#define wapp_queue_item_size(QUEUE_PTR) (wapp_array_item_size((QUEUE_PTR)->items)) +#define wapp_queue_push_back(TYPE, QUEUE_PTR, VALUE_PTR) ( \ + wapp_array_append_capped(TYPE, (QUEUE_PTR)->items, VALUE_PTR) \ +) +#define wapp_queue_push_back_alloc(TYPE, ALLOCATOR_PTR, QUEUE_PTR, VALUE_PTR) ( \ + wapp_array_append_alloc(TYPE, ALLOCATOR_PTR, (QUEUE_PTR)->items, VALUE_PTR) \ +) +#define wapp_queue_pop_front(TYPE, QUEUE_PTR, OUTPUT_PTR) ( \ + _queue_pop_front(QUEUE_PTR, OUTPUT_PTR, sizeof(TYPE)) \ +) + +void _queue_pop_front(GenericQueue *queue, void *output, u64 item_size); + +#ifdef WAPP_PLATFORM_CPP +END_C_LINKAGE +#endif // !WAPP_PLATFORM_CPP + +#endif // !QUEUE_H diff --git a/src/base/wapp_base.c b/src/base/wapp_base.c index b0d1459..8f22291 100644 --- a/src/base/wapp_base.c +++ b/src/base/wapp_base.c @@ -6,6 +6,7 @@ #include "wapp_base.h" #include "array/array.c" #include "dbl_list/dbl_list.c" +#include "queue/queue.c" #include "mem/allocator/mem_allocator.c" #include "mem/utils/mem_utils.c" #include "strings/str8/str8.c" diff --git a/src/base/wapp_base.h b/src/base/wapp_base.h index 6a9274d..4c48c1d 100644 --- a/src/base/wapp_base.h +++ b/src/base/wapp_base.h @@ -3,8 +3,9 @@ #ifndef WAPP_BASE_H #define WAPP_BASE_H -#include "dbl_list/dbl_list.h" #include "array/array.h" +#include "dbl_list/dbl_list.h" +#include "queue/queue.h" #include "mem/allocator/mem_allocator.h" #include "mem/utils/mem_utils.h" #include "strings/str8/str8.h" diff --git a/tests/queue/test_queue.c b/tests/queue/test_queue.c new file mode 100644 index 0000000..b01468f --- /dev/null +++ b/tests/queue/test_queue.c @@ -0,0 +1,63 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#include "wapp.h" +#include "test_queue.h" + +wapp_persist Allocator arena = {0}; +wapp_persist I32Queue queue; + +TestFuncResult test_queue_push_back(void) { + arena = wapp_mem_arena_allocator_init(MB(64)); + + b8 result = true; + queue = wapp_queue_alloc(i32, &arena, 64); + + result = result && queue.items != NULL && wapp_queue_capacity(&queue) == 64 && wapp_queue_count(&queue) == 0; + + i32 n1 = 1; + i32 n2 = 2; + i32 n3 = 3; + i32 n4 = 4; + i32 n5 = 5; + + wapp_queue_push_back(i32, &queue, &n1); + result = result && wapp_queue_count(&queue) == 1; + + wapp_queue_push_back(i32, &queue, &n2); + result = result && wapp_queue_count(&queue) == 2; + + wapp_queue_push_back(i32, &queue, &n3); + result = result && wapp_queue_count(&queue) == 3; + + wapp_queue_push_back(i32, &queue, &n4); + result = result && wapp_queue_count(&queue) == 4; + + wapp_queue_push_back(i32, &queue, &n5); + result = result && wapp_queue_count(&queue) == 5; + + return wapp_tester_result(result); +} + +TestFuncResult test_queue_pop_front(void) { + b8 result = true; + i32 num; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 1; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 2; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 3; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 4; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 5; + + wapp_mem_arena_allocator_destroy(&arena); + + return wapp_tester_result(result); +} diff --git a/tests/queue/test_queue.cc b/tests/queue/test_queue.cc new file mode 100644 index 0000000..a02e6ae --- /dev/null +++ b/tests/queue/test_queue.cc @@ -0,0 +1,61 @@ +#include "wapp.h" +#include "test_queue.h" + +wapp_persist Allocator arena = {}; +wapp_persist I32Queue queue; + +TestFuncResult test_queue_push_back(void) { + arena = wapp_mem_arena_allocator_init(MB(64)); + + b8 result = true; + queue = wapp_queue_alloc(i32, &arena, 64); + + result = result && queue.items != NULL && wapp_queue_capacity(&queue) == 64 && wapp_queue_count(&queue) == 0; + + i32 n1 = 1; + i32 n2 = 2; + i32 n3 = 3; + i32 n4 = 4; + i32 n5 = 5; + + wapp_queue_push_back(i32, &queue, &n1); + result = result && wapp_queue_count(&queue) == 1; + + wapp_queue_push_back(i32, &queue, &n2); + result = result && wapp_queue_count(&queue) == 2; + + wapp_queue_push_back(i32, &queue, &n3); + result = result && wapp_queue_count(&queue) == 3; + + wapp_queue_push_back(i32, &queue, &n4); + result = result && wapp_queue_count(&queue) == 4; + + wapp_queue_push_back(i32, &queue, &n5); + result = result && wapp_queue_count(&queue) == 5; + + return wapp_tester_result(result); +} + +TestFuncResult test_queue_pop_front(void) { + b8 result = true; + i32 num; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 1; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 2; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 3; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 4; + + wapp_queue_pop_front(i32, &queue, &num); + result = result && num == 5; + + wapp_mem_arena_allocator_destroy(&arena); + + return wapp_tester_result(result); +} diff --git a/tests/queue/test_queue.h b/tests/queue/test_queue.h new file mode 100644 index 0000000..15443c5 --- /dev/null +++ b/tests/queue/test_queue.h @@ -0,0 +1,11 @@ +// vim:fileencoding=utf-8:foldmethod=marker + +#ifndef TEST_QUEUE_H +#define TEST_QUEUE_H + +#include "wapp.h" + +TestFuncResult test_queue_push_back(void); +TestFuncResult test_queue_pop_front(void); + +#endif // !TEST_QUEUE_H diff --git a/tests/wapptest.c b/tests/wapptest.c index 52b21c1..24b6eb4 100644 --- a/tests/wapptest.c +++ b/tests/wapptest.c @@ -4,6 +4,7 @@ #include "test_arena.h" #include "test_str8_array.h" #include "test_i32_array.h" +#include "test_queue.h" #include "test_cpath.h" #include "test_file.h" #include "test_shell_commander.h" @@ -43,6 +44,8 @@ int main(void) { test_i32_array_copy_alloc, test_i32_array_pop, test_i32_array_clear, + test_queue_push_back, + test_queue_pop_front, test_str8_lit, test_str8_lit_ro, test_str8_buf, diff --git a/tests/wapptest.cc b/tests/wapptest.cc index 52b21c1..24b6eb4 100644 --- a/tests/wapptest.cc +++ b/tests/wapptest.cc @@ -4,6 +4,7 @@ #include "test_arena.h" #include "test_str8_array.h" #include "test_i32_array.h" +#include "test_queue.h" #include "test_cpath.h" #include "test_file.h" #include "test_shell_commander.h" @@ -43,6 +44,8 @@ int main(void) { test_i32_array_copy_alloc, test_i32_array_pop, test_i32_array_clear, + test_queue_push_back, + test_queue_pop_front, test_str8_lit, test_str8_lit_ro, test_str8_buf,