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