Compare commits

2 Commits

Author SHA1 Message Date
a9f5b9c3c6 Add queue implementation 2026-01-11 23:46:23 +00:00
9af9cedd51 Add pointer offset utility 2026-01-11 23:46:12 +00:00
11 changed files with 249 additions and 5 deletions

View File

@@ -7,8 +7,7 @@
#include "../../common/aliases/aliases.h" #include "../../common/aliases/aliases.h"
#include <stddef.h> #include <stddef.h>
#define _offset_pointer(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET))) #define _array_header(ARRAY) (ArrayHeader *)(wapp_pointer_offset(ARRAY, (i64)sizeof(ArrayHeader) * -1))
#define _array_header(ARRAY) (ArrayHeader *)(_offset_pointer(ARRAY, (i64)sizeof(ArrayHeader) * -1))
wapp_persist inline void _array_validate(const GenericArray array, u64 item_size); wapp_persist inline void _array_validate(const GenericArray array, u64 item_size);
@@ -55,7 +54,7 @@ void *_array_get(GenericArray array, u64 index, u64 item_size) {
ArrayHeader *header = _array_header(array); ArrayHeader *header = _array_header(array);
wapp_runtime_assert(index < header->count, "`index` is out of bounds"); wapp_runtime_assert(index < header->count, "`index` is out of bounds");
return _offset_pointer(array, header->item_size * index); return wapp_pointer_offset(array, header->item_size * index);
} }
void _array_set(GenericArray array, u64 index, void *value, u64 item_size) { void _array_set(GenericArray array, u64 index, void *value, u64 item_size) {
@@ -86,7 +85,7 @@ void _array_extend_capped(GenericArray dst, const GenericArray src, u64 item_siz
u64 remaining_capacity = dst_header->capacity - dst_header->count; u64 remaining_capacity = dst_header->capacity - dst_header->count;
u64 copy_count = src_header->count < remaining_capacity ? src_header->count : remaining_capacity; u64 copy_count = src_header->count < remaining_capacity ? src_header->count : remaining_capacity;
void *dst_ptr = _offset_pointer(dst, dst_header->count * dst_header->item_size); void *dst_ptr = wapp_pointer_offset(dst, dst_header->count * dst_header->item_size);
memcpy(dst_ptr, src, copy_count * src_header->item_size); memcpy(dst_ptr, src, copy_count * src_header->item_size);
dst_header->count += copy_count; dst_header->count += copy_count;
} }

20
src/base/queue/queue.c Normal file
View File

@@ -0,0 +1,20 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "queue.h"
#include "../array/array.h"
#include "../../common/assert/assert.h"
#include <string.h>
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);
}

81
src/base/queue/queue.h Normal file
View File

@@ -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

View File

@@ -6,6 +6,7 @@
#include "wapp_base.h" #include "wapp_base.h"
#include "array/array.c" #include "array/array.c"
#include "dbl_list/dbl_list.c" #include "dbl_list/dbl_list.c"
#include "queue/queue.c"
#include "mem/allocator/mem_allocator.c" #include "mem/allocator/mem_allocator.c"
#include "mem/utils/mem_utils.c" #include "mem/utils/mem_utils.c"
#include "strings/str8/str8.c" #include "strings/str8/str8.c"

View File

@@ -3,8 +3,9 @@
#ifndef WAPP_BASE_H #ifndef WAPP_BASE_H
#define WAPP_BASE_H #define WAPP_BASE_H
#include "dbl_list/dbl_list.h"
#include "array/array.h" #include "array/array.h"
#include "dbl_list/dbl_list.h"
#include "queue/queue.h"
#include "mem/allocator/mem_allocator.h" #include "mem/allocator/mem_allocator.h"
#include "mem/utils/mem_utils.h" #include "mem/utils/mem_utils.h"
#include "strings/str8/str8.h" #include "strings/str8/str8.h"

View File

@@ -48,6 +48,7 @@ BEGIN_C_LINKAGE
) )
#define wapp_is_power_of_two(NUM) ((NUM & (NUM - 1)) == 0) #define wapp_is_power_of_two(NUM) ((NUM & (NUM - 1)) == 0)
#define wapp_pointer_offset(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
#ifdef WAPP_PLATFORM_CPP #ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE END_C_LINKAGE

63
tests/queue/test_queue.c Normal file
View File

@@ -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);
}

61
tests/queue/test_queue.cc Normal file
View File

@@ -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);
}

11
tests/queue/test_queue.h Normal file
View File

@@ -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

View File

@@ -4,6 +4,7 @@
#include "test_arena.h" #include "test_arena.h"
#include "test_str8_array.h" #include "test_str8_array.h"
#include "test_i32_array.h" #include "test_i32_array.h"
#include "test_queue.h"
#include "test_cpath.h" #include "test_cpath.h"
#include "test_file.h" #include "test_file.h"
#include "test_shell_commander.h" #include "test_shell_commander.h"
@@ -43,6 +44,8 @@ int main(void) {
test_i32_array_copy_alloc, test_i32_array_copy_alloc,
test_i32_array_pop, test_i32_array_pop,
test_i32_array_clear, test_i32_array_clear,
test_queue_push_back,
test_queue_pop_front,
test_str8_lit, test_str8_lit,
test_str8_lit_ro, test_str8_lit_ro,
test_str8_buf, test_str8_buf,

View File

@@ -4,6 +4,7 @@
#include "test_arena.h" #include "test_arena.h"
#include "test_str8_array.h" #include "test_str8_array.h"
#include "test_i32_array.h" #include "test_i32_array.h"
#include "test_queue.h"
#include "test_cpath.h" #include "test_cpath.h"
#include "test_file.h" #include "test_file.h"
#include "test_shell_commander.h" #include "test_shell_commander.h"
@@ -43,6 +44,8 @@ int main(void) {
test_i32_array_copy_alloc, test_i32_array_copy_alloc,
test_i32_array_pop, test_i32_array_pop,
test_i32_array_clear, test_i32_array_clear,
test_queue_push_back,
test_queue_pop_front,
test_str8_lit, test_str8_lit,
test_str8_lit_ro, test_str8_lit_ro,
test_str8_buf, test_str8_buf,