]> jfr.im git - solanum.git/blame - librb/src/tools.c
librb: rb_snprinf_append: handle error return value from vsnprintf()
[solanum.git] / librb / src / tools.c
CommitLineData
db137867
AC
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 *
db137867
AC
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 */
c056dba2 34
db137867 35#define _GNU_SOURCE 1
fe037171
EM
36#include <librb_config.h>
37#include <rb_lib.h>
db137867
AC
38#include <rb_tools.h>
39
40
41/*
42 * init_rb_dlink_nodes
43 *
44 */
45static rb_bh *dnode_heap;
46void
47rb_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 */
62rb_dlink_node *
63rb_make_rb_dlink_node(void)
64{
3202e249 65 return (rb_bh_alloc(dnode_heap));
db137867
AC
66}
67
68/*
69 * free_rb_dlink_node
70 *
71 * inputs - pointer to rb_dlink_node
72 * output - NONE
55abcbb2 73 * side effects - free given rb_dlink_node
db137867
AC
74 */
75void
3202e249 76rb_free_rb_dlink_node(rb_dlink_node *ptr)
db137867
AC
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 *
33ded5fc 86 * inputs - string to parse, array to put in (size >= maxpara)
db137867
AC
87 * outputs - number of parameters
88 */
89int
90rb_string_to_array(char *string, char **parv, int maxpara)
91{
92 char *p, *xbuf = string;
93 int x = 0;
94
db137867
AC
95 if(string == NULL || string[0] == '\0')
96 return x;
97
3202e249 98 while(*xbuf == ' ') /* skip leading spaces */
db137867
AC
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;
db137867
AC
109 return x;
110 }
111 else
112 {
113 parv[x++] = xbuf;
db137867
AC
114 if((p = strchr(xbuf, ' ')) != NULL)
115 {
116 *p++ = '\0';
117 xbuf = p;
118 }
119 else
120 return x;
121 }
3202e249 122 while(*xbuf == ' ')
db137867
AC
123 xbuf++;
124 if(*xbuf == '\0')
125 return x;
126 }
3202e249 127 while(x < maxpara - 1);
db137867
AC
128
129 if(*p == ':')
130 p++;
131
132 parv[x++] = p;
db137867
AC
133 return x;
134}
135
508e25a8
EM
136#ifndef HAVE_STRCASECMP
137#ifndef _WIN32
8b813d30 138/* Fallback taken from FreeBSD. --Elizafox */
508e25a8
EM
139int
140rb_strcasecmp(const char *s1, const char *s2)
141{
5a775221 142 const unsigned char *us1 = (const unsigned char *)s1;
8b813d30
EM
143 const unsigned char *us2 = (const unsigned char *)s2;
144
145 while (tolower(*us1) == tolower(*us2++))
508e25a8 146 {
8b813d30
EM
147 if (*us1++ == '\0')
148 return 0;
508e25a8
EM
149 }
150
8b813d30 151 return (tolower(*us1) - tolower(*--us2));
508e25a8
EM
152}
153#else /* _WIN32 */
154int
155rb_strcasecmp(const char *s1, const char *s2)
156{
157 return stricmp(s1, s2);
158}
159#endif /* _WIN32 */
160#else /* HAVE_STRCASECMP */
161int
162rb_strcasecmp(const char *s1, const char *s2)
163{
164 return strcasecmp(s1, s2);
165}
166#endif
167
168#ifndef HAVE_STRNCASECMP
169#ifndef _WIN32
8b813d30 170/* Fallback taken from FreeBSD. --Elizafox */
508e25a8 171int
c9b6f583 172rb_strncasecmp(const char *s1, const char *s2, size_t n)
508e25a8 173{
8b813d30 174 if (n != 0)
508e25a8 175 {
8b813d30
EM
176 const unsigned char *us1 = (const unsigned char *)s1;
177 const unsigned char *us2 = (const unsigned char *)s2;
508e25a8 178
8b813d30
EM
179 do
180 {
181 if (tolower(*us1) != tolower(*us2++))
182 return (tolower(*us1) - tolower(*--us2));
183 if (*us1++ == '\0')
184 break;
185 } while (--n != 0);
186 }
187 return 0;
508e25a8
EM
188}
189#else /* _WIN32 */
190int
191rb_strncasecmp(const char *s1, const char *s2, size_t n)
192{
193 return strnicmp(s1, s2, n);
194}
195#endif /* _WIN32 */
196#else /* HAVE_STRNCASECMP */
197int
198rb_strncasecmp(const char *s1, const char *s2, size_t n)
199{
200 return strncasecmp(s1, s2, n);
201}
202#endif
203
204#ifndef HAVE_STRCASESTR
8b813d30 205/* Fallback taken from FreeBSD. --Elizafox */
508e25a8 206char *
ea3168ff 207rb_strcasestr(const char *s, const char *find)
508e25a8 208{
8b813d30
EM
209 char c, sc;
210 size_t len;
508e25a8 211
8b813d30
EM
212 if ((c = *find++) != 0) {
213 c = tolower((unsigned char)c);
214 len = strlen(find);
215 do {
216 do {
217 if ((sc = *s++) == 0)
218 return (NULL);
219 } while ((char)tolower((unsigned char)sc) != c);
220 } while (rb_strncasecmp(s, find, len) != 0);
221 s--;
508e25a8 222 }
8b813d30 223 return ((char *)s);
508e25a8
EM
224}
225#else
226char *
227rb_strcasestr(const char *s, const char *find)
228{
229 return strcasestr(s, find);
230}
231#endif
232
db137867 233#ifndef HAVE_STRLCAT
3202e249 234size_t
db137867
AC
235rb_strlcat(char *dest, const char *src, size_t count)
236{
3202e249
VY
237 size_t dsize = strlen(dest);
238 size_t len = strlen(src);
239 size_t res = dsize + len;
240
241 dest += dsize;
242 count -= dsize;
243 if(len >= count)
244 len = count - 1;
245 memcpy(dest, src, len);
246 dest[len] = 0;
247 return res;
db137867
AC
248}
249#else
250size_t
251rb_strlcat(char *dest, const char *src, size_t count)
252{
253 return strlcat(dest, src, count);
254}
255#endif
3202e249 256
db137867 257#ifndef HAVE_STRLCPY
3202e249 258size_t
db137867
AC
259rb_strlcpy(char *dest, const char *src, size_t size)
260{
3202e249
VY
261 size_t ret = strlen(src);
262
263 if(size)
264 {
265 size_t len = (ret >= size) ? size - 1 : ret;
266 memcpy(dest, src, len);
267 dest[len] = '\0';
268 }
269 return ret;
db137867
AC
270}
271#else
272size_t
273rb_strlcpy(char *dest, const char *src, size_t size)
274{
275 return strlcpy(dest, src, size);
276}
277#endif
278
279
280#ifndef HAVE_STRNLEN
3202e249 281size_t
db137867 282rb_strnlen(const char *s, size_t count)
3202e249 283{
db137867 284 const char *sc;
3202e249 285 for(sc = s; count-- && *sc != '\0'; ++sc)
5ef68b13 286 ;
db137867 287 return sc - s;
3202e249 288}
db137867
AC
289#else
290size_t
291rb_strnlen(const char *s, size_t count)
292{
293 return strnlen(s, count);
294}
295#endif
296
5203cba5
VI
297/*
298 * rb_snprintf_append()
299 * appends snprintf formatted string to the end of the buffer but not
300 * exceeding len
301 */
302int
303rb_snprintf_append(char *str, size_t len, const char *format, ...)
304{
5203cba5 305 if(len == 0)
8573c340 306 return -1;
5203cba5 307
8573c340 308 int orig_len = strlen(str);
5203cba5 309
8573c340 310 if((int)len < orig_len)
5203cba5
VI
311 {
312 str[len - 1] = '\0';
8573c340 313 return len - 1;
5203cba5
VI
314 }
315
316 va_list ap;
317 va_start(ap, format);
8573c340 318 int append_len = vsnprintf(str + orig_len, len - orig_len, format, ap);
5203cba5
VI
319 va_end(ap);
320
8573c340
SA
321 if (append_len < 0)
322 return append_len;
323
324 return (orig_len + append_len);
5203cba5
VI
325}
326
3202e249
VY
327/* rb_basename
328 *
329 * input -
330 * output -
55abcbb2 331 * side effects -
3202e249
VY
332 */
333char *
334rb_basename(const char *path)
335{
336 const char *s;
337
338 if(!(s = strrchr(path, '/')))
339 s = path;
340 else
341 s++;
342 return rb_strdup(s);
343}
344
345/*
346 * rb_dirname
347 */
348
349char *
350rb_dirname (const char *path)
351{
352 char *s;
353
354 s = strrchr(path, '/');
355 if(s == NULL)
356 {
357 return rb_strdup(".");
55abcbb2 358 }
3202e249
VY
359
360 /* remove extra slashes */
361 while(s > path && *s == '/')
362 --s;
363
55abcbb2 364 return rb_strndup(path, ((uintptr_t)s - (uintptr_t)path) + 2);
3202e249 365}
5225f83d
AC
366
367size_t rb_zstring_serialized(rb_zstring_t *zs, void **buf, size_t *buflen)
368{
369 uint8_t *p;
370 size_t alloclen = sizeof(uint16_t) + zs->len;
371
372 p = rb_malloc(sizeof(alloclen));
373 memcpy(p, &zs->len, sizeof(uint16_t));
374 p += sizeof(uint16_t);
375 memcpy(p, zs->data, zs->len);
376 return alloclen;
377}
378
379size_t rb_zstring_deserialize(rb_zstring_t *zs, void *buf)
380{
381 uint8_t *p = (uint8_t *)buf;
382
383 memcpy(&zs->len, p, sizeof(uint16_t));
384 p += sizeof(uint16_t);
385 if(zs->len == 0)
386 {
387 zs->data = NULL;
388 return sizeof(uint16_t);
389 }
390 zs->data = rb_malloc(zs->len);
391 memcpy(zs->data, p, zs->len);
392 return zs->len + sizeof(uint16_t);
393}
394
395void rb_zstring_free(rb_zstring_t *zs)
396{
397 rb_free(zs->data);
398 rb_free(zs);
399
400}
401
402rb_zstring_t *rb_zstring_alloc(void)
403{
404 rb_zstring_t *zs = rb_malloc(sizeof(rb_zstring_t));
405 return zs;
406}
407
408rb_zstring_t *rb_zstring_from_c_len(const char *buf, size_t len)
409{
410 rb_zstring_t *zs;
411
412 if(len > UINT16_MAX-1)
413 return NULL;
414
415 zs = rb_zstring_alloc();
416 zs->alloclen = zs->len = (uint16_t)len;
417 zs->alloclen = (uint16_t)len;
418 if(zs->alloclen < 128)
419 zs->alloclen = 128;
420 zs->data = rb_malloc(zs->alloclen);
421 memcpy(zs->data, buf, zs->len);
422 return(zs);
423}
424
425rb_zstring_t *rb_zstring_from_c(const char *buf)
426{
427 return rb_zstring_from_c_len(buf, strlen(buf));
428}
429
430size_t rb_zstring_len(rb_zstring_t *zs)
431{
432 return zs->len;
433}
434
435void rb_zstring_append_from_zstring(rb_zstring_t *dst_zs, rb_zstring_t *src_zs)
436{
437 void *ep;
438 size_t nlen = dst_zs->len + src_zs->len;
439
440 if(nlen > dst_zs->alloclen)
441 {
442 dst_zs->alloclen += src_zs->len + 64;
443 dst_zs->data = rb_realloc(dst_zs->data, dst_zs->alloclen);
444 }
445
446 ep = dst_zs->data + dst_zs->len;
447 memcpy(ep, src_zs->data, src_zs->len);
448}
449
450void rb_zstring_append_from_c(rb_zstring_t *zs, const char *buf, size_t len)
451{
452 void *ep;
453 size_t nlen = zs->len + len;
454
455 if(nlen > zs->alloclen)
456 {
457 zs->alloclen += len + 64;
458 zs->data = rb_realloc(zs->data, zs->alloclen);
459 }
460 ep = zs->data + zs->len;
461 zs->len += len;
462 memcpy(ep, buf, len);
463}
464
465char *rb_zstring_to_c(rb_zstring_t *zs, char *buf, size_t len)
466{
467 size_t cpylen;
468 if(len < zs->len)
469 cpylen = len - 1;
470 else
471 cpylen = zs->len;
472 buf[cpylen] = '\0';
473 memcpy(buf, zs->data, cpylen);
474 return buf;
475}
476
477
478char *rb_zstring_to_c_alloc(rb_zstring_t *zs)
479{
480 char *p;
481 p = rb_malloc(zs->len+1);
482 memcpy(p, zs->data, zs->len);
483 return p;
484}
485
486size_t rb_zstring_to_ptr(rb_zstring_t *zs, void **ptr)
487{
488 *ptr = (void *)zs->data;
489 return zs->len;
490}