You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
4.1 KiB

#include <lcthw/list.h>
#include <lcthw/dbg.h>
List *List_create()
{
return calloc(1, sizeof(List));
}
void List_destroy(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
if(cur->prev) {
free(cur->prev);
}
}
free(list->last);
free(list);
}
void List_clear(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
free(cur->value);
}
}
void List_clear_destroy(List *list)
{
List_validate(list);
LIST_FOREACH(list, first, next, cur) {
free(cur->value);
if(cur->prev) {
free(cur->prev);
}
}
free(list->last);
free(list);
}
void List_push(List *list, void *value)
{
List_validate(list);
ListNode *node = calloc(1, sizeof(ListNode));
check_mem(node);
node->value = value;
if(list->last == NULL) {
list->first = node;
list->last = node;
} else {
list->last->next = node;
node->prev = list->last;
list->last = node;
}
list->count++;
error:
return;
}
void *List_pop(List *list)
{
List_validate(list);
ListNode *node = list->last;
return node != NULL ? List_remove(list, node) : NULL;
}
void List_unshift(List *list, void *value)
{
List_validate(list);
ListNode *node = calloc(1, sizeof(ListNode));
check_mem(node);
node->value = value;
if(list->first == NULL) {
list->first = node;
list->last = node;
} else {
node->next = list->first;
list->first->prev = node;
list->first = node;
}
list->count++;
error:
return;
}
void *List_shift(List *list)
{
List_validate(list);
ListNode *node = list->first;
return node != NULL ? List_remove(list, node) : NULL;
}
void *List_remove(List *list, ListNode *node)
{
List_validate(list);
void *result = NULL;
check(list->first && list->last, "List is empty.");
check(node, "node can't be NULL");
if(node == list->first && node == list->last) {
list->first = NULL;
list->last = NULL;
} else if(node == list->first) {
list->first = node->next;
check(list->first != NULL, "Invalid list, somehow got a first that is NULL.");
list->first->prev = NULL;
} else if(node == list->last) {
list->last = node->prev;
check(list->last != NULL, "Invalid list, somehow got a next that is NULL.");
list->last->next = NULL;
} else {
ListNode *after = node->next;
ListNode *before = node->prev;
after->prev = before;
before->next = after;
}
list->count--;
result = node->value;
free(node);
error:
return result;
}
List *List_copy(List *list)
{
List_validate(list);
List *out = List_create();
LIST_FOREACH(list, first, next, cur) {
List_push(out, cur->value);
}
return out;
}
int List_split(List *list, void *split, List *a, List *b)
{
List_validate(list);
check(list->first && list->last, "List is empty.");
check(split, "split can't be NULL");
if(split == list->last->value || (split == list->first->value && split == list->last->value)) {
(*a) = *List_copy(list);
return 0;
} else if(split == list->first->value) {
(*b) = *List_copy(list);
List_push(a, List_shift(b));
return 0;
} else {
int past_split = 0;
LIST_FOREACH(list, first, next, cur) {
if(past_split) {
List_push(b, cur->value);
continue;
}
if(cur->value == split) {
past_split = 1;
}
List_push(a, cur->value);
}
}
return 0;
error:
return -1;
}
void List_join(List *list, List *b)
{
List_validate(list);
List_validate(b);
List *tail = List_copy(b);
list->last->next = tail->first;
list->count += tail->count;
free(tail);
return;
}
void List_swap(ListNode *a, ListNode *b)
{
ListNode *tmp = a->next;
a->next = b->next;
b->next = tmp;
tmp = a->prev;
a->prev = b->prev;
b->prev = tmp;
}
void List_dump(List *list)
{
List_validate(list);
int i = 0;
int j = 0;
LIST_FOREACH(list, first, next, cur) {
if(i > 0) {
for(j = 0; j < (i*4); j++) {
printf(" ");
}
printf("`");
}
printf("-> [%d] ListNode .value = %p (%s)\n", i, cur->value, (char *)cur->value);
i++;
}
}