/* dlist.c Pedro Flynn - pflynn@microsoftsucks.org */ #include "dlist.h" #ifdef __cplusplus extern "C" { #endif DList* dlist_create(int (*match)(const void*,const void*),void (*destroy)(void*)) { DList* dlist; if(!(dlist = (DList*) malloc(sizeof(DList)))) return NULL; dlist->match = match; dlist->destroy = destroy; dlist->size = 0; dlist->head = dlist->tail = NULL; return dlist; } DListElement* dlist_insert_next(DList* dlist,DListElement* element,void* data) { DListElement* newelement; if(!element && dlist->size) return NULL; if(!(newelement = (DListElement*) malloc(sizeof(DListElement)))) return NULL; newelement->data = data; if(!element){ dlist->head = dlist->tail = newelement; newelement->next = newelement->prev = NULL; }else{ if(!(newelement->next = element->next)) dlist->tail = newelement; else element->next->prev = newelement; newelement->prev = element; element->next = newelement; } dlist->size++; return newelement; } DListElement* dlist_insert_prev(DList* dlist,DListElement* element,void* data) { DListElement* newelement; if(!element && dlist->size) return NULL; if(!(newelement = (DListElement*) malloc(sizeof(DListElement)))) return NULL; newelement->data = data; if(!element){ dlist->head = dlist->tail = newelement; newelement->next = newelement->prev = NULL; }else{ newelement->next = element; if(!(newelement->prev = element->prev)) dlist->head = newelement; else element->prev->next = newelement; element->prev = newelement; } dlist->size++; return newelement; } int dlist_remove_element(DList* dlist,DListElement* element,void** data) { if(!dlist->size || !element) return -1; if(element->prev) element->prev->next = element->next; else dlist->head = element->next; if(element->next) element->next->prev = element->prev; else dlist->tail = element->prev; *data = element->data; free(element); dlist->size--; return 0; } DListElement* dlist_get_element(DList* dlist,const void* data) { DListElement* element; if(!dlist->match || !dlist->size) return NULL; element = dlist->head; do if(dlist->match(element->data,data)) return element; while(element = element->next); return NULL; } void dlist_destroy(DList* dlist) { void* data; while(dlist->size) if(!dlist_remove_element(dlist,dlist->head,(void**) &data) && dlist->destroy) dlist->destroy(data); free(dlist); } DListElement* dlist_enqueue_element(DList* dlist,void* data) { return dlist_insert_next(dlist,dlist->tail,data); } int dlist_dequeue_element(DList *dlist,void** data) { return dlist_remove_element(dlist,dlist->head,data); } DListElement* dlist_push_element(DList *dlist,void* data) { return dlist_insert_prev(dlist,dlist->head,data); } int dlist_pop_element(DList *dlist,void** data) { return dlist_remove_element(dlist,dlist->head,data); } #ifdef __cplusplus } #endif