commit 0abee385cd516bb0cbcd784affddb0d445911683
parent b35ce6ae710b2a5e16f7125764591d132c2064f2
Author: vaplv <vaplv@free.fr>
Date: Mon, 20 Jul 2020 13:05:28 +0200
Add and test the str_vprintf and str_append_[v]printf functions
Diffstat:
| M | src/str.c | | | 50 | ++++++++++++++++++++++++++++++++++++++++++-------- |
| M | src/str.h | | | 24 | ++++++++++++++++++++++++ |
| M | src/test_str.c | | | 45 | +++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 111 insertions(+), 8 deletions(-)
diff --git a/src/str.c b/src/str.c
@@ -17,7 +17,6 @@
#include "io_c99.h"
#include "str.h"
-#include <stdarg.h>
#include <string.h>
/*******************************************************************************
@@ -185,22 +184,57 @@ res_T
str_printf(struct str* str, const char* fmt, ...)
{
va_list ap;
- size_t len;
res_T res = RES_OK;
ASSERT(str && fmt);
+ va_start(ap, fmt);
+ res = str_vprintf(str, fmt, ap);
+ va_end(ap);
+ return res;
+}
+res_T
+str_append_printf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ res_T res = RES_OK;
+ ASSERT(str && fmt);
va_start(ap, fmt);
- len = (size_t)vsnprintf(str->cstr, str->allocated, fmt, ap);
+ res = str_append_vprintf(str, fmt, ap);
+ va_end(ap);
+ return res;
+}
+
+res_T
+str_vprintf(struct str* str, const char* fmt, va_list vargs_list)
+{
+ ASSERT(str && fmt);
+ str_clear(str);
+ return str_append_vprintf(str, fmt, vargs_list);
+}
+
+res_T
+str_append_vprintf(struct str* str, const char* fmt, va_list vargs_list)
+{
+ va_list ap;
+ size_t flen; /* Length of the formatted message */
+ size_t slen; /* Length of the string */
+ res_T res = RES_OK;
+ ASSERT(str && fmt);
+
+ slen = str_len(str);
+
+ VA_COPY(ap, vargs_list);
+ flen = (size_t)vsnprintf(str->cstr + slen, str->allocated - slen, fmt, ap);
va_end(ap);
- if(len >= str->allocated) {
- res = ensure_allocated(str, len + 1/* Null char */, 0);
+ if(slen + flen >= str->allocated) {
+ res = ensure_allocated(str, slen + flen + 1/* Null char */, 1);
if(res != RES_OK) goto error;
- va_start(ap, fmt);
- len = (size_t)vsnprintf(str->cstr, str->allocated, fmt, ap);
+ VA_COPY(ap, vargs_list);
+ flen = (size_t)vsnprintf(str->cstr + slen, str->allocated - slen, fmt, ap);
va_end(ap);
- CHK(len < str->allocated);
+ CHK(slen + flen < str->allocated);
}
exit:
diff --git a/src/str.h b/src/str.h
@@ -19,6 +19,8 @@
#include "hash.h"
#include "mem_allocator.h"
#include "rsys.h"
+
+#include <stdarg.h>
#include <string.h>
struct str {
@@ -115,6 +117,28 @@ str_printf
#endif
;
+RSYS_API res_T
+str_append_printf
+ (struct str* str,
+ const char* fmt,
+ ...)
+#ifdef COMPILER_GCC
+ __attribute__((format(printf, 2, 3)))
+#endif
+;
+
+RSYS_API res_T
+str_vprintf
+ (struct str* str,
+ const char* fmt,
+ va_list vargs_list);
+
+RSYS_API res_T
+str_append_vprintf
+ (struct str* str,
+ const char* fmt,
+ va_list vargs_list);
+
END_DECLS
static INLINE res_T
diff --git a/src/test_str.c b/src/test_str.c
@@ -15,8 +15,34 @@
#include "str.h"
#include "test_utils.h"
+#include <stdarg.h>
#include <string.h>
+#ifdef COMPILER_GCC
+__attribute__((format(printf, 2, 3)))
+#endif
+static void
+chk_vprintf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ CHK(str_vprintf(str, fmt, ap) == RES_OK);
+ va_end(ap);
+}
+
+#ifdef COMPILER_GCC
+__attribute__((format(printf, 2, 3)))
+#endif
+static void
+chk_append_vprintf(struct str* str, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ CHK(str_append_vprintf(str, fmt, ap) == RES_OK);
+ va_end(ap);
+}
+
+
int
main(int argc, char** argv)
{
@@ -150,6 +176,25 @@ main(int argc, char** argv)
str_release(&str);
str_init(&allocator_proxy, &str);
+ CHK(str_printf(&str, "Hello, ") == RES_OK);
+ CHK(str_append_printf(&str, "world!") == RES_OK);
+ CHK(!strcmp(str_cget(&str), "Hello, world!"));
+ CHK(str_printf(&str, "%s:%lu", __FILE__, 0xDECAFBADlu) == RES_OK);
+ CHK(str_append_printf(&str, ":%s", __FILE__) == RES_OK);
+ CHK(!strcmp(str_cget(&str), __FILE__":3737844653:"__FILE__));
+ chk_vprintf(&str, "You should have received a copy of the %s %s %d",
+ "GNU", "Lesser General Public License", 3);
+ CHK(!strcmp(str_cget(&str),
+ "You should have received a copy of the "
+ "GNU Lesser General Public License 3"));
+ chk_append_vprintf(&str, " along with the %s library. If not, see %c%s%c.",
+ "RSys", '<', "http://www.gnu.org/licenses/", '>');
+ CHK(!strcmp(str_cget(&str),
+ "You should have received a copy of the GNU Lesser General Public License 3 "
+ "along with the RSys library. If not, see <http://www.gnu.org/licenses/>."));
+ str_release(&str);
+
+ str_init(&allocator_proxy, &str);
CHK(str_set(&str, "abcd") == RES_OK);
CHK(str_len(&str) == 4);
str_get(&str)[3] = '\0';