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
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++;
|
|
}
|
|
}
|