]> jfr.im git - solanum.git/blob - librb/src/tools.c
librb: minor adjustments to rb_strcasestr fallback to avoid warnings.
[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
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 parv[x] = NULL;
96
97 if(string == NULL || string[0] == '\0')
98 return x;
99
100 while(*xbuf == ' ') /* skip leading spaces */
101 xbuf++;
102 if(*xbuf == '\0') /* ignore all-space args */
103 return x;
104
105 do
106 {
107 if(*xbuf == ':') /* Last parameter */
108 {
109 xbuf++;
110 parv[x++] = xbuf;
111 parv[x] = NULL;
112 return x;
113 }
114 else
115 {
116 parv[x++] = xbuf;
117 parv[x] = NULL;
118 if((p = strchr(xbuf, ' ')) != NULL)
119 {
120 *p++ = '\0';
121 xbuf = p;
122 }
123 else
124 return x;
125 }
126 while(*xbuf == ' ')
127 xbuf++;
128 if(*xbuf == '\0')
129 return x;
130 }
131 while(x < maxpara - 1);
132
133 if(*p == ':')
134 p++;
135
136 parv[x++] = p;
137 parv[x] = NULL;
138 return x;
139 }
140
141 #ifndef HAVE_STRCASECMP
142 #ifndef _WIN32
143 /* Crummy fallback impl by me. --Elizafox */
144 int
145 rb_strcasecmp(const char *s1, const char *s2)
146 {
147 for(; *s1 != '\0' || *s2 != '\0'; s1++, s2++)
148 {
149 if(tolower(*s1) != tolower(*s2))
150 return tolower(*s1) - tolower(*s2);
151 }
152
153 if(*s1 == '\0' && *s2 == '\0')
154 return 0;
155
156 return tolower(*(--s1)) - tolower(*(--s2));
157 }
158 #else /* _WIN32 */
159 int
160 rb_strcasecmp(const char *s1, const char *s2)
161 {
162 return stricmp(s1, s2);
163 }
164 #endif /* _WIN32 */
165 #else /* HAVE_STRCASECMP */
166 int
167 rb_strcasecmp(const char *s1, const char *s2)
168 {
169 return strcasecmp(s1, s2);
170 }
171 #endif
172
173 #ifndef HAVE_STRNCASECMP
174 #ifndef _WIN32
175 /* Crummy fallback impl by me. --Elizafox */
176 int
177 rb_strncasecmp(const char *s1, const char *s2, size_t n)
178 {
179 if(n == 0)
180 return 0;
181
182 for(; *s1 != '\0' || *s2 != '\0' || n; s1++, s2++, n--)
183 {
184 if(tolower(*s1) != tolower(*s2))
185 return tolower(*s1) - tolower(*s2);
186 }
187
188 if(*s1 == '\0' && *s2 == '\0')
189 return 0;
190
191 return tolower(*(--s1)) - tolower(*(--s2));
192 }
193 #else /* _WIN32 */
194 int
195 rb_strncasecmp(const char *s1, const char *s2, size_t n)
196 {
197 return strnicmp(s1, s2, n);
198 }
199 #endif /* _WIN32 */
200 #else /* HAVE_STRNCASECMP */
201 int
202 rb_strncasecmp(const char *s1, const char *s2, size_t n)
203 {
204 return strncasecmp(s1, s2, n);
205 }
206 #endif
207
208 #ifndef HAVE_STRCASESTR
209 /* Crummy fallback impl by me. --Elizafox */
210 char *
211 rb_strcasestr(const char *s, const char *find)
212 {
213 size_t len_f = strlen(find);
214
215 if(*s == '\0')
216 return (char *)s;
217
218 for(char *c = (char *)s; *c != '\0'; c++)
219 {
220 if(*c == *find && strncasecmp(c, find, len_f) == 0)
221 return c;
222 }
223
224 return NULL;
225 }
226 #else
227 char *
228 rb_strcasestr(const char *s, const char *find)
229 {
230 return strcasestr(s, find);
231 }
232 #endif
233
234 #ifndef HAVE_STRLCAT
235 size_t
236 rb_strlcat(char *dest, const char *src, size_t count)
237 {
238 size_t dsize = strlen(dest);
239 size_t len = strlen(src);
240 size_t res = dsize + len;
241
242 dest += dsize;
243 count -= dsize;
244 if(len >= count)
245 len = count - 1;
246 memcpy(dest, src, len);
247 dest[len] = 0;
248 return res;
249 }
250 #else
251 size_t
252 rb_strlcat(char *dest, const char *src, size_t count)
253 {
254 return strlcat(dest, src, count);
255 }
256 #endif
257
258 #ifndef HAVE_STRLCPY
259 size_t
260 rb_strlcpy(char *dest, const char *src, size_t size)
261 {
262 size_t ret = strlen(src);
263
264 if(size)
265 {
266 size_t len = (ret >= size) ? size - 1 : ret;
267 memcpy(dest, src, len);
268 dest[len] = '\0';
269 }
270 return ret;
271 }
272 #else
273 size_t
274 rb_strlcpy(char *dest, const char *src, size_t size)
275 {
276 return strlcpy(dest, src, size);
277 }
278 #endif
279
280
281 #ifndef HAVE_STRNLEN
282 size_t
283 rb_strnlen(const char *s, size_t count)
284 {
285 const char *sc;
286 for(sc = s; count-- && *sc != '\0'; ++sc)
287 ;
288 return sc - s;
289 }
290 #else
291 size_t
292 rb_strnlen(const char *s, size_t count)
293 {
294 return strnlen(s, count);
295 }
296 #endif
297
298 /*
299 * rb_snprintf_append()
300 * appends snprintf formatted string to the end of the buffer but not
301 * exceeding len
302 */
303 int
304 rb_snprintf_append(char *str, size_t len, const char *format, ...)
305 {
306 if(len == 0)
307 return 0;
308
309 size_t x = strlen(str);
310
311 if(len < x)
312 {
313 str[len - 1] = '\0';
314 return (int)len - 1;
315 }
316
317 va_list ap;
318 va_start(ap, format);
319 int y = (vsnprintf(str + x, len - x, format, ap) + (int)x);
320 va_end(ap);
321
322 return (y);
323 }
324
325 /* rb_basename
326 *
327 * input -
328 * output -
329 * side effects -
330 */
331 char *
332 rb_basename(const char *path)
333 {
334 const char *s;
335
336 if(!(s = strrchr(path, '/')))
337 s = path;
338 else
339 s++;
340 return rb_strdup(s);
341 }
342
343 /*
344 * rb_dirname
345 */
346
347 char *
348 rb_dirname (const char *path)
349 {
350 char *s;
351
352 s = strrchr(path, '/');
353 if(s == NULL)
354 {
355 return rb_strdup(".");
356 }
357
358 /* remove extra slashes */
359 while(s > path && *s == '/')
360 --s;
361
362 return rb_strndup(path, ((uintptr_t)s - (uintptr_t)path) + 2);
363 }
364
365 size_t rb_zstring_serialized(rb_zstring_t *zs, void **buf, size_t *buflen)
366 {
367 uint8_t *p;
368 size_t alloclen = sizeof(uint16_t) + zs->len;
369
370 p = rb_malloc(sizeof(alloclen));
371 memcpy(p, &zs->len, sizeof(uint16_t));
372 p += sizeof(uint16_t);
373 memcpy(p, zs->data, zs->len);
374 return alloclen;
375 }
376
377 size_t rb_zstring_deserialize(rb_zstring_t *zs, void *buf)
378 {
379 uint8_t *p = (uint8_t *)buf;
380
381 memcpy(&zs->len, p, sizeof(uint16_t));
382 p += sizeof(uint16_t);
383 if(zs->len == 0)
384 {
385 zs->data = NULL;
386 return sizeof(uint16_t);
387 }
388 zs->data = rb_malloc(zs->len);
389 memcpy(zs->data, p, zs->len);
390 return zs->len + sizeof(uint16_t);
391 }
392
393 void rb_zstring_free(rb_zstring_t *zs)
394 {
395 rb_free(zs->data);
396 rb_free(zs);
397
398 }
399
400 rb_zstring_t *rb_zstring_alloc(void)
401 {
402 rb_zstring_t *zs = rb_malloc(sizeof(rb_zstring_t));
403 return zs;
404 }
405
406 rb_zstring_t *rb_zstring_from_c_len(const char *buf, size_t len)
407 {
408 rb_zstring_t *zs;
409
410 if(len > UINT16_MAX-1)
411 return NULL;
412
413 zs = rb_zstring_alloc();
414 zs->alloclen = zs->len = (uint16_t)len;
415 zs->alloclen = (uint16_t)len;
416 if(zs->alloclen < 128)
417 zs->alloclen = 128;
418 zs->data = rb_malloc(zs->alloclen);
419 memcpy(zs->data, buf, zs->len);
420 return(zs);
421 }
422
423 rb_zstring_t *rb_zstring_from_c(const char *buf)
424 {
425 return rb_zstring_from_c_len(buf, strlen(buf));
426 }
427
428 size_t rb_zstring_len(rb_zstring_t *zs)
429 {
430 return zs->len;
431 }
432
433 void rb_zstring_append_from_zstring(rb_zstring_t *dst_zs, rb_zstring_t *src_zs)
434 {
435 void *ep;
436 size_t nlen = dst_zs->len + src_zs->len;
437
438 if(nlen > dst_zs->alloclen)
439 {
440 dst_zs->alloclen += src_zs->len + 64;
441 dst_zs->data = rb_realloc(dst_zs->data, dst_zs->alloclen);
442 }
443
444 ep = dst_zs->data + dst_zs->len;
445 memcpy(ep, src_zs->data, src_zs->len);
446 }
447
448 void rb_zstring_append_from_c(rb_zstring_t *zs, const char *buf, size_t len)
449 {
450 void *ep;
451 size_t nlen = zs->len + len;
452
453 if(nlen > zs->alloclen)
454 {
455 zs->alloclen += len + 64;
456 zs->data = rb_realloc(zs->data, zs->alloclen);
457 }
458 ep = zs->data + zs->len;
459 zs->len += len;
460 memcpy(ep, buf, len);
461 }
462
463 char *rb_zstring_to_c(rb_zstring_t *zs, char *buf, size_t len)
464 {
465 size_t cpylen;
466 if(len < zs->len)
467 cpylen = len - 1;
468 else
469 cpylen = zs->len;
470 buf[cpylen] = '\0';
471 memcpy(buf, zs->data, cpylen);
472 return buf;
473 }
474
475
476 char *rb_zstring_to_c_alloc(rb_zstring_t *zs)
477 {
478 char *p;
479 p = rb_malloc(zs->len+1);
480 memcpy(p, zs->data, zs->len);
481 return p;
482 }
483
484 size_t rb_zstring_to_ptr(rb_zstring_t *zs, void **ptr)
485 {
486 *ptr = (void *)zs->data;
487 return zs->len;
488 }