fixes unnecessary allocations in cx_strcat() family of functions default tip

Tue, 15 Apr 2025 22:16:05 +0200

author
Mike Becker <universe@uap-core.de>
date
Tue, 15 Apr 2025 22:16:05 +0200
changeset 1296
2a2403c63439
parent 1295
b00c6ae1441a

fixes unnecessary allocations in cx_strcat() family of functions

fixes #604

CHANGELOG file | annotate | diff | comparison | revisions
docs/Writerside/topics/about.md file | annotate | diff | comparison | revisions
src/string.c file | annotate | diff | comparison | revisions
--- a/CHANGELOG	Mon Apr 14 19:53:20 2025 +0200
+++ b/CHANGELOG	Tue Apr 15 22:16:05 2025 +0200
@@ -8,6 +8,7 @@
  * adds cxTreeSize()
  * changes grow strategy for the mempory pool to reduce reallocations
  * changes grow strategy for CxBuffer, which does now take the page size into account
+ * fixes unnecessary allocations in cx_strcat() family of functions
  * fixes errno value after failing cxBufferSeek() to be consistently EINVAL
  * fixes implementation of cxBufferTerminate()
  * fixes allocator arguments for some printf.h functions not being const
--- a/docs/Writerside/topics/about.md	Mon Apr 14 19:53:20 2025 +0200
+++ b/docs/Writerside/topics/about.md	Tue Apr 15 22:16:05 2025 +0200
@@ -35,6 +35,7 @@
 * adds cxTreeSize()
 * changes grow strategy for the mempory pool to reduce reallocations
 * changes grow strategy for CxBuffer, which does now take the page size into account
+* fixes unnecessary allocations in cx_strcat() family of functions
 * fixes errno value after failing cxBufferSeek() to be consistently EINVAL
 * fixes implementation of cxBufferTerminate()
 * fixes allocator arguments for some printf.h functions not being const
--- a/src/string.c	Mon Apr 14 19:53:20 2025 +0200
+++ b/src/string.c	Tue Apr 15 22:16:05 2025 +0200
@@ -106,27 +106,16 @@
         ...
 ) {
     if (count == 0) return str;
-
-    cxstring strings_stack[8];
-    cxstring *strings;
-    if (count > 8) {
-        strings = calloc(count, sizeof(cxstring));
-        if (strings == NULL) {
-            return (cxmutstr) {NULL, 0};
-        }
-    } else {
-        strings = strings_stack;
-    }
-
     va_list ap;
     va_start(ap, count);
+    va_list ap2;
+    va_copy(ap2, ap);
 
-    // get all args and overall length
+    // compute overall length
     bool overflow = false;
     size_t slen = str.length;
     for (size_t i = 0; i < count; i++) {
-        cxstring s = va_arg (ap, cxstring);
-        strings[i] = s;
+        cxstring s = va_arg(ap, cxstring);
         if (slen > SIZE_MAX - str.length) overflow = true;
         slen += s.length;
     }
@@ -134,10 +123,8 @@
 
     // abort in case of overflow
     if (overflow) {
+        va_end(ap2);
         errno = EOVERFLOW;
-        if (strings != strings_stack) {
-            free(strings);
-        }
         return (cxmutstr) { NULL, 0 };
     }
 
@@ -149,9 +136,7 @@
         newstr = cxRealloc(alloc, str.ptr, slen + 1);
     }
     if (newstr == NULL) {
-        if (strings != strings_stack) {
-            free(strings);
-        }
+        va_end(ap2);
         return (cxmutstr) {NULL, 0};
     }
     str.ptr = newstr;
@@ -160,19 +145,15 @@
     size_t pos = str.length;
     str.length = slen;
     for (size_t i = 0; i < count; i++) {
-        cxstring s = strings[i];
+        cxstring s = va_arg(ap2, cxstring);
         memcpy(str.ptr + pos, s.ptr, s.length);
         pos += s.length;
     }
+    va_end(ap2);
 
     // terminate string
     str.ptr[str.length] = '\0';
 
-    // free temporary array
-    if (strings != strings_stack) {
-        free(strings);
-    }
-
     return str;
 }
 

mercurial