improves interface of cx_sprintf() variants default tip

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

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));

mercurial