tool_cb_wrt: stop alloc/free for every chunk windows console output

Instead realloc to the largest buffer and keep that for reuse during the
entire lifetime.

Co-authored-by: Jay Satiro <raysatiro@yahoo.com>
Closes #18233
This commit is contained in:
Daniel Stenberg
2025-08-08 22:56:47 +02:00
parent 626051cd8b
commit a46944a599
3 changed files with 33 additions and 18 deletions

View File

@@ -115,8 +115,7 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs,
char *buffer, size_t bytes,
size_t *retp)
{
wchar_t *wc_buf;
DWORD wc_len, chars_written;
DWORD chars_written;
unsigned char *rbuf = (unsigned char *)buffer;
DWORD rlen = (DWORD)bytes;
@@ -206,27 +205,30 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs,
if(rlen) {
/* calculate buffer size for wide characters */
wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
NULL, 0);
if(!wc_len)
DWORD len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf,
(int)rlen, NULL, 0);
if(!len)
return CURL_WRITEFUNC_ERROR;
wc_buf = (wchar_t*) malloc(wc_len * sizeof(wchar_t));
if(!wc_buf)
return CURL_WRITEFUNC_ERROR;
wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
wc_buf, (int)wc_len);
if(!wc_len) {
free(wc_buf);
return CURL_WRITEFUNC_ERROR;
/* grow the buffer if needed */
if(len > global->term.len) {
wchar_t *buf = (wchar_t *) realloc(global->term.buf,
len * sizeof(wchar_t));
if(!buf)
return CURL_WRITEFUNC_ERROR;
global->term.len = len;
global->term.buf = buf;
}
if(!WriteConsoleW((HANDLE) fhnd, wc_buf, wc_len, &chars_written, NULL)) {
free(wc_buf);
len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
global->term.buf,
(int)len);
if(!len)
return CURL_WRITEFUNC_ERROR;
if(!WriteConsoleW((HANDLE) fhnd, global->term.buf,
len, &chars_written, NULL))
return CURL_WRITEFUNC_ERROR;
}
free(wc_buf);
}
*retp = bytes;

View File

@@ -263,6 +263,9 @@ static void free_globalconfig(void)
global->trace_stream = NULL;
tool_safefree(global->libcurl);
#if defined(_WIN32) && !defined(UNDER_CE)
free(global->term.buf);
#endif
}
/*

View File

@@ -339,6 +339,13 @@ struct OperationConfig {
BIT(skip_existing);
};
#if defined(_WIN32) && !defined(UNDER_CE)
struct termout {
wchar_t *buf;
DWORD len;
};
#endif
struct GlobalConfig {
struct State state; /* for create_transfer() */
char *trace_dump; /* file to dump the network trace to */
@@ -351,6 +358,9 @@ struct GlobalConfig {
struct OperationConfig *first;
struct OperationConfig *current;
struct OperationConfig *last;
#if defined(_WIN32) && !defined(UNDER_CE)
struct termout term;
#endif
timediff_t ms_per_transfer; /* start next transfer after (at least) this
many milliseconds */
trace tracetype;