diff C/port/asprintf.c @ 334:0b576ee64d45

* Create brand new hierarchy * Rename DynLib to Dynlib * Remove some warnings
author David Demelier <markand@malikania.fr>
date Sun, 08 Mar 2015 14:26:33 +0100
parents port/asprintf.c@4c9b2a3f2396
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/C/port/asprintf.c	Sun Mar 08 14:26:33 2015 +0100
@@ -0,0 +1,129 @@
+/*
+ * asprintf.c -- basic port of asprintf / vsprintf functions
+ *
+ * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+/*
+ * 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 = 80;
+
+	if ((*res = malloc(base)) == NULL)
+		return -1;
+
+	ok = 0;
+	do {
+		rvalue = vsnprintf(*res, base, format, ap);
+
+		if ((signed int)base <= rvalue || rvalue < 0) {
+			*res = realloc(*res, base * 2);
+			base *= 2;
+		} else
+			ok = 1;
+	} while (!ok && *res != NULL);
+
+	return rvalue;
+}
+
+#endif
+
+int
+asprintf(char **res, const char *fmt, ...)
+{
+	va_list ap;
+	int rvalue;
+
+	va_start(ap, fmt);
+	rvalue = vasprintf(res, fmt, ap);
+	va_end(ap);
+
+	return rvalue;
+}