improves interface of cx_sprintf() variants

Fri, 12 Apr 2024 21:48:12 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 12 Apr 2024 21:48:12 +0200
changeset 849
edb9f875b7f9
parent 848
6456036bbb37
child 850
b2bc48c2b251

improves interface of cx_sprintf() variants

src/cx/printf.h file | annotate | diff | comparison | revisions
src/printf.c file | annotate | diff | comparison | revisions
tests/test_printf.c file | annotate | diff | comparison | revisions
--- a/src/cx/printf.h	Wed Apr 03 21:22:23 2024 +0200
+++ b/src/cx/printf.h	Fri Apr 12 21:48:12 2024 +0200
@@ -168,12 +168,12 @@
 /**
  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * @param str a pointer to the string buffer
- * @param len the current length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param fmt the format string
  * @param ... additional arguments
  * @return the length of produced string
@@ -183,32 +183,32 @@
 /**
  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * \attention The original buffer MUST have been allocated with the same allocator!
  *
  * @param alloc the allocator to use
  * @param str a pointer to the string buffer
- * @param len the current length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param fmt the format string
  * @param ... additional arguments
  * @return the length of produced string
  */
-__attribute__((__nonnull__(1, 2, 4), __format__(printf, 4, 5)))
-int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... );
+__attribute__((__nonnull__(1, 2, 3, 4), __format__(printf, 4, 5)))
+int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... );
 
 
 /**
  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * @param str a pointer to the string buffer
- * @param len the current length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param fmt the format string
  * @param ap argument list
  * @return the length of produced string
@@ -218,38 +218,38 @@
 /**
  * An \c sprintf like function which reallocates the string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * \attention The original buffer MUST have been allocated with the same allocator!
  *
  * @param alloc the allocator to use
  * @param str a pointer to the string buffer
- * @param len the current length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param fmt the format string
  * @param ap argument list
  * @return the length of produced string
  */
 __attribute__((__nonnull__))
-int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap);
+int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap);
 
 
 /**
  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * The location of the resulting string will \em always be stored to \p str. When the buffer
  * was sufficiently large, \p buf itself will be stored to the location of \p str.
  *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  * 
  * \remark When a new string needed to be allocated, the contents of \p buf will be
  * poisoned after the call, because this function tries to produce the string in \p buf, first.
  *
  * @param buf a pointer to the buffer
- * @param len the length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param str a pointer to the location
  * @param fmt the format string
  * @param ... additional arguments
@@ -260,42 +260,42 @@
 /**
  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * The location of the resulting string will \em always be stored to \p str. When the buffer
  * was sufficiently large, \p buf itself will be stored to the location of \p str.
  *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * \remark When a new string needed to be allocated, the contents of \p buf will be
  * poisoned after the call, because this function tries to produce the string in \p buf, first.
  *
  * @param alloc the allocator to use
  * @param buf a pointer to the buffer
- * @param len the length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param str a pointer to the location
  * @param fmt the format string
  * @param ... additional arguments
  * @return the length of produced string
  */
 __attribute__((__nonnull__(1, 2, 4, 5), __format__(printf, 5, 6)))
-int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... );
+int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... );
 
 /**
  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * The location of the resulting string will \em always be stored to \p str. When the buffer
  * was sufficiently large, \p buf itself will be stored to the location of \p str.
  *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * \remark When a new string needed to be allocated, the contents of \p buf will be
  * poisoned after the call, because this function tries to produce the string in \p buf, first.
  *
  * @param buf a pointer to the buffer
- * @param len the length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param str a pointer to the location
  * @param fmt the format string
  * @param ap argument list
@@ -306,26 +306,26 @@
 /**
  * An \c sprintf like function which allocates a new string when the buffer is not large enough.
  *
+ * The size of the buffer will be updated in \p len when necessary.
+ *
  * The location of the resulting string will \em always be stored to \p str. When the buffer
  * was sufficiently large, \p buf itself will be stored to the location of \p str.
  *
  * \note The resulting string is guaranteed to be zero-terminated.
- * That means, when the buffer needed to be reallocated, the new size of the buffer will be
- * the length returned by this function plus one.
  *
  * \remark When a new string needed to be allocated, the contents of \p buf will be
  * poisoned after the call, because this function tries to produce the string in \p buf, first.
  *
  * @param alloc the allocator to use
  * @param buf a pointer to the buffer
- * @param len the length of the buffer
+ * @param len a pointer to the length of the buffer
  * @param str a pointer to the location
  * @param fmt the format string
  * @param ap argument list
  * @return the length of produced string
  */
 __attribute__((__nonnull__))
-int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap);
+int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap);
 
 
 #ifdef __cplusplus
--- a/src/printf.c	Wed Apr 03 21:22:23 2024 +0200
+++ b/src/printf.c	Fri Apr 12 21:48:12 2024 +0200
@@ -132,7 +132,7 @@
     return s;
 }
 
-int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ) {
+int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) {
     va_list ap;
     va_start(ap, fmt);
     int ret = cx_vsprintf_a(alloc, str, len, fmt, ap);
@@ -140,11 +140,11 @@
     return ret;
 }
 
-int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap) {
+int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) {
     va_list ap2;
     va_copy(ap2, ap);
-    int ret = vsnprintf(*str, len, fmt, ap);
-    if ((unsigned) ret >= len) {
+    int ret = vsnprintf(*str, *len, fmt, ap);
+    if ((unsigned) ret >= *len) {
         unsigned newlen = ret + 1;
         char *ptr = cxRealloc(alloc, *str, newlen);
         if (ptr) {
@@ -152,6 +152,7 @@
             if (newret < 0) {
                 cxFree(alloc, ptr);
             } else {
+                *len = newlen;
                 *str = ptr;
                 ret = newret;
             }
@@ -161,7 +162,7 @@
     return ret;
 }
 
-int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ) {
+int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) {
     va_list ap;
     va_start(ap, fmt);
     int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap);
@@ -169,12 +170,12 @@
     return ret;
 }
 
-int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap) {
+int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) {
     va_list ap2;
     va_copy(ap2, ap);
-    int ret = vsnprintf(buf, len, fmt, ap);
+    int ret = vsnprintf(buf, *len, fmt, ap);
     *str = buf;
-    if ((unsigned) ret >= len) {
+    if ((unsigned) ret >= *len) {
         unsigned newlen = ret + 1;
         char *ptr = cxMalloc(alloc, newlen);
         if (ptr) {
@@ -182,6 +183,7 @@
             if (newret < 0) {
                 cxFree(alloc, ptr);
             } else {
+                *len = newlen;
                 *str = ptr;
                 ret = newret;
             }
--- a/tests/test_printf.c	Wed Apr 03 21:22:23 2024 +0200
+++ b/tests/test_printf.c	Fri Apr 12 21:48:12 2024 +0200
@@ -301,9 +301,11 @@
     CxAllocator *alloc = &talloc.base;
     CX_TEST_DO {
         char *oldbuf = buf;
-        size_t len = cx_sprintf_a(alloc, &buf, 16, "Test %d %s", 47, "string");
+        size_t buflen = 16;
+        size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 47, "string");
         CX_TEST_ASSERT(oldbuf == buf);
         CX_TEST_ASSERT(len == 14);
+        CX_TEST_ASSERT(buflen == 16);
         CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 string", 15));
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
     }
@@ -317,8 +319,10 @@
     CxAllocator *alloc = &talloc.base;
     char *buf = cxMalloc(alloc, 8);
     CX_TEST_DO {
-        size_t len = cx_sprintf_a(alloc, &buf, 8, "Test %d %s", 47, "foobar");
+        size_t buflen = 8;
+        size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 47, "foobar");
         CX_TEST_ASSERT(len == 14);
+        CX_TEST_ASSERT(buflen == 15);
         CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 foobar", 15));
         cxFree(alloc, buf);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
@@ -333,8 +337,10 @@
     // make it so that only the zero-terminator does not fit
     char *buf = cxMalloc(alloc, 14);
     CX_TEST_DO {
-        size_t len = cx_sprintf_a(alloc, &buf, 14, "Test %d %s", 13, "string");
+        size_t buflen = 14;
+        size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 13, "string");
         CX_TEST_ASSERT(len == 14);
+        CX_TEST_ASSERT(buflen == 15);
         CX_TEST_ASSERT(0 == memcmp(buf, "Test 13 string", 15));
         cxFree(alloc, buf);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
@@ -349,8 +355,10 @@
     CxAllocator *alloc = &talloc.base;
     CX_TEST_DO {
         char *str;
-        size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Test %d %s", 47, "string");
+        size_t buflen = 16;
+        size_t len = cx_sprintf_sa(alloc, buf, &buflen, &str, "Test %d %s", 47, "string");
         CX_TEST_ASSERT(str == buf);
+        CX_TEST_ASSERT(buflen == 16);
         CX_TEST_ASSERT(len == 14);
         CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 string", 15));
         CX_TEST_ASSERT(0 == memcmp(str, "Test 47 string", 15));
@@ -367,8 +375,10 @@
     CxAllocator *alloc = &talloc.base;
     CX_TEST_DO {
         char *str;
-        size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Hello %d %s", 4711, "larger string");
+        size_t buflen = 16;
+        size_t len = cx_sprintf_sa(alloc, buf, &buflen, &str, "Hello %d %s", 4711, "larger string");
         CX_TEST_ASSERT(str != buf);
+        CX_TEST_ASSERT(buflen == 25);
         CX_TEST_ASSERT(len == 24);
         CX_TEST_ASSERT(0 == memcmp(str, "Hello 4711 larger string", 25));
         cxFree(alloc, str);
@@ -385,9 +395,11 @@
     CxAllocator *alloc = &talloc.base;
     CX_TEST_DO {
         char *str;
-        size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Hello %d %s", 112, "string");
+        size_t buflen = 16;
+        size_t len = cx_sprintf_sa(alloc, buf,&buflen, &str, "Hello %d %s", 112, "string");
         CX_TEST_ASSERT(str != buf);
         CX_TEST_ASSERT(len == 16);
+        CX_TEST_ASSERT(buflen == 17);
         CX_TEST_ASSERT(0 == memcmp(str, "Hello 112 string", 17)); // include terminator
         cxFree(alloc, str);
         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));

mercurial