Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame^] | 1 | #ifndef _LISTHELP_H |
| 2 | #define _LISTHELP_H |
| 3 | #include <linux/config.h> |
| 4 | #include <linux/list.h> |
| 5 | #include <linux/netfilter_ipv4/lockhelp.h> |
| 6 | |
| 7 | /* Header to do more comprehensive job than linux/list.h; assume list |
| 8 | is first entry in structure. */ |
| 9 | |
| 10 | /* Return pointer to first true entry, if any, or NULL. A macro |
| 11 | required to allow inlining of cmpfn. */ |
| 12 | #define LIST_FIND(head, cmpfn, type, args...) \ |
| 13 | ({ \ |
| 14 | const struct list_head *__i, *__j = NULL; \ |
| 15 | \ |
| 16 | ASSERT_READ_LOCK(head); \ |
| 17 | list_for_each(__i, (head)) \ |
| 18 | if (cmpfn((const type)__i , ## args)) { \ |
| 19 | __j = __i; \ |
| 20 | break; \ |
| 21 | } \ |
| 22 | (type)__j; \ |
| 23 | }) |
| 24 | |
| 25 | #define LIST_FIND_W(head, cmpfn, type, args...) \ |
| 26 | ({ \ |
| 27 | const struct list_head *__i, *__j = NULL; \ |
| 28 | \ |
| 29 | ASSERT_WRITE_LOCK(head); \ |
| 30 | list_for_each(__i, (head)) \ |
| 31 | if (cmpfn((type)__i , ## args)) { \ |
| 32 | __j = __i; \ |
| 33 | break; \ |
| 34 | } \ |
| 35 | (type)__j; \ |
| 36 | }) |
| 37 | |
| 38 | /* Just like LIST_FIND but we search backwards */ |
| 39 | #define LIST_FIND_B(head, cmpfn, type, args...) \ |
| 40 | ({ \ |
| 41 | const struct list_head *__i, *__j = NULL; \ |
| 42 | \ |
| 43 | ASSERT_READ_LOCK(head); \ |
| 44 | list_for_each_prev(__i, (head)) \ |
| 45 | if (cmpfn((const type)__i , ## args)) { \ |
| 46 | __j = __i; \ |
| 47 | break; \ |
| 48 | } \ |
| 49 | (type)__j; \ |
| 50 | }) |
| 51 | |
| 52 | static inline int |
| 53 | __list_cmp_same(const void *p1, const void *p2) { return p1 == p2; } |
| 54 | |
| 55 | /* Is this entry in the list? */ |
| 56 | static inline int |
| 57 | list_inlist(struct list_head *head, const void *entry) |
| 58 | { |
| 59 | return LIST_FIND(head, __list_cmp_same, void *, entry) != NULL; |
| 60 | } |
| 61 | |
| 62 | /* Delete from list. */ |
| 63 | #ifdef CONFIG_NETFILTER_DEBUG |
| 64 | #define LIST_DELETE(head, oldentry) \ |
| 65 | do { \ |
| 66 | ASSERT_WRITE_LOCK(head); \ |
| 67 | if (!list_inlist(head, oldentry)) \ |
| 68 | printk("LIST_DELETE: %s:%u `%s'(%p) not in %s.\n", \ |
| 69 | __FILE__, __LINE__, #oldentry, oldentry, #head); \ |
| 70 | else list_del((struct list_head *)oldentry); \ |
| 71 | } while(0) |
| 72 | #else |
| 73 | #define LIST_DELETE(head, oldentry) list_del((struct list_head *)oldentry) |
| 74 | #endif |
| 75 | |
| 76 | /* Append. */ |
| 77 | static inline void |
| 78 | list_append(struct list_head *head, void *new) |
| 79 | { |
| 80 | ASSERT_WRITE_LOCK(head); |
| 81 | list_add((new), (head)->prev); |
| 82 | } |
| 83 | |
| 84 | /* Prepend. */ |
| 85 | static inline void |
| 86 | list_prepend(struct list_head *head, void *new) |
| 87 | { |
| 88 | ASSERT_WRITE_LOCK(head); |
| 89 | list_add(new, head); |
| 90 | } |
| 91 | |
| 92 | /* Insert according to ordering function; insert before first true. */ |
| 93 | #define LIST_INSERT(head, new, cmpfn) \ |
| 94 | do { \ |
| 95 | struct list_head *__i; \ |
| 96 | ASSERT_WRITE_LOCK(head); \ |
| 97 | list_for_each(__i, (head)) \ |
| 98 | if ((new), (typeof (new))__i) \ |
| 99 | break; \ |
| 100 | list_add((struct list_head *)(new), __i->prev); \ |
| 101 | } while(0) |
| 102 | |
| 103 | /* If the field after the list_head is a nul-terminated string, you |
| 104 | can use these functions. */ |
| 105 | static inline int __list_cmp_name(const void *i, const char *name) |
| 106 | { |
| 107 | return strcmp(name, i+sizeof(struct list_head)) == 0; |
| 108 | } |
| 109 | |
| 110 | /* Returns false if same name already in list, otherwise does insert. */ |
| 111 | static inline int |
| 112 | list_named_insert(struct list_head *head, void *new) |
| 113 | { |
| 114 | if (LIST_FIND(head, __list_cmp_name, void *, |
| 115 | new + sizeof(struct list_head))) |
| 116 | return 0; |
| 117 | list_prepend(head, new); |
| 118 | return 1; |
| 119 | } |
| 120 | |
| 121 | /* Find this named element in the list. */ |
| 122 | #define list_named_find(head, name) \ |
| 123 | LIST_FIND(head, __list_cmp_name, void *, name) |
| 124 | |
| 125 | #endif /*_LISTHELP_H*/ |