Reformat base
This commit is contained in:
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user