GRASS GIS 8 Programmer's Manual 8.3.2(2024)-exported
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 */
40
41int 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
69int 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
100int 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
int count