|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #include "IZ_list.h"
-
- bool IZ_ListFindFilterAlwaysTrue(IZ_ListNode** _node, u64 _index, IZ_List* _list) {
- return true;
- }
-
- /**
- * 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->root) {
- IZ_ListDeleteFirstNode(list, IZ_ListFindFilterAlwaysTrue);
- }
- list->iterator = NULL;
- list->length = 0;
- }
-
- /**
- * 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.
- */
- IZ_ListNode** IZ_ListAppendNode(IZ_List* list, void* node_value) {
- IZ_ListNode* new_node = SDL_malloc(sizeof(IZ_ListNode));
- new_node->value = node_value;
- new_node->next = NULL;
-
- if (!(list->root)) {
- list->root = new_node;
- list->length += 1;
- return &list->root;
- }
-
- IZ_ListNode* last_node = list->root;
- while (last_node->next) {
- last_node = last_node->next;
- }
-
- last_node->next = new_node;
- list->length += 1;
- return &last_node->next;
- }
-
- /**
- * Inserts a node at the specified index in the list.
- * @param list - The list to append to.
- * @param node_value - The value of the node to insert.
- * @param index - The index to insert the node at.
- * @return Pointer to the newly created node.
- */
- IZ_ListNode** IZ_ListInsertNodeAtIndex(IZ_List* list, void* node_value, u64 index) {
- if (index > list->length) {
- // we don't want to go out of bounds
- return NULL;
- }
-
- IZ_ListNode* new_node = SDL_malloc(sizeof(IZ_ListNode));
- new_node->value = node_value;
- new_node->next = NULL;
-
- if (!(list->root)) {
- list->root = new_node;
- list->length += 1;
- return &list->root;
- }
-
- if (index == 0) {
- new_node->next = list->root;
- list->root = new_node;
- list->length += 1;
- return &list->root;
- }
-
- IZ_ListNode* last_node = list->root;
- for (u64 i = 0; i < index - 1; i += 1) {
- last_node = last_node->next;
- }
-
- new_node->next = last_node->next;
- last_node->next = new_node;
- list->length += 1;
- return &last_node->next;
- }
-
- /**
- * Deletes the first node in the list that matches the filter.
- * @param list - The list to delete from.
- * @param filter - The filter to use to find the node to delete.
- */
- void IZ_ListDeleteFirstNode(IZ_List* list, IZ_ListFindPredicate filter) {
- if (!(list && list->root)) {
- // should we raise warnings here?
- return;
- }
-
- list->iterator = &list->root;
- IZ_ListNode* previous_node = NULL;
- u64 index = 0;
- do {
- if (!filter(list->iterator, index, list)) {
- previous_node = *list->iterator;
- list->iterator = &((*list->iterator)->next);
- index += 1;
- // we haven't found the node we're looking for, go to the next one
- continue;
- }
-
- if (previous_node) {
- // this is not the first node in the list
- previous_node->next = (*list->iterator)->next;
- } else {
- // this is the first node, set it as new root
- list->root = (*list->iterator)->next;
- // if there is only one item in the list, root, gets set to NULL
- }
-
- SDL_free(*list->iterator);
- list->iterator = NULL;
- if (list->length > 0) {
- // avoid underflow
- list->length -= 1;
- }
- return;
- } while (*list->iterator);
- }
-
- /**
- * 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.
- */
- IZ_ListNode** IZ_ListFindFirstNode(IZ_List* list, IZ_ListFindPredicate filter) {
- if (!(list && list->root)) {
- return NULL;
- }
-
- list->iterator = &list->root;
- u64 index = 0;
- do {
- if (filter(list->iterator, index, list)) {
- return list->iterator;
- }
- list->iterator = &((*list->iterator)->next);
- index += 1;
- } while (*list->iterator);
-
- return NULL;
- }
-
- void IZ_ListFilter(IZ_List* original_list, IZ_ListFindPredicate filter, IZ_List* out_filtered_list) {
- // we assume the new list is already initialized
- IZ_ListNode* node = original_list->root;
- u64 index;
- for (index = 0; node; index += 1) {
- if (!filter(&node, index, original_list)) {
- node = node->next;
- continue;
- }
- IZ_ListAppendNode(out_filtered_list, node->value);
- node = node->next;
- }
- }
-
- void IZ_ListSort(IZ_List* original_list, IZ_ListSortComparatorPredicate sort, IZ_List* out_sorted_list) {
- // we assume the new list is already initialized
- IZ_ListNode* original_node = original_list->root;
- u64 original_index;
-
- for (original_index = 0; original_node; original_index += 1) {
- if (!out_sorted_list->root) {
- IZ_ListAppendNode(out_sorted_list, original_node->value);
- original_node = original_node->next;
- continue;
- }
-
- IZ_ListNode* sorted_node = out_sorted_list->root;
- for (u64 sorted_index = 0; sorted_node; sorted_index += 1) {
- if (sort(&original_node, &sorted_node, original_index, original_list) < 0) {
- IZ_ListInsertNodeAtIndex(out_sorted_list, original_node->value, sorted_index);
- original_node = original_node->next;
- break;
- }
- sorted_node = sorted_node->next;
- }
- }
- }
|