diff options
Diffstat (limited to 'lib/linklist.h')
-rw-r--r-- | lib/linklist.h | 64 |
1 files changed, 53 insertions, 11 deletions
diff --git a/lib/linklist.h b/lib/linklist.h index b766420f..80b21f64 100644 --- a/lib/linklist.h +++ b/lib/linklist.h @@ -22,10 +22,15 @@ #ifndef _ZEBRA_LINKLIST_H #define _ZEBRA_LINKLIST_H +/* listnodes must always contain data to be valid. Adding an empty node + * to a list is invalid + */ struct listnode { struct listnode *next; struct listnode *prev; + + /* private member, use getdata() to retrieve, do not access directly */ void *data; }; @@ -33,25 +38,31 @@ struct list { struct listnode *head; struct listnode *tail; + /* invariant: count is the number of listnodes in the list */ unsigned int count; + /* * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. * Used as definition of sorted for listnode_add_sort */ int (*cmp) (void *val1, void *val2); + + /* callback to free user-owned data when listnode is deleted. supplying + * this callback is very much encouraged! + */ void (*del) (void *val); }; -#define nextnode(X) ((X) = (X)->next) +#define listnextnode(X) ((X)->next) #define listhead(X) ((X)->head) #define listtail(X) ((X)->tail) #define listcount(X) ((X)->count) #define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) -#define getdata(X) ((X)->data) +#define listgetdata(X) (assert((X)->data != NULL), (X)->data) /* Prototypes. */ -struct list *list_new(); +struct list *list_new(); /* encouraged: set list.del callback on new lists */ void list_free (struct list *); void listnode_add (struct list *, void *); @@ -72,13 +83,33 @@ void list_add_node_prev (struct list *, struct listnode *, void *); void list_add_node_next (struct list *, struct listnode *, void *); void list_add_list (struct list *, struct list *); -/* List iteration macro. */ -#define LIST_LOOP(L,V,N) \ - for ((N) = (L)->head; (N); (N) = (N)->next) \ - if (((V) = (N)->data) != NULL) +/* List iteration macro. + * Usage: for (ALL_LIST_ELEMENTS (...) { ... } + * It is safe to delete the listnode using this macro. + */ +#define ALL_LIST_ELEMENTS(list,node,nextnode,data) \ + (node) = listhead(list); \ + (node) != NULL && \ + ((data) = listgetdata(node),(nextnode) = listnextnode(node), 1); \ + (node) = (nextnode) + +/* read-only list iteration macro. + * Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only + * use this macro when it is *immediately obvious* the listnode is not + * deleted in the body of the loop. Does not have forward-reference overhead + * of previous macro. + */ +#define ALL_LIST_ELEMENTS_RO(list,node,data) \ + (node) = listhead(list); \ + (node) != NULL && ((data) = listgetdata(node), 1); \ + (node) = listnextnode(node) -/* List node add macro. */ -#define LISTNODE_ADD(L,N) \ +/* these *do not* cleanup list nodes and referenced data, as the functions + * do - these macros simply {de,at}tach a listnode from/to a list. + */ + +/* List node attach macro. */ +#define LISTNODE_ATTACH(L,N) \ do { \ (N)->prev = (L)->tail; \ if ((L)->head == NULL) \ @@ -89,8 +120,8 @@ void list_add_list (struct list *, struct list *); (L)->count++; \ } while (0) -/* List node delete macro. */ -#define LISTNODE_DELETE(L,N) \ +/* List node detach macro. */ +#define LISTNODE_DETACH(L,N) \ do { \ if ((N)->prev) \ (N)->prev->next = (N)->next; \ @@ -103,4 +134,15 @@ void list_add_list (struct list *, struct list *); (L)->count--; \ } while (0) +/* Deprecated: 20050406 */ +#if !defined(QUAGGA_NO_DEPRECATED_INTERFACES) +#warning "Using deprecated libzebra interfaces" +#define LISTNODE_ADD(L,N) LISTNODE_ATTACH(L,N) +#define LISTNODE_DELETE(L,N) LISTNODE_DETACH(L,N) +#define nextnode(X) ((X) = (X)->next) +#define getdata(X) listgetdata(X) +#define LIST_LOOP(L,V,N) \ + for (ALL_LIST_ELEMENTS_RO (L,N,V)) +#endif /* QUAGGA_NO_DEPRECATED_INTERFACES */ + #endif /* _ZEBRA_LINKLIST_H */ |