From: Daniel Stenberg Date: Tue, 22 Sep 2020 15:28:34 +0000 (+0200) Subject: dynbuf: make *addf() not require extra mallocs X-Git-Tag: curl-7_73_0~61 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7e8561e030fcfaba5cd620d7e9c9ab8356163132;p=thirdparty%2Fcurl.git dynbuf: make *addf() not require extra mallocs ... by introducing a printf() function that appends directly into a dynbuf: Curl_dyn_vprintf(). This avoids the mandatory extra malloc so if the buffer is already big enough it can just printf directly into it. Since this less-malloc version requires tthe use of a library internal printf function, we only provide this version when building libcurl and not for the dynbuf code that is used when building the curl tool. Closes #5998 --- diff --git a/lib/curl_printf.h b/lib/curl_printf.h index 0d37b8e572..9d2de7ba8c 100644 --- a/lib/curl_printf.h +++ b/lib/curl_printf.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms diff --git a/lib/dynbuf.c b/lib/dynbuf.c index 5e15040bb5..2dace34285 100644 --- a/lib/dynbuf.c +++ b/lib/dynbuf.c @@ -181,8 +181,17 @@ CURLcode Curl_dyn_add(struct dynbuf *s, const char *str) */ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...) { - char *str; va_list ap; +#ifdef BUILDING_LIBCURL + int rc; + va_start(ap, fmt); + rc = Curl_dyn_vprintf(s, fmt, ap); + va_end(ap); + + if(!rc) + return CURLE_OK; +#else + char *str; va_start(ap, fmt); str = vaprintf(fmt, ap); /* this allocs a new string to append */ va_end(ap); @@ -194,9 +203,12 @@ CURLcode Curl_dyn_addf(struct dynbuf *s, const char *fmt, ...) } /* If we failed, we cleanup the whole buffer and return error */ Curl_dyn_free(s); +#endif return CURLE_OUT_OF_MEMORY; } + + /* * Returns a pointer to the buffer. */ diff --git a/lib/dynbuf.h b/lib/dynbuf.h index 1360dd4328..94b5dbf689 100644 --- a/lib/dynbuf.h +++ b/lib/dynbuf.h @@ -62,6 +62,10 @@ char *Curl_dyn_ptr(const struct dynbuf *s); unsigned char *Curl_dyn_uptr(const struct dynbuf *s); size_t Curl_dyn_len(const struct dynbuf *s); +/* returns 0 on success, -1 on error */ +/* The implementation of this function exists in mprintf.c */ +int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save); + /* Dynamic buffer max sizes */ #define DYN_DOH_RESPONSE 3000 #define DYN_DOH_CNAME 256 diff --git a/lib/mprintf.c b/lib/mprintf.c index 6b62fdfbc5..8f0011e911 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -169,7 +169,7 @@ struct nsprintf { }; struct asprintf { - struct dynbuf b; + struct dynbuf *b; bool fail; /* if an alloc has failed and thus the output is not the complete data */ }; @@ -1042,50 +1042,61 @@ static int alloc_addbyter(int output, FILE *data) struct asprintf *infop = (struct asprintf *)data; unsigned char outc = (unsigned char)output; - if(Curl_dyn_addn(&infop->b, &outc, 1)) { + if(Curl_dyn_addn(infop->b, &outc, 1)) { infop->fail = 1; return -1; /* fail */ } return outc; /* fputc() returns like this on success */ } -char *curl_maprintf(const char *format, ...) +extern int Curl_dyn_vprintf(struct dynbuf *dyn, + const char *format, va_list ap_save); + +/* appends the formatted string, returns 0 on success, 1 on error */ +int Curl_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save) { - va_list ap_save; /* argument pointer */ int retcode; struct asprintf info; - Curl_dyn_init(&info.b, DYN_APRINTF); + info.b = dyn; info.fail = 0; - va_start(ap_save, format); retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); - va_end(ap_save); if((-1 == retcode) || info.fail) { - Curl_dyn_free(&info.b); - return NULL; + Curl_dyn_free(info.b); + return 1; } - if(Curl_dyn_len(&info.b)) - return Curl_dyn_ptr(&info.b); - return strdup(""); + return 0; } char *curl_mvaprintf(const char *format, va_list ap_save) { int retcode; struct asprintf info; - Curl_dyn_init(&info.b, DYN_APRINTF); + struct dynbuf dyn; + info.b = &dyn; + Curl_dyn_init(info.b, DYN_APRINTF); info.fail = 0; retcode = dprintf_formatf(&info, alloc_addbyter, format, ap_save); if((-1 == retcode) || info.fail) { - Curl_dyn_free(&info.b); + Curl_dyn_free(info.b); return NULL; } - if(Curl_dyn_len(&info.b)) - return Curl_dyn_ptr(&info.b); + if(Curl_dyn_len(info.b)) + return Curl_dyn_ptr(info.b); return strdup(""); } +char *curl_maprintf(const char *format, ...) +{ + va_list ap_save; + char *s; + va_start(ap_save, format); + s = curl_mvaprintf(format, ap_save); + va_end(ap_save); + return s; +} + static int storebuffer(int output, FILE *data) { char **buffer = (char **)data;