initial load of upstream version 1.06.32
[xmlrpc-c] / lib / util / casprintf.c
1 #define _GNU_SOURCE
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #include "xmlrpc_config.h"  /* For HAVE_ASPRINTF, __inline__ */
7 #include "casprintf.h"
8
9
10
11 static __inline__ void
12 simpleVasprintf(char **      const retvalP,
13                 const char * const fmt,
14                 va_list            varargs) {
15 /*----------------------------------------------------------------------------
16    This is a poor man's implementation of vasprintf(), of GNU fame.
17 -----------------------------------------------------------------------------*/
18     size_t const initialSize = 4096;
19     char * result;
20
21     result = malloc(initialSize);
22     if (result != NULL) {
23         size_t bytesNeeded;
24         bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
25         if (bytesNeeded > initialSize) {
26             free(result);
27             result = malloc(bytesNeeded);
28             if (result != NULL)
29                 vsnprintf(result, bytesNeeded, fmt, varargs);
30         } else if (bytesNeeded == initialSize) {
31             if (result[initialSize-1] != '\0') {
32                 /* This is one of those old systems where vsnprintf()
33                    returns the number of bytes it used, instead of the
34                    number that it needed, and it in fact needed more than
35                    we gave it.  Rather than mess with this highly unlikely
36                    case (old system and string > 4095 characters), we just
37                    treat this like an out of memory failure.
38                 */
39                 free(result);
40                 result = NULL;
41             }
42         }
43     }
44     *retvalP = result;
45 }
46
47
48
49 const char * const strsol = "[Insufficient memory to build string]";
50
51
52
53 void
54 cvasprintf(const char ** const retvalP,
55            const char *  const fmt,
56            va_list             varargs) {
57
58     char * string;
59
60 #if HAVE_ASPRINTF
61     vasprintf(&string, fmt, varargs);
62 #else
63     simpleVasprintf(&string, fmt, varargs);
64 #endif
65
66     if (string == NULL)
67         *retvalP = strsol;
68     else
69         *retvalP = string;
70 }
71
72
73
74 void GNU_PRINTF_ATTR(2,3)
75 casprintf(const char ** const retvalP, const char * const fmt, ...) {
76
77     va_list varargs;  /* mysterious structure used by variable arg facility */
78
79     va_start(varargs, fmt); /* start up the mysterious variable arg facility */
80
81     cvasprintf(retvalP, fmt, varargs);
82
83     va_end(varargs);
84 }
85
86
87
88 void
89 strfree(const char * const string) {
90
91     if (string != strsol)
92         free((void *)string);
93 }