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