]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
tool_cb_wrt: stop alloc/free for every chunk windows console output
authorDaniel Stenberg <daniel@haxx.se>
Fri, 8 Aug 2025 20:56:47 +0000 (22:56 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 11 Aug 2025 07:37:29 +0000 (09:37 +0200)
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

src/tool_cb_wrt.c
src/tool_cfgable.c
src/tool_cfgable.h

index ff544e61a23c96f0d0332ddfe08145aa6092197b..6fbf80753de32e820ee3df0c78c48ccb0ad2225c 100644 (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;
+    /* 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;
+    }
 
-    wc_len = (DWORD)MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)rbuf, (int)rlen,
-                                        wc_buf, (int)wc_len);
-    if(!wc_len) {
-      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, wc_buf, wc_len, &chars_written, NULL)) {
-      free(wc_buf);
+    if(!WriteConsoleW((HANDLE) fhnd, global->term.buf,
+                      len, &chars_written, NULL))
       return CURL_WRITEFUNC_ERROR;
-    }
-    free(wc_buf);
   }
 
   *retp = bytes;
index 015ee26cbe2e318283c1f12dfba94d84340d5730..0321848b0d5a95ae6321f54b87bd67eb15a96bb8 100644 (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
 }
 
 /*
index f982d22d6282e08c26f15bd9901fa9f82f0c147a..23e874f448e74e9fe98844e0ae55a72c7ae8f407 100644 (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;