X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/238a9ed590ea50b0e09f1390f6bc2551be1563ab..4b1cce65ed584cc0fdc9f3c5ec84373fdf2566a8:/librb/src/tools.c diff --git a/librb/src/tools.c b/librb/src/tools.c index 03dd632e..f4e2af2f 100644 --- a/librb/src/tools.c +++ b/librb/src/tools.c @@ -20,7 +20,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: tools.c 26170 2008-10-26 20:59:07Z androsyn $ * * Here is the original header: * @@ -32,6 +31,7 @@ * defined, tools.h will build inlined versions of the functions * on supported compilers */ + #define _GNU_SOURCE 1 #include #include @@ -83,7 +83,7 @@ rb_free_rb_dlink_node(rb_dlink_node *ptr) * Changes a given buffer into an array of parameters. * Taken from ircd-ratbox. * - * inputs - string to parse, array to put in + * inputs - string to parse, array to put in (size >= maxpara) * outputs - number of parameters */ int @@ -92,8 +92,6 @@ rb_string_to_array(char *string, char **parv, int maxpara) char *p, *xbuf = string; int x = 0; - parv[x] = NULL; - if(string == NULL || string[0] == '\0') return x; @@ -108,13 +106,11 @@ rb_string_to_array(char *string, char **parv, int maxpara) { xbuf++; parv[x++] = xbuf; - parv[x] = NULL; return x; } else { parv[x++] = xbuf; - parv[x] = NULL; if((p = strchr(xbuf, ' ')) != NULL) { *p++ = '\0'; @@ -134,10 +130,106 @@ rb_string_to_array(char *string, char **parv, int maxpara) p++; parv[x++] = p; - parv[x] = NULL; return x; } +#ifndef HAVE_STRCASECMP +#ifndef _WIN32 +/* Fallback taken from FreeBSD. --Elizafox */ +int +rb_strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + + while (tolower(*us1) == tolower(*us2++)) + { + if (*us1++ == '\0') + return 0; + } + + return (tolower(*us1) - tolower(*--us2)); +} +#else /* _WIN32 */ +int +rb_strcasecmp(const char *s1, const char *s2) +{ + return stricmp(s1, s2); +} +#endif /* _WIN32 */ +#else /* HAVE_STRCASECMP */ +int +rb_strcasecmp(const char *s1, const char *s2) +{ + return strcasecmp(s1, s2); +} +#endif + +#ifndef HAVE_STRNCASECMP +#ifndef _WIN32 +/* Fallback taken from FreeBSD. --Elizafox */ +int +rb_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + + do + { + if (tolower(*us1) != tolower(*us2++)) + return (tolower(*us1) - tolower(*--us2)); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return 0; +} +#else /* _WIN32 */ +int +rb_strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strnicmp(s1, s2, n); +} +#endif /* _WIN32 */ +#else /* HAVE_STRNCASECMP */ +int +rb_strncasecmp(const char *s1, const char *s2, size_t n) +{ + return strncasecmp(s1, s2, n); +} +#endif + +#ifndef HAVE_STRCASESTR +/* Fallback taken from FreeBSD. --Elizafox */ +char * +rb_strcasestr(const char *s, const char *find) +{ + char c, sc; + size_t len; + + if ((c = *find++) != 0) { + c = tolower((unsigned char)c); + len = strlen(find); + do { + do { + if ((sc = *s++) == 0) + return (NULL); + } while ((char)tolower((unsigned char)sc) != c); + } while (rb_strncasecmp(s, find, len) != 0); + s--; + } + return ((char *)s); +} +#else +char * +rb_strcasestr(const char *s, const char *find) +{ + return strcasestr(s, find); +} +#endif + #ifndef HAVE_STRLCAT size_t rb_strlcat(char *dest, const char *src, size_t count) @@ -211,22 +303,60 @@ int rb_snprintf_append(char *str, size_t len, const char *format, ...) { if(len == 0) - return 0; + return -1; - size_t x = strlen(str); + int orig_len = strlen(str); - if(len < x) + if((int)len < orig_len) { str[len - 1] = '\0'; - return (int)len - 1; + return len - 1; + } + + va_list ap; + va_start(ap, format); + int append_len = vsnprintf(str + orig_len, len - orig_len, format, ap); + va_end(ap); + + if (append_len < 0) + return append_len; + + return (orig_len + append_len); +} + +/* + * rb_snprintf_try_append() + * appends snprintf formatted string to the end of the buffer but not + * exceeding len + * returns -1 if there isn't enough space for the whole string to fit + */ +int +rb_snprintf_try_append(char *str, size_t len, const char *format, ...) +{ + if(len == 0) + return -1; + + int orig_len = strlen(str); + + if((int)len < orig_len) { + str[len - 1] = '\0'; + return -1; } va_list ap; va_start(ap, format); - int y = (vsnprintf(str + x, len - x, format, ap) + (int)x); + int append_len = vsnprintf(str + orig_len, len - orig_len, format, ap); va_end(ap); - return (y); + if (append_len < 0) + return append_len; + + if (orig_len + append_len > (int)(len - 1)) { + str[orig_len] = '\0'; + return -1; + } + + return (orig_len + append_len); } /* rb_basename @@ -393,3 +523,69 @@ size_t rb_zstring_to_ptr(rb_zstring_t *zs, void **ptr) *ptr = (void *)zs->data; return zs->len; } + + + +int rb_fsnprint(char *buf, size_t len, const rb_strf_t *strings) +{ + size_t used = 0; + size_t remaining = len; + + while (strings != NULL) { + int ret = 0; + + if (strings->length != 0) { + remaining = strings->length; + if (remaining > len - used) + remaining = len - used; + } + + if (remaining == 0) + break; + + if (strings->format != NULL) { + if (strings->format_args != NULL) { + ret = vsnprintf(buf + used, remaining, + strings->format, *strings->format_args); + } else { + ret = rb_strlcpy(buf + used, + strings->format, remaining); + } + } else if (strings->func != NULL) { + ret = strings->func(buf + used, remaining, + strings->func_args); + } + + if (ret < 0) { + return ret; + } else if ((size_t)ret > remaining - 1) { + used += remaining - 1; + } else { + used += ret; + } + + if (used >= len - 1) { + used = len - 1; + break; + } + + remaining -= ret; + strings = strings->next; + } + + return used; +} + +int rb_fsnprintf(char *buf, size_t len, const rb_strf_t *strings, const char *format, ...) +{ + va_list args; + rb_strf_t prepend_string = { .format = format, .format_args = &args, .next = strings }; + int ret; + + va_start(args, format); + ret = rb_fsnprint(buf, len, &prepend_string); + va_end(args); + + return ret; +} +