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