changeset 227:4c9b2a3f2396

Update asprintf portable function
author David Demelier <markand@malikania.fr>
date Thu, 29 May 2014 10:58:32 +0200
parents 24501d428db3
children 927c4f3b8a88
files port/asprintf.c
diffstat 1 files changed, 73 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/port/asprintf.c	Fri May 09 17:44:36 2014 +0200
+++ b/port/asprintf.c	Thu May 29 10:58:32 2014 +0200
@@ -21,13 +21,80 @@
 #include <string.h>
 #include <stdarg.h>
 
-#define BASE	80	
+/*
+ * The Microsoft implementation relies on the Win32 API function
+ * _vscprintf which count the number of characters needed. Otherwise the C99
+ * function vsnprintf returns the number of character that would be printed.
+ *
+ * Finally, if we don't have C99, we use an optimistic function.
+ *
+ * The asprintf function is common to every implementations.
+ */
+
+#if defined(_MSC_VER)
+
+/*
+ * Windows implementation.
+ */
+int
+vasprintf(char **res, const char *fmt, va_list ap)
+{
+	int total = _vscprintf(fmt, ap);
+
+	if (total < 0) {
+		*res = NULL;
+		return -1;
+	}
+
+	if ((*res = (char *)malloc(sizeof (total) + 1)) == NULL)
+		return -1;
+
+	return vsprintf_s(*res, total + 1, fmt, ap);
+}
+
+#elif __STDC_VERSION__ >= 199901L
 
+/*
+ * C99 implementation using vsnprintf's return value.
+ */
+int
+vasprintf(char **res, const char *fmt, va_list ap)
+{
+	int total, nwritten;
+	va_list copy;
+
+	va_copy(copy, ap);
+	total = vsnprintf(NULL, 0, fmt, copy);
+	va_end(copy);
+
+	if (total < 0) {
+		*res = NULL;
+		return total;
+	}
+
+	if ((*res = malloc(total + 1)) == NULL)
+		return -1;
+
+	if ((nwritten = vsnprintf(*res, total + 1, fmt, ap)) < 0) {
+		free(*res);
+		*res = NULL;
+
+		return -1;
+	}
+
+	return nwritten;
+}
+
+#else
+
+/*
+ * Optimistic function fallback.
+ */
 int
 vasprintf(char **res, const char *format, va_list ap)
 {
 	int rvalue, ok;
-	size_t base = BASE;
+	size_t base = 80;
 
 	if ((*res = malloc(base)) == NULL)
 		return -1;
@@ -37,8 +104,8 @@
 		rvalue = vsnprintf(*res, base, format, ap);
 
 		if ((signed int)base <= rvalue || rvalue < 0) {
-			*res = realloc(*res, base + BASE);
-			base += BASE;
+			*res = realloc(*res, base * 2);
+			base *= 2;
 		} else
 			ok = 1;
 	} while (!ok && *res != NULL);
@@ -46,6 +113,8 @@
 	return rvalue;
 }
 
+#endif
+
 int
 asprintf(char **res, const char *fmt, ...)
 {