3 Commits

Author SHA1 Message Date
abdelrahman 2a20362b44 Add free array and queue utils
Release / release (push) Successful in 7s
2026-07-05 20:51:17 +01:00
Abdelrahman Said 02372cb644 Fix mem op supported bug
Release / release (push) Successful in 6s
2026-06-28 21:46:36 +01:00
Abdelrahman Said 5804c5d345 Add function to check memory op support for allocators
Release / release (push) Successful in 7s
2026-06-28 14:03:58 +01:00
6 changed files with 119 additions and 45 deletions
+1 -1
View File
@@ -1 +1 @@
2.0.1
2.2.0
+45 -35
View File
@@ -7,14 +7,14 @@
#include "../../common/aliases/aliases.h"
#include <stddef.h>
#define _array_header(ARRAY) (WpArrayHeader *)(wpMiscUtilsOffsetPointer(ARRAY, (i64)sizeof(WpArrayHeader) * -1))
#define _arrayHeader(ARRAY) (WpArrayHeader *)(wpMiscUtilsOffsetPointer(ARRAY, (i64)sizeof(WpArrayHeader) * -1))
wp_persist inline void _array_validate(const WpArray array, u64 item_size);
wp_persist inline void _arrayValidate(const WpArray array, u64 item_size);
u64 _arrayCount(WpArray array) {
wpDebugAssert(array != NULL, "`array` should not be NULL");
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(WP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->count;
@@ -23,7 +23,7 @@ u64 _arrayCount(WpArray array) {
u64 _arrayCapacity(WpArray array) {
wpDebugAssert(array != NULL, "`array` should not be NULL");
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(WP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->capacity;
@@ -32,7 +32,7 @@ u64 _arrayCapacity(WpArray array) {
u64 _arrayItemSize(WpArray array) {
wpDebugAssert(array != NULL, "`array` should not be NULL");
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(WP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
return header->item_size;
@@ -41,7 +41,7 @@ u64 _arrayItemSize(WpArray array) {
void _arraySetCount(WpArray array, u64 count) {
wpDebugAssert(array != NULL, "`array` should not be NULL");
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(WP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
header->count = count;
@@ -49,9 +49,9 @@ void _arraySetCount(WpArray array, u64 count) {
void *_arrayGet(WpArray array, u64 index, u64 item_size) {
wpRuntimeAssert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
_arrayValidate(array, item_size);
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(index < header->count, "`index` is out of bounds");
return wpMiscUtilsOffsetPointer(array, header->item_size * index);
@@ -60,15 +60,15 @@ void *_arrayGet(WpArray array, u64 index, u64 item_size) {
void _arraySet(WpArray array, u64 index, void *value, u64 item_size) {
void *item = _arrayGet(array, index, item_size);
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
memcpy(item, value, header->item_size);
}
void _arrayAppendCapped(WpArray array, void *value, u64 item_size) {
wpRuntimeAssert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
_arrayValidate(array, item_size);
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
if (header->count >= header->capacity) { return; }
u64 index = (header->count)++;
@@ -77,11 +77,11 @@ void _arrayAppendCapped(WpArray array, void *value, u64 item_size) {
void _arrayExtendCappend(WpArray dst, const WpArray src, u64 item_size) {
wpRuntimeAssert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
_arrayValidate(dst, item_size);
_arrayValidate(src, item_size);
WpArrayHeader *src_header = _array_header(src);
WpArrayHeader *dst_header = _array_header(dst);
WpArrayHeader *src_header = _arrayHeader(src);
WpArrayHeader *dst_header = _arrayHeader(dst);
u64 remaining_capacity = dst_header->capacity - dst_header->count;
u64 copy_count = src_header->count < remaining_capacity ? src_header->count : remaining_capacity;
@@ -92,13 +92,13 @@ void _arrayExtendCappend(WpArray dst, const WpArray src, u64 item_size) {
void _arrayCopyCapped(WpArray dst, const WpArray src, u64 item_size) {
wpRuntimeAssert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
_arrayValidate(dst, item_size);
_arrayValidate(src, item_size);
_arrayClear(dst, item_size);
WpArrayHeader *src_header = _array_header(src);
WpArrayHeader *dst_header = _array_header(dst);
WpArrayHeader *src_header = _arrayHeader(src);
WpArrayHeader *dst_header = _arrayHeader(dst);
u64 copy_count = src_header->count < dst_header->capacity ? src_header->count : dst_header->capacity;
memcpy((void *)dst, (void *)src, copy_count * src_header->item_size);
dst_header->count = copy_count;
@@ -107,11 +107,11 @@ void _arrayCopyCapped(WpArray dst, const WpArray src, u64 item_size) {
WpArray _arrayAppendAlloc(const WpAllocator *allocator, WpArray array, void *value,
WpArrayInitFlags flags, u64 item_size) {
wpRuntimeAssert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
_array_validate(array, item_size);
_arrayValidate(array, item_size);
WpArray output = array;
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
if (header->count >= header->capacity) {
u64 new_capacity = wpMiscUtilsU64RoundUpPow2(header->capacity * 2);
output = (WpArray )_arrayAllocCapacity(allocator, new_capacity, flags,
@@ -136,13 +136,13 @@ RETURN_ARRAY_APPEND_ALLOC:
WpArray _arrayExtendAlloc(const WpAllocator *allocator, WpArray dst, const WpArray src,
WpArrayInitFlags flags, u64 item_size) {
wpRuntimeAssert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
_arrayValidate(dst, item_size);
_arrayValidate(src, item_size);
WpArray output = dst;
WpArrayHeader *src_header = _array_header(src);
WpArrayHeader *dst_header = _array_header(dst);
WpArrayHeader *src_header = _arrayHeader(src);
WpArrayHeader *dst_header = _arrayHeader(dst);
u64 remaining_capacity = dst_header->capacity - dst_header->count;
if (src_header->count >= remaining_capacity) {
u64 new_capacity = wpMiscUtilsU64RoundUpPow2(dst_header->capacity * 2);
@@ -168,13 +168,13 @@ RETURN_ARRAY_EXTEND_ALLOC:
WpArray _arrayCopyAlloc(const WpAllocator *allocator, WpArray dst, const WpArray src,
WpArrayInitFlags flags, u64 item_size) {
wpRuntimeAssert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
_array_validate(dst, item_size);
_array_validate(src, item_size);
_arrayValidate(dst, item_size);
_arrayValidate(src, item_size);
WpArray output = dst;
WpArrayHeader *src_header = _array_header(src);
WpArrayHeader *dst_header = _array_header(dst);
WpArrayHeader *src_header = _arrayHeader(src);
WpArrayHeader *dst_header = _arrayHeader(dst);
if (src_header->count >= dst_header->capacity) {
u64 new_capacity = wpMiscUtilsU64RoundUpPow2(dst_header->capacity * 2);
output = (WpArray )_arrayAllocCapacity(allocator, new_capacity,
@@ -197,9 +197,9 @@ RETURN_ARRAY_COPY_ALLOC:
void *_arrayPop(WpArray array, u64 item_size) {
wpRuntimeAssert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
_arrayValidate(array, item_size);
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
if (header->count == 0) { return NULL; }
u64 index = header->count - 1;
@@ -210,9 +210,9 @@ void *_arrayPop(WpArray array, u64 item_size) {
void _arrayClear(WpArray array, u64 item_size) {
wpRuntimeAssert(array != NULL, "`array` should not be NULL");
_array_validate(array, item_size);
_arrayValidate(array, item_size);
WpArrayHeader *header = _array_header(array);
WpArrayHeader *header = _arrayHeader(array);
header->count = 0;
}
@@ -259,8 +259,18 @@ WpArray _arrayFromPreallocatedBuffer(void *buffer, u64 buffer_size, WpArrayInitF
return output;
}
wp_persist inline void _array_validate(const WpArray array, u64 item_size) {
WpArrayHeader *header = _array_header(array);
void _arrayDealloc(const WpAllocator *allocator, WpArray *array, u64 item_size) {
wpRuntimeAssert(allocator != NULL, "`allocator` should not be NULL");
u64 capacity = wpArrayCapacity(*array);
u64 allocation_size = _arrayCalcAllocSize(capacity, item_size);
void *header = (void *)_arrayHeader(*array);
wpMemAllocatorFree(allocator, &header, allocation_size);
*array = NULL;
}
wp_persist inline void _arrayValidate(const WpArray array, u64 item_size) {
WpArrayHeader *header = _arrayHeader(array);
wpRuntimeAssert(WP_ARRAY_MAGIC == header->magic, "`array` is not a valid wapp array");
wpRuntimeAssert(item_size == header->item_size, "Invalid item type provided");
}
+5
View File
@@ -176,6 +176,10 @@ typedef enum {
((TYPE *)_arrayAllocCapacity(ALLOCATOR_PTR, CAPACITY, FLAGS, sizeof(TYPE)))
#define wpArrayFromPreallcatedBuffer(TYPE, BUFFER, BUFFER_SIZE) \
((TYPE *)_array_from_preallcated_buffer(BUFFER, BUFFER_SIZE, sizeof(TYPE)))
// Only needed for allocators like malloc where each allocation has to be freed on its own.
// No need to use it for allocators like Arena.
#define wpArrayDealloc(TYPE, ALLOCATOR_PTR, ARRAY_DPTR) \
(_arrayDealloc(ALLOCATOR_PTR, (WpArray *)ARRAY_DPTR, sizeof(TYPE)))
typedef struct WpArrayHeader WpArrayHeader;
@@ -208,6 +212,7 @@ WpArray _arrayAllocCapacity(const WpAllocator *allocator, u64 capacity, WpArrayI
u64 item_size);
WpArray _arrayFromPreallocatedBuffer(void *buffer, u64 buffer_size, WpArrayInitFlags flags,
u64 item_size);
void _arrayDealloc(const WpAllocator *allocator, WpArray *array, u64 item_size);
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
+48 -5
View File
@@ -6,30 +6,73 @@
#include <stdlib.h>
void *wpMemAllocatorAlloc(const WpAllocator *allocator, u64 size) {
wpDebugAssert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_ALLOC)) {
return NULL;
}
return allocator->alloc(size, allocator->obj);
}
void *wpMemAllocatorAllocAligned(const WpAllocator *allocator, u64 size, u64 alignment) {
wpDebugAssert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_ALLOC_ALIGNED)) {
return NULL;
}
return allocator->alloc_aligned(size, alignment, allocator->obj);
}
void *wpMemAllocatorRealloc(const WpAllocator *allocator, void *ptr, u64 old_size, u64 new_size) {
wpDebugAssert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_REALLOC)) {
return NULL;
}
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
}
void *wpMemAllocatorReallocAligned(const WpAllocator *allocator, void *ptr, u64 old_size,
u64 new_size, u64 alignment) {
wpDebugAssert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_REALLOC_ALIGNED)) {
return NULL;
}
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
}
void wpMemAllocatorFree(const WpAllocator *allocator, void **ptr, u64 size) {
if (!allocator || !(allocator->free)) {
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
if (!wpMemAllocatorOpSupported(allocator, WP_MEM_OP_FREE)) {
return;
}
allocator->free(ptr, size, allocator->obj);
}
b8 wpMemAllocatorOpSupported(const WpAllocator *allocator, WpMemOp op) {
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
switch (op) {
case WP_MEM_OP_ALLOC:
return allocator->alloc != NULL;
case WP_MEM_OP_ALLOC_ALIGNED:
return allocator->alloc_aligned != NULL;
case WP_MEM_OP_REALLOC:
return allocator->realloc != NULL;
case WP_MEM_OP_REALLOC_ALIGNED:
return allocator->realloc_aligned != NULL;
case WP_MEM_OP_FREE:
return allocator->free != NULL;
default:
break;
}
return false;
}
+11
View File
@@ -11,6 +11,16 @@
BEGIN_C_LINKAGE
#endif // !WP_PLATFORM_CPP
typedef enum {
WP_MEM_OP_ALLOC,
WP_MEM_OP_ALLOC_ALIGNED,
WP_MEM_OP_REALLOC,
WP_MEM_OP_REALLOC_ALIGNED,
WP_MEM_OP_FREE,
COUNT_MEM_OPS
} WpMemOp;
typedef void *(WpMemAllocFunc)(u64 size, void *alloc_obj);
typedef void *(WpMemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
typedef void *(WpMemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
@@ -42,6 +52,7 @@ void *wpMemAllocatorRealloc(const WpAllocator *allocator, void *ptr, u64 old_siz
void *wpMemAllocatorReallocAligned(const WpAllocator *allocator, void *ptr, u64 old_size,
u64 new_size, u64 alignment);
void wpMemAllocatorFree(const WpAllocator *allocator, void **ptr, u64 size);
b8 wpMemAllocatorOpSupported(const WpAllocator *allocator, WpMemOp op);
#ifdef WP_PLATFORM_CPP
END_C_LINKAGE
+9 -4
View File
@@ -42,7 +42,7 @@ typedef WpQueue WpStr8Queue;
#ifdef WP_PLATFORM_CPP
#define wpQueue(TYPE, CAPACITY) ([&]() { \
wp_persist WpArray arr = wpArrayWithCapacity(TYPE, CAPACITY, WP_ARRAY_INIT_FILLED); \
wp_persist WpArray arr = wpArrayWithCapacity(TYPE, CAPACITY, WP_ARRAY_INIT_FILLED); \
wp_persist WpQueue queue = { \
arr, \
0, \
@@ -54,7 +54,7 @@ typedef WpQueue WpStr8Queue;
}())
#define wpQueueAlloc(TYPE, ALLOCATOR_PTR, CAPACITY) ([&]() { \
wp_persist WpQueue queue = { \
wpArrayAllocCapacity(TYPE, ALLOCATOR_PTR, CAPACITY, WP_ARRAY_INIT_FILLED), \
wpArrayAllocCapacity(TYPE, ALLOCATOR_PTR, CAPACITY, WP_ARRAY_INIT_FILLED), \
0, \
0, \
0, \
@@ -64,13 +64,13 @@ typedef WpQueue WpStr8Queue;
}())
#else
#define wpQueue(TYPE, CAPACITY) ((WpQueue){ \
.items = wpArrayWithCapacity(TYPE, CAPACITY, WP_ARRAY_INIT_FILLED), \
.items = wpArrayWithCapacity(TYPE, CAPACITY, WP_ARRAY_INIT_FILLED), \
.front = 0, \
.back = 0, \
.count = 0, \
})
#define wpQueueAlloc(TYPE, ALLOCATOR_PTR, CAPACITY) ((WpQueue){ \
.items = wpArrayAllocCapacity(TYPE, ALLOCATOR_PTR, CAPACITY, WP_ARRAY_INIT_FILLED), \
.items = wpArrayAllocCapacity(TYPE, ALLOCATOR_PTR, CAPACITY, WP_ARRAY_INIT_FILLED), \
.front = 0, \
.back = 0, \
.count = 0, \
@@ -88,6 +88,11 @@ typedef WpQueue WpStr8Queue;
#define wpQueuePop(TYPE, QUEUE_PTR) ( \
(TYPE *)_queuePop(QUEUE_PTR, sizeof(TYPE)) \
)
#define wpQueueDealloc(TYPE, ALLOCATOR_PTR, QUEUE_PTR) \
(wpArrayDealloc(TYPE, ALLOCATOR_PTR, &((QUEUE_PTR)->items)), \
(QUEUE_PTR)->front = 0, \
(QUEUE_PTR)->back = 0, \
(QUEUE_PTR)->count = 0)
void _queuePush(WpQueue *queue, void *item, u64 item_size);
WpQueue *_queuePushAlloc(const WpAllocator *allocator, WpQueue *queue, void *item, u64 item_size);