/* This file contains functions for lists. $Id: list.c,v 1.1 2005/07/03 23:21:34 jefbed Exp $ */ #include #include #include "list.h" #include "defs.h" enum { YACL_IS_EQUAL=0 }; int yacl_list_push(yacl_list *l,const void *data, size_t r) { assert(l!=NULL); /* Go to end of list. */ L_SEEK_END(l) /* Take memory from heap. */ if((l->next=(yacl_list *)malloc(sizeof(yacl_list))) == NULL ) return YACL_ENOTMEM; l->next->prev = l; l=l->next; if( (l->data=malloc(r)) == NULL ) { free(l); l=NULL; return YACL_ENOTMEM; } memcpy( l->data, data, r); l->next=NULL; return YACL_SUCCESS; } int l_insertEnd(yacl_list *l,const void *data, size_t r) { return(yacl_list_push(l, data, r)); } int l_insertBegin(yacl_list *l,const void *data, size_t r) { assert(l!=NULL); /* Go to the beginning of the list. */ L_SEEK_BEGIN(l) if((l->prev=(yacl_list *)malloc(sizeof(yacl_list))) == NULL) return YACL_ENOTMEM; l->prev->next = l; l = l->prev; if((l->data=malloc(r)) == NULL) { l->next->prev = NULL; free(l); return YACL_ENOTMEM; } memcpy(l->data,data,r); return YACL_SUCCESS; } yacl_list *l_findElem(yacl_list *l, const void *data, int (*porownanie)(const void *, const void *)) { while(l != NULL && (*porownanie)(l->data,data) != YACL_IS_EQUAL) l=l->next; return l; } /* FIXME: Provide better comments/documentation, especially as to the use of POROWNANIE. */ int l_deleteElem(yacl_list *l, void *data, int (*porownanie)(const void *,const void *)) { yacl_list *prev=l; yacl_list *temp=l; do{ prev=temp; temp=temp->next; }while(temp!=NULL && (*porownanie)(temp->data,data) != YACL_IS_EQUAL ); if(temp==NULL) return YACL_EFAILED; prev->next=temp->next; free(temp->data); free(temp); return YACL_SUCCESS; } void * yacl_list_pop(yacl_list *l) { void *data; L_SEEK_END(l); data=l->data; assert(l->prev); l=l->prev; free(l->next); /* It is the user's responsibility to free DATA. */ return(data); } /* This returns the list at ELEMENT past the beginning of the list, in terms of l->next offsets. */ yacl_list * yacl_list_element(yacl_list *l, unsigned int element) { L_SEEK_BEGIN(l); while(element) { assert(l->next); l=l->next; element--; } return(l); } void l_free(yacl_list **l) { yacl_list *temp,*next; temp=(*l); while(temp!=NULL) { next=temp->next; free(temp->data); free(temp); temp=next; } (*l)=NULL; } /* This function counts the number of items in a list. */ unsigned int l_items(yacl_list *l) { unsigned int counter=0; L_SEEK_BEGIN(l); /* The first element of a list counts as element 0. */ while(l->next) { counter++; l=l->next; } return(counter); } void yacl_list_assign(yacl_list *ths, size_t num, const void *val, size_t val_size) { register yacl_list *first = ths; register size_t counter = 0; L_SEEK_BEGIN(first); while(first!=NULL) { if(counter>=num) break; memcpy(first->data, val, val_size); first = first->next; ++counter; } } yacl_list *yacl_list_back(yacl_list *ths) { L_SEEK_END(ths); return ths; } yacl_list *yacl_list_front(yacl_list *ths) { L_SEEK_BEGIN(ths); return ths; } yacl_list * yacl_list_clear(yacl_list *ths) { yacl_list *ret_val; register yacl_list *next; register yacl_list *temp = ths; L_SEEK_BEGIN(temp); ret_val = temp; free(ret_val->data); temp = ret_val->next; while(temp!=NULL) { next=temp->next; free(temp->data); free(temp); temp=next; } ret_val->next = NULL; ret_val->data = NULL; return ret_val; } void yacl_list_pop_back(yacl_list *ths) { L_SEEK_END(ths); if(ths->prev==NULL) return; free(ths->data); ths = ths->prev; free(ths->next); } yacl_list *yacl_list_pop_front(yacl_list *ths) { L_SEEK_BEGIN(ths); if(ths->next==NULL) return NULL; free(ths->data); ths = ths->next; free(ths->prev); return ths; } int yacl_list_push_back(yacl_list *ths, const void *val, size_t val_size) { L_SEEK_END(ths); if((ths->next = (yacl_list *)malloc(sizeof(yacl_list))) == NULL ) return YACL_ENOTMEM; ths->next->prev = ths; ths = ths->next; if((ths->data = malloc(val_size))==NULL) { ths = ths->prev; free(ths->next); return YACL_ENOTMEM; } memcpy(ths->data, val, val_size); return YACL_SUCCESS; } int yacl_list_push_front(yacl_list *ths, const void *val, size_t val_size) { L_SEEK_BEGIN(ths); if((ths->prev = (yacl_list *)malloc(sizeof(yacl_list))) == NULL ) return YACL_ENOTMEM; ths->prev->next = ths; ths = ths->prev; if((ths->data = malloc(val_size))==NULL) { ths = ths->next; free(ths->prev); return YACL_ENOTMEM; } memcpy(ths->data, val, val_size); return YACL_SUCCESS; } yacl_list *yacl_list_remove(yacl_list *ths, const void *val, size_t val_size) { L_SEEK_END(ths); yacl_list *tmp; while(ths->prev!=NULL) { if(memcmp(ths->data, val, val_size)==0) { free(ths->data); ths->prev->next = ths->next; tmp = ths->prev; if(ths->next!=NULL) { ths->next->prev = ths->prev; } free(ths); ths = tmp; continue; } ths = ths->prev; } return ths; } yacl_list *yacl_list_remove_if(yacl_list *ths, yacl_binary_pred cmp, const void *cmp_param) { L_SEEK_BEGIN(ths); yacl_list *tmp; while(ths->prev!=NULL) { if(cmp(ths->data, cmp_param)==0) { free(ths->data); ths->prev->next = ths->next; tmp = ths->prev; if(ths->next!=NULL) { ths->next->prev = ths->prev; } free(ths); ths = tmp; continue; } ths = ths->prev; } return ths; } size_t yacl_list_size(yacl_list *ths) { register size_t ret_val = 1; L_SEEK_BEGIN(ths); while(ths!=NULL); { ++ret_val; ths = ths->next; } return ret_val; } /* FIXME: Implement the following. void yacl_list_resize(yacl_list *ths, const void *val, size_t val_size) { } void yacl_list_reverse(yacl_list *ths) { } void yacl_list_sort(yacl_list *ths, yacl_binary_pred cmp) { } void yacl_list_swap(yacl_list *ths, yacl_list *lst) { } void yacl_list_unique(yacl_list *ths, yacl_binary_pred cmp) {*/ /* sort function implementation needed to implement this */ /* } */