#include "./dbl_list.h" #include "../../common/aliases/aliases.h" #include internal DBL_LIST(void) node_to_list(DBL_NODE(void) *node); DBL_NODE(void) *_dbl_list_get(const DBL_LIST(void) *list, u64 index) { if (index >= list->node_count) { return NULL; } DBL_NODE(void) *output = NULL; DBL_NODE(void) *current = list->first; for (u64 i = 1; i <= index; ++i) { current = current->next; } output = current; return output; } void _dbl_list_push_front(DBL_LIST(void) *list, DBL_NODE(void) *node) { if (!list || !node || !(node->item)) { return; } DBL_LIST(void) node_list = node_to_list(node); if (list->node_count == 0) { *list = node_list; return; } list->node_count += node_list.node_count; DBL_NODE(void) *first = list->first; if (first) { first->prev = node_list.last; } list->first = node_list.first; node_list.last->next = first; } void _dbl_list_push_back(DBL_LIST(void) *list, DBL_NODE(void) *node) { if (!list || !node || !(node->item)) { return; } DBL_LIST(void) node_list = node_to_list(node); if (list->node_count == 0) { *list = node_list; return; } list->node_count += node_list.node_count; DBL_NODE(void) *last = list->last; if (last) { last->next = node_list.first; } list->last = node_list.last; node_list.first->prev = last; } void _dbl_list_insert(DBL_LIST(void) *list, DBL_NODE(void) *node, u64 index) { if (!list || !node || !(node->item)) { return; } if (index == 0) { _dbl_list_push_front(list, node); return; } else if (index == list->node_count) { _dbl_list_push_back(list, node); return; } DBL_NODE(void) *dst_node = _dbl_list_get(list, index); if (!dst_node) { return; } DBL_LIST(void) node_list = node_to_list(node); list->node_count += node_list.node_count; DBL_NODE(void) *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; } DBL_NODE(void) *_dbl_list_pop_front(DBL_LIST(void) *list) { DBL_NODE(void) *output = NULL; if (!list || list->node_count == 0) { goto RETURN_STR8_LIST_POP_FRONT; } output = list->first; if (list->node_count == 1) { *list = (DBL_LIST(void)){0}; goto RETURN_STR8_LIST_POP_FRONT; } --(list->node_count); list->first = output->next; output->prev = output->next = NULL; RETURN_STR8_LIST_POP_FRONT: return output; } DBL_NODE(void) *_dbl_list_pop_back(DBL_LIST(void) *list) { DBL_NODE(void) *output = NULL; if (!list || list->node_count == 0) { goto RETURN_STR8_LIST_POP_BACK; } output = list->last; if (list->node_count == 1) { *list = (DBL_LIST(void)){0}; goto RETURN_STR8_LIST_POP_BACK; } --(list->node_count); list->last = output->prev; output->prev = output->next = NULL; RETURN_STR8_LIST_POP_BACK: return output; } DBL_NODE(void) *_dbl_list_remove(DBL_LIST(void) *list, u64 index) { DBL_NODE(void) *output = NULL; if (!list) { goto RETURN_STR8_LIST_REMOVE; } if (index == 0) { output = _dbl_list_pop_front(list); goto RETURN_STR8_LIST_REMOVE; } else if (index == list->node_count) { output = _dbl_list_pop_back(list); goto RETURN_STR8_LIST_REMOVE; } output = _dbl_list_get(list, index); if (!output) { goto RETURN_STR8_LIST_REMOVE; } output->prev->next = output->next; output->next->prev = output->prev; --(list->node_count); output->prev = output->next = NULL; RETURN_STR8_LIST_REMOVE: return output; } void _dbl_list_empty(DBL_LIST(void) *list) { if (!list) { return; } u64 count = list->node_count; for (u64 i = 0; i < count; ++i) { _dbl_list_pop_back(list); } } internal DBL_LIST(void) node_to_list(DBL_NODE(void) *node) { DBL_LIST(void) output = {.first = node, .last = node, .node_count = 1}; while (output.first->prev != NULL) { output.first = output.first->prev; ++(output.node_count); } while (output.last->next != NULL) { output.last = output.last->next; ++(output.node_count); } return output; }