Restructure the library layers

This commit is contained in:
2025-12-16 17:36:50 +00:00
parent c0d901d7e9
commit 4b95a681d4
55 changed files with 161 additions and 161 deletions

175
src/base/array/array.c Normal file
View File

@@ -0,0 +1,175 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "./array.h"
#include "../../common/assert/assert.h"
#include "../mem/allocator/mem_allocator.h"
#include "../../common/misc/misc_utils.h"
#include "../../common/aliases/aliases.h"
#include <stddef.h>
#define _offset_pointer(PTR, OFFSET) ((void *)((uptr)(PTR) + (OFFSET)))
void *_array_get(Array *array, u64 index, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
return _offset_pointer(array->items, array->item_size * index);
}
void _array_set(Array *array, u64 index, void *value, u64 item_size) {
void *item = _array_get(array, index, item_size);
memcpy(item, value, array->item_size);
}
void _array_append_capped(Array *array, void *value, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
if (array->count >= array->capacity) { return; }
u64 index = (array->count)++;
_array_set(array, index, value, item_size);
}
void _array_extend_capped(Array *dst, const Array *src, u64 item_size) {
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
u64 remaining_capacity = dst->capacity - dst->count;
u64 copy_count = src->count < remaining_capacity ? src->count : remaining_capacity;
void *dst_ptr = _offset_pointer(dst->items, dst->count * dst->item_size);
memcpy(dst_ptr, src->items, copy_count * src->item_size);
dst->count += copy_count;
}
void _array_copy_capped(Array *dst, const Array *src, u64 item_size) {
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
_array_clear(dst, item_size);
u64 copy_count = src->count < dst->capacity ? src->count : dst->capacity;
memcpy(dst->items, src->items, copy_count * src->item_size);
dst->count = copy_count;
}
Array *_array_append_alloc(const Allocator *allocator, Array *array, void *value, u64 item_size) {
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
Array *output = array;
if (array->count >= array->capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
output = (Array *)_array_alloc_capacity(allocator, new_capacity, array->item_size);
if (!output) {
output = array;
goto RETURN_ARRAY_APPEND_ALLOC;
}
_array_copy_capped(output, array, item_size);
}
_array_append_capped(output, value, item_size);
RETURN_ARRAY_APPEND_ALLOC:
return output;
}
Array *_array_extend_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size) {
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
Array *output = dst;
u64 remaining_capacity = dst->capacity - dst->count;
if (src->count >= remaining_capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
output = (Array *)_array_alloc_capacity(allocator, new_capacity, dst->item_size);
if (!output) {
output = dst;
goto RETURN_ARRAY_EXTEND_ALLOC;
}
_array_copy_capped(output, dst, item_size);
}
_array_extend_capped(output, src, item_size);
RETURN_ARRAY_EXTEND_ALLOC:
return output;
}
Array *_array_copy_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size) {
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == dst->magic, "`dst` is not a valid wapp array");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == src->magic, "`src` is not a valid wapp array");
wapp_runtime_assert(item_size == dst->item_size && item_size == src->item_size, "Invalid item type provided");
Array *output = dst;
if (src->count >= dst->capacity) {
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
output = (Array *)_array_alloc_capacity(allocator, new_capacity, src->item_size);
if (!output) {
output = dst;
goto RETURN_ARRAY_COPY_ALLOC;
}
}
_array_copy_capped(output, src, item_size);
RETURN_ARRAY_COPY_ALLOC:
return output;
}
void *_array_pop(Array *array, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
if (array->count == 0) { return NULL; }
u64 index = array->count - 1;
void *out = _array_get(array, index, item_size);
--(array->count);
return out;
}
void _array_clear(Array *array, u64 item_size) {
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
wapp_runtime_assert(item_size == array->item_size, "Invalid item type provided");
array->count = 0;
}
Array *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size) {
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
Array *output = NULL;
u64 allocation_size = sizeof(Array) + item_size * capacity;
output = wapp_mem_allocator_alloc(allocator, allocation_size);
if (!output) {
goto RETURN_ARRAY_ALLOC;
}
output->magic = WAPP_ARRAY_MAGIC;
output->count = 0;
output->capacity = capacity;
output->item_size = item_size;
output->items = (void *)(output + 1);
RETURN_ARRAY_ALLOC:
return output;
}

153
src/base/array/array.h Normal file
View File

@@ -0,0 +1,153 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef ARRAY_H
#define ARRAY_H
#include "../mem/allocator/mem_allocator.h"
#include "../../common/misc/misc_utils.h"
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#define WAPP_ARRAY_MAGIC (u64)0x57415F415252
#define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__)
#define _calc_array_capacity(TYPE, ...) wapp_misc_utils_u64_round_up_pow2(_calc_array_count(TYPE, __VA_ARGS__) * 2)
#define wapp_array_alloc_capacity(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, CAPACITY) \
((ARRAY_TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(ELEM_TYPE)))
#define WAPP_DEF_ARRAY_TYPE(T, NAME) \
typedef struct { \
u64 magic; \
u64 count; \
u64 capacity; \
u64 item_size; \
T *items; \
} NAME
#ifdef WAPP_PLATFORM_CPP
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) ([&]() { \
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : -1 \
] = {__VA_ARGS__}; \
\
return ARRAY_TYPE{ \
WAPP_ARRAY_MAGIC, \
_calc_array_count(ELEM_TYPE, __VA_ARGS__), \
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
sizeof(ELEM_TYPE), \
items, \
}; \
}())
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY) ([&]() { \
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
CAPACITY : -1] = {}; \
\
return ARRAY_TYPE{ \
WAPP_ARRAY_MAGIC, \
0, \
CAPACITY, \
sizeof(ELEM_TYPE), \
items, \
}; \
}())
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) ([&]() { \
if (ARRAY_PTR == NULL || (ARRAY_PTR)->count == 0) { \
ELEM_TYPE result{}; \
return result; \
} \
\
return *((ELEM_TYPE *)_array_pop((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))); \
}())
#else
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) \
((ARRAY_TYPE){ \
.magic = WAPP_ARRAY_MAGIC, \
.count = _calc_array_count(ELEM_TYPE, __VA_ARGS__), \
.capacity = _calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
.item_size = sizeof(ELEM_TYPE), \
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : \
-1]){__VA_ARGS__} \
})
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY) \
((ARRAY_TYPE){ \
.magic = WAPP_ARRAY_MAGIC, \
.count = 0, \
.capacity = CAPACITY, \
.item_size = sizeof(ELEM_TYPE), \
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
CAPACITY : -1]){0} \
})
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) \
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
*((ELEM_TYPE *)_array_pop((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))) : \
(ELEM_TYPE){0} \
)
#endif // !WAPP_PLATFORM_CPP
#define wapp_array_get(ELEM_TYPE, ARRAY_PTR, INDEX) \
((ELEM_TYPE *)_array_get((Array *)ARRAY_PTR, INDEX, sizeof(ELEM_TYPE)))
#define wapp_array_set(ELEM_TYPE, ARRAY_PTR, INDEX, VALUE_PTR) \
_array_set((Array *)ARRAY_PTR, INDEX, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
#define wapp_array_append_capped(ELEM_TYPE, ARRAY_PTR, VALUE_PTR) \
_array_append_capped((Array *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
#define wapp_array_extend_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
_array_extend_capped((Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
#define wapp_array_copy_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
_array_copy_capped((Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
#define wapp_array_append_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, ARRAY_PTR, VALUE_PTR) \
(ARRAY_TYPE *)_array_append_alloc(ALLOCATOR_PTR, (Array *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
#define wapp_array_extend_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
(ARRAY_TYPE *)_array_extend_alloc(ALLOCATOR_PTR, (Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
#define wapp_array_copy_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
(ARRAY_TYPE *)_array_copy_alloc(ALLOCATOR_PTR, (Array *)DST_ARRAY_PTR, (Array *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE))
#define wapp_array_clear(ELEM_TYPE, ARRAY_PTR) \
_array_clear((Array *)ARRAY_PTR, sizeof(ELEM_TYPE))
WAPP_DEF_ARRAY_TYPE(void, Array);
void *_array_get(Array *array, u64 index, u64 item_size);
void _array_set(Array *array, u64 index, void *value, u64 item_size);
void _array_append_capped(Array *array, void *value, u64 item_size);
void _array_extend_capped(Array *dst, const Array *src, u64 item_size);
void _array_copy_capped(Array *dst, const Array *src, u64 item_size);
Array *_array_append_alloc(const Allocator *allocator, Array *array, void *value, u64 item_size);
Array *_array_extend_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size);
Array *_array_copy_alloc(const Allocator *allocator, Array *dst, const Array *src, u64 item_size);
void *_array_pop(Array *array, u64 item_size);
void _array_clear(Array *array, u64 item_size);
Array *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size);
// Base array types
typedef struct str8 Str8;
WAPP_DEF_ARRAY_TYPE(void *, VoidPtrArray);
WAPP_DEF_ARRAY_TYPE(c8 , C8Array);
WAPP_DEF_ARRAY_TYPE(c16 , C16Array);
WAPP_DEF_ARRAY_TYPE(c32 , C32Array);
WAPP_DEF_ARRAY_TYPE(u8 , U8Array);
WAPP_DEF_ARRAY_TYPE(u16 , U16Array);
WAPP_DEF_ARRAY_TYPE(u32 , U32Array);
WAPP_DEF_ARRAY_TYPE(u64 , U64Array);
WAPP_DEF_ARRAY_TYPE(b8 , B8Array);
WAPP_DEF_ARRAY_TYPE(i8 , I8Array);
WAPP_DEF_ARRAY_TYPE(i16 , I16Array);
WAPP_DEF_ARRAY_TYPE(i32 , I32Array);
WAPP_DEF_ARRAY_TYPE(i64 , I64Array);
WAPP_DEF_ARRAY_TYPE(f32 , F32Array);
WAPP_DEF_ARRAY_TYPE(f64 , F64Array);
WAPP_DEF_ARRAY_TYPE(f128 , F128Array);
WAPP_DEF_ARRAY_TYPE(uptr , UptrArray);
WAPP_DEF_ARRAY_TYPE(iptr , IptrArray);
WAPP_DEF_ARRAY_TYPE(Str8 , Str8Array);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !ARRAY_H

3811
src/base/dbl_list/dbl_list.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,520 @@
/**
* THIS FILE IS AUTOMATICALLY GENERATED. ANY MODIFICATIONS TO IT WILL BE OVERWRITTEN.
*/
#ifndef DBL_LIST_H
#define DBL_LIST_H
#include "../../common/aliases/aliases.h"
#include "../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#ifdef WAPP_PLATFORM_CPP
#define wapp_void_ptr_list_node(ITEM_PTR) VoidPNode{ITEM_PTR, nullptr, nullptr}
#define wapp_str8_list_node(ITEM_PTR) Str8Node{ITEM_PTR, nullptr, nullptr}
#define wapp_b8_list_node(ITEM_PTR) B8Node{ITEM_PTR, nullptr, nullptr}
#define wapp_char_list_node(ITEM_PTR) CharNode{ITEM_PTR, nullptr, nullptr}
#define wapp_c8_list_node(ITEM_PTR) C8Node{ITEM_PTR, nullptr, nullptr}
#define wapp_c16_list_node(ITEM_PTR) C16Node{ITEM_PTR, nullptr, nullptr}
#define wapp_c32_list_node(ITEM_PTR) C32Node{ITEM_PTR, nullptr, nullptr}
#define wapp_i8_list_node(ITEM_PTR) I8Node{ITEM_PTR, nullptr, nullptr}
#define wapp_i16_list_node(ITEM_PTR) I16Node{ITEM_PTR, nullptr, nullptr}
#define wapp_i32_list_node(ITEM_PTR) I32Node{ITEM_PTR, nullptr, nullptr}
#define wapp_i64_list_node(ITEM_PTR) I64Node{ITEM_PTR, nullptr, nullptr}
#define wapp_u8_list_node(ITEM_PTR) U8Node{ITEM_PTR, nullptr, nullptr}
#define wapp_u16_list_node(ITEM_PTR) U16Node{ITEM_PTR, nullptr, nullptr}
#define wapp_u32_list_node(ITEM_PTR) U32Node{ITEM_PTR, nullptr, nullptr}
#define wapp_u64_list_node(ITEM_PTR) U64Node{ITEM_PTR, nullptr, nullptr}
#define wapp_f32_list_node(ITEM_PTR) F32Node{ITEM_PTR, nullptr, nullptr}
#define wapp_f64_list_node(ITEM_PTR) F64Node{ITEM_PTR, nullptr, nullptr}
#define wapp_f128_list_node(ITEM_PTR) F128Node{ITEM_PTR, nullptr, nullptr}
#define wapp_iptr_list_node(ITEM_PTR) IptrNode{ITEM_PTR, nullptr, nullptr}
#define wapp_uptr_list_node(ITEM_PTR) UptrNode{ITEM_PTR, nullptr, nullptr}
#else
#define wapp_void_ptr_list_node(ITEM_PTR) ((VoidPNode){.item = ITEM_PTR})
#define wapp_str8_list_node(ITEM_PTR) ((Str8Node){.item = ITEM_PTR})
#define wapp_b8_list_node(ITEM_PTR) ((B8Node){.item = ITEM_PTR})
#define wapp_char_list_node(ITEM_PTR) ((CharNode){.item = ITEM_PTR})
#define wapp_c8_list_node(ITEM_PTR) ((C8Node){.item = ITEM_PTR})
#define wapp_c16_list_node(ITEM_PTR) ((C16Node){.item = ITEM_PTR})
#define wapp_c32_list_node(ITEM_PTR) ((C32Node){.item = ITEM_PTR})
#define wapp_i8_list_node(ITEM_PTR) ((I8Node){.item = ITEM_PTR})
#define wapp_i16_list_node(ITEM_PTR) ((I16Node){.item = ITEM_PTR})
#define wapp_i32_list_node(ITEM_PTR) ((I32Node){.item = ITEM_PTR})
#define wapp_i64_list_node(ITEM_PTR) ((I64Node){.item = ITEM_PTR})
#define wapp_u8_list_node(ITEM_PTR) ((U8Node){.item = ITEM_PTR})
#define wapp_u16_list_node(ITEM_PTR) ((U16Node){.item = ITEM_PTR})
#define wapp_u32_list_node(ITEM_PTR) ((U32Node){.item = ITEM_PTR})
#define wapp_u64_list_node(ITEM_PTR) ((U64Node){.item = ITEM_PTR})
#define wapp_f32_list_node(ITEM_PTR) ((F32Node){.item = ITEM_PTR})
#define wapp_f64_list_node(ITEM_PTR) ((F64Node){.item = ITEM_PTR})
#define wapp_f128_list_node(ITEM_PTR) ((F128Node){.item = ITEM_PTR})
#define wapp_iptr_list_node(ITEM_PTR) ((IptrNode){.item = ITEM_PTR})
#define wapp_uptr_list_node(ITEM_PTR) ((UptrNode){.item = ITEM_PTR})
#endif // !WAPP_PLATFORM_CPP
typedef struct str8 Str8;
typedef struct GenericNode GenericNode;
struct GenericNode {
void *item;
GenericNode *prev;
GenericNode *next;
};
typedef struct GenericList GenericList;
struct GenericList {
GenericNode *first;
GenericNode *last;
u64 node_count;
};
typedef struct VoidPNode VoidPNode;
struct VoidPNode {
void * *item;
VoidPNode *prev;
VoidPNode *next;
};
typedef struct VoidPList VoidPList;
struct VoidPList {
VoidPNode *first;
VoidPNode *last;
u64 node_count;
};
typedef struct Str8Node Str8Node;
struct Str8Node {
Str8 *item;
Str8Node *prev;
Str8Node *next;
};
typedef struct Str8List Str8List;
struct Str8List {
Str8Node *first;
Str8Node *last;
u64 node_count;
};
typedef struct B8Node B8Node;
struct B8Node {
b8 *item;
B8Node *prev;
B8Node *next;
};
typedef struct B8List B8List;
struct B8List {
B8Node *first;
B8Node *last;
u64 node_count;
};
typedef struct CharNode CharNode;
struct CharNode {
char *item;
CharNode *prev;
CharNode *next;
};
typedef struct CharList CharList;
struct CharList {
CharNode *first;
CharNode *last;
u64 node_count;
};
typedef struct C8Node C8Node;
struct C8Node {
c8 *item;
C8Node *prev;
C8Node *next;
};
typedef struct C8List C8List;
struct C8List {
C8Node *first;
C8Node *last;
u64 node_count;
};
typedef struct C16Node C16Node;
struct C16Node {
c16 *item;
C16Node *prev;
C16Node *next;
};
typedef struct C16List C16List;
struct C16List {
C16Node *first;
C16Node *last;
u64 node_count;
};
typedef struct C32Node C32Node;
struct C32Node {
c32 *item;
C32Node *prev;
C32Node *next;
};
typedef struct C32List C32List;
struct C32List {
C32Node *first;
C32Node *last;
u64 node_count;
};
typedef struct I8Node I8Node;
struct I8Node {
i8 *item;
I8Node *prev;
I8Node *next;
};
typedef struct I8List I8List;
struct I8List {
I8Node *first;
I8Node *last;
u64 node_count;
};
typedef struct I16Node I16Node;
struct I16Node {
i16 *item;
I16Node *prev;
I16Node *next;
};
typedef struct I16List I16List;
struct I16List {
I16Node *first;
I16Node *last;
u64 node_count;
};
typedef struct I32Node I32Node;
struct I32Node {
i32 *item;
I32Node *prev;
I32Node *next;
};
typedef struct I32List I32List;
struct I32List {
I32Node *first;
I32Node *last;
u64 node_count;
};
typedef struct I64Node I64Node;
struct I64Node {
i64 *item;
I64Node *prev;
I64Node *next;
};
typedef struct I64List I64List;
struct I64List {
I64Node *first;
I64Node *last;
u64 node_count;
};
typedef struct U8Node U8Node;
struct U8Node {
u8 *item;
U8Node *prev;
U8Node *next;
};
typedef struct U8List U8List;
struct U8List {
U8Node *first;
U8Node *last;
u64 node_count;
};
typedef struct U16Node U16Node;
struct U16Node {
u16 *item;
U16Node *prev;
U16Node *next;
};
typedef struct U16List U16List;
struct U16List {
U16Node *first;
U16Node *last;
u64 node_count;
};
typedef struct U32Node U32Node;
struct U32Node {
u32 *item;
U32Node *prev;
U32Node *next;
};
typedef struct U32List U32List;
struct U32List {
U32Node *first;
U32Node *last;
u64 node_count;
};
typedef struct U64Node U64Node;
struct U64Node {
u64 *item;
U64Node *prev;
U64Node *next;
};
typedef struct U64List U64List;
struct U64List {
U64Node *first;
U64Node *last;
u64 node_count;
};
typedef struct F32Node F32Node;
struct F32Node {
f32 *item;
F32Node *prev;
F32Node *next;
};
typedef struct F32List F32List;
struct F32List {
F32Node *first;
F32Node *last;
u64 node_count;
};
typedef struct F64Node F64Node;
struct F64Node {
f64 *item;
F64Node *prev;
F64Node *next;
};
typedef struct F64List F64List;
struct F64List {
F64Node *first;
F64Node *last;
u64 node_count;
};
typedef struct F128Node F128Node;
struct F128Node {
f128 *item;
F128Node *prev;
F128Node *next;
};
typedef struct F128List F128List;
struct F128List {
F128Node *first;
F128Node *last;
u64 node_count;
};
typedef struct IptrNode IptrNode;
struct IptrNode {
iptr *item;
IptrNode *prev;
IptrNode *next;
};
typedef struct IptrList IptrList;
struct IptrList {
IptrNode *first;
IptrNode *last;
u64 node_count;
};
typedef struct UptrNode UptrNode;
struct UptrNode {
uptr *item;
UptrNode *prev;
UptrNode *next;
};
typedef struct UptrList UptrList;
struct UptrList {
UptrNode *first;
UptrNode *last;
u64 node_count;
};
VoidPNode *wapp_void_ptr_list_get(const VoidPList *list, u64 index);
void wapp_void_ptr_list_push_front(VoidPList *list, VoidPNode *node);
void wapp_void_ptr_list_push_back(VoidPList *list, VoidPNode *node);
void wapp_void_ptr_list_insert(VoidPList *list, VoidPNode *node, u64 index);
VoidPNode *wapp_void_ptr_list_pop_front(VoidPList *list);
VoidPNode *wapp_void_ptr_list_pop_back(VoidPList *list);
VoidPNode *wapp_void_ptr_list_remove(VoidPList *list, u64 index);
void wapp_void_ptr_list_empty(VoidPList *list);
Str8Node *wapp_str8_list_get(const Str8List *list, u64 index);
void wapp_str8_list_push_front(Str8List *list, Str8Node *node);
void wapp_str8_list_push_back(Str8List *list, Str8Node *node);
void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index);
Str8Node *wapp_str8_list_pop_front(Str8List *list);
Str8Node *wapp_str8_list_pop_back(Str8List *list);
Str8Node *wapp_str8_list_remove(Str8List *list, u64 index);
void wapp_str8_list_empty(Str8List *list);
B8Node *wapp_b8_list_get(const B8List *list, u64 index);
void wapp_b8_list_push_front(B8List *list, B8Node *node);
void wapp_b8_list_push_back(B8List *list, B8Node *node);
void wapp_b8_list_insert(B8List *list, B8Node *node, u64 index);
B8Node *wapp_b8_list_pop_front(B8List *list);
B8Node *wapp_b8_list_pop_back(B8List *list);
B8Node *wapp_b8_list_remove(B8List *list, u64 index);
void wapp_b8_list_empty(B8List *list);
CharNode *wapp_char_list_get(const CharList *list, u64 index);
void wapp_char_list_push_front(CharList *list, CharNode *node);
void wapp_char_list_push_back(CharList *list, CharNode *node);
void wapp_char_list_insert(CharList *list, CharNode *node, u64 index);
CharNode *wapp_char_list_pop_front(CharList *list);
CharNode *wapp_char_list_pop_back(CharList *list);
CharNode *wapp_char_list_remove(CharList *list, u64 index);
void wapp_char_list_empty(CharList *list);
C8Node *wapp_c8_list_get(const C8List *list, u64 index);
void wapp_c8_list_push_front(C8List *list, C8Node *node);
void wapp_c8_list_push_back(C8List *list, C8Node *node);
void wapp_c8_list_insert(C8List *list, C8Node *node, u64 index);
C8Node *wapp_c8_list_pop_front(C8List *list);
C8Node *wapp_c8_list_pop_back(C8List *list);
C8Node *wapp_c8_list_remove(C8List *list, u64 index);
void wapp_c8_list_empty(C8List *list);
C16Node *wapp_c16_list_get(const C16List *list, u64 index);
void wapp_c16_list_push_front(C16List *list, C16Node *node);
void wapp_c16_list_push_back(C16List *list, C16Node *node);
void wapp_c16_list_insert(C16List *list, C16Node *node, u64 index);
C16Node *wapp_c16_list_pop_front(C16List *list);
C16Node *wapp_c16_list_pop_back(C16List *list);
C16Node *wapp_c16_list_remove(C16List *list, u64 index);
void wapp_c16_list_empty(C16List *list);
C32Node *wapp_c32_list_get(const C32List *list, u64 index);
void wapp_c32_list_push_front(C32List *list, C32Node *node);
void wapp_c32_list_push_back(C32List *list, C32Node *node);
void wapp_c32_list_insert(C32List *list, C32Node *node, u64 index);
C32Node *wapp_c32_list_pop_front(C32List *list);
C32Node *wapp_c32_list_pop_back(C32List *list);
C32Node *wapp_c32_list_remove(C32List *list, u64 index);
void wapp_c32_list_empty(C32List *list);
I8Node *wapp_i8_list_get(const I8List *list, u64 index);
void wapp_i8_list_push_front(I8List *list, I8Node *node);
void wapp_i8_list_push_back(I8List *list, I8Node *node);
void wapp_i8_list_insert(I8List *list, I8Node *node, u64 index);
I8Node *wapp_i8_list_pop_front(I8List *list);
I8Node *wapp_i8_list_pop_back(I8List *list);
I8Node *wapp_i8_list_remove(I8List *list, u64 index);
void wapp_i8_list_empty(I8List *list);
I16Node *wapp_i16_list_get(const I16List *list, u64 index);
void wapp_i16_list_push_front(I16List *list, I16Node *node);
void wapp_i16_list_push_back(I16List *list, I16Node *node);
void wapp_i16_list_insert(I16List *list, I16Node *node, u64 index);
I16Node *wapp_i16_list_pop_front(I16List *list);
I16Node *wapp_i16_list_pop_back(I16List *list);
I16Node *wapp_i16_list_remove(I16List *list, u64 index);
void wapp_i16_list_empty(I16List *list);
I32Node *wapp_i32_list_get(const I32List *list, u64 index);
void wapp_i32_list_push_front(I32List *list, I32Node *node);
void wapp_i32_list_push_back(I32List *list, I32Node *node);
void wapp_i32_list_insert(I32List *list, I32Node *node, u64 index);
I32Node *wapp_i32_list_pop_front(I32List *list);
I32Node *wapp_i32_list_pop_back(I32List *list);
I32Node *wapp_i32_list_remove(I32List *list, u64 index);
void wapp_i32_list_empty(I32List *list);
I64Node *wapp_i64_list_get(const I64List *list, u64 index);
void wapp_i64_list_push_front(I64List *list, I64Node *node);
void wapp_i64_list_push_back(I64List *list, I64Node *node);
void wapp_i64_list_insert(I64List *list, I64Node *node, u64 index);
I64Node *wapp_i64_list_pop_front(I64List *list);
I64Node *wapp_i64_list_pop_back(I64List *list);
I64Node *wapp_i64_list_remove(I64List *list, u64 index);
void wapp_i64_list_empty(I64List *list);
U8Node *wapp_u8_list_get(const U8List *list, u64 index);
void wapp_u8_list_push_front(U8List *list, U8Node *node);
void wapp_u8_list_push_back(U8List *list, U8Node *node);
void wapp_u8_list_insert(U8List *list, U8Node *node, u64 index);
U8Node *wapp_u8_list_pop_front(U8List *list);
U8Node *wapp_u8_list_pop_back(U8List *list);
U8Node *wapp_u8_list_remove(U8List *list, u64 index);
void wapp_u8_list_empty(U8List *list);
U16Node *wapp_u16_list_get(const U16List *list, u64 index);
void wapp_u16_list_push_front(U16List *list, U16Node *node);
void wapp_u16_list_push_back(U16List *list, U16Node *node);
void wapp_u16_list_insert(U16List *list, U16Node *node, u64 index);
U16Node *wapp_u16_list_pop_front(U16List *list);
U16Node *wapp_u16_list_pop_back(U16List *list);
U16Node *wapp_u16_list_remove(U16List *list, u64 index);
void wapp_u16_list_empty(U16List *list);
U32Node *wapp_u32_list_get(const U32List *list, u64 index);
void wapp_u32_list_push_front(U32List *list, U32Node *node);
void wapp_u32_list_push_back(U32List *list, U32Node *node);
void wapp_u32_list_insert(U32List *list, U32Node *node, u64 index);
U32Node *wapp_u32_list_pop_front(U32List *list);
U32Node *wapp_u32_list_pop_back(U32List *list);
U32Node *wapp_u32_list_remove(U32List *list, u64 index);
void wapp_u32_list_empty(U32List *list);
U64Node *wapp_u64_list_get(const U64List *list, u64 index);
void wapp_u64_list_push_front(U64List *list, U64Node *node);
void wapp_u64_list_push_back(U64List *list, U64Node *node);
void wapp_u64_list_insert(U64List *list, U64Node *node, u64 index);
U64Node *wapp_u64_list_pop_front(U64List *list);
U64Node *wapp_u64_list_pop_back(U64List *list);
U64Node *wapp_u64_list_remove(U64List *list, u64 index);
void wapp_u64_list_empty(U64List *list);
F32Node *wapp_f32_list_get(const F32List *list, u64 index);
void wapp_f32_list_push_front(F32List *list, F32Node *node);
void wapp_f32_list_push_back(F32List *list, F32Node *node);
void wapp_f32_list_insert(F32List *list, F32Node *node, u64 index);
F32Node *wapp_f32_list_pop_front(F32List *list);
F32Node *wapp_f32_list_pop_back(F32List *list);
F32Node *wapp_f32_list_remove(F32List *list, u64 index);
void wapp_f32_list_empty(F32List *list);
F64Node *wapp_f64_list_get(const F64List *list, u64 index);
void wapp_f64_list_push_front(F64List *list, F64Node *node);
void wapp_f64_list_push_back(F64List *list, F64Node *node);
void wapp_f64_list_insert(F64List *list, F64Node *node, u64 index);
F64Node *wapp_f64_list_pop_front(F64List *list);
F64Node *wapp_f64_list_pop_back(F64List *list);
F64Node *wapp_f64_list_remove(F64List *list, u64 index);
void wapp_f64_list_empty(F64List *list);
F128Node *wapp_f128_list_get(const F128List *list, u64 index);
void wapp_f128_list_push_front(F128List *list, F128Node *node);
void wapp_f128_list_push_back(F128List *list, F128Node *node);
void wapp_f128_list_insert(F128List *list, F128Node *node, u64 index);
F128Node *wapp_f128_list_pop_front(F128List *list);
F128Node *wapp_f128_list_pop_back(F128List *list);
F128Node *wapp_f128_list_remove(F128List *list, u64 index);
void wapp_f128_list_empty(F128List *list);
IptrNode *wapp_iptr_list_get(const IptrList *list, u64 index);
void wapp_iptr_list_push_front(IptrList *list, IptrNode *node);
void wapp_iptr_list_push_back(IptrList *list, IptrNode *node);
void wapp_iptr_list_insert(IptrList *list, IptrNode *node, u64 index);
IptrNode *wapp_iptr_list_pop_front(IptrList *list);
IptrNode *wapp_iptr_list_pop_back(IptrList *list);
IptrNode *wapp_iptr_list_remove(IptrList *list, u64 index);
void wapp_iptr_list_empty(IptrList *list);
UptrNode *wapp_uptr_list_get(const UptrList *list, u64 index);
void wapp_uptr_list_push_front(UptrList *list, UptrNode *node);
void wapp_uptr_list_push_back(UptrList *list, UptrNode *node);
void wapp_uptr_list_insert(UptrList *list, UptrNode *node, u64 index);
UptrNode *wapp_uptr_list_pop_front(UptrList *list);
UptrNode *wapp_uptr_list_pop_back(UptrList *list);
UptrNode *wapp_uptr_list_remove(UptrList *list, u64 index);
void wapp_uptr_list_empty(UptrList *list);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !DBL_LIST_H

View File

@@ -0,0 +1,35 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_allocator.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <stdlib.h>
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
return allocator->alloc(size, allocator->obj);
}
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
wapp_debug_assert(allocator != NULL && (allocator->alloc_aligned) != NULL, "`allocator` and `allocator->alloc_aligned` should not be NULL");
return allocator->alloc_aligned(size, alignment, allocator->obj);
}
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
wapp_debug_assert(allocator != NULL && (allocator->realloc) != NULL, "`allocator` and `allocator->realloc` should not be NULL");
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
}
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
u64 new_size, u64 alignment) {
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
}
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
if (!allocator || !(allocator->free)) {
return;
}
allocator->free(ptr, size, allocator->obj);
}

View File

@@ -0,0 +1,50 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_ALLOCATOR_H
#define MEM_ALLOCATOR_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#include <string.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, void *alloc_obj);
typedef void *(MemReallocFunc)(void *ptr, u64 old_size, u64 new_size, void *alloc_obj);
typedef void *(MemReallocAlignedFunc)(void *ptr, u64 old_size, u64 new_size, u64 alignment, void *alloc_obj);
typedef void (MemFreeFunc)(void **ptr, u64 size, void *alloc_obj);
typedef struct allocator Allocator;
struct allocator {
void *obj;
MemAllocFunc *alloc;
MemAllocAlignedFunc *alloc_aligned;
MemReallocFunc *realloc;
MemReallocAlignedFunc *realloc_aligned;
MemFreeFunc *free;
};
#ifdef WAPP_PLATFORM_CPP
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
Allocator alloc{}; \
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
}())
#else
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
#endif // !WAPP_PLATFORM_CPP
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size);
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment);
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size);
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
u64 new_size, u64 alignment);
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_ALLOCATOR_H

View File

@@ -0,0 +1,26 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "mem_utils.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <stddef.h>
wapp_intern b8 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
uptr p = (uptr)ptr;
uptr align = (uptr)alignment;
// Similar to p % align, but it's a faster implementation that works fine
// because align is guaranteed to be a power of 2
uptr modulo = p & (align - 1);
if (modulo != 0) {
p += align - modulo;
}
return (void *)p;
}

View File

@@ -0,0 +1,19 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef MEM_UTILS_H
#define MEM_UTILS_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/platform/platform.h"
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
void *wapp_mem_util_align_forward(void *ptr, u64 alignment);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !MEM_UTILS_H

View File

@@ -0,0 +1,492 @@
// vim:fileencoding=utf-8:foldmethod=marker
#include "str8.h"
#include "../../array/array.h"
#include "../../mem/allocator/mem_allocator.h"
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include <ctype.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
if (!str) {
goto RETURN_STR8;
}
str->buf = (u8 *)str + sizeof(Str8);
str->size = 0;
str->capacity = capacity;
RETURN_STR8:
return str;
}
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
if (out) {
memset(out->buf, 0, capacity);
out->size = capacity;
}
return out;
}
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str) {
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
u64 length = strlen(str);
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
if (!output) {
goto RETURN_ALLOC_CSTR;
}
output->size = length;
memcpy(output->buf, str, length);
RETURN_ALLOC_CSTR:
return output;
}
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
if (!output) {
goto RETURN_ALLOC_STR8;
}
output->size = str->size;
memcpy(output->buf, str->buf, str->size);
RETURN_ALLOC_STR8:
return output;
}
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end) {
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
Str8 *output = NULL;
if (start >= str->size || start >= end) {
goto RETURN_ALLOC_SUBSTR;
}
if (end > str->size) {
end = str->size;
}
output = wapp_str8_alloc_buf(allocator, str->capacity);
if (!output) {
goto RETURN_ALLOC_SUBSTR;
}
output->size = end - start;
memcpy(output->buf, str->buf + start, output->size);
RETURN_ALLOC_SUBSTR:
return output;
}
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str) {
wapp_debug_assert(allocator != NULL && str != NULL && (*str) != NULL, "Either `allocator` is NULL or `str` is an invalid double pointer");
wapp_mem_allocator_free(allocator, (void **)str, STR8_BUF_ALLOC_SIZE((*str)->capacity));
}
c8 wapp_str8_get(const Str8 *str, u64 index) {
if (index >= str->size) {
return '\0';
}
return str->buf[index];
}
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
if (index >= str->size) {
return;
}
str->buf[index] = c;
}
void wapp_str8_push_back(Str8 *str, c8 c) {
if (!(str->size < str->capacity)) {
return;
}
u64 index = (str->size)++;
wapp_str8_set(str, index, c);
}
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
if (s1->size != s2->size) {
return false;
}
return wapp_str8_equal_to_count(s1, s2, s1->size);
}
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
if (!s1 || !s2) {
return false;
}
return memcmp(s1->buf, s2->buf, count) == 0;
}
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
if (start >= str->size || start >= end) {
start = str->size;
end = str->size;
}
if (end > str->size) {
end = str->size;
}
return (Str8RO){
.capacity = end - start,
.size = end - start,
.buf = str->buf + start,
};
}
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src) {
wapp_debug_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
Str8 *output = NULL;
u64 remaining = dst->capacity - dst->size;
if (src->size <= remaining) {
output = dst;
goto SOURCE_STRING_STR8_CONCAT;
}
u64 capacity = dst->capacity + src->size;
output = wapp_str8_alloc_buf(allocator, capacity);
if (!output) {
goto RETURN_STR8_CONCAT;
}
wapp_str8_concat_capped(output, dst);
SOURCE_STRING_STR8_CONCAT:
wapp_str8_concat_capped(output, src);
RETURN_STR8_CONCAT:
return output;
}
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
u64 remaining = dst->capacity - dst->size;
u64 to_copy = remaining < src->size ? remaining : src->size;
memcpy(dst->buf + dst->size, src->buf, to_copy);
dst->size += to_copy;
}
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src) {
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
u64 length = strlen(src);
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
memset(dst->buf, 0, dst->size);
memcpy(dst->buf, src, to_copy);
dst->size = to_copy;
}
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
u64 to_copy = src->size <= dst->capacity ? src->size : dst->capacity;
memset(dst->buf, 0, dst->size);
memcpy(dst->buf, src->buf, to_copy);
dst->size = to_copy;
}
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity) {
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
u64 to_copy = src->size < dst_capacity ? src->size : dst_capacity - 1;
memset(dst, 0, dst_capacity);
memcpy(dst, src->buf, to_copy);
}
void wapp_str8_format(Str8 *dst, const char *format, ...) {
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
va_list args1;
va_list args2;
va_start(args1, format);
va_copy(args2, args1);
u64 total_size = vsnprintf(NULL, 0, format, args1);
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
va_end(args1);
va_end(args2);
}
void wapp_str8_to_lower(Str8 *dst, Str8RO *src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
dst->size = src->size;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 index = 0;
b8 running = true;
while (running) {
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
++index;
running = index < src->size;
}
}
void wapp_str8_to_upper(Str8 *dst, Str8RO *src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
dst->size = src->size;
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 index = 0;
b8 running = true;
while (running) {
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
++index;
running = index < src->size;
}
}
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src) {
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
u64 size = src->count * src->item_size;
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
dst->size = size;
memcpy(dst->buf, src->items, size);
}
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
if (!str || substr.size > str->size) {
return -1;
}
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
u64 char_index = 0;
b8 running = char_index < str->size;
while (running) {
const c8 *sub = str->buf + char_index;
if (memcmp(sub, substr.buf, substr.size) == 0) {
return char_index;
}
++char_index;
running = char_index < str->size;
}
return -1;
}
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
if (!str || substr.size > str->size) {
return -1;
}
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
i64 char_index = str->size - substr.size;
b8 running = char_index >= 0;
while (running) {
const c8 *sub = str->buf + char_index;
if (memcmp(sub, substr.buf, substr.size) == 0) {
return char_index;
}
--char_index;
running = char_index >= 0;
}
return -1;
}
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
if (delimiter->size > str->size) {
Str8 *full = wapp_str8_alloc_str8(allocator, str);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node) {
node->item = full;
wapp_str8_list_push_back(output, node);
}
goto RETURN_STR8_SPLIT;
}
i64 start = 0;
i64 end = 0;
i64 splits = 0;
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
Str8 *before_str;
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
if (max_splits > 0 && splits >= max_splits) {
break;
}
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node && before_str) {
node->item = before_str;
wapp_str8_list_push_back(output, node);
}
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
start += end + delimiter->size;
++splits;
}
// Ensure the last part of the string after the delimiter is added to the list
rest = wapp_str8_alloc_substr(allocator, str, start, str->size);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node && rest) {
node->item = rest;
wapp_str8_list_push_back(output, node);
}
RETURN_STR8_SPLIT:
return output;
}
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
Str8List *output = wapp_mem_allocator_alloc(allocator, sizeof(Str8List));
if (delimiter->size > str->size) {
Str8 *full = wapp_str8_alloc_str8(allocator, str);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node && full) {
node->item = full;
wapp_str8_list_push_back(output, node);
}
goto RETURN_STR8_SPLIT;
}
i64 end = 0;
i64 splits = 0;
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
Str8 *after_str;
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
if (max_splits > 0 && splits >= max_splits) {
break;
}
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node) {
node->item = after_str;
wapp_str8_list_push_front(output, node);
}
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
++splits;
}
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
Str8Node *node = wapp_mem_allocator_alloc(allocator, sizeof(Str8Node));
if (node && rest) {
node->item = rest;
wapp_str8_list_push_front(output, node);
}
RETURN_STR8_SPLIT:
return output;
}
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter) {
wapp_debug_assert(allocator != NULL && list != NULL && delimiter != NULL, "`allocator`, `list` and `delimiter` should not be NULL");
u64 capacity = wapp_str8_list_total_size(list) + (delimiter->size * (list->node_count - 1));
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
Str8Node *node;
u64 node_index = 0;
b8 running = node_index < list->node_count;
while (running) {
node = wapp_str8_list_get(list, node_index);
if (!node) {
break;
}
wapp_str8_concat_capped(output, node->item);
// NOTE (Abdelrahman): Comparison extracted to variable to silence
// MSVC Spectre mitigation warnings
b8 not_last = node_index + 1 < list->node_count;
if (not_last) {
wapp_str8_concat_capped(output, delimiter);
}
++node_index;
running = node_index < list->node_count;
}
return output;
}
u64 wapp_str8_list_total_size(const Str8List *list) {
if (!list) {
return 0;
}
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
// MSVC Spectre mitigation warnings
Str8Node* node;
u64 node_index = 0;
u64 output = 0;
b8 running = node_index < list->node_count;
while (running) {
node = wapp_str8_list_get(list, node_index);
if (!node) {
break;
}
output += node->item->size;
++node_index;
running = node_index < list->node_count;
}
return output;
}

View File

@@ -0,0 +1,141 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef STR8_H
#define STR8_H
#include "../../../common/aliases/aliases.h"
#include "../../../common/assert/assert.h"
#include "../../../common/platform/platform.h"
#include "../../array/array.h"
#include "../../dbl_list/dbl_list.h"
#include "../../mem/allocator/mem_allocator.h"
#include <string.h>
#ifdef WAPP_PLATFORM_CPP
BEGIN_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
typedef struct str8 Str8;
struct str8 {
u64 capacity;
u64 size;
c8 *buf;
};
typedef const Str8 Str8RO;
/**
* Utilities to be used with printf functions
*/
#define WAPP_STR8_SPEC "%.*s"
#define wapp_str8_varg(STRING) (int)((STRING).size), (STRING).buf
/**
* Str8 stack buffers
*/
#ifdef WAPP_PLATFORM_CPP
// Uses a lambda to achieve the same behaviour achieved by the C macro
#define wapp_str8_buf(CAPACITY) ([&](){ \
wapp_persist c8 buf[CAPACITY] = {}; \
memset(buf, 0, CAPACITY); \
return Str8{CAPACITY, 0, buf}; \
}())
// Uses a lambda to achieve the same behaviour achieved by the C macro
#define wapp_str8_lit(STRING) ([&]() { \
wapp_persist c8 buf[sizeof(STRING) * 2] = {}; \
memcpy(buf, STRING, sizeof(STRING)); \
return Str8{(sizeof(STRING) - 1) * 2, sizeof(STRING) - 1, buf}; \
}())
#define wapp_str8_lit_ro(STRING) Str8RO{sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
#define wapp_str8_lit_ro_initialiser_list(STRING) {sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
#else
#define wapp_str8_buf(CAPACITY) ((Str8){.capacity = CAPACITY, .size = 0, .buf = (c8[CAPACITY]){0}})
// Utilises the fact that memcpy returns pointer to dest buffer and that getting
// address of compound literals is valid in C to create a string on the stack
#define wapp_str8_lit(STRING) ((Str8){.capacity = (sizeof(STRING) - 1) * 2, \
.size = sizeof(STRING) - 1, \
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), STRING, sizeof(STRING))})
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
.size = sizeof(STRING) - 1, \
.buf = (c8 *)STRING})
// To be used only when initialising a static storage variable in compilers that don't support
// initialisers with the syntax of wapp_str8_lit_ro (e.g. gcc). Should only be used when necessary
// and only be assigned to a Str8RO variable to avoid any attempt at modifying the string
#define wapp_str8_lit_ro_initialiser_list(STRING) {.capacity = sizeof(STRING) - 1, \
.size = sizeof(STRING) - 1, \
.buf = (c8 *)STRING}
#endif // !WAPP_PLATFORM_CPP
/**
* Str8 allocated buffers
*/
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity);
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity);
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str);
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str);
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end);
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src);
// 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.
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
/**
* Str8 utilities
*/
c8 wapp_str8_get(Str8RO *str, u64 index);
void wapp_str8_set(Str8 *str, u64 index, c8 c);
void wapp_str8_push_back(Str8 *str, c8 c);
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src);
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src);
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity);
void wapp_str8_format(Str8 *dst, const char *format, ...);
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src);
/**
* Str8 find functions
*/
i64 wapp_str8_find(Str8RO *str, Str8RO substr);
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr);
/**
* Str8 split and join
*/
#define wapp_str8_split(ALLOCATOR, STR, DELIMITER) wapp_str8_split_with_max(ALLOCATOR, STR, DELIMITER, -1)
#define wapp_str8_rsplit(ALLOCATOR, STR, DELIMITER) wapp_str8_rsplit_with_max(ALLOCATOR, STR, DELIMITER, -1)
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits);
Str8List *wapp_str8_rsplit_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits);
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter);
/**
* Str8 list utilities
*/
#ifdef WAPP_PLATFORM_CPP
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node([&]() { \
wapp_persist Str8 str = wapp_str8_lit(STRING); \
return &str; \
}())
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node([&]() { \
wapp_persist Str8 str = STRING; \
return &str; \
}())
#else
#define wapp_str8_node_from_cstr(STRING) wapp_str8_list_node(&wapp_str8_lit(STRING))
#define wapp_str8_node_from_str8(STRING) wapp_str8_list_node(&(STRING))
#endif // !WAPP_PLATFORM_CPP
u64 wapp_str8_list_total_size(const Str8List *list);
#ifdef WAPP_PLATFORM_CPP
END_C_LINKAGE
#endif // !WAPP_PLATFORM_CPP
#endif // !STR8_H

13
src/base/wapp_base.c Normal file
View File

@@ -0,0 +1,13 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_BASE_C
#define WAPP_BASE_C
#include "wapp_base.h"
#include "array/array.c"
#include "dbl_list/dbl_list.c"
#include "mem/allocator/mem_allocator.c"
#include "mem/utils/mem_utils.c"
#include "strings/str8/str8.c"
#endif // !WAPP_BASE_C

13
src/base/wapp_base.h Normal file
View File

@@ -0,0 +1,13 @@
// vim:fileencoding=utf-8:foldmethod=marker
#ifndef WAPP_BASE_H
#define WAPP_BASE_H
#include "dbl_list/dbl_list.h"
#include "array/array.h"
#include "mem/allocator/mem_allocator.h"
#include "mem/utils/mem_utils.h"
#include "strings/str8/str8.h"
#include "../common/wapp_common.h"
#endif // !WAPP_BASE_H