libds/src/ll.c

127 lines
3.0 KiB
C

#include "ll.h"
#include <stdlib.h>
void ll_init(ll* ll) {
ll->head = NULL;
ll->tail = NULL;
}
void ll_free(ll* ll) {
ll_node* head = ll->head;
while (head) {
ll_node* to_free = head;
head = head->next;
free(to_free);
}
ll->tail = NULL;
ll->head = NULL;
}
libds_result ll_append(ll* ll, void* data) {
libds_result result = LIBDS_SUCCESS;
ll_node** to_set = ll->head ? &ll->tail->next : &ll->head;
ll_node* new_node = malloc(sizeof(*new_node));
if (new_node) {
new_node->next = NULL;
new_node->prev = ll->tail;
new_node->data = data;
*to_set = new_node;
ll->tail = new_node;
} else {
result = LIBDS_MALLOC;
}
return result;
}
libds_result ll_prepend(ll* ll, void* data) {
libds_result result = LIBDS_SUCCESS;
ll_node** to_set = ll->tail ? &ll->head->prev : &ll->tail;
ll_node* new_node = malloc(sizeof(*new_node));
if (new_node) {
new_node->next = ll->head;
new_node->prev = NULL;
new_node->data = data;
*to_set = new_node;
ll->head = new_node;
}
return result;
}
void ll_remove(ll* ll, void* data) {
ll_node* head = ll->head;
while (head) {
if (head->data == data) {
ll_node* to_delete = head;
head = head->next;
*(to_delete->prev ? &to_delete->prev->next : &ll->head) = to_delete->next;
*(to_delete->next ? &to_delete->next->prev : &ll->tail) = to_delete->prev;
free(to_delete);
} else {
head = head->next;
}
}
}
void* ll_find(const ll* ll, void* data, compare_func compare) {
void* to_return = NULL;
ll_node* head = ll->head;
while (head && to_return == NULL) {
if (compare(data, head->data)) {
to_return = head->data;
}
head = head->next;
}
return to_return;
}
int ll_foreach(const ll* ll, void* data, compare_func compare, foreach_func foreach,
...) {
int return_code = 0;
ll_node* head = ll->head;
va_list args;
while (head && return_code == 0) {
if (compare(data, head->data)) {
va_start(args, foreach);
return_code = foreach (head->data, args);
va_end(args);
}
head = head->next;
}
return return_code;
}
void* ll_head(const ll* ll) { return ll->head ? ll->head->data : NULL; }
void* ll_tail(const ll* ll) { return ll->tail ? ll->tail->data : NULL; }
void* ll_pophead(ll* ll) {
void* to_return = NULL;
if (ll->head) {
ll_node* to_delete = ll->head;
to_return = to_delete->data;
*(to_delete->next ? &to_delete->next->prev : &ll->tail) = NULL;
ll->head = to_delete->next;
free(to_delete);
}
return to_return;
}
void* ll_poptail(ll* ll) {
void* to_return = NULL;
if (ll->tail) {
ll_node* to_delete = ll->tail;
to_return = to_delete->data;
*(to_delete->prev ? &to_delete->prev->next : &ll->head) = NULL;
ll->tail = to_delete->prev;
free(to_delete);
}
return to_return;
}
void ll_clear(ll* ll){
ll_node* head = ll->head;
while(head){
ll_node* to_free = head;
head = head->next;
free(to_free);
}
ll->head = NULL;
ll->tail = NULL;
}