]> jfr.im git - solanum.git/blob - libratbox/include/rb_tools.h
Merge branch 'master' of github.com:charybdis-ircd/charybdis
[solanum.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 26170 2008-10-26 20:59:07Z 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 #ifdef __GNUC__
39 int rb_snprintf_append(char *str, size_t len, const char *format, ...)
40 __attribute__ ((format(printf, 3, 4)));
41 #else
42 int rb_snprintf_append(char *str, const size_t size, const char *, ...);
43 #endif
44
45 char *rb_basename(const char *);
46 char *rb_dirname(const char *);
47
48 int rb_string_to_array(char *string, char **parv, int maxpara);
49
50 /*
51 * double-linked-list stuff
52 */
53 typedef struct _rb_dlink_node rb_dlink_node;
54 typedef struct _rb_dlink_list rb_dlink_list;
55
56 struct _rb_dlink_node
57 {
58 void *data;
59 rb_dlink_node *prev;
60 rb_dlink_node *next;
61
62 };
63
64 struct _rb_dlink_list
65 {
66 rb_dlink_node *head;
67 rb_dlink_node *tail;
68 unsigned long length;
69 };
70
71 rb_dlink_node *rb_make_rb_dlink_node(void);
72 void rb_free_rb_dlink_node(rb_dlink_node *lp);
73 void rb_init_rb_dlink_nodes(size_t dh_size);
74
75 /* This macros are basically swiped from the linux kernel
76 * they are simple yet effective
77 */
78
79 /*
80 * Walks forward of a list.
81 * pos is your node
82 * head is your list head
83 */
84 #define RB_DLINK_FOREACH(pos, head) for (pos = (head); pos != NULL; pos = pos->next)
85
86 /*
87 * Walks forward of a list safely while removing nodes
88 * pos is your node
89 * n is another list head for temporary storage
90 * head is your list head
91 */
92 #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)
93
94 #define RB_DLINK_FOREACH_PREV(pos, head) for (pos = (head); pos != NULL; pos = pos->prev)
95
96
97 /* Returns the list length */
98 #define rb_dlink_list_length(list) (list)->length
99
100 #define rb_dlinkAddAlloc(data, list) rb_dlinkAdd(data, rb_make_rb_dlink_node(), list)
101 #define rb_dlinkAddTailAlloc(data, list) rb_dlinkAddTail(data, rb_make_rb_dlink_node(), list)
102 #define rb_dlinkDestroy(node, list) do { rb_dlinkDelete(node, list); rb_free_rb_dlink_node(node); } while(0)
103
104
105 /*
106 * dlink_ routines are stolen from squid, except for rb_dlinkAddBefore,
107 * which is mine.
108 * -- adrian
109 */
110
111 static inline void
112 rb_dlinkMoveNode(rb_dlink_node *m, rb_dlink_list *oldlist, rb_dlink_list *newlist)
113 {
114 /* Assumption: If m->next == NULL, then list->tail == m
115 * and: If m->prev == NULL, then list->head == m
116 */
117 assert(m != NULL);
118 assert(oldlist != NULL);
119 assert(newlist != NULL);
120
121 if(m->next)
122 m->next->prev = m->prev;
123 else
124 oldlist->tail = m->prev;
125
126 if(m->prev)
127 m->prev->next = m->next;
128 else
129 oldlist->head = m->next;
130
131 m->prev = NULL;
132 m->next = newlist->head;
133 if(newlist->head != NULL)
134 newlist->head->prev = m;
135 else if(newlist->tail == NULL)
136 newlist->tail = m;
137 newlist->head = m;
138
139 oldlist->length--;
140 newlist->length++;
141 }
142
143 static inline void
144 rb_dlinkAdd(void *data, rb_dlink_node *m, rb_dlink_list *list)
145 {
146 assert(data != NULL);
147 assert(m != NULL);
148 assert(list != NULL);
149
150 m->data = data;
151 m->prev = NULL;
152 m->next = list->head;
153
154 /* Assumption: If list->tail != NULL, list->head != NULL */
155 if(list->head != NULL)
156 list->head->prev = m;
157 else if(list->tail == NULL)
158 list->tail = m;
159
160 list->head = m;
161 list->length++;
162 }
163
164 static inline void
165 rb_dlinkAddBefore(rb_dlink_node *b, void *data, rb_dlink_node *m, rb_dlink_list *list)
166 {
167 assert(b != NULL);
168 assert(data != NULL);
169 assert(m != NULL);
170 assert(list != NULL);
171
172 /* Shortcut - if its the first one, call rb_dlinkAdd only */
173 if(b == list->head)
174 {
175 rb_dlinkAdd(data, m, list);
176 }
177 else
178 {
179 m->data = data;
180 b->prev->next = m;
181 m->prev = b->prev;
182 b->prev = m;
183 m->next = b;
184 list->length++;
185 }
186 }
187
188 static inline void
189 rb_dlinkMoveTail(rb_dlink_node *m, rb_dlink_list *list)
190 {
191 if(list->tail == m)
192 return;
193
194 /* From here assume that m->next != NULL as that can only
195 * be at the tail and assume that the node is on the list
196 */
197
198 m->next->prev = m->prev;
199
200 if(m->prev != NULL)
201 m->prev->next = m->next;
202 else
203 list->head = m->next;
204
205 list->tail->next = m;
206 m->prev = list->tail;
207 m->next = NULL;
208 list->tail = m;
209 }
210
211 static inline void
212 rb_dlinkAddTail(void *data, rb_dlink_node *m, rb_dlink_list *list)
213 {
214 assert(m != NULL);
215 assert(list != NULL);
216 assert(data != NULL);
217
218 m->data = data;
219 m->next = NULL;
220 m->prev = list->tail;
221
222 /* Assumption: If list->tail != NULL, list->head != NULL */
223 if(list->tail != NULL)
224 list->tail->next = m;
225 else if(list->head == NULL)
226 list->head = m;
227
228 list->tail = m;
229 list->length++;
230 }
231
232 /* Execution profiles show that this function is called the most
233 * often of all non-spontaneous functions. So it had better be
234 * efficient. */
235 static inline void
236 rb_dlinkDelete(rb_dlink_node *m, rb_dlink_list *list)
237 {
238 assert(m != NULL);
239 assert(list != NULL);
240 /* Assumption: If m->next == NULL, then list->tail == m
241 * and: If m->prev == NULL, then list->head == m
242 */
243 if(m->next)
244 m->next->prev = m->prev;
245 else
246 list->tail = m->prev;
247
248 if(m->prev)
249 m->prev->next = m->next;
250 else
251 list->head = m->next;
252
253 m->next = m->prev = NULL;
254 list->length--;
255 }
256
257 static inline rb_dlink_node *
258 rb_dlinkFindDelete(void *data, rb_dlink_list *list)
259 {
260 rb_dlink_node *m;
261 assert(list != NULL);
262 assert(data != NULL);
263 RB_DLINK_FOREACH(m, list->head)
264 {
265 if(m->data != data)
266 continue;
267
268 if(m->next)
269 m->next->prev = m->prev;
270 else
271 list->tail = m->prev;
272
273 if(m->prev)
274 m->prev->next = m->next;
275 else
276 list->head = m->next;
277
278 m->next = m->prev = NULL;
279 list->length--;
280 return m;
281 }
282 return NULL;
283 }
284
285 static inline int
286 rb_dlinkFindDestroy(void *data, rb_dlink_list *list)
287 {
288 void *ptr;
289
290 assert(list != NULL);
291 assert(data != NULL);
292 ptr = rb_dlinkFindDelete(data, list);
293
294 if(ptr != NULL)
295 {
296 rb_free_rb_dlink_node(ptr);
297 return 1;
298 }
299 return 0;
300 }
301
302 /*
303 * rb_dlinkFind
304 * inputs - list to search
305 * - data
306 * output - pointer to link or NULL if not found
307 * side effects - Look for ptr in the linked listed pointed to by link.
308 */
309 static inline rb_dlink_node *
310 rb_dlinkFind(void *data, rb_dlink_list *list)
311 {
312 rb_dlink_node *ptr;
313 assert(list != NULL);
314 assert(data != NULL);
315
316 RB_DLINK_FOREACH(ptr, list->head)
317 {
318 if(ptr->data == data)
319 return (ptr);
320 }
321 return (NULL);
322 }
323
324 static inline void
325 rb_dlinkMoveList(rb_dlink_list *from, rb_dlink_list *to)
326 {
327 assert(from != NULL);
328 assert(to != NULL);
329
330 /* There are three cases */
331 /* case one, nothing in from list */
332 if(from->head == NULL)
333 return;
334
335 /* case two, nothing in to list */
336 if(to->head == NULL)
337 {
338 to->head = from->head;
339 to->tail = from->tail;
340 from->head = from->tail = NULL;
341 to->length = from->length;
342 from->length = 0;
343 return;
344 }
345
346 /* third case play with the links */
347 from->tail->next = to->head;
348 to->head->prev = from->tail;
349 to->head = from->head;
350 from->head = from->tail = NULL;
351 to->length += from->length;
352 from->length = 0;
353 }
354
355 typedef struct _rb_zstring
356 {
357 uint16_t len; /* big enough */
358 uint16_t alloclen;
359 uint8_t *data;
360 } rb_zstring_t;
361
362 size_t rb_zstring_serialized(rb_zstring_t *zs, void **buf, size_t *buflen);
363 size_t rb_zstring_deserialize(rb_zstring_t *zs, void *buf);
364 void rb_zstring_free(rb_zstring_t *zs);
365 rb_zstring_t *rb_zstring_alloc(void);
366 rb_zstring_t *rb_zstring_from_c_len(const char *buf, size_t len);
367 rb_zstring_t *rb_zstring_from_c(const char *buf);
368 size_t rb_zstring_len(rb_zstring_t *zs);
369 void rb_zstring_append_from_zstring(rb_zstring_t *dst_zs, rb_zstring_t *src_zs);
370 void rb_zstring_append_from_c(rb_zstring_t *zs, const char *buf, size_t len);
371 char *rb_zstring_to_c(rb_zstring_t *zs, char *buf, size_t len);
372 char *rb_zstring_to_c_alloc(rb_zstring_t *zs);
373 size_t rb_zstring_to_ptr(rb_zstring_t *zs, void **ptr);
374
375 #endif /* __TOOLS_H__ */