Mercurial > code
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, ...) {