Compare commits
4 Commits
main
...
4333b16090
| Author | SHA1 | Date | |
|---|---|---|---|
| 4333b16090 | |||
| ed72ccc139 | |||
| 31a22b74e9 | |||
| a32ef94522 |
@@ -12,162 +12,162 @@
|
|||||||
wapp_persist inline void _array_validate(const GenericArray *array, u64 item_size);
|
wapp_persist inline void _array_validate(const GenericArray *array, u64 item_size);
|
||||||
|
|
||||||
void *_array_get(GenericArray *array, u64 index, u64 item_size) {
|
void *_array_get(GenericArray *array, u64 index, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
_array_validate(array, item_size);
|
_array_validate(array, item_size);
|
||||||
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
|
wapp_runtime_assert(index < array->count, "`index` is out of bounds");
|
||||||
|
|
||||||
return _offset_pointer(array->items, array->item_size * index);
|
return _offset_pointer(array->items, array->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) {
|
||||||
void *item = _array_get(array, index, item_size);
|
void *item = _array_get(array, index, item_size);
|
||||||
memcpy(item, value, array->item_size);
|
memcpy(item, value, array->item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_append_capped(GenericArray *array, void *value, u64 item_size) {
|
void _array_append_capped(GenericArray *array, void *value, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
_array_validate(array, item_size);
|
_array_validate(array, item_size);
|
||||||
|
|
||||||
if (array->count >= array->capacity) { return; }
|
if (array->count >= array->capacity) { return; }
|
||||||
|
|
||||||
u64 index = (array->count)++;
|
u64 index = (array->count)++;
|
||||||
_array_set(array, index, value, item_size);
|
_array_set(array, index, value, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_extend_capped(GenericArray *dst, const GenericArray *src, u64 item_size) {
|
void _array_extend_capped(GenericArray *dst, const GenericArray *src, u64 item_size) {
|
||||||
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
_array_validate(dst, item_size);
|
_array_validate(dst, item_size);
|
||||||
_array_validate(src, item_size);
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
u64 remaining_capacity = dst->capacity - dst->count;
|
u64 remaining_capacity = dst->capacity - dst->count;
|
||||||
|
|
||||||
u64 copy_count = src->count < remaining_capacity ? src->count : remaining_capacity;
|
u64 copy_count = src->count < remaining_capacity ? src->count : remaining_capacity;
|
||||||
void *dst_ptr = _offset_pointer(dst->items, dst->count * dst->item_size);
|
void *dst_ptr = _offset_pointer(dst->items, dst->count * dst->item_size);
|
||||||
memcpy(dst_ptr, src->items, copy_count * src->item_size);
|
memcpy(dst_ptr, src->items, copy_count * src->item_size);
|
||||||
dst->count += copy_count;
|
dst->count += copy_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_copy_capped(GenericArray *dst, const GenericArray *src, u64 item_size) {
|
void _array_copy_capped(GenericArray *dst, const GenericArray *src, u64 item_size) {
|
||||||
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_runtime_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
_array_validate(dst, item_size);
|
_array_validate(dst, item_size);
|
||||||
_array_validate(src, item_size);
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
_array_clear(dst, item_size);
|
_array_clear(dst, item_size);
|
||||||
u64 copy_count = src->count < dst->capacity ? src->count : dst->capacity;
|
u64 copy_count = src->count < dst->capacity ? src->count : dst->capacity;
|
||||||
memcpy(dst->items, src->items, copy_count * src->item_size);
|
memcpy(dst->items, src->items, copy_count * src->item_size);
|
||||||
dst->count = copy_count;
|
dst->count = copy_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericArray *_array_append_alloc(const Allocator *allocator, GenericArray *array, void *value, u64 item_size) {
|
GenericArray *_array_append_alloc(const Allocator *allocator, GenericArray *array, void *value, u64 item_size) {
|
||||||
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
wapp_runtime_assert(allocator != NULL && array != NULL, "`allocator` and `array` should not be NULL");
|
||||||
_array_validate(array, item_size);
|
_array_validate(array, item_size);
|
||||||
|
|
||||||
GenericArray *output = array;
|
GenericArray *output = array;
|
||||||
|
|
||||||
if (array->count >= array->capacity) {
|
if (array->count >= array->capacity) {
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(array->capacity * 2);
|
||||||
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, array->item_size, false);
|
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, array->item_size, false);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
output = array;
|
output = array;
|
||||||
goto RETURN_ARRAY_APPEND_ALLOC;
|
goto RETURN_ARRAY_APPEND_ALLOC;
|
||||||
}
|
}
|
||||||
_array_copy_capped(output, array, item_size);
|
_array_copy_capped(output, array, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
_array_append_capped(output, value, item_size);
|
_array_append_capped(output, value, item_size);
|
||||||
|
|
||||||
RETURN_ARRAY_APPEND_ALLOC:
|
RETURN_ARRAY_APPEND_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericArray *_array_extend_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size) {
|
GenericArray *_array_extend_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size) {
|
||||||
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
_array_validate(dst, item_size);
|
_array_validate(dst, item_size);
|
||||||
_array_validate(src, item_size);
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
GenericArray *output = dst;
|
GenericArray *output = dst;
|
||||||
|
|
||||||
u64 remaining_capacity = dst->capacity - dst->count;
|
u64 remaining_capacity = dst->capacity - dst->count;
|
||||||
if (src->count >= remaining_capacity) {
|
if (src->count >= remaining_capacity) {
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
||||||
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, dst->item_size, false);
|
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, dst->item_size, false);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
output = dst;
|
output = dst;
|
||||||
goto RETURN_ARRAY_EXTEND_ALLOC;
|
goto RETURN_ARRAY_EXTEND_ALLOC;
|
||||||
}
|
}
|
||||||
_array_copy_capped(output, dst, item_size);
|
_array_copy_capped(output, dst, item_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
_array_extend_capped(output, src, item_size);
|
_array_extend_capped(output, src, item_size);
|
||||||
|
|
||||||
RETURN_ARRAY_EXTEND_ALLOC:
|
RETURN_ARRAY_EXTEND_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericArray *_array_copy_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size) {
|
GenericArray *_array_copy_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size) {
|
||||||
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
wapp_runtime_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
_array_validate(dst, item_size);
|
_array_validate(dst, item_size);
|
||||||
_array_validate(src, item_size);
|
_array_validate(src, item_size);
|
||||||
|
|
||||||
GenericArray *output = dst;
|
GenericArray *output = dst;
|
||||||
|
|
||||||
if (src->count >= dst->capacity) {
|
if (src->count >= dst->capacity) {
|
||||||
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
u64 new_capacity = wapp_misc_utils_u64_round_up_pow2(dst->capacity * 2);
|
||||||
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, src->item_size, false);
|
output = (GenericArray *)_array_alloc_capacity(allocator, new_capacity, src->item_size, false);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
output = dst;
|
output = dst;
|
||||||
goto RETURN_ARRAY_COPY_ALLOC;
|
goto RETURN_ARRAY_COPY_ALLOC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_array_copy_capped(output, src, item_size);
|
_array_copy_capped(output, src, item_size);
|
||||||
|
|
||||||
RETURN_ARRAY_COPY_ALLOC:
|
RETURN_ARRAY_COPY_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_array_pop(GenericArray *array, u64 item_size) {
|
void *_array_pop(GenericArray *array, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
_array_validate(array, item_size);
|
_array_validate(array, item_size);
|
||||||
|
|
||||||
if (array->count == 0) { return NULL; }
|
if (array->count == 0) { return NULL; }
|
||||||
|
|
||||||
u64 index = array->count - 1;
|
u64 index = array->count - 1;
|
||||||
void *out = _array_get(array, index, item_size);
|
void *out = _array_get(array, index, item_size);
|
||||||
--(array->count);
|
--(array->count);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _array_clear(GenericArray *array, u64 item_size) {
|
void _array_clear(GenericArray *array, u64 item_size) {
|
||||||
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
wapp_runtime_assert(array != NULL, "`array` should not be NULL");
|
||||||
_array_validate(array, item_size);
|
_array_validate(array, item_size);
|
||||||
|
|
||||||
array->count = 0;
|
array->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size, b8 fill) {
|
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size, b8 fill) {
|
||||||
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
|
wapp_runtime_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
GenericArray *output = NULL;
|
GenericArray *output = NULL;
|
||||||
|
|
||||||
u64 allocation_size = sizeof(GenericArray) + item_size * capacity;
|
u64 allocation_size = sizeof(GenericArray) + item_size * capacity;
|
||||||
|
|
||||||
output = wapp_mem_allocator_alloc(allocator, allocation_size);
|
output = wapp_mem_allocator_alloc(allocator, allocation_size);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ARRAY_ALLOC;
|
goto RETURN_ARRAY_ALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->magic = WAPP_ARRAY_MAGIC;
|
output->magic = WAPP_ARRAY_MAGIC;
|
||||||
output->count = fill ? capacity : 0;
|
output->count = fill ? capacity : 0;
|
||||||
output->capacity = capacity;
|
output->capacity = capacity;
|
||||||
output->item_size = item_size;
|
output->item_size = item_size;
|
||||||
output->items = (void *)(output + 1);
|
output->items = (void *)(output + 1);
|
||||||
|
|
||||||
RETURN_ARRAY_ALLOC:
|
RETURN_ARRAY_ALLOC:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_persist inline void _array_validate(const GenericArray *array, u64 item_size) {
|
wapp_persist inline void _array_validate(const GenericArray *array, u64 item_size) {
|
||||||
wapp_runtime_assert(WAPP_ARRAY_MAGIC == array->magic, "`array` is not a valid wapp array");
|
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(item_size == array->item_size, "Invalid item type provided");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,144 +17,144 @@ BEGIN_C_LINKAGE
|
|||||||
#define _calc_array_count(TYPE, ...) wapp_misc_utils_va_args_count(TYPE, __VA_ARGS__)
|
#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 _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, FILL) \
|
#define wapp_array_alloc_capacity(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, CAPACITY, FILL) \
|
||||||
((ARRAY_TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(ELEM_TYPE), FILL))
|
((ARRAY_TYPE *)_array_alloc_capacity(ALLOCATOR_PTR, CAPACITY, sizeof(ELEM_TYPE), FILL))
|
||||||
|
|
||||||
#define WAPP_DEF_ARRAY_TYPE(T, NAME) \
|
#define WAPP_DEF_ARRAY_TYPE(T, NAME) \
|
||||||
typedef struct { \
|
typedef struct { \
|
||||||
u64 magic; \
|
u64 magic; \
|
||||||
u64 count; \
|
u64 count; \
|
||||||
u64 capacity; \
|
u64 capacity; \
|
||||||
u64 item_size; \
|
u64 item_size; \
|
||||||
T *items; \
|
T *items; \
|
||||||
} NAME
|
} NAME
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) ([&]() { \
|
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) ([&]() { \
|
||||||
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : -1 \
|
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : -1 \
|
||||||
] = {__VA_ARGS__}; \
|
] = {__VA_ARGS__}; \
|
||||||
\
|
\
|
||||||
return ARRAY_TYPE{ \
|
return ARRAY_TYPE{ \
|
||||||
WAPP_ARRAY_MAGIC, \
|
WAPP_ARRAY_MAGIC, \
|
||||||
_calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
_calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
||||||
sizeof(ELEM_TYPE), \
|
sizeof(ELEM_TYPE), \
|
||||||
items, \
|
items, \
|
||||||
}; \
|
}; \
|
||||||
}())
|
}())
|
||||||
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY, FILL) ([&]() { \
|
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY, FILL) ([&]() { \
|
||||||
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
wapp_persist ELEM_TYPE items[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE{}).items)) ? \
|
||||||
CAPACITY : -1] = {}; \
|
CAPACITY : -1] = {}; \
|
||||||
\
|
\
|
||||||
return ARRAY_TYPE{ \
|
return ARRAY_TYPE{ \
|
||||||
WAPP_ARRAY_MAGIC, \
|
WAPP_ARRAY_MAGIC, \
|
||||||
FILL ? CAPACITY : 0, \
|
FILL ? CAPACITY : 0, \
|
||||||
CAPACITY, \
|
CAPACITY, \
|
||||||
sizeof(ELEM_TYPE), \
|
sizeof(ELEM_TYPE), \
|
||||||
items, \
|
items, \
|
||||||
}; \
|
}; \
|
||||||
}())
|
}())
|
||||||
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) ([&]() { \
|
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) ([&]() { \
|
||||||
if (ARRAY_PTR == NULL || (ARRAY_PTR)->count == 0) { \
|
if (ARRAY_PTR == NULL || (ARRAY_PTR)->count == 0) { \
|
||||||
ELEM_TYPE result{}; \
|
ELEM_TYPE result{}; \
|
||||||
return result; \
|
return result; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
return *((ELEM_TYPE *)_array_pop((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))); \
|
return *((ELEM_TYPE *)_array_pop((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))); \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) \
|
#define wapp_array(ELEM_TYPE, ARRAY_TYPE, ...) \
|
||||||
((ARRAY_TYPE){ \
|
((ARRAY_TYPE){ \
|
||||||
.magic = WAPP_ARRAY_MAGIC, \
|
.magic = WAPP_ARRAY_MAGIC, \
|
||||||
.count = _calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
.count = _calc_array_count(ELEM_TYPE, __VA_ARGS__), \
|
||||||
.capacity = _calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
.capacity = _calc_array_capacity(ELEM_TYPE, __VA_ARGS__), \
|
||||||
.item_size = sizeof(ELEM_TYPE), \
|
.item_size = sizeof(ELEM_TYPE), \
|
||||||
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
||||||
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : \
|
_calc_array_capacity(ELEM_TYPE, __VA_ARGS__) : \
|
||||||
-1]){__VA_ARGS__} \
|
-1]){__VA_ARGS__} \
|
||||||
})
|
})
|
||||||
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY, FILL) \
|
#define wapp_array_with_capacity(ELEM_TYPE, ARRAY_TYPE, CAPACITY, FILL) \
|
||||||
((ARRAY_TYPE){ \
|
((ARRAY_TYPE){ \
|
||||||
.magic = WAPP_ARRAY_MAGIC, \
|
.magic = WAPP_ARRAY_MAGIC, \
|
||||||
.count = FILL ? CAPACITY : 0, \
|
.count = FILL ? CAPACITY : 0, \
|
||||||
.capacity = CAPACITY, \
|
.capacity = CAPACITY, \
|
||||||
.item_size = sizeof(ELEM_TYPE), \
|
.item_size = sizeof(ELEM_TYPE), \
|
||||||
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
.items = (ELEM_TYPE[sizeof(ELEM_TYPE) == sizeof(*((ARRAY_TYPE){0}.items)) ? \
|
||||||
CAPACITY : -1]){0} \
|
CAPACITY : -1]){0} \
|
||||||
})
|
})
|
||||||
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) \
|
#define wapp_array_pop(ELEM_TYPE, ARRAY_PTR) \
|
||||||
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
(ARRAY_PTR != NULL && (ARRAY_PTR)->count > 0 ? \
|
||||||
*((ELEM_TYPE *)_array_pop((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))) : \
|
*((ELEM_TYPE *)_array_pop((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))) : \
|
||||||
(ELEM_TYPE){0} \
|
(ELEM_TYPE){0} \
|
||||||
)
|
)
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define wapp_array_get(ELEM_TYPE, ARRAY_PTR, INDEX) \
|
#define wapp_array_get(ELEM_TYPE, ARRAY_PTR, INDEX) \
|
||||||
((ELEM_TYPE *)_array_get((GenericArray *)ARRAY_PTR, INDEX, sizeof(ELEM_TYPE)))
|
((ELEM_TYPE *)_array_get((GenericArray *)ARRAY_PTR, INDEX, sizeof(ELEM_TYPE)))
|
||||||
#define wapp_array_set(ELEM_TYPE, ARRAY_PTR, INDEX, VALUE_PTR) \
|
#define wapp_array_set(ELEM_TYPE, ARRAY_PTR, INDEX, VALUE_PTR) \
|
||||||
_array_set((GenericArray *)ARRAY_PTR, INDEX, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
_array_set((GenericArray *)ARRAY_PTR, INDEX, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_array_append_capped(ELEM_TYPE, ARRAY_PTR, VALUE_PTR) \
|
#define wapp_array_append_capped(ELEM_TYPE, ARRAY_PTR, VALUE_PTR) \
|
||||||
_array_append_capped((GenericArray *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
_array_append_capped((GenericArray *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_array_extend_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_extend_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
||||||
_array_extend_capped( \
|
_array_extend_capped( \
|
||||||
(GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
(GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
||||||
)
|
)
|
||||||
#define wapp_array_copy_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_copy_capped(ELEM_TYPE, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
||||||
_array_copy_capped( \
|
_array_copy_capped( \
|
||||||
(GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
(GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
||||||
)
|
)
|
||||||
#define wapp_array_append_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, ARRAY_PTR, VALUE_PTR) \
|
#define wapp_array_append_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, ARRAY_PTR, VALUE_PTR) \
|
||||||
(ARRAY_TYPE *)_array_append_alloc( \
|
(ARRAY_TYPE *)_array_append_alloc( \
|
||||||
ALLOCATOR_PTR, (GenericArray *)ARRAY_PTR, (void *)VALUE_PTR, sizeof(ELEM_TYPE) \
|
ALLOCATOR_PTR, (GenericArray *)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) \
|
#define wapp_array_extend_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
||||||
(ARRAY_TYPE *)_array_extend_alloc( \
|
(ARRAY_TYPE *)_array_extend_alloc( \
|
||||||
ALLOCATOR_PTR, (GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
ALLOCATOR_PTR, (GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
||||||
)
|
)
|
||||||
#define wapp_array_copy_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
#define wapp_array_copy_alloc(ELEM_TYPE, ARRAY_TYPE, ALLOCATOR_PTR, DST_ARRAY_PTR, SRC_ARRAY_PTR) \
|
||||||
(ARRAY_TYPE *)_array_copy_alloc( \
|
(ARRAY_TYPE *)_array_copy_alloc( \
|
||||||
ALLOCATOR_PTR, (GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
ALLOCATOR_PTR, (GenericArray *)DST_ARRAY_PTR, (GenericArray *)SRC_ARRAY_PTR, sizeof(ELEM_TYPE) \
|
||||||
)
|
)
|
||||||
#define wapp_array_clear(ELEM_TYPE, ARRAY_PTR) \
|
#define wapp_array_clear(ELEM_TYPE, ARRAY_PTR) \
|
||||||
_array_clear((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))
|
_array_clear((GenericArray *)ARRAY_PTR, sizeof(ELEM_TYPE))
|
||||||
|
|
||||||
WAPP_DEF_ARRAY_TYPE(void, GenericArray);
|
WAPP_DEF_ARRAY_TYPE(void, GenericArray);
|
||||||
|
|
||||||
void *_array_get(GenericArray *array, u64 index, u64 item_size);
|
void *_array_get(GenericArray *array, u64 index, u64 item_size);
|
||||||
void _array_set(GenericArray *array, u64 index, void *value, u64 item_size);
|
void _array_set(GenericArray *array, u64 index, void *value, u64 item_size);
|
||||||
void _array_append_capped(GenericArray *array, void *value, u64 item_size);
|
void _array_append_capped(GenericArray *array, void *value, u64 item_size);
|
||||||
void _array_extend_capped(GenericArray *dst, const GenericArray *src, u64 item_size);
|
void _array_extend_capped(GenericArray *dst, const GenericArray *src, u64 item_size);
|
||||||
void _array_copy_capped(GenericArray *dst, const GenericArray *src, u64 item_size);
|
void _array_copy_capped(GenericArray *dst, const GenericArray *src, u64 item_size);
|
||||||
GenericArray *_array_append_alloc(const Allocator *allocator, GenericArray *array, void *value, u64 item_size);
|
GenericArray *_array_append_alloc(const Allocator *allocator, GenericArray *array, void *value, u64 item_size);
|
||||||
GenericArray *_array_extend_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size);
|
GenericArray *_array_extend_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size);
|
||||||
GenericArray *_array_copy_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size);
|
GenericArray *_array_copy_alloc(const Allocator *allocator, GenericArray *dst, const GenericArray *src, u64 item_size);
|
||||||
void *_array_pop(GenericArray *array, u64 item_size);
|
void *_array_pop(GenericArray *array, u64 item_size);
|
||||||
void _array_clear(GenericArray *array, u64 item_size);
|
void _array_clear(GenericArray *array, u64 item_size);
|
||||||
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size, b8 fill);
|
GenericArray *_array_alloc_capacity(const Allocator *allocator, u64 capacity, u64 item_size, b8 fill);
|
||||||
|
|
||||||
// Base array types
|
// Base array types
|
||||||
typedef struct str8 Str8;
|
typedef struct str8 Str8;
|
||||||
|
|
||||||
WAPP_DEF_ARRAY_TYPE(void *, VoidPtrArray);
|
WAPP_DEF_ARRAY_TYPE(void *, VoidPtrArray);
|
||||||
WAPP_DEF_ARRAY_TYPE(c8 , C8Array);
|
WAPP_DEF_ARRAY_TYPE(c8 , C8Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(c16 , C16Array);
|
WAPP_DEF_ARRAY_TYPE(c16 , C16Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(c32 , C32Array);
|
WAPP_DEF_ARRAY_TYPE(c32 , C32Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(u8 , U8Array);
|
WAPP_DEF_ARRAY_TYPE(u8 , U8Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(u16 , U16Array);
|
WAPP_DEF_ARRAY_TYPE(u16 , U16Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(u32 , U32Array);
|
WAPP_DEF_ARRAY_TYPE(u32 , U32Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(u64 , U64Array);
|
WAPP_DEF_ARRAY_TYPE(u64 , U64Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(b8 , B8Array);
|
WAPP_DEF_ARRAY_TYPE(b8 , B8Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(i8 , I8Array);
|
WAPP_DEF_ARRAY_TYPE(i8 , I8Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(i16 , I16Array);
|
WAPP_DEF_ARRAY_TYPE(i16 , I16Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(i32 , I32Array);
|
WAPP_DEF_ARRAY_TYPE(i32 , I32Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(i64 , I64Array);
|
WAPP_DEF_ARRAY_TYPE(i64 , I64Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(f32 , F32Array);
|
WAPP_DEF_ARRAY_TYPE(f32 , F32Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(f64 , F64Array);
|
WAPP_DEF_ARRAY_TYPE(f64 , F64Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(f128 , F128Array);
|
WAPP_DEF_ARRAY_TYPE(f128 , F128Array);
|
||||||
WAPP_DEF_ARRAY_TYPE(uptr , UptrArray);
|
WAPP_DEF_ARRAY_TYPE(uptr , UptrArray);
|
||||||
WAPP_DEF_ARRAY_TYPE(iptr , IptrArray);
|
WAPP_DEF_ARRAY_TYPE(iptr , IptrArray);
|
||||||
WAPP_DEF_ARRAY_TYPE(Str8 , Str8Array);
|
WAPP_DEF_ARRAY_TYPE(Str8 , Str8Array);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -12,247 +12,247 @@ wapp_intern inline void _dbl_list_validate(const GenericList *list, u64 item_siz
|
|||||||
wapp_intern inline void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size);
|
wapp_intern inline void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size);
|
||||||
|
|
||||||
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size) {
|
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size) {
|
||||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
GenericList *list = wapp_mem_allocator_alloc(allocator, sizeof(GenericList));
|
GenericList *list = wapp_mem_allocator_alloc(allocator, sizeof(GenericList));
|
||||||
if (!list) { goto DBL_LIST_ALLOC_RETURN; }
|
if (!list) { goto DBL_LIST_ALLOC_RETURN; }
|
||||||
|
|
||||||
memset((void *)list, 0, sizeof(GenericList));
|
memset((void *)list, 0, sizeof(GenericList));
|
||||||
list->magic = WAPP_DBL_LIST_MAGIC;
|
list->magic = WAPP_DBL_LIST_MAGIC;
|
||||||
list->item_size = item_size;
|
list->item_size = item_size;
|
||||||
|
|
||||||
DBL_LIST_ALLOC_RETURN:
|
DBL_LIST_ALLOC_RETURN:
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, u64 item_size) {
|
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, u64 item_size) {
|
||||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
GenericNode *node = wapp_mem_allocator_alloc(allocator, sizeof(GenericNode));
|
GenericNode *node = wapp_mem_allocator_alloc(allocator, sizeof(GenericNode));
|
||||||
if (!node) { goto DBL_LIST_NODE_ALLOC_RETURN; }
|
if (!node) { goto DBL_LIST_NODE_ALLOC_RETURN; }
|
||||||
|
|
||||||
memset((void *)node, 0, sizeof(GenericNode));
|
memset((void *)node, 0, sizeof(GenericNode));
|
||||||
node->magic = WAPP_DBL_NODE_MAGIC;
|
node->magic = WAPP_DBL_NODE_MAGIC;
|
||||||
node->item_size = item_size;
|
node->item_size = item_size;
|
||||||
|
|
||||||
DBL_LIST_NODE_ALLOC_RETURN:
|
DBL_LIST_NODE_ALLOC_RETURN:
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size) {
|
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
|
wapp_runtime_assert(index < list->node_count, "`index` is out of bounds");
|
||||||
|
|
||||||
GenericNode *output = NULL;
|
GenericNode *output = NULL;
|
||||||
GenericNode *current = list->first;
|
GenericNode *current = list->first;
|
||||||
for (u64 i = 1; i <= index; ++i) {
|
for (u64 i = 1; i <= index; ++i) {
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = current;
|
output = current;
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size) {
|
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
_dbl_list_node_validate(list, node, item_size);
|
_dbl_list_node_validate(list, node, item_size);
|
||||||
|
|
||||||
GenericList node_list = _node_to_list(node, item_size);
|
GenericList node_list = _node_to_list(node, item_size);
|
||||||
|
|
||||||
if (list->node_count == 0) {
|
if (list->node_count == 0) {
|
||||||
*list = node_list;
|
*list = node_list;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
list->node_count += node_list.node_count;
|
||||||
|
|
||||||
GenericNode *first = list->first;
|
GenericNode *first = list->first;
|
||||||
if (first) {
|
if (first) {
|
||||||
first->prev = node_list.last;
|
first->prev = node_list.last;
|
||||||
}
|
}
|
||||||
|
|
||||||
list->first = node_list.first;
|
list->first = node_list.first;
|
||||||
node_list.last->next = first;
|
node_list.last->next = first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size) {
|
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
_dbl_list_node_validate(list, node, item_size);
|
_dbl_list_node_validate(list, node, item_size);
|
||||||
|
|
||||||
GenericList node_list = _node_to_list(node, item_size);
|
GenericList node_list = _node_to_list(node, item_size);
|
||||||
|
|
||||||
if (list->node_count == 0) {
|
if (list->node_count == 0) {
|
||||||
*list = node_list;
|
*list = node_list;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
list->node_count += node_list.node_count;
|
||||||
|
|
||||||
GenericNode *last = list->last;
|
GenericNode *last = list->last;
|
||||||
if (last) {
|
if (last) {
|
||||||
last->next = node_list.first;
|
last->next = node_list.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
list->last = node_list.last;
|
list->last = node_list.last;
|
||||||
node_list.first->prev = last;
|
node_list.first->prev = last;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size) {
|
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
wapp_debug_assert(list != NULL && node != NULL && (node->item) != NULL, "`list`, `node` and `node->item` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
_dbl_list_node_validate(list, node, item_size);
|
_dbl_list_node_validate(list, node, item_size);
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
_dbl_list_push_front(list, node, item_size);
|
_dbl_list_push_front(list, node, item_size);
|
||||||
return;
|
return;
|
||||||
} else if (index == list->node_count) {
|
} else if (index == list->node_count) {
|
||||||
_dbl_list_push_back(list, node, item_size);
|
_dbl_list_push_back(list, node, item_size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *dst_node = _dbl_list_get(list, index, item_size);
|
GenericNode *dst_node = _dbl_list_get(list, index, item_size);
|
||||||
if (!dst_node) {
|
if (!dst_node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericList node_list = _node_to_list(node, item_size);
|
GenericList node_list = _node_to_list(node, item_size);
|
||||||
|
|
||||||
list->node_count += node_list.node_count;
|
list->node_count += node_list.node_count;
|
||||||
|
|
||||||
GenericNode *prev = dst_node->prev;
|
GenericNode *prev = dst_node->prev;
|
||||||
|
|
||||||
dst_node->prev = node_list.last;
|
dst_node->prev = node_list.last;
|
||||||
prev->next = node_list.first;
|
prev->next = node_list.first;
|
||||||
|
|
||||||
node_list.first->prev = prev;
|
node_list.first->prev = prev;
|
||||||
node_list.last->next = dst_node;
|
node_list.last->next = dst_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size) {
|
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
|
|
||||||
GenericNode *output = NULL;
|
GenericNode *output = NULL;
|
||||||
|
|
||||||
if (list->node_count == 0) {
|
if (list->node_count == 0) {
|
||||||
goto RETURN_I32_LIST_POP_FRONT;
|
goto RETURN_I32_LIST_POP_FRONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = list->first;
|
output = list->first;
|
||||||
|
|
||||||
if (list->node_count == 1) {
|
if (list->node_count == 1) {
|
||||||
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
|
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
|
||||||
goto RETURN_I32_LIST_POP_FRONT;
|
goto RETURN_I32_LIST_POP_FRONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
--(list->node_count);
|
--(list->node_count);
|
||||||
list->first = output->next;
|
list->first = output->next;
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
output->prev = output->next = NULL;
|
||||||
|
|
||||||
RETURN_I32_LIST_POP_FRONT:
|
RETURN_I32_LIST_POP_FRONT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size) {
|
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
|
|
||||||
GenericNode *output = NULL;
|
GenericNode *output = NULL;
|
||||||
|
|
||||||
if (list->node_count == 0) {
|
if (list->node_count == 0) {
|
||||||
goto RETURN_I32_LIST_POP_BACK;
|
goto RETURN_I32_LIST_POP_BACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = list->last;
|
output = list->last;
|
||||||
|
|
||||||
if (list->node_count == 1) {
|
if (list->node_count == 1) {
|
||||||
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
|
*list = (GenericList){.magic = WAPP_DBL_LIST_MAGIC, .item_size = item_size};
|
||||||
goto RETURN_I32_LIST_POP_BACK;
|
goto RETURN_I32_LIST_POP_BACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
--(list->node_count);
|
--(list->node_count);
|
||||||
list->last = output->prev;
|
list->last = output->prev;
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
output->prev = output->next = NULL;
|
||||||
|
|
||||||
RETURN_I32_LIST_POP_BACK:
|
RETURN_I32_LIST_POP_BACK:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size) {
|
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
|
|
||||||
GenericNode *output = NULL;
|
GenericNode *output = NULL;
|
||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
output = _dbl_list_pop_front(list, item_size);
|
output = _dbl_list_pop_front(list, item_size);
|
||||||
goto RETURN_I32_LIST_REMOVE;
|
goto RETURN_I32_LIST_REMOVE;
|
||||||
} else if (index == list->node_count) {
|
} else if (index == list->node_count) {
|
||||||
output = _dbl_list_pop_back(list, item_size);
|
output = _dbl_list_pop_back(list, item_size);
|
||||||
goto RETURN_I32_LIST_REMOVE;
|
goto RETURN_I32_LIST_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = _dbl_list_get(list, index, item_size);
|
output = _dbl_list_get(list, index, item_size);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_I32_LIST_REMOVE;
|
goto RETURN_I32_LIST_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->prev->next = output->next;
|
output->prev->next = output->next;
|
||||||
output->next->prev = output->prev;
|
output->next->prev = output->prev;
|
||||||
|
|
||||||
--(list->node_count);
|
--(list->node_count);
|
||||||
|
|
||||||
output->prev = output->next = NULL;
|
output->prev = output->next = NULL;
|
||||||
|
|
||||||
RETURN_I32_LIST_REMOVE:
|
RETURN_I32_LIST_REMOVE:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _dbl_list_empty(GenericList *list, u64 item_size) {
|
void _dbl_list_empty(GenericList *list, u64 item_size) {
|
||||||
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
wapp_debug_assert(list != NULL, "`list` should not be NULL");
|
||||||
_dbl_list_validate(list, item_size);
|
_dbl_list_validate(list, item_size);
|
||||||
|
|
||||||
u64 count = list->node_count;
|
u64 count = list->node_count;
|
||||||
for (u64 i = 0; i < count; ++i) {
|
for (u64 i = 0; i < count; ++i) {
|
||||||
_dbl_list_pop_back(list, item_size);
|
_dbl_list_pop_back(list, item_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern GenericList _node_to_list(GenericNode *node, u64 item_size) {
|
wapp_intern GenericList _node_to_list(GenericNode *node, u64 item_size) {
|
||||||
GenericList output = {
|
GenericList output = {
|
||||||
.magic = WAPP_DBL_LIST_MAGIC,
|
.magic = WAPP_DBL_LIST_MAGIC,
|
||||||
.first = node,
|
.first = node,
|
||||||
.last = node,
|
.last = node,
|
||||||
.node_count = 1,
|
.node_count = 1,
|
||||||
.item_size = item_size,
|
.item_size = item_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
while (output.first->prev != NULL) {
|
while (output.first->prev != NULL) {
|
||||||
output.first = output.first->prev;
|
output.first = output.first->prev;
|
||||||
++(output.node_count);
|
++(output.node_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (output.last->next != NULL) {
|
while (output.last->next != NULL) {
|
||||||
output.last = output.last->next;
|
output.last = output.last->next;
|
||||||
++(output.node_count);
|
++(output.node_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void _dbl_list_validate(const GenericList *list, u64 item_size) {
|
wapp_intern void _dbl_list_validate(const GenericList *list, u64 item_size) {
|
||||||
wapp_runtime_assert(list->magic == WAPP_DBL_LIST_MAGIC, "`list` isn't a valid wapp list type");
|
wapp_runtime_assert(list->magic == WAPP_DBL_LIST_MAGIC, "`list` isn't a valid wapp list type");
|
||||||
wapp_runtime_assert(list->item_size == item_size, "Invalid item provided");
|
wapp_runtime_assert(list->item_size == item_size, "Invalid item provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size) {
|
wapp_intern void _dbl_list_node_validate(const GenericList *list, const GenericNode *node, u64 item_size) {
|
||||||
wapp_runtime_assert(node->magic == WAPP_DBL_NODE_MAGIC, "`node` isn't a valid wapp node type");
|
wapp_runtime_assert(node->magic == WAPP_DBL_NODE_MAGIC, "`node` isn't a valid wapp node type");
|
||||||
wapp_runtime_assert(list->item_size == node->item_size, "Mismatched `list` and `node` types");
|
wapp_runtime_assert(list->item_size == node->item_size, "Mismatched `list` and `node` types");
|
||||||
wapp_runtime_assert(node->item_size == item_size, "Invalid item provided");
|
wapp_runtime_assert(node->item_size == item_size, "Invalid item provided");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,94 +14,94 @@ BEGIN_C_LINKAGE
|
|||||||
#define WAPP_DBL_LIST_MAGIC (u64)0x57415f444c5354
|
#define WAPP_DBL_LIST_MAGIC (u64)0x57415f444c5354
|
||||||
#define WAPP_DBL_NODE_MAGIC (u64)0x57415f444e44
|
#define WAPP_DBL_NODE_MAGIC (u64)0x57415f444e44
|
||||||
|
|
||||||
#define WAPP_DEF_DBL_LIST_TYPE(T, NODE_NAME, LIST_NAME) \
|
#define WAPP_DEF_DBL_LIST_TYPE(T, NODE_NAME, LIST_NAME) \
|
||||||
typedef struct NODE_NAME NODE_NAME; \
|
typedef struct NODE_NAME NODE_NAME; \
|
||||||
struct NODE_NAME { \
|
struct NODE_NAME { \
|
||||||
u64 magic; \
|
u64 magic; \
|
||||||
T *item; \
|
T *item; \
|
||||||
NODE_NAME *prev; \
|
NODE_NAME *prev; \
|
||||||
NODE_NAME *next; \
|
NODE_NAME *next; \
|
||||||
u64 item_size; \
|
u64 item_size; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
typedef struct { \
|
typedef struct { \
|
||||||
u64 magic; \
|
u64 magic; \
|
||||||
NODE_NAME *first; \
|
NODE_NAME *first; \
|
||||||
NODE_NAME *last; \
|
NODE_NAME *last; \
|
||||||
u64 node_count; \
|
u64 node_count; \
|
||||||
u64 item_size; \
|
u64 item_size; \
|
||||||
} LIST_NAME
|
} LIST_NAME
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
#define wapp_dbl_list(ELEM_TYPE, LIST_TYPE) \
|
#define wapp_dbl_list(ELEM_TYPE, LIST_TYPE) \
|
||||||
LIST_TYPE{WAPP_DBL_LIST_MAGIC, nullptr, nullptr, 0, sizeof(ELEM_TYPE)}
|
LIST_TYPE{WAPP_DBL_LIST_MAGIC, nullptr, nullptr, 0, sizeof(ELEM_TYPE)}
|
||||||
#define wapp_dbl_list_node(ELEM_TYPE, NODE_TYPE, ELEM_PTR) \
|
#define wapp_dbl_list_node(ELEM_TYPE, NODE_TYPE, ELEM_PTR) \
|
||||||
NODE_TYPE{WAPP_DBL_NODE_MAGIC, ELEM_PTR, nullptr, nullptr, sizeof(ELEM_TYPE)}
|
NODE_TYPE{WAPP_DBL_NODE_MAGIC, ELEM_PTR, nullptr, nullptr, sizeof(ELEM_TYPE)}
|
||||||
#else
|
#else
|
||||||
#define wapp_dbl_list(ELEM_TYPE, LIST_TYPE) ( \
|
#define wapp_dbl_list(ELEM_TYPE, LIST_TYPE) ( \
|
||||||
(LIST_TYPE){.magic = WAPP_DBL_LIST_MAGIC, .item_size = sizeof(ELEM_TYPE)} \
|
(LIST_TYPE){.magic = WAPP_DBL_LIST_MAGIC, .item_size = sizeof(ELEM_TYPE)} \
|
||||||
)
|
)
|
||||||
#define wapp_dbl_list_node(ELEM_TYPE, NODE_TYPE, ELEM_PTR) ( \
|
#define wapp_dbl_list_node(ELEM_TYPE, NODE_TYPE, ELEM_PTR) ( \
|
||||||
(NODE_TYPE){.magic = WAPP_DBL_NODE_MAGIC, .item = ELEM_PTR, .item_size = sizeof(ELEM_TYPE)} \
|
(NODE_TYPE){.magic = WAPP_DBL_NODE_MAGIC, .item = ELEM_PTR, .item_size = sizeof(ELEM_TYPE)} \
|
||||||
)
|
)
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
#define wapp_dbl_list_alloc(ELEM_TYPE, LIST_TYPE, ALLOCATOR) \
|
#define wapp_dbl_list_alloc(ELEM_TYPE, LIST_TYPE, ALLOCATOR) \
|
||||||
(LIST_TYPE *)_dbl_list_alloc(ALLOCATOR, sizeof(ELEM_TYPE))
|
(LIST_TYPE *)_dbl_list_alloc(ALLOCATOR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_node_alloc(ELEM_TYPE, NODE_TYPE, ALLOCATOR) \
|
#define wapp_dbl_list_node_alloc(ELEM_TYPE, NODE_TYPE, ALLOCATOR) \
|
||||||
(NODE_TYPE *)_dbl_list_node_alloc(ALLOCATOR, sizeof(ELEM_TYPE))
|
(NODE_TYPE *)_dbl_list_node_alloc(ALLOCATOR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_get(ELEM_TYPE, NODE_TYPE, LIST_PTR, ELEM_INDEX) \
|
#define wapp_dbl_list_get(ELEM_TYPE, NODE_TYPE, LIST_PTR, ELEM_INDEX) \
|
||||||
(NODE_TYPE *)_dbl_list_get((GenericList *)LIST_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
(NODE_TYPE *)_dbl_list_get((GenericList *)LIST_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_push_front(ELEM_TYPE, LIST_PTR, NODE_PTR) \
|
#define wapp_dbl_list_push_front(ELEM_TYPE, LIST_PTR, NODE_PTR) \
|
||||||
_dbl_list_push_front((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, sizeof(ELEM_TYPE))
|
_dbl_list_push_front((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_push_back(ELEM_TYPE, LIST_PTR, NODE_PTR) \
|
#define wapp_dbl_list_push_back(ELEM_TYPE, LIST_PTR, NODE_PTR) \
|
||||||
_dbl_list_push_back((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, sizeof(ELEM_TYPE))
|
_dbl_list_push_back((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_insert(ELEM_TYPE, LIST_PTR, NODE_PTR, ELEM_INDEX) \
|
#define wapp_dbl_list_insert(ELEM_TYPE, LIST_PTR, NODE_PTR, ELEM_INDEX) \
|
||||||
_dbl_list_insert((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
_dbl_list_insert((GenericList *)LIST_PTR, (GenericNode *)NODE_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_pop_front(ELEM_TYPE, NODE_TYPE, LIST_PTR) \
|
#define wapp_dbl_list_pop_front(ELEM_TYPE, NODE_TYPE, LIST_PTR) \
|
||||||
(NODE_TYPE *)_dbl_list_pop_front((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
(NODE_TYPE *)_dbl_list_pop_front((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_pop_back(ELEM_TYPE, NODE_TYPE, LIST_PTR) \
|
#define wapp_dbl_list_pop_back(ELEM_TYPE, NODE_TYPE, LIST_PTR) \
|
||||||
(NODE_TYPE *)_dbl_list_pop_back((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
(NODE_TYPE *)_dbl_list_pop_back((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_remove(ELEM_TYPE, NODE_TYPE, LIST_PTR, ELEM_INDEX) \
|
#define wapp_dbl_list_remove(ELEM_TYPE, NODE_TYPE, LIST_PTR, ELEM_INDEX) \
|
||||||
(NODE_TYPE *)_dbl_list_remove((GenericList *)LIST_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
(NODE_TYPE *)_dbl_list_remove((GenericList *)LIST_PTR, ELEM_INDEX, sizeof(ELEM_TYPE))
|
||||||
#define wapp_dbl_list_empty(ELEM_TYPE, LIST_PTR) \
|
#define wapp_dbl_list_empty(ELEM_TYPE, LIST_PTR) \
|
||||||
_dbl_list_empty((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
_dbl_list_empty((GenericList *)LIST_PTR, sizeof(ELEM_TYPE))
|
||||||
|
|
||||||
WAPP_DEF_DBL_LIST_TYPE(void, GenericNode, GenericList);
|
WAPP_DEF_DBL_LIST_TYPE(void, GenericNode, GenericList);
|
||||||
|
|
||||||
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size);
|
GenericList *_dbl_list_alloc(const Allocator *allocator, u64 item_size);
|
||||||
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, u64 item_size);
|
GenericNode *_dbl_list_node_alloc(const Allocator *allocator, u64 item_size);
|
||||||
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size);
|
GenericNode *_dbl_list_get(const GenericList *list, u64 index, u64 item_size);
|
||||||
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size);
|
void _dbl_list_push_front(GenericList *list, GenericNode *node, u64 item_size);
|
||||||
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size);
|
void _dbl_list_push_back(GenericList *list, GenericNode *node, u64 item_size);
|
||||||
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size);
|
void _dbl_list_insert(GenericList *list, GenericNode *node, u64 index, u64 item_size);
|
||||||
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size);
|
GenericNode *_dbl_list_pop_front(GenericList *list, u64 item_size);
|
||||||
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size);
|
GenericNode *_dbl_list_pop_back(GenericList *list, u64 item_size);
|
||||||
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size);
|
GenericNode *_dbl_list_remove(GenericList *list, u64 index, u64 item_size);
|
||||||
void _dbl_list_empty(GenericList *list, u64 item_size);
|
void _dbl_list_empty(GenericList *list, u64 item_size);
|
||||||
|
|
||||||
// Base list types
|
// Base list types
|
||||||
typedef struct str8 Str8;
|
typedef struct str8 Str8;
|
||||||
|
|
||||||
WAPP_DEF_DBL_LIST_TYPE(void *, VoidPtrNode, VoidPtrList);
|
WAPP_DEF_DBL_LIST_TYPE(void * , VoidPtrNode , VoidPtrList);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(c8 , C8Node , C8List);
|
WAPP_DEF_DBL_LIST_TYPE(c8 , C8Node , C8List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(c16 , C16Node , C16List);
|
WAPP_DEF_DBL_LIST_TYPE(c16 , C16Node , C16List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(c32 , C32Node , C32List);
|
WAPP_DEF_DBL_LIST_TYPE(c32 , C32Node , C32List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(u8 , U8Node , U8List);
|
WAPP_DEF_DBL_LIST_TYPE(u8 , U8Node , U8List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(u16 , U16Node , U16List);
|
WAPP_DEF_DBL_LIST_TYPE(u16 , U16Node , U16List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(u32 , U32Node , U32List);
|
WAPP_DEF_DBL_LIST_TYPE(u32 , U32Node , U32List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(u64 , U64Node , U64List);
|
WAPP_DEF_DBL_LIST_TYPE(u64 , U64Node , U64List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(b8 , B8Node , B8List);
|
WAPP_DEF_DBL_LIST_TYPE(b8 , B8Node , B8List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(i8 , I8Node , I8List);
|
WAPP_DEF_DBL_LIST_TYPE(i8 , I8Node , I8List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(i16 , I16Node , I16List);
|
WAPP_DEF_DBL_LIST_TYPE(i16 , I16Node , I16List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(i32 , I32Node , I32List);
|
WAPP_DEF_DBL_LIST_TYPE(i32 , I32Node , I32List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(i64 , I64Node , I64List);
|
WAPP_DEF_DBL_LIST_TYPE(i64 , I64Node , I64List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(f32 , F32Node , F32List);
|
WAPP_DEF_DBL_LIST_TYPE(f32 , F32Node , F32List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(f64 , F64Node , F64List);
|
WAPP_DEF_DBL_LIST_TYPE(f64 , F64Node , F64List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(f128 , F128Node , F128List);
|
WAPP_DEF_DBL_LIST_TYPE(f128 , F128Node , F128List);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(uptr , UptrNode , UptrList);
|
WAPP_DEF_DBL_LIST_TYPE(uptr , UptrNode , UptrList);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(iptr , IptrNode , IptrList);
|
WAPP_DEF_DBL_LIST_TYPE(iptr , IptrNode , IptrList);
|
||||||
WAPP_DEF_DBL_LIST_TYPE(Str8 , Str8Node , Str8List);
|
WAPP_DEF_DBL_LIST_TYPE(Str8 , Str8Node , Str8List);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -6,30 +6,30 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc(const Allocator *allocator, u64 size) {
|
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");
|
wapp_debug_assert(allocator != NULL && (allocator->alloc) != NULL, "`allocator` and `allocator->alloc` should not be NULL");
|
||||||
return allocator->alloc(size, allocator->obj);
|
return allocator->alloc(size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_alloc_aligned(const Allocator *allocator, u64 size, u64 alignment) {
|
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");
|
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);
|
return allocator->alloc_aligned(size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc(const Allocator *allocator, void *ptr, u64 old_size, u64 new_size) {
|
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");
|
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);
|
return allocator->realloc(ptr, old_size, new_size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||||
u64 new_size, u64 alignment) {
|
u64 new_size, u64 alignment) {
|
||||||
wapp_debug_assert(allocator != NULL && (allocator->realloc_aligned) != NULL, "`allocator` and `allocator->realloc_aligned` should not be NULL");
|
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);
|
return allocator->realloc_aligned(ptr, old_size, new_size, alignment, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size) {
|
||||||
if (!allocator || !(allocator->free)) {
|
if (!allocator || !(allocator->free)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocator->free(ptr, size, allocator->obj);
|
allocator->free(ptr, size, allocator->obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,26 +11,26 @@
|
|||||||
BEGIN_C_LINKAGE
|
BEGIN_C_LINKAGE
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
typedef void *(MemAllocFunc)(u64 size, void *alloc_obj);
|
||||||
typedef void *(MemAllocAlignedFunc)(u64 size, u64 alignment, 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 *(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 *(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 void (MemFreeFunc)(void **ptr, u64 size, void *alloc_obj);
|
||||||
|
|
||||||
typedef struct allocator Allocator;
|
typedef struct allocator Allocator;
|
||||||
struct allocator {
|
struct allocator {
|
||||||
void *obj;
|
void *obj;
|
||||||
MemAllocFunc *alloc;
|
MemAllocFunc *alloc;
|
||||||
MemAllocAlignedFunc *alloc_aligned;
|
MemAllocAlignedFunc *alloc_aligned;
|
||||||
MemReallocFunc *realloc;
|
MemReallocFunc *realloc;
|
||||||
MemReallocAlignedFunc *realloc_aligned;
|
MemReallocAlignedFunc *realloc_aligned;
|
||||||
MemFreeFunc *free;
|
MemFreeFunc *free;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
|
#define wapp_mem_allocator_invalid(ALLOCATOR) ([&]() { \
|
||||||
Allocator alloc{}; \
|
Allocator alloc{}; \
|
||||||
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
|
return memcmp(ALLOCATOR, &alloc, sizeof(Allocator)) == 0; \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
|
#define wapp_mem_allocator_invalid(ALLOCATOR) (memcmp(ALLOCATOR, &((Allocator){0}), sizeof(Allocator)) == 0)
|
||||||
@@ -40,7 +40,7 @@ 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_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(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,
|
void *wapp_mem_allocator_realloc_aligned(const Allocator *allocator, void *ptr, u64 old_size,
|
||||||
u64 new_size, u64 alignment);
|
u64 new_size, u64 alignment);
|
||||||
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size);
|
void wapp_mem_allocator_free(const Allocator *allocator, void **ptr, u64 size);
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -8,19 +8,19 @@
|
|||||||
wapp_intern b8 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
wapp_intern b8 is_power_of_two(u64 num) { return (num & (num - 1)) == 0; }
|
||||||
|
|
||||||
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
void *wapp_mem_util_align_forward(void *ptr, u64 alignment) {
|
||||||
wapp_debug_assert(ptr != NULL, "`ptr` should not be NULL");
|
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");
|
wapp_runtime_assert(is_power_of_two(alignment), "`alignment` value is not a power of two");
|
||||||
|
|
||||||
uptr p = (uptr)ptr;
|
uptr p = (uptr)ptr;
|
||||||
uptr align = (uptr)alignment;
|
uptr align = (uptr)alignment;
|
||||||
|
|
||||||
// Similar to p % align, but it's a faster implementation that works fine
|
// Similar to p % align, but it's a faster implementation that works fine
|
||||||
// because align is guaranteed to be a power of 2
|
// because align is guaranteed to be a power of 2
|
||||||
uptr modulo = p & (align - 1);
|
uptr modulo = p & (align - 1);
|
||||||
|
|
||||||
if (modulo != 0) {
|
if (modulo != 0) {
|
||||||
p += align - modulo;
|
p += align - modulo;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void *)p;
|
return (void *)p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,479 +14,479 @@
|
|||||||
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
|
#define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY)
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
|
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) {
|
||||||
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
wapp_debug_assert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
|
Str8 *str = wapp_mem_allocator_alloc(allocator, STR8_BUF_ALLOC_SIZE(capacity));
|
||||||
if (!str) {
|
if (!str) {
|
||||||
goto RETURN_STR8;
|
goto RETURN_STR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
str->buf = (u8 *)str + sizeof(Str8);
|
str->buf = (u8 *)str + sizeof(Str8);
|
||||||
str->size = 0;
|
str->size = 0;
|
||||||
str->capacity = capacity;
|
str->capacity = capacity;
|
||||||
|
|
||||||
RETURN_STR8:
|
RETURN_STR8:
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
|
Str8 *wapp_str8_alloc_and_fill_buf(const Allocator *allocator, u64 capacity) {
|
||||||
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
|
Str8 *out = wapp_str8_alloc_buf(allocator, capacity);
|
||||||
if (out) {
|
if (out) {
|
||||||
memset(out->buf, 0, capacity);
|
memset(out->buf, 0, capacity);
|
||||||
out->size = capacity;
|
out->size = capacity;
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str) {
|
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");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
u64 length = strlen(str);
|
u64 length = strlen(str);
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
|
Str8 *output = wapp_str8_alloc_buf(allocator, length * 2);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_CSTR;
|
goto RETURN_ALLOC_CSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = length;
|
output->size = length;
|
||||||
memcpy(output->buf, str, length);
|
memcpy(output->buf, str, length);
|
||||||
|
|
||||||
RETURN_ALLOC_CSTR:
|
RETURN_ALLOC_CSTR:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
|
Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
|
Str8 *output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_STR8;
|
goto RETURN_ALLOC_STR8;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = str->size;
|
output->size = str->size;
|
||||||
memcpy(output->buf, str->buf, str->size);
|
memcpy(output->buf, str->buf, str->size);
|
||||||
|
|
||||||
RETURN_ALLOC_STR8:
|
RETURN_ALLOC_STR8:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end) {
|
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");
|
wapp_debug_assert(allocator != NULL && str != NULL, "`allocator` and `str` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
|
|
||||||
if (start >= str->size || start >= end) {
|
if (start >= str->size || start >= end) {
|
||||||
goto RETURN_ALLOC_SUBSTR;
|
goto RETURN_ALLOC_SUBSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end > str->size) {
|
if (end > str->size) {
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, str->capacity);
|
output = wapp_str8_alloc_buf(allocator, str->capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_ALLOC_SUBSTR;
|
goto RETURN_ALLOC_SUBSTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->size = end - start;
|
output->size = end - start;
|
||||||
memcpy(output->buf, str->buf + start, output->size);
|
memcpy(output->buf, str->buf + start, output->size);
|
||||||
|
|
||||||
RETURN_ALLOC_SUBSTR:
|
RETURN_ALLOC_SUBSTR:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str) {
|
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_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));
|
wapp_mem_allocator_free(allocator, (void **)str, STR8_BUF_ALLOC_SIZE((*str)->capacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
c8 wapp_str8_get(const Str8 *str, u64 index) {
|
c8 wapp_str8_get(const Str8 *str, u64 index) {
|
||||||
if (index >= str->size) {
|
if (index >= str->size) {
|
||||||
return '\0';
|
return '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
return str->buf[index];
|
return str->buf[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
|
void wapp_str8_set(Str8 *str, u64 index, c8 c) {
|
||||||
if (index >= str->size) {
|
if (index >= str->size) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
str->buf[index] = c;
|
str->buf[index] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_push_back(Str8 *str, c8 c) {
|
void wapp_str8_push_back(Str8 *str, c8 c) {
|
||||||
if (!(str->size < str->capacity)) {
|
if (!(str->size < str->capacity)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 index = (str->size)++;
|
u64 index = (str->size)++;
|
||||||
wapp_str8_set(str, index, c);
|
wapp_str8_set(str, index, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
|
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2) {
|
||||||
if (s1->size != s2->size) {
|
if (s1->size != s2->size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wapp_str8_equal_to_count(s1, s2, s1->size);
|
return wapp_str8_equal_to_count(s1, s2, s1->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
|
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count) {
|
||||||
if (!s1 || !s2) {
|
if (!s1 || !s2) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return memcmp(s1->buf, s2->buf, count) == 0;
|
return memcmp(s1->buf, s2->buf, count) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
|
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end) {
|
||||||
if (start >= str->size || start >= end) {
|
if (start >= str->size || start >= end) {
|
||||||
start = str->size;
|
start = str->size;
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end > str->size) {
|
if (end > str->size) {
|
||||||
end = str->size;
|
end = str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Str8RO){
|
return (Str8RO){
|
||||||
.capacity = end - start,
|
.capacity = end - start,
|
||||||
.size = end - start,
|
.size = end - start,
|
||||||
.buf = str->buf + start,
|
.buf = str->buf + start,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_alloc_concat(const Allocator *allocator, Str8 *dst, Str8RO *src) {
|
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");
|
wapp_debug_assert(allocator != NULL && dst != NULL && src != NULL, "`allocator`, `dst` and `src` should not be NULL");
|
||||||
|
|
||||||
Str8 *output = NULL;
|
Str8 *output = NULL;
|
||||||
u64 remaining = dst->capacity - dst->size;
|
u64 remaining = dst->capacity - dst->size;
|
||||||
if (src->size <= remaining) {
|
if (src->size <= remaining) {
|
||||||
output = dst;
|
output = dst;
|
||||||
goto SOURCE_STRING_STR8_CONCAT;
|
goto SOURCE_STRING_STR8_CONCAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 capacity = dst->capacity + src->size;
|
u64 capacity = dst->capacity + src->size;
|
||||||
|
|
||||||
output = wapp_str8_alloc_buf(allocator, capacity);
|
output = wapp_str8_alloc_buf(allocator, capacity);
|
||||||
if (!output) {
|
if (!output) {
|
||||||
goto RETURN_STR8_CONCAT;
|
goto RETURN_STR8_CONCAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(output, dst);
|
wapp_str8_concat_capped(output, dst);
|
||||||
|
|
||||||
SOURCE_STRING_STR8_CONCAT:
|
SOURCE_STRING_STR8_CONCAT:
|
||||||
wapp_str8_concat_capped(output, src);
|
wapp_str8_concat_capped(output, src);
|
||||||
|
|
||||||
RETURN_STR8_CONCAT:
|
RETURN_STR8_CONCAT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
|
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 remaining = dst->capacity - dst->size;
|
u64 remaining = dst->capacity - dst->size;
|
||||||
u64 to_copy = remaining < src->size ? remaining : src->size;
|
u64 to_copy = remaining < src->size ? remaining : src->size;
|
||||||
|
|
||||||
memcpy(dst->buf + dst->size, src->buf, to_copy);
|
memcpy(dst->buf + dst->size, src->buf, to_copy);
|
||||||
dst->size += to_copy;
|
dst->size += to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *src) {
|
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");
|
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 length = strlen(src);
|
u64 length = strlen(src);
|
||||||
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
|
u64 to_copy = length <= dst->capacity ? length : dst->capacity;
|
||||||
|
|
||||||
memset(dst->buf, 0, dst->size);
|
memset(dst->buf, 0, dst->size);
|
||||||
memcpy(dst->buf, src, to_copy);
|
memcpy(dst->buf, src, to_copy);
|
||||||
dst->size = to_copy;
|
dst->size = to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
|
void wapp_str8_copy_str8_capped(Str8 *dst, Str8RO *src) {
|
||||||
wapp_debug_assert(dst != NULL && src != NULL, "`dst` and `src` should not be NULL");
|
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;
|
u64 to_copy = src->size <= dst->capacity ? src->size : dst->capacity;
|
||||||
|
|
||||||
memset(dst->buf, 0, dst->size);
|
memset(dst->buf, 0, dst->size);
|
||||||
memcpy(dst->buf, src->buf, to_copy);
|
memcpy(dst->buf, src->buf, to_copy);
|
||||||
dst->size = to_copy;
|
dst->size = to_copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity) {
|
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");
|
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;
|
u64 to_copy = src->size < dst_capacity ? src->size : dst_capacity - 1;
|
||||||
|
|
||||||
memset(dst, 0, dst_capacity);
|
memset(dst, 0, dst_capacity);
|
||||||
memcpy(dst, src->buf, to_copy);
|
memcpy(dst, src->buf, to_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_format(Str8 *dst, const char *format, ...) {
|
void wapp_str8_format(Str8 *dst, const char *format, ...) {
|
||||||
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
|
wapp_debug_assert(dst != NULL && format != NULL, "`dst` and `format` should not be NULL");
|
||||||
|
|
||||||
va_list args1;
|
va_list args1;
|
||||||
va_list args2;
|
va_list args2;
|
||||||
|
|
||||||
va_start(args1, format);
|
va_start(args1, format);
|
||||||
va_copy(args2, args1);
|
va_copy(args2, args1);
|
||||||
|
|
||||||
u64 total_size = vsnprintf(NULL, 0, format, args1);
|
u64 total_size = vsnprintf(NULL, 0, format, args1);
|
||||||
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
|
dst->size = total_size <= dst->capacity ? total_size : dst->capacity;
|
||||||
|
|
||||||
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
|
vsnprintf((char *)(dst->buf), dst->capacity, format, args2);
|
||||||
|
|
||||||
va_end(args1);
|
va_end(args1);
|
||||||
va_end(args2);
|
va_end(args2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_to_lower(Str8 *dst, Str8RO *src) {
|
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(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = src->size;
|
dst->size = src->size;
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
|
wapp_str8_set(dst, index, (u8)tolower(wapp_str8_get(src, index)));
|
||||||
++index;
|
++index;
|
||||||
running = index < src->size;
|
running = index < src->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_to_upper(Str8 *dst, Str8RO *src) {
|
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(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= src->capacity, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = src->size;
|
dst->size = src->size;
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 index = 0;
|
u64 index = 0;
|
||||||
b8 running = true;
|
b8 running = true;
|
||||||
while (running) {
|
while (running) {
|
||||||
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
|
wapp_str8_set(dst, index, (u8)toupper(wapp_str8_get(src, index)));
|
||||||
++index;
|
++index;
|
||||||
running = index < src->size;
|
running = index < src->size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src) {
|
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src) {
|
||||||
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
wapp_debug_assert(src != NULL && dst != NULL, "`dst` and `src` should not be NULL");
|
||||||
|
|
||||||
u64 size = src->count * src->item_size;
|
u64 size = src->count * src->item_size;
|
||||||
|
|
||||||
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
|
wapp_debug_assert(dst->capacity >= size, "`dst` does not have enough capacity");
|
||||||
|
|
||||||
dst->size = size;
|
dst->size = size;
|
||||||
memcpy(dst->buf, src->items, size);
|
memcpy(dst->buf, src->items, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
|
i64 wapp_str8_find(Str8RO *str, Str8RO substr) {
|
||||||
if (!str || substr.size > str->size) {
|
if (!str || substr.size > str->size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
u64 char_index = 0;
|
u64 char_index = 0;
|
||||||
b8 running = char_index < str->size;
|
b8 running = char_index < str->size;
|
||||||
while (running) {
|
while (running) {
|
||||||
const c8 *sub = str->buf + char_index;
|
const c8 *sub = str->buf + char_index;
|
||||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||||
return char_index;
|
return char_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
++char_index;
|
++char_index;
|
||||||
running = char_index < str->size;
|
running = char_index < str->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
|
i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) {
|
||||||
if (!str || substr.size > str->size) {
|
if (!str || substr.size > str->size) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
i64 char_index = str->size - substr.size;
|
i64 char_index = str->size - substr.size;
|
||||||
b8 running = char_index >= 0;
|
b8 running = char_index >= 0;
|
||||||
while (running) {
|
while (running) {
|
||||||
const c8 *sub = str->buf + char_index;
|
const c8 *sub = str->buf + char_index;
|
||||||
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
if (memcmp(sub, substr.buf, substr.size) == 0) {
|
||||||
return char_index;
|
return char_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
--char_index;
|
--char_index;
|
||||||
running = char_index >= 0;
|
running = char_index >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8List *wapp_str8_split_with_max(const Allocator *allocator, Str8RO *str, Str8RO *delimiter, i64 max_splits) {
|
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");
|
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||||
|
|
||||||
Str8List *output = wapp_dbl_list_alloc(Str8, Str8List, allocator);
|
Str8List *output = wapp_dbl_list_alloc(Str8, Str8List, allocator);
|
||||||
|
|
||||||
if (delimiter->size > str->size) {
|
if (delimiter->size > str->size) {
|
||||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node) {
|
if (node) {
|
||||||
node->item = full;
|
node->item = full;
|
||||||
wapp_dbl_list_push_back(Str8, output, node);
|
wapp_dbl_list_push_back(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto RETURN_STR8_SPLIT;
|
goto RETURN_STR8_SPLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 start = 0;
|
i64 start = 0;
|
||||||
i64 end = 0;
|
i64 end = 0;
|
||||||
i64 splits = 0;
|
i64 splits = 0;
|
||||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8 *before_str;
|
Str8 *before_str;
|
||||||
|
|
||||||
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
|
while ((end = wapp_str8_find(rest, *delimiter)) != -1) {
|
||||||
if (max_splits > 0 && splits >= max_splits) {
|
if (max_splits > 0 && splits >= max_splits) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
|
before_str = wapp_str8_alloc_substr(allocator, str, start, start + end);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node && before_str) {
|
if (node && before_str) {
|
||||||
node->item = before_str;
|
node->item = before_str;
|
||||||
wapp_dbl_list_push_back(Str8, output, node);
|
wapp_dbl_list_push_back(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||||
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
|
rest = wapp_str8_alloc_substr(allocator, str, start + end + delimiter->size, str->size);
|
||||||
start += end + delimiter->size;
|
start += end + delimiter->size;
|
||||||
|
|
||||||
++splits;
|
++splits;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the last part of the string after the delimiter is added to the list
|
// 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);
|
rest = wapp_str8_alloc_substr(allocator, str, start, str->size);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node && rest) {
|
if (node && rest) {
|
||||||
node->item = rest;
|
node->item = rest;
|
||||||
wapp_dbl_list_push_back(Str8, output, node);
|
wapp_dbl_list_push_back(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_STR8_SPLIT:
|
RETURN_STR8_SPLIT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8List *wapp_str8_rsplit_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) {
|
||||||
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
wapp_debug_assert(allocator != NULL && str != NULL && delimiter != NULL, "`allocator`, `str` and `delimiter` should not be NULL");
|
||||||
|
|
||||||
Str8List *output = wapp_dbl_list_alloc(Str8, Str8List, allocator);
|
Str8List *output = wapp_dbl_list_alloc(Str8, Str8List, allocator);
|
||||||
|
|
||||||
if (delimiter->size > str->size) {
|
if (delimiter->size > str->size) {
|
||||||
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
Str8 *full = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node && full) {
|
if (node && full) {
|
||||||
node->item = full;
|
node->item = full;
|
||||||
wapp_dbl_list_push_back(Str8, output, node);
|
wapp_dbl_list_push_back(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto RETURN_STR8_SPLIT;
|
goto RETURN_STR8_SPLIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 end = 0;
|
i64 end = 0;
|
||||||
i64 splits = 0;
|
i64 splits = 0;
|
||||||
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
Str8 *rest = wapp_str8_alloc_str8(allocator, str);
|
||||||
Str8 *after_str;
|
Str8 *after_str;
|
||||||
|
|
||||||
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
|
while ((end = wapp_str8_rfind(rest, *delimiter)) != -1) {
|
||||||
if (max_splits > 0 && splits >= max_splits) {
|
if (max_splits > 0 && splits >= max_splits) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
|
after_str = wapp_str8_alloc_substr(allocator, rest, end + delimiter->size, str->size);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node) {
|
if (node) {
|
||||||
node->item = after_str;
|
node->item = after_str;
|
||||||
wapp_dbl_list_push_front(Str8, output, node);
|
wapp_dbl_list_push_front(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
wapp_mem_allocator_free(allocator, (void **)&rest, sizeof(Str8));
|
||||||
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
|
rest = wapp_str8_alloc_substr(allocator, rest, 0, end);
|
||||||
|
|
||||||
++splits;
|
++splits;
|
||||||
}
|
}
|
||||||
|
|
||||||
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
|
rest = wapp_str8_alloc_substr(allocator, str, 0, rest->size);
|
||||||
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
Str8Node *node = wapp_dbl_list_node_alloc(Str8, Str8Node, allocator);
|
||||||
if (node && rest) {
|
if (node && rest) {
|
||||||
node->item = rest;
|
node->item = rest;
|
||||||
wapp_dbl_list_push_front(Str8, output, node);
|
wapp_dbl_list_push_front(Str8, output, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_STR8_SPLIT:
|
RETURN_STR8_SPLIT:
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter) {
|
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");
|
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));
|
u64 capacity = wapp_str8_list_total_size(list) + (delimiter->size * (list->node_count - 1));
|
||||||
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
|
Str8 *output = wapp_str8_alloc_buf(allocator, capacity * 2);
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
Str8Node *node;
|
Str8Node *node;
|
||||||
u64 node_index = 0;
|
u64 node_index = 0;
|
||||||
b8 running = node_index < list->node_count;
|
b8 running = node_index < list->node_count;
|
||||||
while (running) {
|
while (running) {
|
||||||
node = wapp_dbl_list_get(Str8, Str8Node, list, node_index);
|
node = wapp_dbl_list_get(Str8, Str8Node, list, node_index);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_str8_concat_capped(output, node->item);
|
wapp_str8_concat_capped(output, node->item);
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Comparison extracted to variable to silence
|
// NOTE (Abdelrahman): Comparison extracted to variable to silence
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
b8 not_last = node_index + 1 < list->node_count;
|
b8 not_last = node_index + 1 < list->node_count;
|
||||||
if (not_last) {
|
if (not_last) {
|
||||||
wapp_str8_concat_capped(output, delimiter);
|
wapp_str8_concat_capped(output, delimiter);
|
||||||
}
|
}
|
||||||
|
|
||||||
++node_index;
|
++node_index;
|
||||||
running = node_index < list->node_count;
|
running = node_index < list->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 wapp_str8_list_total_size(const Str8List *list) {
|
u64 wapp_str8_list_total_size(const Str8List *list) {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
// NOTE (Abdelrahman): Uses a while loop instead of a for loop to get rid of
|
||||||
// MSVC Spectre mitigation warnings
|
// MSVC Spectre mitigation warnings
|
||||||
Str8Node* node;
|
Str8Node* node;
|
||||||
u64 node_index = 0;
|
u64 node_index = 0;
|
||||||
u64 output = 0;
|
u64 output = 0;
|
||||||
b8 running = node_index < list->node_count;
|
b8 running = node_index < list->node_count;
|
||||||
while (running) {
|
while (running) {
|
||||||
node = wapp_dbl_list_get(Str8, Str8Node, list, node_index);
|
node = wapp_dbl_list_get(Str8, Str8Node, list, node_index);
|
||||||
if (!node) {
|
if (!node) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
output += node->item->size;
|
output += node->item->size;
|
||||||
++node_index;
|
++node_index;
|
||||||
running = node_index < list->node_count;
|
running = node_index < list->node_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ BEGIN_C_LINKAGE
|
|||||||
|
|
||||||
typedef struct str8 Str8;
|
typedef struct str8 Str8;
|
||||||
struct str8 {
|
struct str8 {
|
||||||
u64 capacity;
|
u64 capacity;
|
||||||
u64 size;
|
u64 size;
|
||||||
c8 *buf;
|
c8 *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef const Str8 Str8RO;
|
typedef const Str8 Str8RO;
|
||||||
@@ -36,17 +36,17 @@ typedef const Str8 Str8RO;
|
|||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||||
#define wapp_str8_buf(CAPACITY) ([&](){ \
|
#define wapp_str8_buf(CAPACITY) ([&](){ \
|
||||||
wapp_persist c8 buf[CAPACITY] = {}; \
|
wapp_persist c8 buf[CAPACITY] = {}; \
|
||||||
memset(buf, 0, CAPACITY); \
|
memset(buf, 0, CAPACITY); \
|
||||||
return Str8{CAPACITY, 0, buf}; \
|
return Str8{CAPACITY, 0, buf}; \
|
||||||
}())
|
}())
|
||||||
|
|
||||||
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
// Uses a lambda to achieve the same behaviour achieved by the C macro
|
||||||
#define wapp_str8_lit(STRING) ([&]() { \
|
#define wapp_str8_lit(STRING) ([&]() { \
|
||||||
wapp_persist c8 buf[sizeof(STRING) * 2] = {}; \
|
wapp_persist c8 buf[sizeof(STRING) * 2] = {}; \
|
||||||
memcpy(buf, STRING, sizeof(STRING)); \
|
memcpy(buf, STRING, sizeof(STRING)); \
|
||||||
return Str8{(sizeof(STRING) - 1) * 2, sizeof(STRING) - 1, buf}; \
|
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(STRING) Str8RO{sizeof(STRING) - 1, sizeof(STRING) - 1, (c8 *)STRING}
|
||||||
@@ -56,29 +56,29 @@ typedef const Str8 Str8RO;
|
|||||||
|
|
||||||
// Utilises the fact that memcpy returns pointer to dest buffer and that getting
|
// 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
|
// 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, \
|
#define wapp_str8_lit(STRING) ((Str8){.capacity = (sizeof(STRING) - 1) * 2, \
|
||||||
.size = sizeof(STRING) - 1, \
|
.size = sizeof(STRING) - 1, \
|
||||||
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), STRING, sizeof(STRING))})
|
.buf = memcpy(&((c8 [sizeof(STRING) * 2]){0}), STRING, sizeof(STRING))})
|
||||||
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
|
#define wapp_str8_lit_ro(STRING) ((Str8RO){.capacity = sizeof(STRING) - 1, \
|
||||||
.size = sizeof(STRING) - 1, \
|
.size = sizeof(STRING) - 1, \
|
||||||
.buf = (c8 *)STRING})
|
.buf = (c8 *)STRING})
|
||||||
// To be used only when initialising a static storage variable in compilers that don't support
|
// 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
|
// 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
|
// 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, \
|
#define wapp_str8_lit_ro_initialiser_list(STRING) {.capacity = sizeof(STRING) - 1, \
|
||||||
.size = sizeof(STRING) - 1, \
|
.size = sizeof(STRING) - 1, \
|
||||||
.buf = (c8 *)STRING}
|
.buf = (c8 *)STRING}
|
||||||
#endif // !WAPP_PLATFORM_CPP
|
#endif // !WAPP_PLATFORM_CPP
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Str8 allocated buffers
|
* Str8 allocated buffers
|
||||||
*/
|
*/
|
||||||
Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity);
|
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_and_fill_buf(const Allocator *allocator, u64 capacity);
|
||||||
Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str);
|
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_str8(const Allocator *allocator, Str8RO *str);
|
||||||
Str8 *wapp_str8_alloc_substr(const Allocator *allocator, Str8RO *str, u64 start, u64 end);
|
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);
|
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.
|
// 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.
|
// No need to use it for allocators like Arena.
|
||||||
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
|
void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
|
||||||
@@ -86,20 +86,20 @@ void wapp_str8_dealloc_buf(const Allocator *allocator, Str8 **str);
|
|||||||
/**
|
/**
|
||||||
* Str8 utilities
|
* Str8 utilities
|
||||||
*/
|
*/
|
||||||
c8 wapp_str8_get(Str8RO *str, u64 index);
|
c8 wapp_str8_get(Str8RO *str, u64 index);
|
||||||
void wapp_str8_set(Str8 *str, u64 index, c8 c);
|
void wapp_str8_set(Str8 *str, u64 index, c8 c);
|
||||||
void wapp_str8_push_back(Str8 *str, c8 c);
|
void wapp_str8_push_back(Str8 *str, c8 c);
|
||||||
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
|
b8 wapp_str8_equal(Str8RO *s1, Str8RO *s2);
|
||||||
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
|
b8 wapp_str8_equal_to_count(Str8RO* s1, Str8RO* s2, u64 count);
|
||||||
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
|
Str8 wapp_str8_slice(Str8RO *str, u64 start, u64 end);
|
||||||
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
|
void wapp_str8_concat_capped(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_copy_cstr_capped(Str8 *dst, const char *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_str8_capped(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_copy_to_cstr(char *dst, Str8RO *src, u64 dst_capacity);
|
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_format(Str8 *dst, const char *format, ...);
|
||||||
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
|
void wapp_str8_to_lower(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
|
void wapp_str8_to_upper(Str8 *dst, Str8RO *src);
|
||||||
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src);
|
void wapp_str8_from_bytes(Str8 *dst, const U8Array *src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Str8 find functions
|
* Str8 find functions
|
||||||
@@ -112,9 +112,9 @@ i64 wapp_str8_rfind(Str8RO *str, Str8RO substr);
|
|||||||
*/
|
*/
|
||||||
#define wapp_str8_split(ALLOCATOR, STR, DELIMITER) wapp_str8_split_with_max(ALLOCATOR, STR, DELIMITER, -1)
|
#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)
|
#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_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);
|
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 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *delimiter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Str8 list utilities
|
* Str8 list utilities
|
||||||
@@ -128,18 +128,18 @@ END_C_LINKAGE
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr bool is_lvalue(T&&) {
|
constexpr bool is_lvalue(T&&) {
|
||||||
return std::is_lvalue_reference<T>{};
|
return std::is_lvalue_reference<T>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#define wapp_str8_node_from_cstr(STRING) wapp_dbl_list_node(Str8, Str8Node, [&]() { \
|
#define wapp_str8_node_from_cstr(STRING) wapp_dbl_list_node(Str8, Str8Node, [&]() { \
|
||||||
wapp_persist Str8 str = wapp_str8_lit(STRING); \
|
wapp_persist Str8 str = wapp_str8_lit(STRING); \
|
||||||
return &str; \
|
return &str; \
|
||||||
}())
|
}())
|
||||||
#define wapp_str8_node_from_str8(STRING) wapp_dbl_list_node(Str8, Str8Node, [&]() { \
|
#define wapp_str8_node_from_str8(STRING) wapp_dbl_list_node(Str8, Str8Node, [&]() { \
|
||||||
if (is_lvalue(STRING)) { return &STRING; } \
|
if (is_lvalue(STRING)) { return &STRING; } \
|
||||||
\
|
\
|
||||||
wapp_persist Str8 str = STRING; \
|
wapp_persist Str8 str = STRING; \
|
||||||
return &str; \
|
return &str; \
|
||||||
}())
|
}())
|
||||||
#else
|
#else
|
||||||
#define wapp_str8_node_from_cstr(STRING) wapp_dbl_list_node(Str8, Str8Node, &wapp_str8_lit(STRING))
|
#define wapp_str8_node_from_cstr(STRING) wapp_dbl_list_node(Str8, Str8Node, &wapp_str8_lit(STRING))
|
||||||
|
|||||||
@@ -7,20 +7,20 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
#if defined(WAPP_PLATFORM_C) && WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C11_VERSION && !defined(WAPP_PLATFORM_APPLE)
|
||||||
#include <uchar.h>
|
#include <uchar.h>
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
#if WAPP_PLATFORM_C_VERSION >= WAPP_PLATFORM_C23_VERSION
|
||||||
#define c8 char8_t
|
#define c8 char8_t
|
||||||
#else
|
#else
|
||||||
#define c8 uint8_t
|
#define c8 uint8_t
|
||||||
#endif // !WAPP_PLATFORM_C23_VERSION
|
#endif // !WAPP_PLATFORM_C23_VERSION
|
||||||
|
|
||||||
#define c16 char16_t
|
#define c16 char16_t
|
||||||
#define c32 char32_t
|
#define c32 char32_t
|
||||||
#else
|
#else
|
||||||
#define c8 uint8_t
|
#define c8 uint8_t
|
||||||
#define c16 uint16_t
|
#define c16 uint16_t
|
||||||
#define c32 uint32_t
|
#define c32 uint32_t
|
||||||
#endif // !WAPP_PLATFORM_C
|
#endif // !WAPP_PLATFORM_C
|
||||||
|
|
||||||
#define u8 uint8_t
|
#define u8 uint8_t
|
||||||
|
|||||||
@@ -16,42 +16,42 @@ BEGIN_C_LINKAGE
|
|||||||
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
#define wapp_static_assert(EXPR, MSG) extern char ASSERTION_FAILED[EXPR ? 1 : -1]
|
||||||
|
|
||||||
#ifndef WAPP_NO_RUNTIME_ASSERT
|
#ifndef WAPP_NO_RUNTIME_ASSERT
|
||||||
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
#define wapp_runtime_assert(EXPR, MSG) __wapp_runtime_assert(EXPR, MSG)
|
||||||
#else
|
#else
|
||||||
#define wapp_runtime_assert(EXPR, MSG)
|
#define wapp_runtime_assert(EXPR, MSG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WAPP_DEBUG_ASSERT
|
#ifdef WAPP_DEBUG_ASSERT
|
||||||
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
#define wapp_debug_assert(EXPR, MSG) wapp_runtime_assert(EXPR, MSG)
|
||||||
#else
|
#else
|
||||||
#define wapp_debug_assert(EXPR, MSG)
|
#define wapp_debug_assert(EXPR, MSG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_WINDOWS
|
#ifdef WAPP_PLATFORM_WINDOWS
|
||||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||||
__pragma(warning(push)) \
|
__pragma(warning(push)) \
|
||||||
__pragma(warning(disable:4127)) \
|
__pragma(warning(disable:4127)) \
|
||||||
if (!(EXPR)) { \
|
if (!(EXPR)) { \
|
||||||
__pragma(warning(pop)) \
|
__pragma(warning(pop)) \
|
||||||
__runtime_assert_failed(EXPR, MSG); \
|
__runtime_assert_failed(EXPR, MSG); \
|
||||||
} \
|
} \
|
||||||
} while(false)
|
} while(false)
|
||||||
#else
|
#else
|
||||||
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
#define __wapp_runtime_assert(EXPR, MSG) do { \
|
||||||
if (!(EXPR)) { \
|
if (!(EXPR)) { \
|
||||||
__runtime_assert_failed(EXPR, MSG); \
|
__runtime_assert_failed(EXPR, MSG); \
|
||||||
} \
|
} \
|
||||||
} while(false)
|
} while(false)
|
||||||
#endif // !WAPP_PLATFORM_WINDOWS
|
#endif // !WAPP_PLATFORM_WINDOWS
|
||||||
|
|
||||||
#define __runtime_assert_failed(EXPR, MSG) do { \
|
#define __runtime_assert_failed(EXPR, MSG) do { \
|
||||||
fprintf( \
|
fprintf( \
|
||||||
stderr, \
|
stderr, \
|
||||||
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
"%s:%d (In function `%s`): Assertion failed (%" PRIu32 ")\nDiagnostic: %s\n\n", \
|
||||||
__FILE__, __LINE__, __func__, \
|
__FILE__, __LINE__, __func__, \
|
||||||
EXPR, MSG \
|
EXPR, MSG \
|
||||||
); \
|
); \
|
||||||
abort(); \
|
abort(); \
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -16,35 +16,35 @@ BEGIN_C_LINKAGE
|
|||||||
#define PiB(SIZE) (((u64)SIZE) << 50)
|
#define PiB(SIZE) (((u64)SIZE) << 50)
|
||||||
#define EiB(SIZE) (((u64)SIZE) << 60)
|
#define EiB(SIZE) (((u64)SIZE) << 60)
|
||||||
|
|
||||||
#define KB(SIZE) (((u64)SIZE) * 1000llu)
|
#define KB(SIZE) (((u64)SIZE) * 1000llu)
|
||||||
#define MB(SIZE) (KB(SIZE) * 1000llu)
|
#define MB(SIZE) (KB(SIZE) * 1000llu)
|
||||||
#define GB(SIZE) (MB(SIZE) * 1000llu)
|
#define GB(SIZE) (MB(SIZE) * 1000llu)
|
||||||
#define TB(SIZE) (GB(SIZE) * 1000llu)
|
#define TB(SIZE) (GB(SIZE) * 1000llu)
|
||||||
#define PB(SIZE) (TB(SIZE) * 1000llu)
|
#define PB(SIZE) (TB(SIZE) * 1000llu)
|
||||||
#define EB(SIZE) (PB(SIZE) * 1000llu)
|
#define EB(SIZE) (PB(SIZE) * 1000llu)
|
||||||
|
|
||||||
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
#define wapp_misc_utils_padding_size(SIZE) u8 reserved_padding[sizeof(void *) - ((SIZE) % sizeof(void *))]
|
||||||
|
|
||||||
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
#define U64_RSHIFT_OR_1(X) (((u64)X) | (((u64)X) >> 1))
|
||||||
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
#define U64_RSHIFT_OR_2(X) (((u64)X) | (((u64)X) >> 2))
|
||||||
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
|
#define U64_RSHIFT_OR_4(X) (((u64)X) | (((u64)X) >> 4))
|
||||||
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
#define U64_RSHIFT_OR_8(X) (((u64)X) | (((u64)X) >> 8))
|
||||||
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
|
#define U64_RSHIFT_OR_16(X) (((u64)X) | (((u64)X) >> 16))
|
||||||
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
#define U64_RSHIFT_OR_32(X) (((u64)X) | (((u64)X) >> 32))
|
||||||
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
#define wapp_misc_utils_u64_round_up_pow2(X) ( \
|
||||||
( \
|
( \
|
||||||
U64_RSHIFT_OR_32( \
|
U64_RSHIFT_OR_32( \
|
||||||
U64_RSHIFT_OR_16( \
|
U64_RSHIFT_OR_16( \
|
||||||
U64_RSHIFT_OR_8( \
|
U64_RSHIFT_OR_8( \
|
||||||
U64_RSHIFT_OR_4( \
|
U64_RSHIFT_OR_4( \
|
||||||
U64_RSHIFT_OR_2( \
|
U64_RSHIFT_OR_2( \
|
||||||
U64_RSHIFT_OR_1(X - 1) \
|
U64_RSHIFT_OR_1(X - 1) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) \
|
) \
|
||||||
) + 1 \
|
) + 1 \
|
||||||
)
|
)
|
||||||
|
|
||||||
#ifdef WAPP_PLATFORM_CPP
|
#ifdef WAPP_PLATFORM_CPP
|
||||||
|
|||||||
@@ -4,111 +4,111 @@
|
|||||||
#define PLATFORM_H
|
#define PLATFORM_H
|
||||||
|
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
#define WAPP_PLATFORM_ANDROID
|
#define WAPP_PLATFORM_ANDROID
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
#define WAPP_PLATFORM_FREE_BSD
|
#define WAPP_PLATFORM_FREE_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
#define WAPP_PLATFORM_NET_BSD
|
#define WAPP_PLATFORM_NET_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
#define WAPP_PLATFORM_OPEN_BSD
|
#define WAPP_PLATFORM_OPEN_BSD
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__DragonFly__)
|
#elif defined(__DragonFly__)
|
||||||
#define WAPP_PLATFORM_DRAGON_FLY
|
#define WAPP_PLATFORM_DRAGON_FLY
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__bsdi__)
|
#elif defined(__bsdi__)
|
||||||
#define WAPP_PLATFORM_BSD
|
#define WAPP_PLATFORM_BSD
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__gnu_linux__)
|
#elif defined(__linux__) || defined(linux) || defined(__linux) || defined(__gnu_linux__)
|
||||||
#define WAPP_PLATFORM_LINUX
|
#define WAPP_PLATFORM_LINUX
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__GNU__) || defined(__gnu_hurd__)
|
#elif defined(__GNU__) || defined(__gnu_hurd__)
|
||||||
#define WAPP_PLATFORM_GNU
|
#define WAPP_PLATFORM_GNU
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif defined(__APPLE__) || defined(__MACH__)
|
#elif defined(__APPLE__) || defined(__MACH__)
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
#if TARGET_OS_IPHONE
|
#if TARGET_OS_IPHONE
|
||||||
#define WAPP_PLATFORM_IOS
|
#define WAPP_PLATFORM_IOS
|
||||||
#define WAPP_PLATFORM_APPLE
|
#define WAPP_PLATFORM_APPLE
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#elif TARGET_OS_MAC
|
#elif TARGET_OS_MAC
|
||||||
#define WAPP_PLATFORM_MACOS
|
#define WAPP_PLATFORM_MACOS
|
||||||
#define WAPP_PLATFORM_APPLE
|
#define WAPP_PLATFORM_APPLE
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised Apple platform"
|
#error "Unrecognised Apple platform"
|
||||||
#endif
|
#endif
|
||||||
#elif defined(_WIN64)
|
#elif defined(_WIN64)
|
||||||
#define WAPP_PLATFORM_WINDOWS64
|
#define WAPP_PLATFORM_WINDOWS64
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#define WAPP_PLATFORM_WINDOWS32
|
#define WAPP_PLATFORM_WINDOWS32
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(__CYGWIN__)
|
#elif defined(__CYGWIN__)
|
||||||
#define WAPP_PLATFORM_CYGWIN
|
#define WAPP_PLATFORM_CYGWIN
|
||||||
#define WAPP_PLATFORM_WINDOWS
|
#define WAPP_PLATFORM_WINDOWS
|
||||||
#elif defined(__unix__) || defined(__unix)
|
#elif defined(__unix__) || defined(__unix)
|
||||||
#define WAPP_PLATFORM_UNIX
|
#define WAPP_PLATFORM_UNIX
|
||||||
#define WAPP_PLATFORM_POSIX
|
#define WAPP_PLATFORM_POSIX
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised platform"
|
#error "Unrecognised platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define WAPP_PLATFORM_CPP
|
#define WAPP_PLATFORM_CPP
|
||||||
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
#define WAPP_PLATFORM_CPP_VERSION __cplusplus
|
||||||
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
#define WAPP_PLATFORM_CPP98_VERSION 199711L
|
||||||
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
#define WAPP_PLATFORM_CPP11_VERSION 201103L
|
||||||
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
#define WAPP_PLATFORM_CPP14_VERSION 201402L
|
||||||
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
#define WAPP_PLATFORM_CPP17_VERSION 201703L
|
||||||
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
#define WAPP_PLATFORM_CPP20_VERSION 202002L
|
||||||
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
#define WAPP_PLATFORM_CPP23_VERSION 202302L
|
||||||
|
|
||||||
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
#if WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP98_VERSION
|
||||||
#define WAPP_PLATFORM_CPP98
|
#define WAPP_PLATFORM_CPP98
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP11_VERSION
|
||||||
#define WAPP_PLATFORM_CPP11
|
#define WAPP_PLATFORM_CPP11
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP14_VERSION
|
||||||
#define WAPP_PLATFORM_CPP14
|
#define WAPP_PLATFORM_CPP14
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP17_VERSION
|
||||||
#define WAPP_PLATFORM_CPP17
|
#define WAPP_PLATFORM_CPP17
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP20_VERSION
|
||||||
#define WAPP_PLATFORM_CPP20
|
#define WAPP_PLATFORM_CPP20
|
||||||
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
#elif WAPP_PLATFORM_CPP_VERSION == WAPP_PLATFORM_CPP23_VERSION
|
||||||
#define WAPP_PLATFORM_CPP23
|
#define WAPP_PLATFORM_CPP23
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised C++ version"
|
#error "Unrecognised C++ version"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define WAPP_PLATFORM_C
|
#define WAPP_PLATFORM_C
|
||||||
|
|
||||||
#if defined(__STDC_VERSION__)
|
#if defined(__STDC_VERSION__)
|
||||||
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
#define WAPP_PLATFORM_C_VERSION __STDC_VERSION__
|
||||||
#define WAPP_PLATFORM_C99_VERSION 199901L
|
#define WAPP_PLATFORM_C99_VERSION 199901L
|
||||||
#define WAPP_PLATFORM_C11_VERSION 201112L
|
#define WAPP_PLATFORM_C11_VERSION 201112L
|
||||||
#define WAPP_PLATFORM_C17_VERSION 201710L
|
#define WAPP_PLATFORM_C17_VERSION 201710L
|
||||||
#define WAPP_PLATFORM_C23_VERSION 202311L
|
#define WAPP_PLATFORM_C23_VERSION 202311L
|
||||||
|
|
||||||
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
#if WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C99_VERSION
|
||||||
#define WAPP_PLATFORM_C99
|
#define WAPP_PLATFORM_C99
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C11_VERSION
|
||||||
#define WAPP_PLATFORM_C11
|
#define WAPP_PLATFORM_C11
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C17_VERSION
|
||||||
#define WAPP_PLATFORM_C17
|
#define WAPP_PLATFORM_C17
|
||||||
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
#elif WAPP_PLATFORM_C_VERSION == WAPP_PLATFORM_C23_VERSION
|
||||||
#define WAPP_PLATFORM_C23
|
#define WAPP_PLATFORM_C23
|
||||||
#else
|
#else
|
||||||
#error "Unrecognised C version"
|
#error "Unrecognised C version"
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#define WAPP_PLATFORM_C89
|
#define WAPP_PLATFORM_C89
|
||||||
#endif
|
#endif
|
||||||
#endif // !__cplusplus
|
#endif // !__cplusplus
|
||||||
|
|
||||||
#endif // !PLATFORM_H
|
#endif // !PLATFORM_H
|
||||||
|
|||||||
@@ -11,48 +11,48 @@
|
|||||||
|
|
||||||
typedef struct uuid4 UUID4;
|
typedef struct uuid4 UUID4;
|
||||||
struct uuid4 {
|
struct uuid4 {
|
||||||
u64 high;
|
u64 high;
|
||||||
u64 low;
|
u64 low;
|
||||||
};
|
};
|
||||||
|
|
||||||
wapp_intern UUID4 generate_uuid4(void);
|
wapp_intern UUID4 generate_uuid4(void);
|
||||||
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid);
|
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid);
|
||||||
|
|
||||||
WUUID *wapp_uuid_init_uuid4(WUUID *uuid) {
|
WUUID *wapp_uuid_init_uuid4(WUUID *uuid) {
|
||||||
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
|
wapp_debug_assert(uuid != NULL, "`uuid` should not be NULL");
|
||||||
|
|
||||||
UUID4 uuid4 = generate_uuid4();
|
UUID4 uuid4 = generate_uuid4();
|
||||||
uuid4_to_uuid(&uuid4, uuid);
|
uuid4_to_uuid(&uuid4, uuid);
|
||||||
|
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern UUID4 generate_uuid4(void) {
|
wapp_intern UUID4 generate_uuid4(void) {
|
||||||
wapp_persist XOR256State state = {0};
|
wapp_persist XOR256State state = {0};
|
||||||
wapp_persist b8 initialised = false;
|
wapp_persist b8 initialised = false;
|
||||||
|
|
||||||
if (!initialised) {
|
if (!initialised) {
|
||||||
initialised = true;
|
initialised = true;
|
||||||
state = wapp_prng_xorshift_init_state();
|
state = wapp_prng_xorshift_init_state();
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID4 uuid = (UUID4){
|
UUID4 uuid = (UUID4){
|
||||||
.high = wapp_prng_xorshift_256(&state),
|
.high = wapp_prng_xorshift_256(&state),
|
||||||
.low = wapp_prng_xorshift_256(&state),
|
.low = wapp_prng_xorshift_256(&state),
|
||||||
};
|
};
|
||||||
|
|
||||||
uuid.high = (uuid.high & 0xffffffffffff0fff) | 0x0000000000004000;
|
uuid.high = (uuid.high & 0xffffffffffff0fff) | 0x0000000000004000;
|
||||||
uuid.low = (uuid.low & 0x3fffffffffffffff) | 0x8000000000000000;
|
uuid.low = (uuid.low & 0x3fffffffffffffff) | 0x8000000000000000;
|
||||||
|
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid) {
|
wapp_intern void uuid4_to_uuid(const UUID4* uuid4, WUUID *uuid) {
|
||||||
u64 group1 = uuid4->high >> 32;
|
u64 group1 = uuid4->high >> 32;
|
||||||
u64 group2 = (uuid4->high << 32) >> 48;
|
u64 group2 = (uuid4->high << 32) >> 48;
|
||||||
u64 group3 = (uuid4->high << 48) >> 48;
|
u64 group3 = (uuid4->high << 48) >> 48;
|
||||||
u64 group4 = uuid4->low >> 48;
|
u64 group4 = uuid4->low >> 48;
|
||||||
u64 group5 = (uuid4->low << 16) >> 16;
|
u64 group5 = (uuid4->low << 16) >> 16;
|
||||||
|
|
||||||
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, group1, group2, group3, group4, group5);
|
wapp_str8_format(&(uuid->uuid), UUID_STR_FORMAT, group1, group2, group3, group4, group5);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ BEGIN_C_LINKAGE
|
|||||||
|
|
||||||
typedef struct wapp_uuid WUUID;
|
typedef struct wapp_uuid WUUID;
|
||||||
struct wapp_uuid {
|
struct wapp_uuid {
|
||||||
Str8 uuid;
|
Str8 uuid;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
|
#define wapp_uuid_gen_uuid4() *(wapp_uuid_init_uuid4(&wapp_uuid_create()))
|
||||||
|
|||||||
Reference in New Issue
Block a user