diff options
Diffstat (limited to 'src/linked_list.c')
| -rw-r--r-- | src/linked_list.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/linked_list.c b/src/linked_list.c new file mode 100644 index 0000000..c655fe4 --- /dev/null +++ b/src/linked_list.c @@ -0,0 +1,86 @@ +#include "linked_list.h" +#include <stdlib.h> + +LinkedList *linked_list_new(void) { + LinkedList *ll = malloc(sizeof(LinkedList)); + if (!ll) return NULL; + + ll->head = NULL; + ll->tail = NULL; + ll->size = 0; + + return ll; +} + +void linked_list_delete(LinkedList *ll) { + LinkedListNode *node = ll->head; + LinkedListNode *next; + + while (node) { + next = node->next; + free(node); + node = next; + } + + free(ll); +} + +LinkedListNode *linked_list_append(LinkedList *ll, void *elem) { + LinkedListNode *new_node = malloc(sizeof(LinkedListNode)); + if (!new_node) return NULL; + + new_node->data = elem; + new_node->next = NULL; + if (!ll->head) { + new_node->prev = NULL; + ll->head = new_node; + ll->tail = new_node; + } else { + ll->tail->next = new_node; + new_node->prev = ll->tail; + ll->tail = new_node; + } + + ll->size++; + return new_node; +} + +void *linked_list_popfront(LinkedList *ll) { + if (!ll->head) return NULL; + + void *elem = ll->head->data; + LinkedListNode *node = ll->head; + ll->head = ll->head->next; + + ll->size--; + free(node); + return elem; +} + +LinkedListNode *linked_list_find(LinkedList *ll, void *elem) { + if (!ll->head) return NULL; + + LinkedListNode *node = ll->head; + while (node) { + /* !NOTE should use a given comparator function + * instead of '==' operator */ + if (node->data == elem) return node; + node = node->next; + } + + return NULL; // Couldn't find the element +} + +void *linked_list_remove(LinkedList *ll, LinkedListNode *node) { + void *elem = node->data; + + if (node->prev) node->prev->next = node->next; + else ll->head = node->next; + + if (node->next) node->next->prev = node->prev; + else ll->tail = node->prev; + + free(node); + ll->size--; + return elem; +} |