1 #ifndef CCAN_TEVENT_TEVENT_UTIL_H
2 #define CCAN_TEVENT_TEVENT_UTIL_H
4 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 1998-2010
7 Copyright (C) Jelmer Vernooij 2005
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* To use these macros you must have a structure containing a next and
30 February 2010 - changed list format to have a prev pointer from the
31 list head. This makes DLIST_ADD_END() O(1) even though we only have
34 The scheme is as follows:
36 1) with no entries in the list:
39 2) with 1 entry in the list:
40 list_head->next == NULL
41 list_head->prev == list_head
43 3) with 2 entries in the list:
44 list_head->next == element2
45 list_head->prev == element2
46 element2->prev == list_head
47 element2->next == NULL
49 4) with N entries in the list:
50 list_head->next == element2
51 list_head->prev == elementN
52 elementN->prev == element{N-1}
53 elementN->next == NULL
55 This allows us to find the tail of the list by using
56 list_head->prev, which means we can add to the end of the list in
60 Note that the 'type' arguments below are no longer needed, but
61 are kept for now to prevent an incompatible argument change
66 add an element at the front of a list
68 #define DLIST_ADD(list, p) \
71 (p)->prev = (list) = (p); \
74 (p)->prev = (list)->prev; \
82 remove an element from a list
83 Note that the element doesn't have to be in the list. If it
84 isn't then this is a no-op
86 #define DLIST_REMOVE(list, p) \
88 if ((p) == (list)) { \
89 if ((p)->next) (p)->next->prev = (p)->prev; \
91 } else if ((list) && (p) == (list)->prev) { \
92 (p)->prev->next = NULL; \
93 (list)->prev = (p)->prev; \
95 if ((p)->prev) (p)->prev->next = (p)->next; \
96 if ((p)->next) (p)->next->prev = (p)->prev; \
98 if ((p) != (list)) (p)->next = (p)->prev = NULL; \
102 find the head of the list given any element in it.
103 Note that this costs O(N), so you should avoid this macro
106 #define DLIST_HEAD(p, result_head) \
108 (result_head) = (p); \
109 while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \
112 /* return the last element in the list */
113 #define DLIST_TAIL(list) ((list)?(list)->prev:NULL)
115 /* return the previous element in the list. */
116 #define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL)
118 /* insert 'p' after the given element 'el' in a list. If el is NULL then
119 this is the same as a DLIST_ADD() */
120 #define DLIST_ADD_AFTER(list, p, el) \
122 if (!(list) || !(el)) { \
123 DLIST_ADD(list, p); \
126 (p)->next = (el)->next; \
128 if ((p)->next) (p)->next->prev = (p); \
129 if ((list)->prev == (el)) (list)->prev = (p); \
135 add to the end of a list.
136 Note that 'type' is ignored
138 #define DLIST_ADD_END(list, p, type) \
141 DLIST_ADD(list, p); \
143 DLIST_ADD_AFTER(list, p, (list)->prev); \
147 /* promote an element to the from of a list */
148 #define DLIST_PROMOTE(list, p) \
150 DLIST_REMOVE(list, p); \
151 DLIST_ADD(list, p); \
155 demote an element to the end of a list.
156 Note that 'type' is ignored
158 #define DLIST_DEMOTE(list, p, type) \
160 DLIST_REMOVE(list, p); \
161 DLIST_ADD_END(list, p, NULL); \
165 concatenate two lists - putting all elements of the 2nd list at the
166 end of the first list.
167 Note that 'type' is ignored
169 #define DLIST_CONCATENATE(list1, list2, type) \
174 (list1)->prev->next = (list2); \
176 void *_tmplist = (void *)(list1)->prev; \
177 (list1)->prev = (list2)->prev; \
178 (list2)->prev = _tmplist; \
183 #endif /* _DLINKLIST_H */
185 const char **ev_str_list_add(const char **list, const char *s);
186 int ev_set_blocking(int fd, bool set);
187 size_t ev_str_list_length(const char **list);
189 /* Defined here so we can build against older talloc versions that don't
190 * have this define yet. */
192 #define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0)
195 #define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
198 #endif /* CCAN_TEVENT_TEVENT_UTIL_H */