mirror of
https://github.com/moparisthebest/curl
synced 2025-01-10 21:48:10 -05:00
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:
parent
2355857702
commit
7e8561e030
@ -7,7 +7,7 @@
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
* Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||
*
|
||||
* This software is licensed as described in the file COPYING, which
|
||||
* you should have received as part of this distribution. The terms
|
||||
|
14
lib/dynbuf.c
14
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.
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user