GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-835afb4352
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 
41 int G_vasprintf(char **out, const char *fmt, va_list ap)
42 {
43 #ifdef HAVE_ASPRINTF
44  return vasprintf(out, fmt, ap);
45 #else
46  size_t size = strlen(fmt) + 50;
47  char *buf = G_malloc(size);
48  int count;
49 
50  for (;;) {
51  /* BUG: according to man vsnprintf,
52  * va_start() should be called immediately before vsnprintf(),
53  * and va_end() immediately after vsnprintf()
54  * otherwise there will be memory corruption */
55  count = vsnprintf(buf, size, fmt, ap);
56  if (count >= 0 && count < size)
57  break;
58  size *= 2;
59  buf = G_realloc(buf, size);
60  }
61 
62  buf = G_realloc(buf, count + 1);
63  *out = buf;
64 
65  return count;
66 #endif /* HAVE_ASPRINTF */
67 }
68 
69 int G_asprintf(char **out, const char *fmt, ...)
70 {
71  va_list ap;
72  int count;
73 
74  va_start(ap, fmt);
75  count = G_vasprintf(out, fmt, ap);
76  va_end(ap);
77 
78  return count;
79 }
80 
81 #endif /* G_asprintf */
82 
83 /**
84  * \brief Reallocating version of <i>asprintf()</i>.
85  *
86  * Reallocate a string large enough to hold the output, including the
87  * terminating NULL, and return the number of characters printed.
88  * Contrary to <i>G_asprintf()</i>, any existing buffer pointed to by
89  * out of size osize is used to hold the output and enlarged if
90  * necessary. This is useful when <i>G_rasprintf</i> is called many
91  * times in a loop.
92  *
93  * \param[out] out
94  * \param[out] osize
95  * \param[in] fmt
96  * \param ap
97  * \return number of bytes written
98  */
99 
100 int G_rasprintf(char **out, size_t *size, const char *fmt, ...)
101 {
102  va_list ap;
103  int count;
104  char *buf = *out;
105  size_t osize = *size;
106 
107  if (osize < strlen(fmt) + 50) {
108  osize = strlen(fmt) + 50;
109  buf = G_realloc(buf, osize);
110  }
111 
112  for (;;) {
113  va_start(ap, fmt);
114  count = vsnprintf(buf, osize, fmt, ap);
115  va_end(ap);
116  if (count >= 0 && (size_t)count < osize)
117  break;
118  if (count > -1)
119  osize = count + 1;
120  else
121  osize *= 2;
122 
123  buf = G_realloc(buf, osize);
124  }
125 
126  *out = buf;
127  *size = osize;
128 
129  return count;
130 }
int G_rasprintf(char **out, size_t *size, const char *fmt,...)
Reallocating version of asprintf().
Definition: asprintf.c:100
int G_asprintf(char **out, const char *fmt,...)
Definition: asprintf.c:69
int G_vasprintf(char **out, const char *fmt, va_list ap)
Safe replacement for asprintf().
Definition: asprintf.c:41
#define G_realloc(p, n)
Definition: defs/gis.h:96
#define G_malloc(n)
Definition: defs/gis.h:94
int count