nesemu/utils/linked_list.c

129 lines
2.9 KiB
C

//
// Created by william on 1/16/24.
//
#include <stddef.h>
#include <malloc.h>
#include <stdlib.h>
#include <assert.h>
#include "linked_list.h"
LinkedList linked_list_init(bool circular) {
LinkedList list;
list.circular = circular;
list.size = 0;
list.head = NULL;
list.end = NULL;
list.current = NULL;
return list;
}
void linked_list_add(LinkedList *list, void *data) {
assert(list != NULL);
LinkedListNode *node = malloc(sizeof(LinkedListNode));
if (node == NULL) {
perror("Failed to allocate memory for linked list node");
exit(EXIT_FAILURE);
}
node->data = data;
node->previous = list->end;
if (list->head == NULL) {
list->head = node;
list->current = node;
}
if (list->end != NULL) {
list->end->next = node;
}
if (list->circular) {
node->next = list->head;
} else {
node->next = NULL;
}
list->end = node;
list->size++;
}
LinkedListNode *linked_list_next(LinkedList* list) {
assert(list != NULL);
if (list->head == NULL) {
return NULL;
}
LinkedListNode *next = list->current->next;
list->current = next;
return next;
}
void linked_list_cursor_reset(LinkedList *list) {
assert(list != NULL);
list->current = list->head;
}
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) {
assert(list != NULL);
assert(predicate != NULL);
LinkedListNode *node = list->head;
while (node != NULL) {
if (predicate(node->data, userdata)) {
return node;
}
node = node->next;
}
return NULL;
}
LinkedListNode *linked_list_get_near(LinkedList *list, int(*compute_distance)(void *, void *), void *userdata) {
assert(list != NULL);
assert(compute_distance != NULL);
LinkedListNode *near_node = list->head;
int current_distance = compute_distance(near_node->data, userdata);
if (current_distance == 0) {
return near_node;
}
// TODO
int last_distance = 0x7fffffff;
LinkedListNode *node = near_node->next;
while (current_distance < last_distance && near_node->next != NULL) {
node = near_node->next;
last_distance = current_distance;
current_distance = compute_distance(node->data, userdata);
}
// After the loop, we have found the nearest node in the list, assuming there is only one point of convergence
return near_node;
}
void linked_list_uninit(LinkedList *list) {
assert(list != NULL);
LinkedListNode *node = list->head;
while (node != NULL) {
LinkedListNode *current_node = node;
node = node->next;
free(current_node->data);
free(current_node);
if (node == list->head) {
// The list may be circular, we don't want an infinite free loop
break;
}
}
}