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