123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- /*!
- * \file lib/gis/asprintf.c
- *
- * \brief GIS Library - GRASS implementation of asprintf().
- *
- * Eric G. Miller - Thu, 2 May 2002 17:51:54 -0700
- *
- * Rewritten by Glynn Clements, Sat, 6 Feb 2010
- * Assumes that vsnprintf() is available
- *
- * (C) 2002-2014 by the GRASS Development Team
- * (C) 2010 by Glynn Clements
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- */
- #define _GNU_SOURCE /* enable asprintf */
- #include <stdio.h>
- #include <stdarg.h>
- #include <string.h>
- #include <grass/gis.h>
- #ifndef G_asprintf
- /**
- * \brief Safe replacement for <i>asprintf()</i>.
- *
- * Allocate a string large enough to hold the new output, including the
- * terminating NULL, and return the number of characters printed. The
- * pointer out is set to the output string and should be passed to
- * <i>G_free()</i> to release the allocated storage when it is no longer
- * needed.
- *
- * \param[out] out
- * \param[in] fmt
- * \param ap
- * \return number of bytes written
- */
- int G_vasprintf(char **out, const char *fmt, va_list ap)
- {
- #ifdef HAVE_ASPRINTF
- return vasprintf(out, fmt, ap);
- #else
- size_t size = strlen(fmt) + 50;
- char *buf = G_malloc(size);
- int count;
- for (;;) {
- /* BUG: according to man vsnprintf,
- * va_start() should be called immediately before vsnprintf(),
- * and va_end() immediately after vsnprintf()
- * otherwise there will be memory corruption */
- count = vsnprintf(buf, size, fmt, ap);
- if (count >= 0 && count < size)
- break;
- size *= 2;
- buf = G_realloc(buf, size);
- }
- buf = G_realloc(buf, count + 1);
- *out = buf;
- return count;
- #endif /* HAVE_ASPRINTF */
- }
- int G_asprintf(char **out, const char *fmt, ...)
- {
- va_list ap;
- int count;
- va_start(ap, fmt);
- count = G_vasprintf(out, fmt, ap);
- va_end(ap);
- return count;
- }
- #endif /* G_asprintf */
- /**
- * \brief Reallocating version of <i>asprintf()</i>.
- *
- * Reallocate a string large enough to hold the output, including the
- * terminating NULL, and return the number of characters printed.
- * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
- * out of size osize is used to hold the output and enlarged if
- * necessary. This is useful when <i>G_rasprintf</i> is called many
- * times in a loop.
- *
- * \param[out] out
- * \param[out] osize
- * \param[in] fmt
- * \param ap
- * \return number of bytes written
- */
- int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
- {
- va_list ap;
- int count;
- char *buf = *out;
- size_t osize = *size;
- if (osize < strlen(fmt) + 50) {
- osize = strlen(fmt) + 50;
- buf = G_realloc(buf, osize);
- }
- for (;;) {
- va_start(ap, fmt);
- count = vsnprintf(buf, osize, fmt, ap);
- va_end(ap);
- if (count >= 0 && count < osize)
- break;
- if (count > -1)
- osize = count + 1;
- else
- osize *= 2;
-
- buf = G_realloc(buf, osize);
- }
- *out = buf;
- *size = osize;
- return count;
- }
|