/* * Copyright (C) James R. Leu 2000 * jleu@mindspring.com * * This software is covered under the LGPL, for more * info check out http://www.gnu.org/copyleft/lgpl.html */ #ifndef _LDP_LIST_H_ #define _LDP_LIST_H_ #define LDP_LIST_ROOT(name,type) \ struct name { \ struct type *llh_first; \ struct type *llh_last; \ } #define LDP_LIST_ELEM(type) \ struct { \ struct type *lle_next; \ struct type *lle_prev; \ } #define LDP_LIST_REMOVE(head, elm, field) { \ if((elm)->field.lle_next == (void *)(head)) \ (head)->llh_last = (elm)->field.lle_prev; \ else \ (elm)->field.lle_next->field.lle_prev = (elm)->field.lle_prev; \ if((elm)->field.lle_prev == (void *)(head)) \ (head)->llh_first = (elm)->field.lle_next; \ else \ (elm)->field.lle_prev->field.lle_next = (elm)->field.lle_next; \ } #define LDP_LIST_INSERT_BEFORE(head,listelm,elm,field) { \ (elm)->field.lle_next = (listelm); \ (elm)->field.lle_prev = (listelm)->field.lle_prev; \ if((listelm)->field.lle_prev == (void *)(head)) \ (head)->llh_first = (elm); \ else \ (listelm)->field.lle_prev->field.lle_next = (elm); \ (listelm)->field.lle_prev = (elm); \ } #define LDP_LIST_INIT(head,type) { \ (head)->llh_first = (struct type *)(head); \ (head)->llh_last = (struct type *)(head); \ } #define LDP_LIST_ADD_HEAD(head, elm, field, type) { \ (elm)->field.lle_next = (head)->llh_first; \ (elm)->field.lle_prev = (struct type *)(head); \ if ((head)->llh_last == (struct type *)(head)) \ (head)->llh_last = (elm); \ else \ (head)->llh_first->field.lle_prev = (elm); \ (head)->llh_first = (elm); \ } #define LDP_LIST_ADD_TAIL(head, elm, field, type) { \ (elm)->field.lle_next = (struct type *)(head); \ (elm)->field.lle_prev = (head)->llh_last; \ if ((head)->llh_first == (struct type *)(head)) \ (head)->llh_first = (elm); \ else \ (head)->llh_last->field.lle_next = (elm); \ (head)->llh_last = (elm); \ } #define LDP_LIST_REMOVE_TAIL(root,elem,field) { \ (elem) = (root)->llh_last; \ if((elem) && (elem) != (void*)(root)) { \ LDP_LIST_REMOVE(root,elem,field); \ } else { \ (elem) = NULL; \ } \ } #define LDP_LIST_REMOVE_HEAD(root,elem,field) { \ (elem) = (root)->llh_first; \ if((elem) && (elem) != (void*)(root)) { \ LDP_LIST_REMOVE(root,elem,field); \ } else { \ (elem) = NULL; \ } \ } #define LDP_LIST_ELEM_INIT(elem,field) { \ (elem)->field.lle_next = NULL; \ (elem)->field.lle_prev = NULL; \ } #define LDP_LIST_HEAD(root) (((root)->llh_first == (void*)(root))?(NULL):((root)->llh_first)) #define LDP_LIST_NEXT(root,elem,field) ((((elem)->field.lle_next) == (void*)(root))?(NULL):((elem)->field.lle_next)) #define LDP_LIST_PREV(root,elem,field) ((((elem)->field.lle_prev) == (void*)(root))?(NULL):((elem)->field.lle_prev)) #define LDP_LIST_TAIL(root) (((root)->llh_last == (void*)(root))?(NULL):((root)->llh_last)) #endif