/* * $Id$ * * List handling functions safe from a memory management point of view * */ #include #include #include #include "mr_list.h" /* List allocation and initialization */ void mr_list_alloc(struct mr_list *list) { list = mr_malloc(sizeof(struct mr_list)); list->first = NULL; list->last = NULL; } /* Elt of list allocation and initialization */ void mr_list_alloc_elt(struct mr_list_elt *elt, void *data, void (*mr_free_data)(void *data)) { elt = mr_malloc(sizeof(struct mr_list_elt)); elt->mr_free_data = mr_free_data; elt->data = (void *)data; elt->prev = NULL; elt->next = NULL; } void mr_list_free_elt(struct mr_list_elt *elt) { elt->mr_free_data(elt->data); mr_free(elt->data); mr_free(elt); } /* List desallocation and removal */ void mr_list_free(struct mr_list *list) { struct mr_list_elt *elt = list->first; struct mr_list_elt *elt2 = NULL; while (elt != NULL) { /* preserve next elt */ elt2 = elt->next; /* Purge elt */ mr_list_free_elt(elt); /* next elt to consider */ elt = elt2; } mr_free(list); } /* Count the number of elements in the list */ int mr_list_length(struct mr_list *list) { int i = 0; struct mr_list_elt *p = list->first; while (p != NULL) { i++; p = p->next; } return(i); } /* Add an element first in the list */ void mr_list_add_elt_first(struct mr_list *list, struct mr_list_elt *elt) { if (list->first != NULL) { /* if there was a first elt shift it */ list->first->prev = elt; elt->next = list->first; } else { /* if there was no first, there was no last as well, so set it up */ list->last = elt; } list->first = elt; } /* Add an element last in the list */ void mr_list_add_elt_last(struct mr_list *list, struct mr_list_elt *elt) { if (list->last != NULL) { /* if there was a last elt use it */ list->last->next = elt; elt->prev = list->last; } else { /* if there was no last, there was no first as well, so set it up */ list->first = elt; } list->last = elt; } /* Add an element in the list after the ref elt given in parameter */ void mr_list_add_elt_after(struct mr_list *list, struct mr_list_elt *ref, struct mr_list_elt *elt) { if (ref->next != NULL) { /* if there was a next elt, shit it */ ref->next->prev = elt; elt->next = ref->next; } else { /* If not, it's the last elt */ list->last = elt; } ref->next = elt; elt->prev = ref; } /* Add an element in the list before the ref elt given in parameter */ void mr_list_add_elt_before(struct mr_list *list, struct mr_list_elt *ref, struct mr_list_elt *elt) { if (ref->prev != NULL) { /* if there was a prev elt, shit it */ ref->prev->next = elt; elt->prev = ref->prev; } else { /* If not, it's the first elt */ list->first = elt; } ref->prev = elt; elt->next = ref; } /* Delete the first element in the list */ void mr_list_del_elt_first(struct mr_list *list) { struct mr_list_elt *elt = list->first; if (elt->next != NULL) { /* There are other elts behind */ list->first = elt->next; } mr_list_free_elt(elt); } /* Delete the last element in the list */ void mr_list_del_elt_last(struct mr_list *list) { struct mr_list_elt *elt = list->last; if (elt->prev != NULL) { /* There are other elts before */ list->last = elt->prev; } mr_list_free_elt(elt); } /* Delete an element in the list after the ref elt given in parameter */ void mr_list_del_elt_after(struct mr_list *list, struct mr_list_elt *ref) { struct mr_list_elt *elt = ref->next; if (elt != NULL) { /* if there was a next elt, delete it */ if (elt->next != NULL) { /* there is an elt behind, shift it */ elt->prev->next = elt->next; elt->next->prev = elt->prev; mr_list_free_elt(elt); } else { /* that elt is the last one */ mr_list_del_elt_last(list); } } else { /* If not, ref is the last elt */ mr_msg(3, "No elt to delete available after the last one"); } } /* Delete an element in the list before the ref elt given in parameter */ void mr_list_del_elt_before(struct mr_list *list, struct mr_list_elt *ref) { struct mr_list_elt *elt = ref->prev; if (elt != NULL) { /* if there was a previous elt, delete it */ if (elt->prev != NULL) { /* there is an elt before, shift it */ elt->prev->next = elt->next; elt->next->prev = elt->prev; mr_list_free_elt(elt); } else { /* that elt is the first one */ mr_list_del_elt_firt(list); } } else { /* If not, ref is the first elt */ mr_msg(3, "No elt to delete available before the first one"); } }