diff --git a/src/core/strings/str8/str8.c b/src/core/strings/str8/str8.c index d19e31b..bcb3caf 100644 --- a/src/core/strings/str8/str8.c +++ b/src/core/strings/str8/str8.c @@ -2,6 +2,9 @@ #include "aliases.h" #include "mem_allocator.h" #include +#include + +internal Str8List node_to_list(Str8Node *node); Str8 *wapp_str8_buf_alloc(const Allocator *allocator, u64 capacity) { Str8 *str = NULL; @@ -84,6 +87,14 @@ void wapp_str8_set(Str8 *str, u64 index, c8 c) { str->buf[index] = c; } +bool wapp_str8_equal(Str8RO *s1, Str8RO *s2) { + if (s1->size != s2->size) { + return false; + } + + return memcmp(s1->buf, s2->buf, s1->size) == 0; +} + Str8RO wapp_str8_substr(Str8RO *str, u64 start, u64 end) { if (start >= str->size || start >= end) { return (Str8RO){0}; @@ -129,3 +140,196 @@ i64 wapp_str8_rfind(Str8RO *str, Str8RO substr) { return -1; } + +Str8Node *wapp_str8_list_get(Str8List *list, u64 index) { + if (index >= list->node_count) { + return NULL; + } + + Str8Node *output = NULL; + Str8Node *current = list->first; + for (u64 i = 1; i <= index; ++i) { + current = current->next; + } + + output = current; + + return output; +} + +void wapp_str8_list_push_front(Str8List *list, Str8Node *node) { + if (!list || !node || !(node->string)) { + return; + } + + Str8List node_list = node_to_list(node); + + if (list->node_count == 0) { + *list = node_list; + return; + } + + list->total_size += node_list.total_size; + list->node_count += node_list.node_count; + + Str8Node *first = list->first; + if (first) { + first->prev = node_list.last; + } + + list->first = node_list.first; + node_list.last->next = first; +} + +void wapp_str8_list_push_back(Str8List *list, Str8Node *node) { + if (!list || !node || !(node->string)) { + return; + } + + Str8List node_list = node_to_list(node); + + if (list->node_count == 0) { + *list = node_list; + return; + } + + list->total_size += node_list.total_size; + list->node_count += node_list.node_count; + + Str8Node *last = list->last; + if (last) { + last->next = node_list.first; + } + + list->last = node_list.last; + node_list.first->prev = last; +} + +void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index) { + if (!list || !node || !(node->string)) { + return; + } + + if (index == 0) { + wapp_str8_list_push_front(list, node); + return; + } else if (index == list->node_count) { + wapp_str8_list_push_back(list, node); + return; + } + + Str8Node *dst_node = wapp_str8_list_get(list, index); + if (!dst_node) { + return; + } + + Str8List node_list = node_to_list(node); + + list->total_size += node_list.total_size; + list->node_count += node_list.node_count; + + Str8Node *prev = dst_node->prev; + + dst_node->prev = node_list.last; + prev->next = node_list.first; + + node_list.first->prev = prev; + node_list.last->next = dst_node; +} + +Str8Node *wapp_str8_list_pop_front(Str8List *list) { + Str8Node *output = NULL; + + if (!list || list->node_count == 0) { + goto RETURN_STR8_LIST_POP_FRONT; + } + + output = list->first; + + if (list->node_count == 1) { + *list = (Str8List){0}; + goto RETURN_STR8_LIST_POP_FRONT; + } + + --(list->node_count); + list->total_size -= output->string->size; + list->first = output->next; + + output->prev = output->next = NULL; + +RETURN_STR8_LIST_POP_FRONT: + return output; +} + +Str8Node *wapp_str8_list_pop_back(Str8List *list) { + Str8Node *output = NULL; + + if (!list || list->node_count == 0) { + goto RETURN_STR8_LIST_POP_BACK; + } + + output = list->last; + + if (list->node_count == 1) { + *list = (Str8List){0}; + goto RETURN_STR8_LIST_POP_BACK; + } + + --(list->node_count); + list->total_size -= output->string->size; + list->last = output->prev; + + output->prev = output->next = NULL; + +RETURN_STR8_LIST_POP_BACK: + return output; +} + +Str8Node *wapp_str8_list_remove(Str8List *list, u64 index) { + Str8Node *output = NULL; + if (!list) { + goto RETURN_STR8_LIST_REMOVE; + } + + if (index == 0) { + output = wapp_str8_list_pop_front(list); + goto RETURN_STR8_LIST_REMOVE; + } else if (index == list->node_count) { + output = wapp_str8_list_pop_back(list); + goto RETURN_STR8_LIST_REMOVE; + } + + output = wapp_str8_list_get(list, index); + if (!output) { + goto RETURN_STR8_LIST_REMOVE; + } + + output->prev->next = output->next; + output->next->prev = output->prev; + + --(list->node_count); + list->total_size -= output->string->size; + + output->prev = output->next = NULL; + +RETURN_STR8_LIST_REMOVE: + return output; +} + +internal Str8List node_to_list(Str8Node *node) { + Str8List output = {.first = node, .last = node, .total_size = node->string->size, .node_count = 1}; + + while (output.first->prev != NULL) { + output.total_size += output.first->prev->string->size; + output.first = output.first->prev; + ++(output.node_count); + } + + while (output.last->next != NULL) { + output.total_size += output.last->next->string->size; + output.last = output.last->next; + ++(output.node_count); + } + + return output; +} diff --git a/src/core/strings/str8/str8.h b/src/core/strings/str8/str8.h index cb3397b..d0aa575 100644 --- a/src/core/strings/str8/str8.h +++ b/src/core/strings/str8/str8.h @@ -4,6 +4,7 @@ #include "aliases.h" #include "mem_allocator.h" #include +#include #ifdef __cplusplus BEGIN_C_LINKAGE @@ -18,10 +19,30 @@ struct str8 { typedef const Str8 Str8RO; -// Utilities to be used with printf functions +typedef struct str8_node Str8Node; +struct str8_node { + Str8RO *string; + Str8Node *prev; + Str8Node *next; +}; + +typedef struct str8_list Str8List; +struct str8_list { + Str8Node *first; + Str8Node *last; + u64 total_size; + u64 node_count; +}; + +/** + * Utilities to be used with printf functions + */ #define WAPP_STR8_SPEC "%.*s" #define wapp_str8_varg(STRING) (int)STRING.size, STRING.buf +/** + * Str8 stack buffers + */ #define wapp_str8_buf(CAPACITY) ((Str8){.capacity = CAPACITY, .size = 0, .buf = (c8[CAPACITY]){0}}) // Utilises the fact that memcpy returns pointer to dest buffer and that getting @@ -33,17 +54,38 @@ typedef const Str8 Str8RO; .size = sizeof(STRING) - 1, \ .buf = (c8 *)STRING}) +/** + * Str8 allocated buffers + */ Str8 *wapp_str8_buf_alloc(const Allocator *allocator, u64 capacity); Str8 *wapp_str8_alloc_cstr(const Allocator *allocator, const char *str); Str8 *wapp_str8_alloc_str8(const Allocator *allocator, Str8RO *str); +/** + * Str8 utilities + */ c8 wapp_str8_get(Str8RO *str, u64 index); void wapp_str8_set(Str8 *str, u64 index, c8 c); +bool wapp_str8_equal(Str8RO *s1, Str8RO *s2); Str8RO wapp_str8_substr(Str8RO *str, u64 start, u64 end); +/** + * Str8 find functions + */ i64 wapp_str8_find(Str8RO *str, Str8RO substr); i64 wapp_str8_rfind(Str8RO *str, Str8RO substr); +/** + * Str8 list functions + */ +Str8Node *wapp_str8_list_get(Str8List *list, u64 index); +void wapp_str8_list_push_front(Str8List *list, Str8Node *node); +void wapp_str8_list_push_back(Str8List *list, Str8Node *node); +void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index); +Str8Node *wapp_str8_list_pop_front(Str8List *list); +Str8Node *wapp_str8_list_pop_back(Str8List *list); +Str8Node *wapp_str8_list_remove(Str8List *list, u64 index); + #ifdef __cplusplus END_C_LINKAGE #endif // !__cplusplus