GRASS 8 Programmer's Manual 8.6.0dev(2026)-ddeab64dbf
Loading...
Searching...
No Matches
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 */
40int 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
68int 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 */
98int 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:141
#define G_malloc(n)
Definition defs/gis.h:139
int count