2016-12-23 22:39:10 -08:00
|
|
|
#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(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;
|
|
|
|
}
|
2016-12-25 00:28:29 -08:00
|
|
|
head = head->next;
|
2016-12-23 22:39:10 -08:00
|
|
|
}
|
|
|
|
return to_return;
|
|
|
|
}
|
|
|
|
int ll_foreach(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(ll* ll) { return ll->head ? ll->head->data : NULL; }
|
|
|
|
void* ll_tail(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;
|
|
|
|
}
|
2016-12-25 15:55:48 -08:00
|
|
|
|
|
|
|
void ll_clear(ll* ll){
|
|
|
|
ll_node* head = ll->head;
|
2016-12-26 00:32:51 -08:00
|
|
|
while(head){
|
2016-12-25 15:55:48 -08:00
|
|
|
ll_node* to_free = head;
|
|
|
|
head = head->next;
|
|
|
|
free(to_free);
|
|
|
|
}
|
|
|
|
ll->head = NULL;
|
|
|
|
ll->tail = NULL;
|
|
|
|
}
|