Mercurial > code
view 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 source
/* * 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; }