X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/8573c3409e0c4552851825f3bc987df73531b691..4b1cce65ed584cc0fdc9f3c5ec84373fdf2566a8:/librb/src/tools.c diff --git a/librb/src/tools.c b/librb/src/tools.c index 05c7e3eb..f4e2af2f 100644 --- a/librb/src/tools.c +++ b/librb/src/tools.c @@ -324,6 +324,41 @@ rb_snprintf_append(char *str, size_t len, const char *format, ...) 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 append_len = vsnprintf(str + orig_len, len - orig_len, format, ap); + va_end(ap); + + 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 * * input - @@ -488,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; +} +