paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 1 | /* Generic linked list |
| 2 | * Copyright (C) 1997, 2000 Kunihiro Ishiguro |
| 3 | * |
| 4 | * This file is part of GNU Zebra. |
| 5 | * |
| 6 | * GNU Zebra is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the |
| 8 | * Free Software Foundation; either version 2, or (at your option) any |
| 9 | * later version. |
| 10 | * |
| 11 | * GNU Zebra is distributed in the hope that it will be useful, but |
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with GNU Zebra; see the file COPYING. If not, write to the Free |
| 18 | * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA |
| 19 | * 02111-1307, USA. |
| 20 | */ |
| 21 | |
| 22 | #ifndef _ZEBRA_LINKLIST_H |
| 23 | #define _ZEBRA_LINKLIST_H |
| 24 | |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 25 | /* listnodes must always contain data to be valid. Adding an empty node |
| 26 | * to a list is invalid |
| 27 | */ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 28 | struct listnode |
| 29 | { |
| 30 | struct listnode *next; |
| 31 | struct listnode *prev; |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 32 | |
| 33 | /* private member, use getdata() to retrieve, do not access directly */ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 34 | void *data; |
| 35 | }; |
| 36 | |
| 37 | struct list |
| 38 | { |
| 39 | struct listnode *head; |
| 40 | struct listnode *tail; |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 41 | |
gdt | a7a9990 | 2003-12-22 16:07:52 +0000 | [diff] [blame] | 42 | /* invariant: count is the number of listnodes in the list */ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 43 | unsigned int count; |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 44 | |
gdt | a7a9990 | 2003-12-22 16:07:52 +0000 | [diff] [blame] | 45 | /* |
| 46 | * Returns -1 if val1 < val2, 0 if equal?, 1 if val1 > val2. |
| 47 | * Used as definition of sorted for listnode_add_sort |
| 48 | */ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 49 | int (*cmp) (void *val1, void *val2); |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 50 | |
| 51 | /* callback to free user-owned data when listnode is deleted. supplying |
| 52 | * this callback is very much encouraged! |
| 53 | */ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 54 | void (*del) (void *val); |
| 55 | }; |
| 56 | |
Josh Bailey | 54dd612 | 2012-03-21 10:00:07 -0700 | [diff] [blame] | 57 | #define listnextnode(X) ((X) ? ((X)->next) : NULL) |
| 58 | #define listhead(X) ((X) ? ((X)->head) : NULL) |
| 59 | #define listtail(X) ((X) ? ((X)->tail) : NULL) |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 60 | #define listcount(X) ((X)->count) |
| 61 | #define list_isempty(X) ((X)->head == NULL && (X)->tail == NULL) |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 62 | #define listgetdata(X) (assert((X)->data != NULL), (X)->data) |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 63 | |
| 64 | /* Prototypes. */ |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 65 | extern struct list *list_new(void); /* encouraged: set list.del callback on new lists */ |
| 66 | extern void list_free (struct list *); |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 67 | |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 68 | extern void listnode_add (struct list *, void *); |
| 69 | extern void listnode_add_sort (struct list *, void *); |
| 70 | extern void listnode_add_after (struct list *, struct listnode *, void *); |
Paul Jakma | 6d83113 | 2014-10-09 16:05:15 +0100 | [diff] [blame] | 71 | extern void listnode_move_to_tail (struct list *, struct listnode *); |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 72 | extern void listnode_delete (struct list *, void *); |
| 73 | extern struct listnode *listnode_lookup (struct list *, void *); |
| 74 | extern void *listnode_head (struct list *); |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 75 | |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 76 | extern void list_delete (struct list *); |
| 77 | extern void list_delete_all_node (struct list *); |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 78 | |
| 79 | /* For ospfd and ospf6d. */ |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 80 | extern void list_delete_node (struct list *, struct listnode *); |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 81 | |
| 82 | /* For ospf_spf.c */ |
paul | 8cc4198 | 2005-05-06 21:25:49 +0000 | [diff] [blame] | 83 | extern void list_add_node_prev (struct list *, struct listnode *, void *); |
| 84 | extern void list_add_node_next (struct list *, struct listnode *, void *); |
| 85 | extern void list_add_list (struct list *, struct list *); |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 86 | |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 87 | /* List iteration macro. |
| 88 | * Usage: for (ALL_LIST_ELEMENTS (...) { ... } |
| 89 | * It is safe to delete the listnode using this macro. |
| 90 | */ |
| 91 | #define ALL_LIST_ELEMENTS(list,node,nextnode,data) \ |
Josh Bailey | 54dd612 | 2012-03-21 10:00:07 -0700 | [diff] [blame] | 92 | (node) = listhead(list), ((data) = NULL); \ |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 93 | (node) != NULL && \ |
David Lamparter | a5c851c | 2012-11-27 03:21:44 +0100 | [diff] [blame] | 94 | ((data) = listgetdata(node),(nextnode) = node->next, 1); \ |
Josh Bailey | 54dd612 | 2012-03-21 10:00:07 -0700 | [diff] [blame] | 95 | (node) = (nextnode), ((data) = NULL) |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 96 | |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 97 | /* read-only list iteration macro. |
| 98 | * Usage: as per ALL_LIST_ELEMENTS, but not safe to delete the listnode Only |
| 99 | * use this macro when it is *immediately obvious* the listnode is not |
| 100 | * deleted in the body of the loop. Does not have forward-reference overhead |
| 101 | * of previous macro. |
| 102 | */ |
| 103 | #define ALL_LIST_ELEMENTS_RO(list,node,data) \ |
Josh Bailey | 54dd612 | 2012-03-21 10:00:07 -0700 | [diff] [blame] | 104 | (node) = listhead(list), ((data) = NULL);\ |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 105 | (node) != NULL && ((data) = listgetdata(node), 1); \ |
Josh Bailey | 54dd612 | 2012-03-21 10:00:07 -0700 | [diff] [blame] | 106 | (node) = listnextnode(node), ((data) = NULL) |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 107 | |
| 108 | /* these *do not* cleanup list nodes and referenced data, as the functions |
| 109 | * do - these macros simply {de,at}tach a listnode from/to a list. |
| 110 | */ |
| 111 | |
| 112 | /* List node attach macro. */ |
| 113 | #define LISTNODE_ATTACH(L,N) \ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 114 | do { \ |
| 115 | (N)->prev = (L)->tail; \ |
| 116 | if ((L)->head == NULL) \ |
| 117 | (L)->head = (N); \ |
| 118 | else \ |
| 119 | (L)->tail->next = (N); \ |
| 120 | (L)->tail = (N); \ |
paul | 071fced | 2003-08-12 05:40:28 +0000 | [diff] [blame] | 121 | (L)->count++; \ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 122 | } while (0) |
| 123 | |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 124 | /* List node detach macro. */ |
| 125 | #define LISTNODE_DETACH(L,N) \ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 126 | do { \ |
| 127 | if ((N)->prev) \ |
| 128 | (N)->prev->next = (N)->next; \ |
| 129 | else \ |
| 130 | (L)->head = (N)->next; \ |
| 131 | if ((N)->next) \ |
| 132 | (N)->next->prev = (N)->prev; \ |
| 133 | else \ |
| 134 | (L)->tail = (N)->prev; \ |
paul | 071fced | 2003-08-12 05:40:28 +0000 | [diff] [blame] | 135 | (L)->count--; \ |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 136 | } while (0) |
| 137 | |
paul | 1eb8ef2 | 2005-04-07 07:30:20 +0000 | [diff] [blame] | 138 | /* Deprecated: 20050406 */ |
| 139 | #if !defined(QUAGGA_NO_DEPRECATED_INTERFACES) |
| 140 | #warning "Using deprecated libzebra interfaces" |
| 141 | #define LISTNODE_ADD(L,N) LISTNODE_ATTACH(L,N) |
| 142 | #define LISTNODE_DELETE(L,N) LISTNODE_DETACH(L,N) |
| 143 | #define nextnode(X) ((X) = (X)->next) |
| 144 | #define getdata(X) listgetdata(X) |
| 145 | #define LIST_LOOP(L,V,N) \ |
| 146 | for (ALL_LIST_ELEMENTS_RO (L,N,V)) |
| 147 | #endif /* QUAGGA_NO_DEPRECATED_INTERFACES */ |
| 148 | |
paul | 718e374 | 2002-12-13 20:15:29 +0000 | [diff] [blame] | 149 | #endif /* _ZEBRA_LINKLIST_H */ |