/* * Linked lists implementation */ #include #include #include "lists.h" /* SINGLY LINKED LIST */ void list_init(List *list, void (*destroy)(void *data)) { list->size = 0; list->destroy = destroy; list->head = NULL; list-tail = NULL; return; } void list_destroy(List *list) { void *data = NULL; while (list_size(list) > 0) { /* list_rem_next removes head's element if passed NULL */ if (list_rem_next(list, NULL, (void **)&data) == 0 && list->destroy != NULL) list->destroy(data); } memset(list, 0, sizeof(List)); return; } int list_ins_next(List *list, ListElmt *element, const void *data) { ListElmt *new_element; if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) return -1; new_element->data = (void *)data; if (element == NULL) { if (list_size(list) == 0) list->tail = new_element; new_element->next = list->head; list->head = new_element; } else { if (element->next == NULL) list->tail = new_element; new_element->next = element->next; element->next = new_element } list->size++; return 0; } int list_rem_next(List *list, ListElmt *element, void **data) { ListElmt *old_element; if (list_size(list) == 0) return -1; if (element == NULL) { *data = list->head->data; old_element = list->head; list->head = list->head->next; if (list_size(list) == 1) list->tail = NULL; } else { if (element->next == NULL) return -1; *data = element->next->data; old_element = element->next; element->next = element->next->next; if (element->next == NULL) list->tail = element; } free(old_element); list->size--; return 0; } /* SINGLY LINKED LIST -- END */ /* DOUBLY LINKED LIST */ void dlist_init(struct DList *list, void (*destroy)(void *data)) { /* Initialize list */ list->size = 0; list->destroy = destroy; list->head = NULL; list->tail = NULL; return; } void dlist_destroy(struct DList *list) { void *data; /* Remove elements */ while (dlist_size(list) > 0) { if (dlist_remove(list, dlist_tail(list), (void **)&data) == 0 && list->destroy != NULL) list->destroy(data); } /* clear list struct just in case */ memset(list, 0, sizeof(DList)); return; } int dlist_ins_next(struct DList *list, struct DListElmt *element, const void *data) { struct DListElmt *new; /* No NULL elements allowed */ if (element == NULL && dlist_size(list) != 0) return -1; if ((new = (struct DListElmt *)malloc(sizeof(struct DListElmt))) == NULL) return -1; new->data = (void *)data; if (dlist_size(list) == 0) { list->head = new; list->head->prev = NULL; list->head->next = NULL; list->tail = new; } else { new->next = element->next; new->prev = element; if (new->next == NULL) list->tail = new; else new->next->prev = new; element->next = new; } list->size++; return 0 } int dlist_ins_prev(struct DList *list, struct DListElmt *element, const void *data) { struct DListElmt *new; /* No NULL elements allowed */ if (element == NULL && dlist_size(list) != 0) return -1; if ((new = (struct DListElmt *)malloc(sizeof(struct DListElmt))) == NULL) return -1; new->data = (void *)data; if (dlist_size(list) == 0) { /* insert on head */ list->head = new; list->head->prev = NULL; list->head->next = NULL; list->tail = new; } else { new->next = element; new->prev = element->prev; if (new->prev == NULL) list->head = new; else element->prev->next = new; element->prev = new; } list_size++; return 0; } int dlist_remove(struct DList *list, struct DListElmt *element, void **data) { /* No NULL element allowed or removal from empty */ if (element == NULL || dlist_size(list == 0)) return -1; /* Remove element */ *data = element->data; if (element == list->head) { list->head = element->next; if (list->head == NULL) list->tail = NULL; else list->head->prev = NULL; } else { element->prev->next = element->next; if (element->next == NULL) list->tail = element->prev; else element->next->prev = element->prev; } free(element); list->size--; return 0; }