Mercurial > code
diff port/C/asprintf.c @ 543:dc1b5143c5e3
Misc: new hierarchy
author | David Demelier <markand@malikania.fr> |
---|---|
date | Mon, 13 Jun 2016 16:13:40 +0200 |
parents | port/asprintf.c@7ee8da32da98 |
children | f48bb09bccc7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/port/C/asprintf.c Mon Jun 13 16:13:40 2016 +0200 @@ -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; +}