root / logic / trunk / src / mxml / mxml-string.c @ 71
History | View | Annotate | Download (9.34 KB)
1 | 49 | Janez1 | /*
|
---|---|---|---|
2 | * "$Id: mxml-string.c 387 2009-04-18 17:05:52Z mike $"
|
||
3 | *
|
||
4 | * String functions for Mini-XML, a small XML-like file parsing library.
|
||
5 | *
|
||
6 | * Copyright 2003-2009 by Michael Sweet.
|
||
7 | *
|
||
8 | * This program is free software; you can redistribute it and/or
|
||
9 | * modify it under the terms of the GNU Library General Public
|
||
10 | * License as published by the Free Software Foundation; either
|
||
11 | * version 2, or (at your option) any later version.
|
||
12 | *
|
||
13 | * This program is distributed in the hope that it will be useful,
|
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
16 | * GNU General Public License for more details.
|
||
17 | *
|
||
18 | * Contents:
|
||
19 | *
|
||
20 | * _mxml_snprintf() - Format a string.
|
||
21 | * _mxml_strdup() - Duplicate a string.
|
||
22 | * _mxml_strdupf() - Format and duplicate a string.
|
||
23 | * _mxml_vsnprintf() - Format a string into a fixed size buffer.
|
||
24 | * _mxml_vstrdupf() - Format and duplicate a string.
|
||
25 | */
|
||
26 | |||
27 | /*
|
||
28 | * Include necessary headers...
|
||
29 | */
|
||
30 | |||
31 | #include "config.h" |
||
32 | |||
33 | |||
34 | #ifndef HAVE_SNPRINTF
|
||
35 | /*
|
||
36 | * '_mxml_snprintf()' - Format a string.
|
||
37 | */
|
||
38 | |||
39 | int /* O - Number of bytes formatted */ |
||
40 | _mxml_snprintf(char *buffer, /* I - Output buffer */ |
||
41 | size_t bufsize, /* I - Size of output buffer */
|
||
42 | const char *format, /* I - Printf-style format string */ |
||
43 | ...) /* I - Additional arguments as needed */
|
||
44 | { |
||
45 | va_list ap; /* Argument list */
|
||
46 | int bytes; /* Number of bytes formatted */ |
||
47 | |||
48 | |||
49 | va_start(ap, format); |
||
50 | bytes = vsnprintf(buffer, bufsize, format, ap); |
||
51 | va_end(ap); |
||
52 | |||
53 | return (bytes);
|
||
54 | } |
||
55 | #endif /* !HAVE_SNPRINTF */ |
||
56 | |||
57 | |||
58 | /*
|
||
59 | * '_mxml_strdup()' - Duplicate a string.
|
||
60 | */
|
||
61 | |||
62 | #ifndef HAVE_STRDUP
|
||
63 | char * /* O - New string pointer */ |
||
64 | _mxml_strdup(const char *s) /* I - String to duplicate */ |
||
65 | { |
||
66 | char *t; /* New string pointer */ |
||
67 | |||
68 | |||
69 | if (s == NULL) |
||
70 | return (NULL); |
||
71 | |||
72 | if ((t = malloc(strlen(s) + 1)) == NULL) |
||
73 | return (NULL); |
||
74 | |||
75 | return (strcpy(t, s));
|
||
76 | } |
||
77 | #endif /* !HAVE_STRDUP */ |
||
78 | |||
79 | |||
80 | /*
|
||
81 | * '_mxml_strdupf()' - Format and duplicate a string.
|
||
82 | */
|
||
83 | |||
84 | char * /* O - New string pointer */ |
||
85 | _mxml_strdupf(const char *format, /* I - Printf-style format string */ |
||
86 | ...) /* I - Additional arguments as needed */
|
||
87 | { |
||
88 | va_list ap; /* Pointer to additional arguments */
|
||
89 | char *s; /* Pointer to formatted string */ |
||
90 | |||
91 | |||
92 | /*
|
||
93 | * Get a pointer to the additional arguments, format the string,
|
||
94 | * and return it...
|
||
95 | */
|
||
96 | |||
97 | va_start(ap, format); |
||
98 | s = _mxml_vstrdupf(format, ap); |
||
99 | va_end(ap); |
||
100 | |||
101 | return (s);
|
||
102 | } |
||
103 | |||
104 | |||
105 | #ifndef HAVE_VSNPRINTF
|
||
106 | /*
|
||
107 | * '_mxml_vsnprintf()' - Format a string into a fixed size buffer.
|
||
108 | */
|
||
109 | |||
110 | int /* O - Number of bytes formatted */ |
||
111 | _mxml_vsnprintf(char *buffer, /* O - Output buffer */ |
||
112 | size_t bufsize, /* O - Size of output buffer */
|
||
113 | const char *format, /* I - Printf-style format string */ |
||
114 | va_list ap) /* I - Pointer to additional arguments */
|
||
115 | { |
||
116 | char *bufptr, /* Pointer to position in buffer */ |
||
117 | *bufend, /* Pointer to end of buffer */
|
||
118 | sign, /* Sign of format width */
|
||
119 | size, /* Size character (h, l, L) */
|
||
120 | type; /* Format type character */
|
||
121 | int width, /* Width of field */ |
||
122 | prec; /* Number of characters of precision */
|
||
123 | char tformat[100], /* Temporary format string for sprintf() */ |
||
124 | *tptr, /* Pointer into temporary format */
|
||
125 | temp[1024]; /* Buffer for formatted numbers */ |
||
126 | char *s; /* Pointer to string */ |
||
127 | int slen; /* Length of string */ |
||
128 | int bytes; /* Total number of bytes needed */ |
||
129 | |||
130 | |||
131 | /*
|
||
132 | * Loop through the format string, formatting as needed...
|
||
133 | */
|
||
134 | |||
135 | bufptr = buffer; |
||
136 | bufend = buffer + bufsize - 1;
|
||
137 | bytes = 0;
|
||
138 | |||
139 | while (*format)
|
||
140 | { |
||
141 | if (*format == '%') |
||
142 | { |
||
143 | tptr = tformat; |
||
144 | *tptr++ = *format++; |
||
145 | |||
146 | if (*format == '%') |
||
147 | { |
||
148 | if (bufptr && bufptr < bufend) *bufptr++ = *format;
|
||
149 | bytes ++; |
||
150 | format ++; |
||
151 | continue;
|
||
152 | } |
||
153 | else if (strchr(" -+#\'", *format)) |
||
154 | { |
||
155 | *tptr++ = *format; |
||
156 | sign = *format++; |
||
157 | } |
||
158 | else
|
||
159 | sign = 0;
|
||
160 | |||
161 | if (*format == '*') |
||
162 | { |
||
163 | /*
|
||
164 | * Get width from argument...
|
||
165 | */
|
||
166 | |||
167 | format ++; |
||
168 | width = va_arg(ap, int);
|
||
169 | |||
170 | snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width); |
||
171 | tptr += strlen(tptr); |
||
172 | } |
||
173 | else
|
||
174 | { |
||
175 | width = 0;
|
||
176 | |||
177 | while (isdigit(*format & 255)) |
||
178 | { |
||
179 | if (tptr < (tformat + sizeof(tformat) - 1)) |
||
180 | *tptr++ = *format; |
||
181 | |||
182 | width = width * 10 + *format++ - '0'; |
||
183 | } |
||
184 | } |
||
185 | |||
186 | if (*format == '.') |
||
187 | { |
||
188 | if (tptr < (tformat + sizeof(tformat) - 1)) |
||
189 | *tptr++ = *format; |
||
190 | |||
191 | format ++; |
||
192 | |||
193 | if (*format == '*') |
||
194 | { |
||
195 | /*
|
||
196 | * Get precision from argument...
|
||
197 | */
|
||
198 | |||
199 | format ++; |
||
200 | prec = va_arg(ap, int);
|
||
201 | |||
202 | snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec); |
||
203 | tptr += strlen(tptr); |
||
204 | } |
||
205 | else
|
||
206 | { |
||
207 | prec = 0;
|
||
208 | |||
209 | while (isdigit(*format & 255)) |
||
210 | { |
||
211 | if (tptr < (tformat + sizeof(tformat) - 1)) |
||
212 | *tptr++ = *format; |
||
213 | |||
214 | prec = prec * 10 + *format++ - '0'; |
||
215 | } |
||
216 | } |
||
217 | } |
||
218 | else
|
||
219 | prec = -1;
|
||
220 | |||
221 | if (*format == 'l' && format[1] == 'l') |
||
222 | { |
||
223 | size = 'L';
|
||
224 | |||
225 | if (tptr < (tformat + sizeof(tformat) - 2)) |
||
226 | { |
||
227 | *tptr++ = 'l';
|
||
228 | *tptr++ = 'l';
|
||
229 | } |
||
230 | |||
231 | format += 2;
|
||
232 | } |
||
233 | else if (*format == 'h' || *format == 'l' || *format == 'L') |
||
234 | { |
||
235 | if (tptr < (tformat + sizeof(tformat) - 1)) |
||
236 | *tptr++ = *format; |
||
237 | |||
238 | size = *format++; |
||
239 | } |
||
240 | |||
241 | if (!*format)
|
||
242 | break;
|
||
243 | |||
244 | if (tptr < (tformat + sizeof(tformat) - 1)) |
||
245 | *tptr++ = *format; |
||
246 | |||
247 | type = *format++; |
||
248 | *tptr = '\0';
|
||
249 | |||
250 | switch (type)
|
||
251 | { |
||
252 | case 'E' : /* Floating point formats */ |
||
253 | case 'G' : |
||
254 | case 'e' : |
||
255 | case 'f' : |
||
256 | case 'g' : |
||
257 | if ((width + 2) > sizeof(temp)) |
||
258 | break;
|
||
259 | |||
260 | sprintf(temp, tformat, va_arg(ap, double));
|
||
261 | |||
262 | bytes += strlen(temp); |
||
263 | |||
264 | if (bufptr)
|
||
265 | { |
||
266 | if ((bufptr + strlen(temp)) > bufend)
|
||
267 | { |
||
268 | strncpy(bufptr, temp, (size_t)(bufend - bufptr)); |
||
269 | bufptr = bufend; |
||
270 | } |
||
271 | else
|
||
272 | { |
||
273 | strcpy(bufptr, temp); |
||
274 | bufptr += strlen(temp); |
||
275 | } |
||
276 | } |
||
277 | break;
|
||
278 | |||
279 | case 'B' : /* Integer formats */ |
||
280 | case 'X' : |
||
281 | case 'b' : |
||
282 | case 'd' : |
||
283 | case 'i' : |
||
284 | case 'o' : |
||
285 | case 'u' : |
||
286 | case 'x' : |
||
287 | if ((width + 2) > sizeof(temp)) |
||
288 | break;
|
||
289 | |||
290 | #ifdef HAVE_LONG_LONG
|
||
291 | if (size == 'L') |
||
292 | sprintf(temp, tformat, va_arg(ap, long long)); |
||
293 | else
|
||
294 | #endif /* HAVE_LONG_LONG */ |
||
295 | sprintf(temp, tformat, va_arg(ap, int));
|
||
296 | |||
297 | bytes += strlen(temp); |
||
298 | |||
299 | if (bufptr)
|
||
300 | { |
||
301 | if ((bufptr + strlen(temp)) > bufend)
|
||
302 | { |
||
303 | strncpy(bufptr, temp, (size_t)(bufend - bufptr)); |
||
304 | bufptr = bufend; |
||
305 | } |
||
306 | else
|
||
307 | { |
||
308 | strcpy(bufptr, temp); |
||
309 | bufptr += strlen(temp); |
||
310 | } |
||
311 | } |
||
312 | break;
|
||
313 | |||
314 | case 'p' : /* Pointer value */ |
||
315 | if ((width + 2) > sizeof(temp)) |
||
316 | break;
|
||
317 | |||
318 | sprintf(temp, tformat, va_arg(ap, void *));
|
||
319 | |||
320 | bytes += strlen(temp); |
||
321 | |||
322 | if (bufptr)
|
||
323 | { |
||
324 | if ((bufptr + strlen(temp)) > bufend)
|
||
325 | { |
||
326 | strncpy(bufptr, temp, (size_t)(bufend - bufptr)); |
||
327 | bufptr = bufend; |
||
328 | } |
||
329 | else
|
||
330 | { |
||
331 | strcpy(bufptr, temp); |
||
332 | bufptr += strlen(temp); |
||
333 | } |
||
334 | } |
||
335 | break;
|
||
336 | |||
337 | case 'c' : /* Character or character array */ |
||
338 | bytes += width; |
||
339 | |||
340 | if (bufptr)
|
||
341 | { |
||
342 | if (width <= 1) |
||
343 | *bufptr++ = va_arg(ap, int);
|
||
344 | else
|
||
345 | { |
||
346 | if ((bufptr + width) > bufend)
|
||
347 | width = bufend - bufptr; |
||
348 | |||
349 | memcpy(bufptr, va_arg(ap, char *), (size_t)width);
|
||
350 | bufptr += width; |
||
351 | } |
||
352 | } |
||
353 | break;
|
||
354 | |||
355 | case 's' : /* String */ |
||
356 | if ((s = va_arg(ap, char *)) == NULL) |
||
357 | s = "(null)";
|
||
358 | |||
359 | slen = strlen(s); |
||
360 | if (slen > width && prec != width)
|
||
361 | width = slen; |
||
362 | |||
363 | bytes += width; |
||
364 | |||
365 | if (bufptr)
|
||
366 | { |
||
367 | if ((bufptr + width) > bufend)
|
||
368 | width = bufend - bufptr; |
||
369 | |||
370 | if (slen > width)
|
||
371 | slen = width; |
||
372 | |||
373 | if (sign == '-') |
||
374 | { |
||
375 | strncpy(bufptr, s, (size_t)slen); |
||
376 | memset(bufptr + slen, ' ', (size_t)(width - slen));
|
||
377 | } |
||
378 | else
|
||
379 | { |
||
380 | memset(bufptr, ' ', (size_t)(width - slen));
|
||
381 | strncpy(bufptr + width - slen, s, (size_t)slen); |
||
382 | } |
||
383 | |||
384 | bufptr += width; |
||
385 | } |
||
386 | break;
|
||
387 | |||
388 | case 'n' : /* Output number of chars so far */ |
||
389 | *(va_arg(ap, int *)) = bytes;
|
||
390 | break;
|
||
391 | } |
||
392 | } |
||
393 | else
|
||
394 | { |
||
395 | bytes ++; |
||
396 | |||
397 | if (bufptr && bufptr < bufend)
|
||
398 | *bufptr++ = *format; |
||
399 | |||
400 | format ++; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | /*
|
||
405 | * Nul-terminate the string and return the number of characters needed.
|
||
406 | */
|
||
407 | |||
408 | *bufptr = '\0';
|
||
409 | |||
410 | return (bytes);
|
||
411 | } |
||
412 | #endif /* !HAVE_VSNPRINTF */ |
||
413 | |||
414 | |||
415 | /*
|
||
416 | * '_mxml_vstrdupf()' - Format and duplicate a string.
|
||
417 | */
|
||
418 | |||
419 | char * /* O - New string pointer */ |
||
420 | _mxml_vstrdupf(const char *format, /* I - Printf-style format string */ |
||
421 | va_list ap) /* I - Pointer to additional arguments */
|
||
422 | { |
||
423 | int bytes; /* Number of bytes required */ |
||
424 | char *buffer, /* String buffer */ |
||
425 | temp[256]; /* Small buffer for first vsnprintf */ |
||
426 | |||
427 | |||
428 | /*
|
||
429 | * First format with a tiny buffer; this will tell us how many bytes are
|
||
430 | * needed...
|
||
431 | */
|
||
432 | |||
433 | bytes = vsnprintf(temp, sizeof(temp), format, ap);
|
||
434 | |||
435 | if (bytes < sizeof(temp)) |
||
436 | { |
||
437 | /*
|
||
438 | * Hey, the formatted string fits in the tiny buffer, so just dup that...
|
||
439 | */
|
||
440 | |||
441 | return (strdup(temp));
|
||
442 | } |
||
443 | |||
444 | /*
|
||
445 | * Allocate memory for the whole thing and reformat to the new, larger
|
||
446 | * buffer...
|
||
447 | */
|
||
448 | |||
449 | if ((buffer = calloc(1, bytes + 1)) != NULL) |
||
450 | vsnprintf(buffer, bytes + 1, format, ap);
|
||
451 | |||
452 | /*
|
||
453 | * Return the new string...
|
||
454 | */
|
||
455 | |||
456 | return (buffer);
|
||
457 | } |
||
458 | |||
459 | |||
460 | /*
|
||
461 | * End of "$Id: mxml-string.c 387 2009-04-18 17:05:52Z mike $".
|
||
462 | */ |