]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
dynbuf: make *addf() not require extra mallocs
authorDaniel Stenberg <daniel@haxx.se>
Tue, 22 Sep 2020 15:28:34 +0000 (17:28 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 23 Sep 2020 06:54:42 +0000 (08:54 +0200)
... 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

lib/curl_printf.h
lib/dynbuf.c
lib/dynbuf.h
lib/mprintf.c

index 0d37b8e57203646422a62460f7083b5f6e1a2f71..9d2de7ba8c6d98c4f5bde95e67571ed10d78be84 100644 (file)
@@ -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
index 5e15040bb51ef99634879106d910d573c7dda1db..2dace34285c8a5ee624055ffa7b0dd8165850755 100644 (file)
@@ -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.
  */
index 1360dd43286f327b058cea90ef574445e17f4370..94b5dbf689aa1ca72e6cc0e34cebbe8996f08845 100644 (file)
@@ -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
index 6b62fdfbc57878b10d2cbad6b45036ea6a00b0c2..8f0011e91199433bcf3bfd36834378accafb1907 100644 (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;