initial load of upstream version 1.06.32
[xmlrpc-c] / lib / util / casprintf.c
diff --git a/lib/util/casprintf.c b/lib/util/casprintf.c
new file mode 100644 (file)
index 0000000..8a56512
--- /dev/null
@@ -0,0 +1,93 @@
+#define _GNU_SOURCE
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "xmlrpc_config.h"  /* For HAVE_ASPRINTF, __inline__ */
+#include "casprintf.h"
+
+
+
+static __inline__ void
+simpleVasprintf(char **      const retvalP,
+                const char * const fmt,
+                va_list            varargs) {
+/*----------------------------------------------------------------------------
+   This is a poor man's implementation of vasprintf(), of GNU fame.
+-----------------------------------------------------------------------------*/
+    size_t const initialSize = 4096;
+    char * result;
+
+    result = malloc(initialSize);
+    if (result != NULL) {
+        size_t bytesNeeded;
+        bytesNeeded = vsnprintf(result, initialSize, fmt, varargs);
+        if (bytesNeeded > initialSize) {
+            free(result);
+            result = malloc(bytesNeeded);
+            if (result != NULL)
+                vsnprintf(result, bytesNeeded, fmt, varargs);
+        } else if (bytesNeeded == initialSize) {
+            if (result[initialSize-1] != '\0') {
+                /* This is one of those old systems where vsnprintf()
+                   returns the number of bytes it used, instead of the
+                   number that it needed, and it in fact needed more than
+                   we gave it.  Rather than mess with this highly unlikely
+                   case (old system and string > 4095 characters), we just
+                   treat this like an out of memory failure.
+                */
+                free(result);
+                result = NULL;
+            }
+        }
+    }
+    *retvalP = result;
+}
+
+
+
+const char * const strsol = "[Insufficient memory to build string]";
+
+
+
+void
+cvasprintf(const char ** const retvalP,
+           const char *  const fmt,
+           va_list             varargs) {
+
+    char * string;
+
+#if HAVE_ASPRINTF
+    vasprintf(&string, fmt, varargs);
+#else
+    simpleVasprintf(&string, fmt, varargs);
+#endif
+
+    if (string == NULL)
+        *retvalP = strsol;
+    else
+        *retvalP = string;
+}
+
+
+
+void GNU_PRINTF_ATTR(2,3)
+casprintf(const char ** const retvalP, const char * const fmt, ...) {
+
+    va_list varargs;  /* mysterious structure used by variable arg facility */
+
+    va_start(varargs, fmt); /* start up the mysterious variable arg facility */
+
+    cvasprintf(retvalP, fmt, varargs);
+
+    va_end(varargs);
+}
+
+
+
+void
+strfree(const char * const string) {
+
+    if (string != strsol)
+        free((void *)string);
+}