/* list.h - Linked List macros inspired by BSD queue.h * Jon Mayo * PUBLIC DOMAIN - December 5, 2008 */ #ifndef LIST_H #define LIST_H /* linked lists with double pointers */ #define LIST_ENTRY(type) struct { type *_next, **_prev; } #define LIST_HEAD(headname, type) headname { type *_head; } #define LIST_INIT(head) ((head)->_head=NULL) #define LIST_ENTRY_INIT(elm, name) do { (elm)->name._next=NULL; (elm)->name._prev=NULL; } while(0) #define LIST_TOP(head) ((head)._head) #define LIST_NEXT(elm, name) ((elm)->name._next) #define LIST_ISEMPTY(head) ((head)->_head==NULL) #define LIST_PREVPTR(elm, name) ((elm)->name._prev) #define LIST_INSERT_ATPTR(prevptr, elm, name) do { \ (elm)->name._prev=(prevptr); \ if(((elm)->name._next=*(prevptr))!=NULL) \ (elm)->name._next->name._prev=&(elm)->name._next; \ *(prevptr)=(elm); \ } while(0) #define LIST_INSERT_AFTER(where, elm, name) do { \ assert(where != NULL && elm != NULL); \ (elm)->name._prev=&(where)->name._next; \ if(((elm)->name._next=(where)->name._next)!=NULL) \ (where)->name._next->name._prev=&(elm)->name._next; \ *(elm)->name._prev=(elm); \ } while(0) #define LIST_INSERT_HEAD(head, elm, name) do { \ assert(head != NULL && elm != NULL); \ (elm)->name._prev=&(head)->_head; \ if(((elm)->name._next=(head)->_head)!=NULL) \ (head)->_head->name._prev=&(elm)->name._next; \ (head)->_head=(elm); \ } while(0) #define LIST_REMOVE(elm, name) do { \ assert(elm != NULL); \ if((elm)->name._next!=NULL) \ (elm)->name._next->name._prev=(elm)->name._prev; \ if((elm)->name._prev) \ *(elm)->name._prev=(elm)->name._next; \ } while(0) #define LIST_REMOVE_HEAD(head, name) LIST_REMOVE(LIST_TOP(head), name) #define LIST_TAIL_ADD(tailptr, elm, name) do { \ assert(tailptr != NULL && elm != NULL); \ (elm)->name._prev=(tailptr); \ *(tailptr)=(elm); \ (tailptr)=&(elm)->name._next; \ } while(0) #define LIST_TAIL_INIT(head, tailptr) (tailptr)=&LIST_TOP(head) #define LIST_FOREACH(i_var, head, name) \ for((i_var)=LIST_TOP(head);(i_var);(i_var)=LIST_NEXT(i_var, name)) /* singly linked lists */ #define SLIST_ENTRY(type) struct { type *_next; } #define SLIST_HEAD(headname, type) headname { type *_head; } #define SLIST_INIT(head) ((head)->_head=NULL) #define SLIST_ENTRY_INIT(elm, name) do { (elm)->name._next=NULL; } while(0) #define SLIST_TOP(head) ((head)._head) #define SLIST_NEXT(elm, name) ((elm)->name._next) #define SLIST_ISEMPTY(head) ((head)->_head==NULL) #define SLIST_INSERT_HEAD(head, elm, name) do { \ assert(head != NULL && elm != NULL); \ (elm)->name._next=(head)->_head; \ (head)->_head=(elm); \ } while(0) /* nextptr : pointer to the previous element's next field or pointer to the _head pointer */ #define SLIST_REMOVE(elm, name, nextptr) do { \ assert(elm != NULL); \ assert(nextptr != NULL); \ *(nextptr)=(elm)->name._next; \ (elm)->name._next=NULL; \ } while(0) #define SLIST_REMOVE_HEAD(head, name) do { \ void *_tmp; \ assert(head != NULL); \ _tmp=SLIST_NEXT((head)->_head, name); \ SLIST_NEXT((head)->_head, name)=NULL; \ (head)->_head=_tmp; \ } while(0) #define SLIST_INSERT_AFTER(where, elm, name) do { \ assert((where) != NULL && (elm) != NULL); \ SLIST_NEXT((elm), name)=SLIST_NEXT((where), name); \ SLIST_NEXT((where), name)=(elm); \ } while(0) #define SLIST_FOREACH(i_var, head, name) \ for((i_var)=SLIST_TOP(head);(i_var);(i_var)=SLIST_NEXT(i_var, name)) #endif