|
- #include <stdio.h>
- #include "IZ_list.h"
-
- void IZ_ListDoDeleteNode(IZ_ListNode* node) {
- if (!(node && node->list)) {
- // should we raise warnings here?
- return;
- }
-
- if (node->previous) {
- node->previous->next = node->next;
- } else {
- if (node->next) {
- node->next->previous = NULL;
- }
- node->list->root = node->next;
- }
-
- if (node->list->length > 0) {
- node->list->length -= 1;
- }
-
- IZ_free(node);
- }
-
- void IZ_ListDoAppendNode(IZ_List* list, void* node_value, IZ_ListNode** new_node_ref) {
- IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode));
- new_node->value = node_value;
- new_node->next = NULL;
- new_node->list = list;
- new_node->list->length += 1;
-
- if (!(new_node->list->root)) {
- new_node->previous = NULL;
- new_node->list->root = new_node;
- if (new_node_ref) {
- *new_node_ref = new_node;
- }
- return;
- }
-
- IZ_ListNode** cursor_node = &new_node->list->root;
- while ((*cursor_node)->next) {
- cursor_node = &(*cursor_node)->next;
- }
-
- new_node->previous = *cursor_node;
- (*cursor_node)->next = new_node;
- if (new_node_ref) {
- *new_node_ref = new_node;
- }
- }
-
- #ifdef IZ_DEBUG
- void IZ_ListPrintNodeValues(IZ_List* list) {
- list->iterator = &list->root;
- u64 index = 0;
- printf("\nlist@%p\n", list);
- do {
- printf(" %lu@%p:%u\n", index, *list->iterator, *((unsigned int*)(*list->iterator)->value));
- index += 1;
- list->iterator = &(*list->iterator)->next;
- } while (*list->iterator);
- list->iterator = NULL;
- }
- #endif
-
- /**
- * Initializes a list.
- * @param list - The list to initialize.
- */
- void IZ_ListInitialize(IZ_List* list) {
- list->root = NULL;
- list->length = 0;
- list->iterator = NULL;
- }
-
- /**
- * Performs cleanup on a list.
- * @param list - The list to clean up.
- */
- void IZ_ListTeardown(IZ_List* list) {
- while (list->length > 0) {
- IZ_ListDoDeleteNode(list->root);
- }
- }
-
- /**
- * Appends a node to the end of the list.
- * @param list - The list to append to.
- * @param node_value - The value of the node to append.
- * @return Pointer to the newly created node.
- */
- void IZ_ListAppendNode(IZ_List* list, void* node_value, IZ_ListNode** new_node) {
- IZ_ListDoAppendNode(list, node_value, new_node);
- }
-
- /**
- * Deletes the first node in the list that matches the filter.
- * @param node - The node to delete.
- */
- void IZ_ListDeleteNode(IZ_ListNode* node) {
- IZ_ListDoDeleteNode(node);
- }
-
- /**
- * Finds the first node in the list that matches the filter.
- * @param list - The list to search.
- * @param filter - The filter to use to find the node.
- * @return Pointer to the node that matches the filter.
- * @see IZ_ListFindPredicate
- * @see IZ_ListFindAllNodes
- * @note This function will set the list's iterator to the node that was found. Ensure that the iterator is previously
- * set to an existing node in the list before calling this function to know where to begin the search.
- */
- void IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindPredicate filter, IZ_ListNode** found_node) {
- if (!(list && list->root)) {
- return;
- }
-
- u64 index = 0;
- do {
- if (!filter(list->iterator, index, list)) {
- list->iterator = &((*list->iterator)->next);
- index += 1;
- continue;
- }
- *found_node = *list->iterator;
- return;
- } while (*list->iterator);
-
- }
-
- /**
- * Finds all nodes in the list that match the filter.
- * @param list - The list to search.
- * @param filter - The filter to use to find the node.
- * @param found_nodes - The list to append the found nodes to.
- * @return New list containing nodes that match the filter.
- * @see IZ_ListFindPredicate
- * @see IZ_ListFindFirstNode
- * @note This function will set the list's iterator to the node that was found. Ensure that the iterator is previously
- * set to an existing node in the list before calling this function to know where to begin the search.
- */
- void IZ_ListFindAllNodes(IZ_List* list, IZ_ListFindPredicate filter, IZ_List* found_nodes) {
- if (!(list && list->root)) {
- return;
- }
-
- list->iterator = &list->root;
- u64 index;
- for (index = 0; index < list->length; index += 1) {
- if (filter(list->iterator, index, list)) {
- IZ_ListDoAppendNode(found_nodes, (*list->iterator)->value, NULL);
- }
-
- list->iterator = &((*list->iterator)->next);
- }
- }
-
- /**
- * Inserts a node at the specified index.
- * @param list - The list to append to.
- * @param node_value - The value of the node to append.
- * @param dest_index - The index to insert the node at.
- * @return Pointer to the newly created node.
- */
- void IZ_ListInsertNodeAtIndex(IZ_List* list, void* node_value, u64 dest_index, IZ_ListNode** new_node_ref) {
- if (dest_index > list->length) {
- // to consumer: check your bounds first!
- return;
- }
-
- if (dest_index == list->length) {
- IZ_ListDoAppendNode(list, node_value, new_node_ref);
- return;
- }
-
- IZ_ListNode* new_node = IZ_malloc(sizeof(IZ_ListNode));
- new_node->value = node_value;
- new_node->list = list;
-
- if (!(new_node->list->root)) {
- new_node->previous = NULL;
- new_node->next = NULL;
- new_node->list->root = new_node;
- if (new_node_ref) {
- *new_node_ref = new_node;
- }
- return;
- }
-
- IZ_ListNode** cursor_node = NULL;
- u64 index;
- for (
- index = 0, cursor_node = &new_node->list->root;
- index < dest_index;
- index += 1, cursor_node = &((*cursor_node)->next)
- );
-
- new_node->next = *cursor_node;
- new_node->previous = (*cursor_node)->previous;
-
- if (dest_index == 0) {
- new_node->list->root = new_node;
- } else if (dest_index < list->length) {
- (*cursor_node)->previous->next = new_node;
- } else {
- (*cursor_node)->next = new_node;
- }
-
- new_node->list->length += 1;
- if (new_node_ref) {
- *new_node_ref = new_node;
- }
- }
|