Fri, 12 Apr 2024 21:48:12 +0200
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 |
1.1 --- a/src/cx/printf.h Wed Apr 03 21:22:23 2024 +0200 1.2 +++ b/src/cx/printf.h Fri Apr 12 21:48:12 2024 +0200 1.3 @@ -168,12 +168,12 @@ 1.4 /** 1.5 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 1.6 * 1.7 + * The size of the buffer will be updated in \p len when necessary. 1.8 + * 1.9 * \note The resulting string is guaranteed to be zero-terminated. 1.10 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.11 - * the length returned by this function plus one. 1.12 * 1.13 * @param str a pointer to the string buffer 1.14 - * @param len the current length of the buffer 1.15 + * @param len a pointer to the length of the buffer 1.16 * @param fmt the format string 1.17 * @param ... additional arguments 1.18 * @return the length of produced string 1.19 @@ -183,32 +183,32 @@ 1.20 /** 1.21 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 1.22 * 1.23 + * The size of the buffer will be updated in \p len when necessary. 1.24 + * 1.25 * \note The resulting string is guaranteed to be zero-terminated. 1.26 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.27 - * the length returned by this function plus one. 1.28 * 1.29 * \attention The original buffer MUST have been allocated with the same allocator! 1.30 * 1.31 * @param alloc the allocator to use 1.32 * @param str a pointer to the string buffer 1.33 - * @param len the current length of the buffer 1.34 + * @param len a pointer to the length of the buffer 1.35 * @param fmt the format string 1.36 * @param ... additional arguments 1.37 * @return the length of produced string 1.38 */ 1.39 -__attribute__((__nonnull__(1, 2, 4), __format__(printf, 4, 5))) 1.40 -int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ); 1.41 +__attribute__((__nonnull__(1, 2, 3, 4), __format__(printf, 4, 5))) 1.42 +int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ); 1.43 1.44 1.45 /** 1.46 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 1.47 * 1.48 + * The size of the buffer will be updated in \p len when necessary. 1.49 + * 1.50 * \note The resulting string is guaranteed to be zero-terminated. 1.51 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.52 - * the length returned by this function plus one. 1.53 * 1.54 * @param str a pointer to the string buffer 1.55 - * @param len the current length of the buffer 1.56 + * @param len a pointer to the length of the buffer 1.57 * @param fmt the format string 1.58 * @param ap argument list 1.59 * @return the length of produced string 1.60 @@ -218,38 +218,38 @@ 1.61 /** 1.62 * An \c sprintf like function which reallocates the string when the buffer is not large enough. 1.63 * 1.64 + * The size of the buffer will be updated in \p len when necessary. 1.65 + * 1.66 * \note The resulting string is guaranteed to be zero-terminated. 1.67 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.68 - * the length returned by this function plus one. 1.69 * 1.70 * \attention The original buffer MUST have been allocated with the same allocator! 1.71 * 1.72 * @param alloc the allocator to use 1.73 * @param str a pointer to the string buffer 1.74 - * @param len the current length of the buffer 1.75 + * @param len a pointer to the length of the buffer 1.76 * @param fmt the format string 1.77 * @param ap argument list 1.78 * @return the length of produced string 1.79 */ 1.80 __attribute__((__nonnull__)) 1.81 -int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap); 1.82 +int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap); 1.83 1.84 1.85 /** 1.86 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 1.87 * 1.88 + * The size of the buffer will be updated in \p len when necessary. 1.89 + * 1.90 * The location of the resulting string will \em always be stored to \p str. When the buffer 1.91 * was sufficiently large, \p buf itself will be stored to the location of \p str. 1.92 * 1.93 * \note The resulting string is guaranteed to be zero-terminated. 1.94 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.95 - * the length returned by this function plus one. 1.96 * 1.97 * \remark When a new string needed to be allocated, the contents of \p buf will be 1.98 * poisoned after the call, because this function tries to produce the string in \p buf, first. 1.99 * 1.100 * @param buf a pointer to the buffer 1.101 - * @param len the length of the buffer 1.102 + * @param len a pointer to the length of the buffer 1.103 * @param str a pointer to the location 1.104 * @param fmt the format string 1.105 * @param ... additional arguments 1.106 @@ -260,42 +260,42 @@ 1.107 /** 1.108 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 1.109 * 1.110 + * The size of the buffer will be updated in \p len when necessary. 1.111 + * 1.112 * The location of the resulting string will \em always be stored to \p str. When the buffer 1.113 * was sufficiently large, \p buf itself will be stored to the location of \p str. 1.114 * 1.115 * \note The resulting string is guaranteed to be zero-terminated. 1.116 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.117 - * the length returned by this function plus one. 1.118 * 1.119 * \remark When a new string needed to be allocated, the contents of \p buf will be 1.120 * poisoned after the call, because this function tries to produce the string in \p buf, first. 1.121 * 1.122 * @param alloc the allocator to use 1.123 * @param buf a pointer to the buffer 1.124 - * @param len the length of the buffer 1.125 + * @param len a pointer to the length of the buffer 1.126 * @param str a pointer to the location 1.127 * @param fmt the format string 1.128 * @param ... additional arguments 1.129 * @return the length of produced string 1.130 */ 1.131 __attribute__((__nonnull__(1, 2, 4, 5), __format__(printf, 5, 6))) 1.132 -int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ); 1.133 +int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ); 1.134 1.135 /** 1.136 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 1.137 * 1.138 + * The size of the buffer will be updated in \p len when necessary. 1.139 + * 1.140 * The location of the resulting string will \em always be stored to \p str. When the buffer 1.141 * was sufficiently large, \p buf itself will be stored to the location of \p str. 1.142 * 1.143 * \note The resulting string is guaranteed to be zero-terminated. 1.144 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.145 - * the length returned by this function plus one. 1.146 * 1.147 * \remark When a new string needed to be allocated, the contents of \p buf will be 1.148 * poisoned after the call, because this function tries to produce the string in \p buf, first. 1.149 * 1.150 * @param buf a pointer to the buffer 1.151 - * @param len the length of the buffer 1.152 + * @param len a pointer to the length of the buffer 1.153 * @param str a pointer to the location 1.154 * @param fmt the format string 1.155 * @param ap argument list 1.156 @@ -306,26 +306,26 @@ 1.157 /** 1.158 * An \c sprintf like function which allocates a new string when the buffer is not large enough. 1.159 * 1.160 + * The size of the buffer will be updated in \p len when necessary. 1.161 + * 1.162 * The location of the resulting string will \em always be stored to \p str. When the buffer 1.163 * was sufficiently large, \p buf itself will be stored to the location of \p str. 1.164 * 1.165 * \note The resulting string is guaranteed to be zero-terminated. 1.166 - * That means, when the buffer needed to be reallocated, the new size of the buffer will be 1.167 - * the length returned by this function plus one. 1.168 * 1.169 * \remark When a new string needed to be allocated, the contents of \p buf will be 1.170 * poisoned after the call, because this function tries to produce the string in \p buf, first. 1.171 * 1.172 * @param alloc the allocator to use 1.173 * @param buf a pointer to the buffer 1.174 - * @param len the length of the buffer 1.175 + * @param len a pointer to the length of the buffer 1.176 * @param str a pointer to the location 1.177 * @param fmt the format string 1.178 * @param ap argument list 1.179 * @return the length of produced string 1.180 */ 1.181 __attribute__((__nonnull__)) 1.182 -int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap); 1.183 +int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap); 1.184 1.185 1.186 #ifdef __cplusplus
2.1 --- a/src/printf.c Wed Apr 03 21:22:23 2024 +0200 2.2 +++ b/src/printf.c Fri Apr 12 21:48:12 2024 +0200 2.3 @@ -132,7 +132,7 @@ 2.4 return s; 2.5 } 2.6 2.7 -int cx_sprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, ... ) { 2.8 +int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) { 2.9 va_list ap; 2.10 va_start(ap, fmt); 2.11 int ret = cx_vsprintf_a(alloc, str, len, fmt, ap); 2.12 @@ -140,11 +140,11 @@ 2.13 return ret; 2.14 } 2.15 2.16 -int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t len, const char *fmt, va_list ap) { 2.17 +int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) { 2.18 va_list ap2; 2.19 va_copy(ap2, ap); 2.20 - int ret = vsnprintf(*str, len, fmt, ap); 2.21 - if ((unsigned) ret >= len) { 2.22 + int ret = vsnprintf(*str, *len, fmt, ap); 2.23 + if ((unsigned) ret >= *len) { 2.24 unsigned newlen = ret + 1; 2.25 char *ptr = cxRealloc(alloc, *str, newlen); 2.26 if (ptr) { 2.27 @@ -152,6 +152,7 @@ 2.28 if (newret < 0) { 2.29 cxFree(alloc, ptr); 2.30 } else { 2.31 + *len = newlen; 2.32 *str = ptr; 2.33 ret = newret; 2.34 } 2.35 @@ -161,7 +162,7 @@ 2.36 return ret; 2.37 } 2.38 2.39 -int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, ... ) { 2.40 +int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) { 2.41 va_list ap; 2.42 va_start(ap, fmt); 2.43 int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap); 2.44 @@ -169,12 +170,12 @@ 2.45 return ret; 2.46 } 2.47 2.48 -int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t len, char **str, const char *fmt, va_list ap) { 2.49 +int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) { 2.50 va_list ap2; 2.51 va_copy(ap2, ap); 2.52 - int ret = vsnprintf(buf, len, fmt, ap); 2.53 + int ret = vsnprintf(buf, *len, fmt, ap); 2.54 *str = buf; 2.55 - if ((unsigned) ret >= len) { 2.56 + if ((unsigned) ret >= *len) { 2.57 unsigned newlen = ret + 1; 2.58 char *ptr = cxMalloc(alloc, newlen); 2.59 if (ptr) { 2.60 @@ -182,6 +183,7 @@ 2.61 if (newret < 0) { 2.62 cxFree(alloc, ptr); 2.63 } else { 2.64 + *len = newlen; 2.65 *str = ptr; 2.66 ret = newret; 2.67 }
3.1 --- a/tests/test_printf.c Wed Apr 03 21:22:23 2024 +0200 3.2 +++ b/tests/test_printf.c Fri Apr 12 21:48:12 2024 +0200 3.3 @@ -301,9 +301,11 @@ 3.4 CxAllocator *alloc = &talloc.base; 3.5 CX_TEST_DO { 3.6 char *oldbuf = buf; 3.7 - size_t len = cx_sprintf_a(alloc, &buf, 16, "Test %d %s", 47, "string"); 3.8 + size_t buflen = 16; 3.9 + size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 47, "string"); 3.10 CX_TEST_ASSERT(oldbuf == buf); 3.11 CX_TEST_ASSERT(len == 14); 3.12 + CX_TEST_ASSERT(buflen == 16); 3.13 CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 string", 15)); 3.14 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 3.15 } 3.16 @@ -317,8 +319,10 @@ 3.17 CxAllocator *alloc = &talloc.base; 3.18 char *buf = cxMalloc(alloc, 8); 3.19 CX_TEST_DO { 3.20 - size_t len = cx_sprintf_a(alloc, &buf, 8, "Test %d %s", 47, "foobar"); 3.21 + size_t buflen = 8; 3.22 + size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 47, "foobar"); 3.23 CX_TEST_ASSERT(len == 14); 3.24 + CX_TEST_ASSERT(buflen == 15); 3.25 CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 foobar", 15)); 3.26 cxFree(alloc, buf); 3.27 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 3.28 @@ -333,8 +337,10 @@ 3.29 // make it so that only the zero-terminator does not fit 3.30 char *buf = cxMalloc(alloc, 14); 3.31 CX_TEST_DO { 3.32 - size_t len = cx_sprintf_a(alloc, &buf, 14, "Test %d %s", 13, "string"); 3.33 + size_t buflen = 14; 3.34 + size_t len = cx_sprintf_a(alloc, &buf, &buflen, "Test %d %s", 13, "string"); 3.35 CX_TEST_ASSERT(len == 14); 3.36 + CX_TEST_ASSERT(buflen == 15); 3.37 CX_TEST_ASSERT(0 == memcmp(buf, "Test 13 string", 15)); 3.38 cxFree(alloc, buf); 3.39 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 3.40 @@ -349,8 +355,10 @@ 3.41 CxAllocator *alloc = &talloc.base; 3.42 CX_TEST_DO { 3.43 char *str; 3.44 - size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Test %d %s", 47, "string"); 3.45 + size_t buflen = 16; 3.46 + size_t len = cx_sprintf_sa(alloc, buf, &buflen, &str, "Test %d %s", 47, "string"); 3.47 CX_TEST_ASSERT(str == buf); 3.48 + CX_TEST_ASSERT(buflen == 16); 3.49 CX_TEST_ASSERT(len == 14); 3.50 CX_TEST_ASSERT(0 == memcmp(buf, "Test 47 string", 15)); 3.51 CX_TEST_ASSERT(0 == memcmp(str, "Test 47 string", 15)); 3.52 @@ -367,8 +375,10 @@ 3.53 CxAllocator *alloc = &talloc.base; 3.54 CX_TEST_DO { 3.55 char *str; 3.56 - size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Hello %d %s", 4711, "larger string"); 3.57 + size_t buflen = 16; 3.58 + size_t len = cx_sprintf_sa(alloc, buf, &buflen, &str, "Hello %d %s", 4711, "larger string"); 3.59 CX_TEST_ASSERT(str != buf); 3.60 + CX_TEST_ASSERT(buflen == 25); 3.61 CX_TEST_ASSERT(len == 24); 3.62 CX_TEST_ASSERT(0 == memcmp(str, "Hello 4711 larger string", 25)); 3.63 cxFree(alloc, str); 3.64 @@ -385,9 +395,11 @@ 3.65 CxAllocator *alloc = &talloc.base; 3.66 CX_TEST_DO { 3.67 char *str; 3.68 - size_t len = cx_sprintf_sa(alloc, buf, 16, &str, "Hello %d %s", 112, "string"); 3.69 + size_t buflen = 16; 3.70 + size_t len = cx_sprintf_sa(alloc, buf,&buflen, &str, "Hello %d %s", 112, "string"); 3.71 CX_TEST_ASSERT(str != buf); 3.72 CX_TEST_ASSERT(len == 16); 3.73 + CX_TEST_ASSERT(buflen == 17); 3.74 CX_TEST_ASSERT(0 == memcmp(str, "Hello 112 string", 17)); // include terminator 3.75 cxFree(alloc, str); 3.76 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));