]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/include/rb_tools.h
14bfda65dceadf852cd63f00026c68a9c0a12b7a
[irc/rqf/shadowircd.git] / libratbox / include / rb_tools.h
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * tools.h: Header for the various tool functions.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
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 2 of the License, or
12 * (at your option) any later version.
13 *
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.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
22 * USA
23 *
24 * $Id: rb_tools.h 25042 2008-01-23 16:14:08Z androsyn $
25 */
26
27 #ifndef RB_LIB_H
28 # error "Do not use tools.h directly"
29 #endif
30
31 #ifndef __TOOLS_H__
32 #define __TOOLS_H__
33
34 size_t rb_strlcpy(char *dst, const char *src, size_t siz);
35 size_t rb_strlcat(char *dst, const char *src, size_t siz);
36 size_t rb_strnlen(const char *s, size_t count);
37
38 int rb_string_to_array(char *string, char **parv, int maxpara);
39
40 /*
41 * double-linked-list stuff
42 */
43 typedef struct _rb_dlink_node rb_dlink_node;
44 typedef struct _rb_dlink_list rb_dlink_list;
45
46 struct _rb_dlink_node
47 {
48 void *data;
49 rb_dlink_node *prev;
50 rb_dlink_node *next;
51
52 };
53
54 struct _rb_dlink_list
55 {
56 rb_dlink_node *head;
57 rb_dlink_node *tail;
58 unsigned long length;
59 };
60
61 rb_dlink_node *rb_make_rb_dlink_node(void);
62 void rb_free_rb_dlink_node(rb_dlink_node * lp);
63 void rb_init_rb_dlink_nodes(size_t dh_size);
64
65 /* This macros are basically swiped from the linux kernel
66 * they are simple yet effective
67 */
68
69 /*
70 * Walks forward of a list.
71 * pos is your node
72 * head is your list head
73 */
74 #define RB_DLINK_FOREACH(pos, head) for (pos = (head); pos != NULL; pos = pos->next)
75
76 /*
77 * Walks forward of a list safely while removing nodes
78 * pos is your node
79 * n is another list head for temporary storage
80 * head is your list head
81 */
82 #define RB_DLINK_FOREACH_SAFE(pos, n, head) for (pos = (head), n = pos ? pos->next : NULL; pos != NULL; pos = n, n = pos ? pos->next : NULL)
83
84 #define RB_DLINK_FOREACH_PREV(pos, head) for (pos = (head); pos != NULL; pos = pos->prev)
85
86
87 /* Returns the list length */
88 #define rb_dlink_list_length(list) (list)->length
89
90 #define rb_dlinkAddAlloc(data, list) rb_dlinkAdd(data, rb_make_rb_dlink_node(), list)
91 #define rb_dlinkAddTailAlloc(data, list) rb_dlinkAddTail(data, rb_make_rb_dlink_node(), list)
92 #define rb_dlinkDestroy(node, list) do { rb_dlinkDelete(node, list); rb_free_rb_dlink_node(node); } while(0)
93
94
95 /*
96 * dlink_ routines are stolen from squid, except for rb_dlinkAddBefore,
97 * which is mine.
98 * -- adrian
99 */
100
101 static inline void
102 rb_dlinkMoveNode(rb_dlink_node * m, rb_dlink_list * oldlist, rb_dlink_list * newlist)
103 {
104 /* Assumption: If m->next == NULL, then list->tail == m
105 * and: If m->prev == NULL, then list->head == m
106 */
107 assert(m != NULL);
108 assert(oldlist != NULL);
109 assert(newlist != NULL);
110
111 if(m->next)
112 m->next->prev = m->prev;
113 else
114 oldlist->tail = m->prev;
115
116 if(m->prev)
117 m->prev->next = m->next;
118 else
119 oldlist->head = m->next;
120
121 m->prev = NULL;
122 m->next = newlist->head;
123 if(newlist->head != NULL)
124 newlist->head->prev = m;
125 else if(newlist->tail == NULL)
126 newlist->tail = m;
127 newlist->head = m;
128
129 oldlist->length--;
130 newlist->length++;
131 }
132
133 static inline void
134 rb_dlinkAdd(void *data, rb_dlink_node * m, rb_dlink_list * list)
135 {
136 assert(data != NULL);
137 assert(m != NULL);
138 assert(list != NULL);
139
140 m->data = data;
141 m->prev = NULL;
142 m->next = list->head;
143
144 /* Assumption: If list->tail != NULL, list->head != NULL */
145 if(list->head != NULL)
146 list->head->prev = m;
147 else if(list->tail == NULL)
148 list->tail = m;
149
150 list->head = m;
151 list->length++;
152 }
153
154 static inline void
155 rb_dlinkAddBefore(rb_dlink_node * b, void *data, rb_dlink_node * m, rb_dlink_list * list)
156 {
157 assert(b != NULL);
158 assert(data != NULL);
159 assert(m != NULL);
160 assert(list != NULL);
161
162 /* Shortcut - if its the first one, call rb_dlinkAdd only */
163 if(b == list->head)
164 {
165 rb_dlinkAdd(data, m, list);
166 }
167 else
168 {
169 m->data = data;
170 b->prev->next = m;
171 m->prev = b->prev;
172 b->prev = m;
173 m->next = b;
174 list->length++;
175 }
176 }
177
178 static inline void
179 rb_dlinkMoveTail(rb_dlink_node *m, rb_dlink_list *list)
180 {
181 if(list->tail == m)
182 return;
183
184 /* From here assume that m->next != NULL as that can only
185 * be at the tail and assume that the node is on the list
186 */
187
188 m->next->prev = m->prev;
189
190 if(m->prev != NULL)
191 m->prev->next = m->next;
192 else
193 list->head = m->next;
194
195 list->tail->next = m;
196 m->prev = list->tail;
197 m->next = NULL;
198 list->tail = m;
199 }
200
201 static inline void
202 rb_dlinkAddTail(void *data, rb_dlink_node * m, rb_dlink_list * list)
203 {
204 assert(m != NULL);
205 assert(list != NULL);
206 assert(data != NULL);
207
208 m->data = data;
209 m->next = NULL;
210 m->prev = list->tail;
211
212 /* Assumption: If list->tail != NULL, list->head != NULL */
213 if(list->tail != NULL)
214 list->tail->next = m;
215 else if(list->head == NULL)
216 list->head = m;
217
218 list->tail = m;
219 list->length++;
220 }
221
222 /* Execution profiles show that this function is called the most
223 * often of all non-spontaneous functions. So it had better be
224 * efficient. */
225 static inline void
226 rb_dlinkDelete(rb_dlink_node * m, rb_dlink_list * list)
227 {
228 assert(m != NULL);
229 assert(list != NULL);
230 /* Assumption: If m->next == NULL, then list->tail == m
231 * and: If m->prev == NULL, then list->head == m
232 */
233 if(m->next)
234 m->next->prev = m->prev;
235 else
236 list->tail = m->prev;
237
238 if(m->prev)
239 m->prev->next = m->next;
240 else
241 list->head = m->next;
242
243 m->next = m->prev = NULL;
244 list->length--;
245 }
246
247 static inline rb_dlink_node *
248 rb_dlinkFindDelete(void *data, rb_dlink_list *list)
249 {
250 rb_dlink_node *m;
251 assert(list != NULL);
252 assert(data != NULL);
253 RB_DLINK_FOREACH(m, list->head)
254 {
255 if(m->data != data)
256 continue;
257
258 if(m->next)
259 m->next->prev = m->prev;
260 else
261 list->tail = m->prev;
262
263 if(m->prev)
264 m->prev->next = m->next;
265 else
266 list->head = m->next;
267
268 m->next = m->prev = NULL;
269 list->length--;
270 return m;
271 }
272 return NULL;
273 }
274
275 static inline int
276 rb_dlinkFindDestroy(void *data, rb_dlink_list *list)
277 {
278 void *ptr;
279
280 assert(list != NULL);
281 assert(data != NULL);
282 ptr = rb_dlinkFindDelete(data, list);
283
284 if(ptr != NULL)
285 {
286 rb_free_rb_dlink_node(ptr);
287 return 1;
288 }
289 return 0;
290 }
291
292 /*
293 * rb_dlinkFind
294 * inputs - list to search
295 * - data
296 * output - pointer to link or NULL if not found
297 * side effects - Look for ptr in the linked listed pointed to by link.
298 */
299 static inline rb_dlink_node *
300 rb_dlinkFind(void *data, rb_dlink_list *list)
301 {
302 rb_dlink_node *ptr;
303 assert(list != NULL);
304 assert(data != NULL);
305
306 RB_DLINK_FOREACH(ptr, list->head)
307 {
308 if(ptr->data == data)
309 return (ptr);
310 }
311 return (NULL);
312 }
313
314 static inline void
315 rb_dlinkMoveList(rb_dlink_list * from, rb_dlink_list * to)
316 {
317 assert(from != NULL);
318 assert(to != NULL);
319
320 /* There are three cases */
321 /* case one, nothing in from list */
322 if(from->head == NULL)
323 return;
324
325 /* case two, nothing in to list */
326 if(to->head == NULL)
327 {
328 to->head = from->head;
329 to->tail = from->tail;
330 from->head = from->tail = NULL;
331 to->length = from->length;
332 from->length = 0;
333 return;
334 }
335
336 /* third case play with the links */
337 from->tail->next = to->head;
338 to->head->prev = from->tail;
339 to->head = from->head;
340 from->head = from->tail = NULL;
341 to->length += from->length;
342 from->length = 0;
343 }
344
345 #endif /* __TOOLS_H__ */