aboutsummaryrefslogtreecommitdiff
path: root/src/asprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/asprintf.c')
-rw-r--r--src/asprintf.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/asprintf.c b/src/asprintf.c
new file mode 100644
index 0000000..d493fcb
--- /dev/null
+++ b/src/asprintf.c
@@ -0,0 +1,85 @@
1/* grecs - Gray's Extensible Configuration System
2 Copyright (C) 2007-2011 Sergey Poznyakoff
3
4 Grecs is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 3 of the License, or (at your
7 option) any later version.
8
9 Grecs is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with Grecs. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdlib.h>
21#include <string.h>
22#include <errno.h>
23#include "grecs.h"
24
25int
26grecs_vasprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap)
27{
28 char *buf = *pbuf;
29 size_t buflen = *psize;
30 int rc = 0;
31
32 if (!buf) {
33 if (buflen == 0)
34 buflen = 512; /* Initial allocation */
35
36 buf = calloc(1, buflen);
37 if (buf == NULL)
38 return ENOMEM;
39 }
40
41 for (;;) {
42 ssize_t n = vsnprintf(buf, buflen, fmt, ap);
43 if (n < 0 || n >= buflen || !memchr(buf, '\0', n + 1)) {
44 char *newbuf;
45 size_t newlen = buflen * 2;
46 if (newlen < buflen) {
47 rc = ENOMEM;
48 break;
49 }
50 newbuf = realloc(buf, newlen);
51 if (newbuf == NULL) {
52 rc = ENOMEM;
53 break;
54 }
55 buflen = newlen;
56 buf = newbuf;
57 } else
58 break;
59 }
60
61 if (rc) {
62 if (!*pbuf) {
63 /* We made first allocation, now free it */
64 free(buf);
65 buf = NULL;
66 buflen = 0;
67 }
68 }
69
70 *pbuf = buf;
71 *psize = buflen;
72 return rc;
73}
74
75int
76grecs_asprintf(char **pbuf, size_t *psize, const char *fmt, ...)
77{
78 int rc;
79 va_list ap;
80
81 va_start(ap, fmt);
82 rc = grecs_vasprintf(pbuf, psize, fmt, ap);
83 va_end(ap);
84 return rc;
85}

Return to:

Send suggestions and report system problems to the System administrator.