]> jfr.im git - solanum.git/blob - librb/src/tools.c
Remove Windows support
[solanum.git] / librb / src / tools.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * tools.c: Various functions needed here and there.
4 *
5 * Copyright (C) 1996-2002 Hybrid Development Team
6 * Copyright (C) 2002-2005 ircd-ratbox development team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 *
23 *
24 * Here is the original header:
25 *
26 * Useful stuff, ripped from places ..
27 * adrian chadd <adrian@creative.net.au>
28 *
29 * The TOOLS_C define builds versions of the functions in tools.h
30 * so that they end up in the resulting object files. If its not
31 * defined, tools.h will build inlined versions of the functions
32 * on supported compilers
33 */
34
35 #define _GNU_SOURCE 1
36 #include <librb_config.h>
37 #include <rb_lib.h>
38 #include <rb_tools.h>
39
40
41 /*
42 * init_rb_dlink_nodes
43 *
44 */
45 static rb_bh *dnode_heap;
46 void
47 rb_init_rb_dlink_nodes(size_t dh_size)
48 {
49
50 dnode_heap = rb_bh_create(sizeof(rb_dlink_node), dh_size, "librb_dnode_heap");
51 if(dnode_heap == NULL)
52 rb_outofmemory();
53 }
54
55 /*
56 * make_rb_dlink_node
57 *
58 * inputs - NONE
59 * output - pointer to new rb_dlink_node
60 * side effects - NONE
61 */
62 rb_dlink_node *
63 rb_make_rb_dlink_node(void)
64 {
65 return (rb_bh_alloc(dnode_heap));
66 }
67
68 /*
69 * free_rb_dlink_node
70 *
71 * inputs - pointer to rb_dlink_node
72 * output - NONE
73 * side effects - free given rb_dlink_node
74 */
75 void
76 rb_free_rb_dlink_node(rb_dlink_node *ptr)
77 {
78 assert(ptr != NULL);
79 rb_bh_free(dnode_heap, ptr);
80 }
81
82 /* rb_string_to_array()
83 * Changes a given buffer into an array of parameters.
84 * Taken from ircd-ratbox.
85 *
86 * inputs - string to parse, array to put in (size >= maxpara)
87 * outputs - number of parameters
88 */
89 int
90 rb_string_to_array(char *string, char **parv, int maxpara)
91 {
92 char *p, *xbuf = string;
93 int x = 0;
94
95 if(string == NULL || string[0] == '\0')
96 return x;
97
98 while(*xbuf == ' ') /* skip leading spaces */
99 xbuf++;
100 if(*xbuf == '\0') /* ignore all-space args */
101 return x;
102
103 do
104 {
105 if(*xbuf == ':') /* Last parameter */
106 {
107 xbuf++;
108 parv[x++] = xbuf;
109 return x;
110 }
111 else
112 {
113 parv[x++] = xbuf;
114 if((p = strchr(xbuf, ' ')) != NULL)
115 {
116 *p++ = '\0';
117 xbuf = p;
118 }
119 else
120 return x;
121 }
122 while(*xbuf == ' ')
123 xbuf++;
124 if(*xbuf == '\0')
125 return x;
126 }
127 while(x < maxpara - 1);
128
129 if(*p == ':')
130 p++;
131
132 parv[x++] = p;
133 return x;
134 }
135
136 #ifndef HAVE_STRCASECMP
137 /* Fallback taken from FreeBSD. --Elizafox */
138 int
139 rb_strcasecmp(const char *s1, const char *s2)
140 {
141 const unsigned char *us1 = (const unsigned char *)s1;
142 const unsigned char *us2 = (const unsigned char *)s2;
143
144 while (tolower(*us1) == tolower(*us2++))
145 {
146 if (*us1++ == '\0')
147 return 0;
148 }
149
150 return (tolower(*us1) - tolower(*--us2));
151 }
152 #else
153 int
154 rb_strcasecmp(const char *s1, const char *s2)
155 {
156 return strcasecmp(s1, s2);
157 }
158 #endif
159
160 #ifndef HAVE_STRNCASECMP
161 /* Fallback taken from FreeBSD. --Elizafox */
162 int
163 rb_strncasecmp(const char *s1, const char *s2, size_t n)
164 {
165 if (n != 0)
166 {
167 const unsigned char *us1 = (const unsigned char *)s1;
168 const unsigned char *us2 = (const unsigned char *)s2;
169
170 do
171 {
172 if (tolower(*us1) != tolower(*us2++))
173 return (tolower(*us1) - tolower(*--us2));
174 if (*us1++ == '\0')
175 break;
176 } while (--n != 0);
177 }
178 return 0;
179 }
180 #else
181 int
182 rb_strncasecmp(const char *s1, const char *s2, size_t n)
183 {
184 return strncasecmp(s1, s2, n);
185 }
186 #endif
187
188 #ifndef HAVE_STRCASESTR
189 /* Fallback taken from FreeBSD. --Elizafox */
190 char *
191 rb_strcasestr(const char *s, const char *find)
192 {
193 char c, sc;
194 size_t len;
195
196 if ((c = *find++) != 0) {
197 c = tolower((unsigned char)c);
198 len = strlen(find);
199 do {
200 do {
201 if ((sc = *s++) == 0)
202 return (NULL);
203 } while ((char)tolower((unsigned char)sc) != c);
204 } while (rb_strncasecmp(s, find, len) != 0);
205 s--;
206 }
207 return ((char *)s);
208 }
209 #else
210 char *
211 rb_strcasestr(const char *s, const char *find)
212 {
213 return strcasestr(s, find);
214 }
215 #endif
216
217 #ifndef HAVE_STRLCAT
218 size_t
219 rb_strlcat(char *dest, const char *src, size_t count)
220 {
221 size_t dsize = strlen(dest);
222 size_t len = strlen(src);
223 size_t res = dsize + len;
224
225 dest += dsize;
226 count -= dsize;
227 if(len >= count)
228 len = count - 1;
229 memcpy(dest, src, len);
230 dest[len] = 0;
231 return res;
232 }
233 #else
234 size_t
235 rb_strlcat(char *dest, const char *src, size_t count)
236 {
237 return strlcat(dest, src, count);
238 }
239 #endif
240
241 #ifndef HAVE_STRLCPY
242 size_t
243 rb_strlcpy(char *dest, const char *src, size_t size)
244 {
245 size_t ret = strlen(src);
246
247 if(size)
248 {
249 size_t len = (ret >= size) ? size - 1 : ret;
250 memcpy(dest, src, len);
251 dest[len] = '\0';
252 }
253 return ret;
254 }
255 #else
256 size_t
257 rb_strlcpy(char *dest, const char *src, size_t size)
258 {
259 return strlcpy(dest, src, size);
260 }
261 #endif
262
263
264 #ifndef HAVE_STRNLEN
265 size_t
266 rb_strnlen(const char *s, size_t count)
267 {
268 const char *sc;
269 for(sc = s; count-- && *sc != '\0'; ++sc)
270 ;
271 return sc - s;
272 }
273 #else
274 size_t
275 rb_strnlen(const char *s, size_t count)
276 {
277 return strnlen(s, count);
278 }
279 #endif
280
281 /*
282 * rb_snprintf_append()
283 * appends snprintf formatted string to the end of the buffer but not
284 * exceeding len
285 */
286 int
287 rb_snprintf_append(char *str, size_t len, const char *format, ...)
288 {
289 if(len == 0)
290 return -1;
291
292 int orig_len = strlen(str);
293
294 if((int)len < orig_len)
295 {
296 str[len - 1] = '\0';
297 return len - 1;
298 }
299
300 va_list ap;
301 va_start(ap, format);
302 int append_len = vsnprintf(str + orig_len, len - orig_len, format, ap);
303 va_end(ap);
304
305 if (append_len < 0)
306 return append_len;
307
308 return (orig_len + append_len);
309 }
310
311 /*
312 * rb_snprintf_try_append()
313 * appends snprintf formatted string to the end of the buffer but not
314 * exceeding len
315 * returns -1 if there isn't enough space for the whole string to fit
316 */
317 int
318 rb_snprintf_try_append(char *str, size_t len, const char *format, ...)
319 {
320 if(len == 0)
321 return -1;
322
323 int orig_len = strlen(str);
324
325 if((int)len < orig_len) {
326 str[len - 1] = '\0';
327 return -1;
328 }
329
330 va_list ap;
331 va_start(ap, format);
332 int append_len = vsnprintf(str + orig_len, len - orig_len, format, ap);
333 va_end(ap);
334
335 if (append_len < 0)
336 return append_len;
337
338 if (orig_len + append_len > (int)(len - 1)) {
339 str[orig_len] = '\0';
340 return -1;
341 }
342
343 return (orig_len + append_len);
344 }
345
346 /* rb_basename
347 *
348 * input -
349 * output -
350 * side effects -
351 */
352 char *
353 rb_basename(const char *path)
354 {
355 const char *s;
356
357 if(!(s = strrchr(path, '/')))
358 s = path;
359 else
360 s++;
361 return rb_strdup(s);
362 }
363
364 /*
365 * rb_dirname
366 */
367
368 char *
369 rb_dirname (const char *path)
370 {
371 char *s;
372
373 s = strrchr(path, '/');
374 if(s == NULL)
375 {
376 return rb_strdup(".");
377 }
378
379 /* remove extra slashes */
380 while(s > path && *s == '/')
381 --s;
382
383 return rb_strndup(path, ((uintptr_t)s - (uintptr_t)path) + 2);
384 }
385
386
387
388 int rb_fsnprint(char *buf, size_t len, const rb_strf_t *strings)
389 {
390 size_t used = 0;
391 size_t remaining = len;
392
393 while (strings != NULL) {
394 int ret = 0;
395
396 if (strings->length != 0) {
397 remaining = strings->length;
398 if (remaining > len - used)
399 remaining = len - used;
400 }
401
402 if (remaining == 0)
403 break;
404
405 if (strings->format != NULL) {
406 if (strings->format_args != NULL) {
407 ret = vsnprintf(buf + used, remaining,
408 strings->format, *strings->format_args);
409 } else {
410 ret = rb_strlcpy(buf + used,
411 strings->format, remaining);
412 }
413 } else if (strings->func != NULL) {
414 ret = strings->func(buf + used, remaining,
415 strings->func_args);
416 }
417
418 if (ret < 0) {
419 return ret;
420 } else if ((size_t)ret > remaining - 1) {
421 used += remaining - 1;
422 } else {
423 used += ret;
424 }
425
426 if (used >= len - 1) {
427 used = len - 1;
428 break;
429 }
430
431 remaining -= ret;
432 strings = strings->next;
433 }
434
435 return used;
436 }
437
438 int rb_fsnprintf(char *buf, size_t len, const rb_strf_t *strings, const char *format, ...)
439 {
440 va_list args;
441 rb_strf_t prepend_string = { .format = format, .format_args = &args, .next = strings };
442 int ret;
443
444 va_start(args, format);
445 ret = rb_fsnprint(buf, len, &prepend_string);
446 va_end(args);
447
448 return ret;
449 }
450