change cx_strcat variants to allow handling of ENOMEM

Sat, 07 Dec 2024 23:59:54 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 07 Dec 2024 23:59:54 +0100
changeset 1001
5c9ec5a0a4ef
parent 1000
1aecddf7e209
child 1002
1483c47063a8

change cx_strcat variants to allow handling of ENOMEM

CHANGELOG file | annotate | diff | comparison | revisions
src/cx/string.h file | annotate | diff | comparison | revisions
src/string.c file | annotate | diff | comparison | revisions
--- a/CHANGELOG	Thu Dec 05 01:54:12 2024 +0100
+++ b/CHANGELOG	Sat Dec 07 23:59:54 2024 +0100
@@ -16,6 +16,7 @@
  * changes all functions, for which there is no dedicated xyz_a variant,
    to accept NULL as allocator argument (in which case a default allocator will be used)
  * changes the name of destroy functions that actually free the memory to better indicate their behavior
+ * change cx_strcat variants to allow handling of ENOMEM
  * moves cx_compare_func typedef to compare.h
  * moves cx_szmul() to common.h
  * moves stream copy functions to new streams.h
--- a/src/cx/string.h	Thu Dec 05 01:54:12 2024 +0100
+++ b/src/cx/string.h	Sat Dec 07 23:59:54 2024 +0100
@@ -313,7 +313,11 @@
  * If \p str already contains a string, the memory will be reallocated and
  * the other strings are appended. Otherwise, new memory is allocated.
  *
- * \note It is guaranteed that there is only one allocation.
+ * If memory allocation fails, the pointer in the returned string will
+ * be \c NULL. Depending on the allocator, \c errno might be set.
+ *
+ * \note It is guaranteed that there is only one allocation for the
+ * resulting string.
  * It is also guaranteed that the returned string is zero-terminated.
  *
  * @param alloc the allocator to use
@@ -337,7 +341,11 @@
  * The resulting string will be allocated by the specified allocator.
  * So developers \em must pass the return value to cx_strfree_a() eventually.
  *
- * \note It is guaranteed that there is only one allocation.
+* If memory allocation fails, the pointer in the returned string will
+ * be \c NULL. Depending on the allocator, \c errno might be set.
+ *
+ * \note It is guaranteed that there is only one allocation for the
+ * resulting string.
  * It is also guaranteed that the returned string is zero-terminated.
  *
  * @param alloc the allocator to use
@@ -354,7 +362,11 @@
  * The resulting string will be allocated by standard \c malloc().
  * So developers \em must pass the return value to cx_strfree() eventually.
  *
- * \note It is guaranteed that there is only one allocation.
+* If memory allocation fails, the pointer in the returned string will
+ * be \c NULL and \c errno might be set.
+ *
+ * \note It is guaranteed that there is only one allocation for the
+ * resulting string.
  * It is also guaranteed that the returned string is zero-terminated.
  *
  * @param count   the number of the other following strings to concatenate
@@ -373,7 +385,11 @@
  * If \p str already contains a string, the memory will be reallocated and
  * the other strings are appended. Otherwise, new memory is allocated.
  *
- * \note It is guaranteed that there is only one allocation.
+* If memory allocation fails, the pointer in the returned string will
+ * be \c NULL and \c errno might be set.
+ *
+ * \note It is guaranteed that there is only one allocation for the
+ * resulting string.
  * It is also guaranteed that the returned string is zero-terminated.
  *
  * @param str     the string the other strings shall be concatenated to
--- a/src/string.c	Thu Dec 05 01:54:12 2024 +0100
+++ b/src/string.c	Sat Dec 07 23:59:54 2024 +0100
@@ -107,8 +107,16 @@
 ) {
     if (count == 0) return str;
 
-    cxstring *strings = calloc(count, sizeof(cxstring));
-    if (!strings) abort();
+    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);
@@ -123,12 +131,17 @@
     va_end(ap);
 
     // reallocate or create new string
+    char *newstr;
     if (str.ptr == NULL) {
-        str.ptr = cxMalloc(alloc, slen + 1);
+        newstr = cxMalloc(alloc, slen + 1);
     } else {
-        str.ptr = cxRealloc(alloc, str.ptr, slen + 1);
+        newstr = cxRealloc(alloc, str.ptr, slen + 1);
     }
-    if (str.ptr == NULL) abort();
+    if (newstr == NULL) {
+        free(strings);
+        return (cxmutstr) {NULL, 0};
+    }
+    str.ptr = newstr;
 
     // concatenate strings
     size_t pos = str.length;
@@ -143,7 +156,9 @@
     str.ptr[str.length] = '\0';
 
     // free temporary array
-    free(strings);
+    if (strings != strings_stack) {
+        free(strings);
+    }
 
     return str;
 }

mercurial