486
|
1 /* |
|
2 * asprintf.c -- basic port of asprintf / vsprintf functions |
|
3 * |
|
4 * Copyright (c) 2011, 2012 David Demelier <markand@malikania.fr> |
|
5 * |
|
6 * Permission to use, copy, modify, and/or distribute this software for any |
|
7 * purpose with or without fee is hereby granted, provided that the above |
|
8 * copyright notice and this permission notice appear in all copies. |
|
9 * |
|
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
17 */ |
|
18 |
|
19 #include <stdio.h> |
|
20 #include <stdlib.h> |
|
21 #include <string.h> |
|
22 #include <stdarg.h> |
|
23 |
|
24 /* |
|
25 * The Microsoft implementation relies on the Win32 API function |
|
26 * _vscprintf which count the number of characters needed. Otherwise the C99 |
|
27 * function vsnprintf returns the number of character that would be printed. |
|
28 * |
|
29 * Finally, if we don't have C99, we use an optimistic function. |
|
30 * |
|
31 * The asprintf function is common to every implementations. |
|
32 */ |
|
33 |
|
34 #if defined(_MSC_VER) |
|
35 |
|
36 /* |
|
37 * Windows implementation. |
|
38 */ |
|
39 int |
|
40 vasprintf(char **res, const char *fmt, va_list ap) |
|
41 { |
|
42 int total = _vscprintf(fmt, ap); |
|
43 |
|
44 if (total < 0) { |
|
45 *res = NULL; |
|
46 return -1; |
|
47 } |
|
48 |
|
49 if ((*res = (char *)malloc(sizeof (total) + 1)) == NULL) |
|
50 return -1; |
|
51 |
|
52 return vsprintf_s(*res, total + 1, fmt, ap); |
|
53 } |
|
54 |
|
55 #elif __STDC_VERSION__ >= 199901L |
|
56 |
|
57 /* |
|
58 * C99 implementation using vsnprintf's return value. |
|
59 */ |
|
60 int |
|
61 vasprintf(char **res, const char *fmt, va_list ap) |
|
62 { |
|
63 int total, nwritten; |
|
64 va_list copy; |
|
65 |
|
66 va_copy(copy, ap); |
|
67 total = vsnprintf(NULL, 0, fmt, copy); |
|
68 va_end(copy); |
|
69 |
|
70 if (total < 0) { |
|
71 *res = NULL; |
|
72 return total; |
|
73 } |
|
74 |
|
75 if ((*res = malloc(total + 1)) == NULL) |
|
76 return -1; |
|
77 |
|
78 if ((nwritten = vsnprintf(*res, total + 1, fmt, ap)) < 0) { |
|
79 free(*res); |
|
80 *res = NULL; |
|
81 |
|
82 return -1; |
|
83 } |
|
84 |
|
85 return nwritten; |
|
86 } |
|
87 |
|
88 #else |
|
89 |
|
90 /* |
|
91 * Optimistic function fallback. |
|
92 */ |
|
93 int |
|
94 vasprintf(char **res, const char *format, va_list ap) |
|
95 { |
|
96 int rvalue, ok; |
|
97 size_t base = 80; |
|
98 |
|
99 if ((*res = malloc(base)) == NULL) |
|
100 return -1; |
|
101 |
|
102 ok = 0; |
|
103 do { |
|
104 rvalue = vsnprintf(*res, base, format, ap); |
|
105 |
|
106 if ((signed int)base <= rvalue || rvalue < 0) { |
|
107 *res = realloc(*res, base * 2); |
|
108 base *= 2; |
|
109 } else |
|
110 ok = 1; |
|
111 } while (!ok && *res != NULL); |
|
112 |
|
113 return rvalue; |
|
114 } |
|
115 |
|
116 #endif |
|
117 |
|
118 int |
|
119 asprintf(char **res, const char *fmt, ...) |
|
120 { |
|
121 va_list ap; |
|
122 int rvalue; |
|
123 |
|
124 va_start(ap, fmt); |
|
125 rvalue = vasprintf(res, fmt, ap); |
|
126 va_end(ap); |
|
127 |
|
128 return rvalue; |
|
129 } |