This source file includes following definitions.
- guess_strlen
- pmix_asprintf
- pmix_vasprintf
- pmix_snprintf
- pmix_vsnprintf
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <src/include/pmix_config.h>
26
27
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32
33 #include "src/util/printf.h"
34 #include "src/util/output.h"
35
36
37
38
39
40
41
42 static int guess_strlen(const char *fmt, va_list ap)
43 {
44 char *sarg, carg;
45 double darg;
46 float farg;
47 size_t i;
48 int iarg;
49 int len;
50 long larg;
51
52
53
54
55 len = (int)strlen(fmt) + 128;
56 for (i = 0; i < strlen(fmt); ++i) {
57 if ('%' == fmt[i] && i + 1 < strlen(fmt)
58 && '%' != fmt[i + 1]) {
59 ++i;
60 switch (fmt[i]) {
61 case 'c':
62 carg = va_arg(ap, int);
63 len += 1;
64 (void)carg;
65 break;
66 case 's':
67 sarg = va_arg(ap, char *);
68
69
70
71
72 if (NULL != sarg) {
73 len += (int)strlen(sarg);
74 } else {
75 #if PMIX_ENABLE_DEBUG
76 pmix_output(0, "PMIX DEBUG WARNING: Got a NULL argument to pmix_vasprintf!\n");
77 #endif
78 len += 5;
79 }
80 break;
81
82 case 'd':
83 case 'i':
84 iarg = va_arg(ap, int);
85
86 if (iarg < 0)
87 ++len;
88
89 do {
90 ++len;
91 iarg /= 10;
92 } while (0 != iarg);
93 break;
94
95 case 'x':
96 case 'X':
97 iarg = va_arg(ap, int);
98
99 do {
100 ++len;
101 iarg /= 16;
102 } while (0 != iarg);
103 break;
104
105 case 'f':
106 farg = (float)va_arg(ap, int);
107
108 if (farg < 0) {
109 ++len;
110 farg = -farg;
111 }
112
113 len += 4;
114
115 do {
116 ++len;
117 farg /= 10.0;
118 } while (0 != farg);
119 break;
120
121 case 'g':
122 darg = va_arg(ap, int);
123
124 if (darg < 0) {
125 ++len;
126 darg = -darg;
127 }
128
129 len += 4;
130
131 do {
132 ++len;
133 darg /= 10.0;
134 } while (0 != darg);
135 break;
136
137 case 'l':
138
139 if (i + 1 < strlen(fmt)) {
140 ++i;
141 switch (fmt[i]) {
142 case 'x':
143 case 'X':
144 larg = va_arg(ap, int);
145
146 do {
147 ++len;
148 larg /= 16;
149 } while (0 != larg);
150 break;
151
152 case 'f':
153 darg = va_arg(ap, int);
154
155 if (darg < 0) {
156 ++len;
157 darg = -darg;
158 }
159
160 len += 4;
161
162 do {
163 ++len;
164 darg /= 10.0;
165 } while (0 != darg);
166 break;
167
168 case 'd':
169 default:
170 larg = va_arg(ap, int);
171
172 do {
173 ++len;
174 larg /= 10;
175 } while (0 != larg);
176 break;
177 }
178 }
179
180 default:
181 break;
182 }
183 }
184 }
185
186 return len;
187 }
188
189
190 int pmix_asprintf(char **ptr, const char *fmt, ...)
191 {
192 int length;
193 va_list ap;
194
195 va_start(ap, fmt);
196 length = pmix_vasprintf(ptr, fmt, ap);
197 va_end(ap);
198
199 return length;
200 }
201
202
203 int pmix_vasprintf(char **ptr, const char *fmt, va_list ap)
204 {
205 int length;
206 va_list ap2;
207
208
209
210
211 #if PMIX_HAVE_VA_COPY
212 va_copy(ap2, ap);
213 #elif PMIX_HAVE_UNDERSCORE_VA_COPY
214 __va_copy(ap2, ap);
215 #else
216 memcpy (&ap2, &ap, sizeof(va_list));
217 #endif
218
219
220 length = guess_strlen(fmt, ap);
221
222
223 *ptr = (char *) malloc((size_t) length + 1);
224 if (NULL == *ptr) {
225 errno = ENOMEM;
226 va_end(ap2);
227 return -1;
228 }
229
230
231 length = vsprintf(*ptr, fmt, ap2);
232 #if PMIX_HAVE_VA_COPY || PMIX_HAVE_UNDERSCORE_VA_COPY
233 va_end(ap2);
234 #endif
235
236
237 *ptr = (char*) realloc(*ptr, (size_t) length + 1);
238 if (NULL == *ptr) {
239 errno = ENOMEM;
240 return -1;
241 }
242
243 return length;
244 }
245
246
247 int pmix_snprintf(char *str, size_t size, const char *fmt, ...)
248 {
249 int length;
250 va_list ap;
251
252 va_start(ap, fmt);
253 length = pmix_vsnprintf(str, size, fmt, ap);
254 va_end(ap);
255
256 return length;
257 }
258
259
260 int pmix_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
261 {
262 int length;
263 char *buf;
264
265 length = pmix_vasprintf(&buf, fmt, ap);
266 if (length < 0) {
267 return length;
268 }
269
270
271 if (str) {
272 if ((size_t) length < size) {
273 strcpy(str, buf);
274 } else {
275 memcpy(str, buf, size - 1);
276 str[size] = '\0';
277 }
278 }
279
280
281 free(buf);
282
283 return length;
284 }
285
286
287 #ifdef TEST
288
289 int main(int argc, char *argv[])
290 {
291 char a[10];
292 char b[173];
293 char *s;
294 int length;
295
296 puts("test for NULL buffer in snprintf:");
297 length = pmix_snprintf(NULL, 0, "this is a string %d", 1004);
298 printf("length = %d\n", length);
299
300 puts("test of snprintf to an undersize buffer:");
301 length = pmix_snprintf(a, sizeof(a), "this is a string %d", 1004);
302 printf("string = %s\n", a);
303 printf("length = %d\n", length);
304 printf("strlen = %d\n", (int) strlen(a));
305
306 puts("test of snprintf to an oversize buffer:");
307 length = pmix_snprintf(b, sizeof(b), "this is a string %d", 1004);
308 printf("string = %s\n", b);
309 printf("length = %d\n", length);
310 printf("strlen = %d\n", (int) strlen(b));
311
312 puts("test of asprintf:");
313 length = pmix_asprintf(&s, "this is a string %d", 1004);
314 printf("string = %s\n", s);
315 printf("length = %d\n", length);
316 printf("strlen = %d\n", (int) strlen(s));
317
318 free(s);
319
320 return 0;
321 }
322
323 #endif