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
This commit is contained in:
Daniel Stenberg 2020-09-22 17:28:34 +02:00
parent 2355857702
commit 7e8561e030
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
4 changed files with 45 additions and 18 deletions

View file

@ -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;