GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
asprintf.c
Go to the documentation of this file.
1 /*!
2  * \file lib/gis/asprintf.c
3  *
4  * \brief GIS Library - GRASS implementation of asprintf().
5  *
6  * Eric G. Miller - Thu, 2 May 2002 17:51:54 -0700
7  *
8  * Rewritten by Glynn Clements, Sat, 6 Feb 2010
9  * Assumes that vsnprintf() is available
10  *
11  * (C) 2002-2014 by the GRASS Development Team
12  * (C) 2010 by Glynn Clements
13  *
14  * This program is free software under the GNU General Public License
15  * (>=v2). Read the file COPYING that comes with GRASS for details.
16  */
17 
18 #define _GNU_SOURCE /* enable asprintf */
19 #include <stdio.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <grass/gis.h>
23 
24 #ifndef G_asprintf
25 
26 /**
27  * \brief Safe replacement for <i>asprintf()</i>.
28  *
29  * Allocate a string large enough to hold the new output, including the
30  * terminating NULL, and return the number of characters printed. The
31  * pointer out is set to the output string and should be passed to
32  * <i>G_free()</i> to release the allocated storage when it is no longer
33  * needed.
34  *
35  * \param[out] out
36  * \param[in] fmt
37  * \param ap
38  * \return number of bytes written
39  */
40 int G_vasprintf(char **out, const char *fmt, va_list ap)
41 {
42 #ifdef HAVE_ASPRINTF
43  return vasprintf(out, fmt, ap);
44 #else
45  size_t size = strlen(fmt) + 50;
46  char *buf = G_malloc(size);
47  int count;
48 
49  for (;;) {
50  /* BUG: according to man vsnprintf,
51  * va_start() should be called immediately before vsnprintf(),
52  * and va_end() immediately after vsnprintf()
53  * otherwise there will be memory corruption */
54  count = vsnprintf(buf, size, fmt, ap);
55  if (count >= 0 && count < size)
56  break;
57  size *= 2;
58  buf = G_realloc(buf, size);
59  }
60 
61  buf = G_realloc(buf, count + 1);
62  *out = buf;
63 
64  return count;
65 #endif /* HAVE_ASPRINTF */
66 }
67 
68 int G_asprintf(char **out, const char *fmt, ...)
69 {
70  va_list ap;
71  int count;
72 
73  va_start(ap, fmt);
74  count = G_vasprintf(out, fmt, ap);
75  va_end(ap);
76 
77  return count;
78 }
79 
80 #endif /* G_asprintf */
81 
82 /**
83  * \brief Reallocating version of <i>asprintf()</i>.
84  *
85  * Reallocate a string large enough to hold the output, including the
86  * terminating NULL, and return the number of characters printed.
87  * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
88  * out of size osize is used to hold the output and enlarged if
89  * necessary. This is useful when <i>G_rasprintf</i> is called many
90  * times in a loop.
91  *
92  * \param[out] out
93  * \param[out] size
94  * \param[in] fmt
95  * \param ap
96  * \return number of bytes written
97  */
98 int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
99 {
100  va_list ap;
101  int count;
102  char *buf = *out;
103  size_t osize = *size;
104 
105  if (osize < strlen(fmt) + 50) {
106  osize = strlen(fmt) + 50;
107  buf = G_realloc(buf, osize);
108  }
109 
110  for (;;) {
111  va_start(ap, fmt);
112  count = vsnprintf(buf, osize, fmt, ap);
113  va_end(ap);
114  if (count >= 0 && (size_t)count < osize)
115  break;
116  if (count > -1)
117  osize = count + 1;
118  else
119  osize *= 2;
120 
121  buf = G_realloc(buf, osize);
122  }
123 
124  *out = buf;
125  *size = osize;
126 
127  return count;
128 }
int G_rasprintf(char **out, size_t *size, const char *fmt,...)
Reallocating version of asprintf().
Definition: asprintf.c:98
int G_asprintf(char **out, const char *fmt,...)
Definition: asprintf.c:68
int G_vasprintf(char **out, const char *fmt, va_list ap)
Safe replacement for asprintf().
Definition: asprintf.c:40
#define G_realloc(p, n)
Definition: defs/gis.h:96
#define G_malloc(n)
Definition: defs/gis.h:94
int count