diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..886eb69 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "codegen/lib"] + path = codegen/lib + url = git@git.thewizardapprentice.com:abdelrahman/codegen diff --git a/codegen/__init__.py b/codegen/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/codegen/__main__.py b/codegen/__main__.py new file mode 100644 index 0000000..9135022 --- /dev/null +++ b/codegen/__main__.py @@ -0,0 +1,9 @@ +from codegen.dbl_list.gen_dbl_list import gen_dbl_list + + +def main(): + gen_dbl_list() + + +if __name__ == "__main__": + main() diff --git a/codegen/constants.py b/codegen/constants.py new file mode 100644 index 0000000..d092b2c --- /dev/null +++ b/codegen/constants.py @@ -0,0 +1,5 @@ +from pathlib import Path + + +PACKAGE_DIR = Path(__file__).parent +WAPP_SRC_ROOT = PACKAGE_DIR.parent / "src" diff --git a/codegen/dbl_list/__init__.py b/codegen/dbl_list/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/codegen/dbl_list/gen_dbl_list.py b/codegen/dbl_list/gen_dbl_list.py new file mode 100644 index 0000000..ee00fae --- /dev/null +++ b/codegen/dbl_list/gen_dbl_list.py @@ -0,0 +1,206 @@ +from pathlib import Path +from dataclasses import dataclass, field +from codegen.constants import WAPP_SRC_ROOT +from codegen.lib.codegen.utils import load_func_body_from_file +from codegen.lib.codegen.datatypes import ( + CDataType, + CStruct, + CFunc, + CHeader, + CSource, + CArg, + CType, + CPointer, + CPointerType, + CQualifier, + CInclude, + get_datatype_string, +) + + +@dataclass +class DblListData: + out_dir: Path + common_includes: list[CInclude] = field(default_factory=list) + hdr_includes: list[CInclude] = field(default_factory=list) + src_includes: list[CInclude] = field(default_factory=list) + common_decl_types: list[CStruct] = field(default_factory=list) + hdr_decl_types: list[CStruct] = field(default_factory=list) + src_decl_types: list[CStruct] = field(default_factory=list) + + +def gen_dbl_list(): + def __format_func_body(filename: Path, type_string: str): + return load_func_body_from_file(filename).format( + T=type_string, + Tupper=type_string.upper(), + Tlower=type_string.lower(), + ) + + datatypes: dict[CDataType, DblListData] = { + "Str8": DblListData( + common_includes=[ + CInclude(header="../../../common/aliases/aliases.h", local=True), + ], + src_includes=[ + CInclude(header="./str8.h", local=True), + ], + hdr_decl_types=[ + CStruct(name="str8", cargs=[], typedef_name="Str8"), + ], + out_dir=WAPP_SRC_ROOT / "core/strings/str8/", + ), + } + snippets_dir = Path(__file__).parent / "snippets" + + for _type, dbl_list_data in datatypes.items(): + type_string = get_datatype_string(_type) + + node = CStruct( + name=f"{type_string}Node", + cargs=[ + CArg(name="string", _type=type_string, pointer=CPointer(_type=CPointerType.SINGLE)), + CArg(name="prev", _type=f"{type_string}Node", pointer=CPointer(_type=CPointerType.SINGLE)), + CArg(name="next", _type=f"{type_string}Node", pointer=CPointer(_type=CPointerType.SINGLE)), + ], + ) + + dl_list = CStruct( + name=f"{type_string}List", + cargs=[ + CArg(name="first", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), + CArg(name="last", _type=node, pointer=CPointer(_type=CPointerType.SINGLE)), + CArg(name="total_size", _type=CType.U64), + CArg(name="node_count", _type=CType.U64), + ], + ) + + get_func = CFunc( + name=f"wapp_{type_string.lower()}_list_get", + ret_type=node, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE), qualifier=CQualifier.CONST), + CArg(name="index", _type=CType.U64), + ], + body=__format_func_body(snippets_dir / "list_get", type_string), + pointer=CPointer(CPointerType.SINGLE), + ) + + push_front_func = CFunc( + name=f"wapp_{type_string.lower()}_list_push_front", + ret_type=CType.VOID, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "list_push_front", type_string), + ) + + push_back_func = CFunc( + name=f"wapp_{type_string.lower()}_list_push_back", + ret_type=CType.VOID, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "list_push_back", type_string), + ) + + insert_func = CFunc( + name=f"wapp_{type_string.lower()}_list_insert", + ret_type=CType.VOID, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), + CArg(name="index", _type=CType.U64), + ], + body=__format_func_body(snippets_dir / "list_insert", type_string), + ) + + pop_front_func = CFunc( + name=f"wapp_{type_string.lower()}_list_pop_front", + ret_type=node, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "list_pop_front", type_string), + pointer=CPointer(CPointerType.SINGLE), + ) + + pop_back_func = CFunc( + name=f"wapp_{type_string.lower()}_list_pop_back", + ret_type=node, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "list_pop_back", type_string), + pointer=CPointer(CPointerType.SINGLE), + ) + + remove_func = CFunc( + name=f"wapp_{type_string.lower()}_list_remove", + ret_type=node, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + CArg(name="index", _type=CType.U64), + ], + body=__format_func_body(snippets_dir / "list_remove", type_string), + pointer=CPointer(CPointerType.SINGLE), + ) + + empty_func = CFunc( + name=f"wapp_{type_string.lower()}_list_empty", + ret_type=CType.VOID, + args=[ + CArg(name="list", _type=dl_list, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "list_empty", type_string), + ) + + node_to_list_func = CFunc( + name=f"{type_string.lower()}_node_to_list", + ret_type=dl_list, + args=[ + CArg(name="node", _type=node, pointer=CPointer(CPointerType.SINGLE)), + ], + body=__format_func_body(snippets_dir / "node_to_list", type_string), + qualifiers=[CQualifier.INTERNAL], + ) + + header = CHeader( + name=f"{type_string.lower()}_list", + decl_types=dbl_list_data.common_decl_types + dbl_list_data.hdr_decl_types, + includes=[], + types=[node, dl_list], + funcs=[ + get_func, + push_front_func, + push_back_func, + insert_func, + pop_front_func, + pop_back_func, + remove_func, + empty_func, + ] + ) + + source = CSource( + name=header.name, + decl_types=dbl_list_data.common_decl_types + dbl_list_data.src_decl_types, + includes=[CInclude(header, local=True, same_dir=True), CInclude(header="stddef.h")], + internal_funcs=[node_to_list_func], + funcs=header.funcs + ) + + if len(dbl_list_data.common_includes) > 0: + header.includes.extend(dbl_list_data.common_includes) + source.includes.extend(dbl_list_data.common_includes) + + if len(dbl_list_data.hdr_includes) > 0: + header.includes.extend(dbl_list_data.hdr_includes) + + if len(dbl_list_data.src_includes) > 0: + source.includes.extend(dbl_list_data.src_includes) + + header.save(dbl_list_data.out_dir) + source.save(dbl_list_data.out_dir) diff --git a/codegen/dbl_list/snippets/list_empty b/codegen/dbl_list/snippets/list_empty new file mode 100644 index 0000000..c14804f --- /dev/null +++ b/codegen/dbl_list/snippets/list_empty @@ -0,0 +1,8 @@ + if (!list) {{ + return; + }} + + u64 count = list->node_count; + for (u64 i = 0; i < count; ++i) {{ + wapp_str8_list_pop_back(list); + }} diff --git a/codegen/dbl_list/snippets/list_get b/codegen/dbl_list/snippets/list_get new file mode 100644 index 0000000..c65985e --- /dev/null +++ b/codegen/dbl_list/snippets/list_get @@ -0,0 +1,13 @@ + if (index >= list->node_count) {{ + return NULL; + }} + + {T}Node *output = NULL; + {T}Node *current = list->first; + for (u64 i = 1; i <= index; ++i) {{ + current = current->next; + }} + + output = current; + + return output; diff --git a/codegen/dbl_list/snippets/list_insert b/codegen/dbl_list/snippets/list_insert new file mode 100644 index 0000000..0b6aa52 --- /dev/null +++ b/codegen/dbl_list/snippets/list_insert @@ -0,0 +1,29 @@ + 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; + }} + + {T}Node *dst_node = wapp_str8_list_get(list, index); + if (!dst_node) {{ + return; + }} + + {T}List node_list = {Tlower}_node_to_list(node); + + list->total_size += node_list.total_size; + list->node_count += node_list.node_count; + + {T}Node *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; diff --git a/codegen/dbl_list/snippets/list_pop_back b/codegen/dbl_list/snippets/list_pop_back new file mode 100644 index 0000000..3ee8a15 --- /dev/null +++ b/codegen/dbl_list/snippets/list_pop_back @@ -0,0 +1,21 @@ + {T}Node *output = NULL; + + if (!list || list->node_count == 0) {{ + goto RETURN_{Tupper}_LIST_POP_BACK; + }} + + output = list->last; + + if (list->node_count == 1) {{ + *list = ({T}List){{0}}; + goto RETURN_{Tupper}_LIST_POP_BACK; + }} + + --(list->node_count); + list->total_size -= output->string->size; + list->last = output->prev; + + output->prev = output->next = NULL; + +RETURN_{Tupper}_LIST_POP_BACK: + return output; diff --git a/codegen/dbl_list/snippets/list_pop_front b/codegen/dbl_list/snippets/list_pop_front new file mode 100644 index 0000000..caba8c9 --- /dev/null +++ b/codegen/dbl_list/snippets/list_pop_front @@ -0,0 +1,21 @@ + {T}Node *output = NULL; + + if (!list || list->node_count == 0) {{ + goto RETURN_{Tupper}_LIST_POP_FRONT; + }} + + output = list->first; + + if (list->node_count == 1) {{ + *list = ({T}List){{0}}; + goto RETURN_{Tupper}_LIST_POP_FRONT; + }} + + --(list->node_count); + list->total_size -= output->string->size; + list->first = output->next; + + output->prev = output->next = NULL; + +RETURN_{Tupper}_LIST_POP_FRONT: + return output; diff --git a/codegen/dbl_list/snippets/list_push_back b/codegen/dbl_list/snippets/list_push_back new file mode 100644 index 0000000..cc51dac --- /dev/null +++ b/codegen/dbl_list/snippets/list_push_back @@ -0,0 +1,21 @@ + if (!list || !node || !(node->string)) {{ + return; + }} + + {T}List node_list = {Tlower}_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; + + {T}Node *last = list->last; + if (last) {{ + last->next = node_list.first; + }} + + list->last = node_list.last; + node_list.first->prev = last; diff --git a/codegen/dbl_list/snippets/list_push_front b/codegen/dbl_list/snippets/list_push_front new file mode 100644 index 0000000..8989beb --- /dev/null +++ b/codegen/dbl_list/snippets/list_push_front @@ -0,0 +1,21 @@ + if (!list || !node || !(node->string)) {{ + return; + }} + + {T}List node_list = {Tlower}_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; + + {T}Node *first = list->first; + if (first) {{ + first->prev = node_list.last; + }} + + list->first = node_list.first; + node_list.last->next = first; diff --git a/codegen/dbl_list/snippets/list_remove b/codegen/dbl_list/snippets/list_remove new file mode 100644 index 0000000..cc213c4 --- /dev/null +++ b/codegen/dbl_list/snippets/list_remove @@ -0,0 +1,28 @@ + {T}Node *output = NULL; + if (!list) {{ + goto RETURN_{Tupper}_LIST_REMOVE; + }} + + if (index == 0) {{ + output = wapp_str8_list_pop_front(list); + goto RETURN_{Tupper}_LIST_REMOVE; + }} else if (index == list->node_count) {{ + output = wapp_str8_list_pop_back(list); + goto RETURN_{Tupper}_LIST_REMOVE; + }} + + output = wapp_str8_list_get(list, index); + if (!output) {{ + goto RETURN_{Tupper}_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_{Tupper}_LIST_REMOVE: + return output; diff --git a/codegen/dbl_list/snippets/node_to_list b/codegen/dbl_list/snippets/node_to_list new file mode 100644 index 0000000..2c52609 --- /dev/null +++ b/codegen/dbl_list/snippets/node_to_list @@ -0,0 +1,15 @@ + {T}List 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/codegen/lib b/codegen/lib new file mode 160000 index 0000000..9ac75eb --- /dev/null +++ b/codegen/lib @@ -0,0 +1 @@ +Subproject commit 9ac75ebc8ccf31026c6020b65d246a4d638f256a diff --git a/src/core/strings/str8/str8.c b/src/core/strings/str8/str8.c index 3639ffd..59d82e3 100644 --- a/src/core/strings/str8/str8.c +++ b/src/core/strings/str8/str8.c @@ -9,8 +9,6 @@ #define STR8_BUF_ALLOC_SIZE(CAPACITY) (sizeof(Str8) + sizeof(c8) * CAPACITY) -internal Str8List node_to_list(Str8Node *node); - Str8 *wapp_str8_alloc_buf(const Allocator *allocator, u64 capacity) { Str8 *str = NULL; @@ -435,207 +433,3 @@ Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8RO *d return output; } - -Str8Node *wapp_str8_list_get(const 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; -} - -void wapp_str8_list_empty(Str8List *list) { - if (!list) { - return; - } - - u64 count = list->node_count; - for (u64 i = 0; i < count; ++i) { - wapp_str8_list_pop_back(list); - } -} - -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 3693c04..894e4c2 100644 --- a/src/core/strings/str8/str8.h +++ b/src/core/strings/str8/str8.h @@ -1,6 +1,7 @@ #ifndef STR8_H #define STR8_H +#include "./str8_list.h" #include "../../../common/aliases/aliases.h" #include "../../mem/allocator/mem_allocator.h" #include @@ -19,21 +20,6 @@ struct str8 { typedef const Str8 Str8RO; -typedef struct str8_node Str8Node; -struct str8_node { - Str8 *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 */ @@ -107,14 +93,6 @@ Str8 *wapp_str8_join(const Allocator *allocator, const Str8List *list, Str8R */ #define wapp_str8_node_from_cstr(STRING) ((Str8Node){.string = &wapp_str8_lit(STRING)}) #define wapp_str8_node_from_str8(STRING) ((Str8Node){.string = &(STRING)}) -Str8Node *wapp_str8_list_get(const Str8List *list, u64 index); -void wapp_str8_list_push_front(Str8List *list, Str8Node *node); -void wapp_str8_list_push_back(Str8List *list, Str8Node *node); -void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index); -Str8Node *wapp_str8_list_pop_front(Str8List *list); -Str8Node *wapp_str8_list_pop_back(Str8List *list); -Str8Node *wapp_str8_list_remove(Str8List *list, u64 index); -void wapp_str8_list_empty(Str8List *list); #ifdef __cplusplus END_C_LINKAGE diff --git a/src/core/strings/str8/str8_list.c b/src/core/strings/str8/str8_list.c new file mode 100644 index 0000000..34f7926 --- /dev/null +++ b/src/core/strings/str8/str8_list.c @@ -0,0 +1,220 @@ +#include "./str8_list.h" +#include "../../../common/aliases/aliases.h" +#include "./str8.h" +#include + +internal Str8List str8_node_to_list(Str8Node *node); + +Str8Node *wapp_str8_list_get(const 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 = str8_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 = str8_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 = str8_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; + +} + +void wapp_str8_list_empty(Str8List *list) { + if (!list) { + return; + } + + u64 count = list->node_count; + for (u64 i = 0; i < count; ++i) { + wapp_str8_list_pop_back(list); + } + +} + +internal Str8List str8_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_list.h b/src/core/strings/str8/str8_list.h new file mode 100644 index 0000000..62db6d6 --- /dev/null +++ b/src/core/strings/str8/str8_list.h @@ -0,0 +1,40 @@ +#ifndef STR8_LIST_H +#define STR8_LIST_H + +#include "../../../common/aliases/aliases.h" + +#ifdef __cplusplus +BEGIN_C_LINKAGE +#endif // !__cplusplus + +typedef struct str8 Str8; + +typedef struct Str8Node Str8Node; +struct Str8Node { + Str8 *string; + Str8Node *prev; + Str8Node *next; +}; + +typedef struct Str8List Str8List; +struct Str8List { + Str8Node *first; + Str8Node *last; + u64 total_size; + u64 node_count; +}; + +Str8Node *wapp_str8_list_get(const Str8List *list, u64 index); +void wapp_str8_list_push_front(Str8List *list, Str8Node *node); +void wapp_str8_list_push_back(Str8List *list, Str8Node *node); +void wapp_str8_list_insert(Str8List *list, Str8Node *node, u64 index); +Str8Node *wapp_str8_list_pop_front(Str8List *list); +Str8Node *wapp_str8_list_pop_back(Str8List *list); +Str8Node *wapp_str8_list_remove(Str8List *list, u64 index); +void wapp_str8_list_empty(Str8List *list); + +#ifdef __cplusplus +END_C_LINKAGE +#endif // !__cplusplus + +#endif // !STR8_LIST_H diff --git a/src/core/wapp_core.c b/src/core/wapp_core.c index 9100102..d41bc27 100644 --- a/src/core/wapp_core.c +++ b/src/core/wapp_core.c @@ -3,6 +3,7 @@ #include "wapp_core.h" #include "strings/str8/str8.c" +#include "strings/str8/str8_list.c" #include "os/shell/termcolour/posix/termcolour_posix.c" #include "os/shell/termcolour/win/termcolour_win.c" #include "os/shell/termcolour/termcolour.c" diff --git a/src/core/wapp_core.h b/src/core/wapp_core.h index 320d1a9..d698b47 100644 --- a/src/core/wapp_core.h +++ b/src/core/wapp_core.h @@ -2,6 +2,7 @@ #define WAPP_CORE_H #include "strings/str8/str8.h" +#include "strings/str8/str8_list.h" #include "os/shell/termcolour/termcolour.h" #include "os/shell/termcolour/terminal_colours.h" #include "os/shell/commander/commander.h"