X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/508e25a85be26f6120550d12651b48889b4484ca..4b1cce65ed584cc0fdc9f3c5ec84373fdf2566a8:/librb/src/tools.c diff --git a/librb/src/tools.c b/librb/src/tools.c index cbd1551e..f4e2af2f 100644 --- a/librb/src/tools.c +++ b/librb/src/tools.c @@ -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,26 +130,25 @@ rb_string_to_array(char *string, char **parv, int maxpara) p++; parv[x++] = p; - parv[x] = NULL; return x; } #ifndef HAVE_STRCASECMP #ifndef _WIN32 -/* Crummy fallback impl by me. --Elizafox */ +/* Fallback taken from FreeBSD. --Elizafox */ int rb_strcasecmp(const char *s1, const char *s2) { - for(; *s1 != '\0' || *s2 != '\0'; s1++, s2++) + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + + while (tolower(*us1) == tolower(*us2++)) { - if(tolower(*s1) != tolower(*s2)) - return tolower(*s1) - tolower(*s2); + if (*us1++ == '\0') + return 0; } - if(*s1 == '\0' && *s2 == '\0') - return 0; - - return tolower(*(--s1)) - tolower(*(--s2)); + return (tolower(*us1) - tolower(*--us2)); } #else /* _WIN32 */ int @@ -172,23 +167,24 @@ rb_strcasecmp(const char *s1, const char *s2) #ifndef HAVE_STRNCASECMP #ifndef _WIN32 -/* Crummy fallback impl by me. --Elizafox */ +/* Fallback taken from FreeBSD. --Elizafox */ int rb_strncasecmp(const char *s1, const char *s2, size_t n) { - if(n == 0) - return 0; - - for(; *s1 != '\0' || *s2 != '\0' || n; s1++, s2++, n--) + if (n != 0) { - if(tolower(*s1) != tolower(*s2)) - return tolower(*s1) - tolower(*s2); - } - - if(*s1 == '\0' && *s2 == '\0') - return 0; + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; - return tolower(*(--s1)) - tolower(*(--s2)); + do + { + if (tolower(*us1) != tolower(*us2++)) + return (tolower(*us1) - tolower(*--us2)); + if (*us1++ == '\0') + break; + } while (--n != 0); + } + return 0; } #else /* _WIN32 */ int @@ -206,22 +202,25 @@ rb_strncasecmp(const char *s1, const char *s2, size_t n) #endif #ifndef HAVE_STRCASESTR -/* Crummy fallback impl by me. --Elizafox */ +/* Fallback taken from FreeBSD. --Elizafox */ char * rb_strcasestr(const char *s, const char *find) { - size_t len_f = strlen(find); - - if(*s == '\0') - return s; - - for(char *c = s; *c != '\0'; c++) - { - if(*c == *find && strncasecmp(c, find, len_f) == 0) - return c; + 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 NULL; + return ((char *)s); } #else char * @@ -304,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 @@ -486,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; +} +