123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #define _XOPEN_SOURCE 600 /* Make sure strdup() is in <string.h> */
- #ifdef __APPLE__
- #define _DARWIN_C_SOURCE
- #endif
- #ifndef _GNU_SOURCE
- #define _GNU_SOURCE /* But only when HAVE_ASPRINTF */
- #endif
- #include <stdarg.h>
- #include <stdarg.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <limits.h>
- #include "xmlrpc_config.h" /* For HAVE_ASPRINTF, __inline__ */
- #include "xmlrpc-c/string_int.h"
- #include "bool.h"
- static __inline__ void
- newVsnprintf(char * const buffer,
- size_t const bufferSize,
- const char * const fmt,
- va_list varargs,
- size_t * const formattedSizeP) {
- /*----------------------------------------------------------------------------
- This is vsnprintf() with the new behavior, where not fitting in the buffer
- is not a failure.
- Unfortunately, we can't practically return the size of the formatted string
- if the C library has old vsnprintf() and the formatted string doesn't fit
- in the buffer, so in that case we just return something larger than the
- buffer.
- -----------------------------------------------------------------------------*/
- if (bufferSize > INT_MAX/2) {
- /* There's a danger we won't be able to coerce the return value
- of XMLRPC_VSNPRINTF to an integer (which we have to do because,
- while for POSIX its return value is ssize_t, on Windows it is int),
- or return double the buffer size.
- */
- *formattedSizeP = 0;
- } else {
- int rc;
- rc = XMLRPC_VSNPRINTF(buffer, bufferSize, fmt, varargs);
- if (rc < 0) {
- /* We have old vsnprintf() (or Windows) and the formatted value
- doesn't fit in the buffer, but we don't know how big a buffer it
- needs.
- */
- *formattedSizeP = bufferSize * 2;
- } else {
- /* Either the string fits in the buffer or we have new vsnprintf()
- which tells us how big the string is regardless.
- */
- *formattedSizeP = rc;
- }
- }
- }
- 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.
- -----------------------------------------------------------------------------*/
- char * result;
- size_t bufferSize;
- bool outOfMemory;
- for (result = NULL, bufferSize = 4096, outOfMemory = false;
- !result && !outOfMemory;
- ) {
- result = malloc(bufferSize);
- if (!result)
- outOfMemory = true;
- else {
- size_t bytesNeeded;
- newVsnprintf(result, bufferSize, fmt, varargs, &bytesNeeded);
- if (bytesNeeded > bufferSize) {
- free(result);
- result = NULL;
- bufferSize = bytesNeeded;
- }
- }
- }
- *retvalP = result;
- }
- static const char * const xmlrpc_strsol =
- "[insufficient memory to build string]";
- bool
- xmlrpc_strnomem(const char * const string) {
- /*----------------------------------------------------------------------------
- The string 'string' was generated by a function in this file because it
- couldn't get enough memory to generate the string that it was supposed to
- generate. I.e. a preceding call to a string function failed.
- -----------------------------------------------------------------------------*/
- return string == xmlrpc_strsol;
- }
- const char *
- xmlrpc_strnomemval() {
- return xmlrpc_strsol;
- }
- void
- xmlrpc_vasprintf(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 = xmlrpc_strsol;
- else
- *retvalP = string;
- }
- void XMLRPC_PRINTF_ATTR(2,3)
- xmlrpc_asprintf(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 */
- xmlrpc_vasprintf(retvalP, fmt, varargs);
- va_end(varargs);
- }
- const char *
- xmlrpc_strdupsol(const char * const string) {
- const char * retvalOrNull;
- retvalOrNull = strdup(string);
- return retvalOrNull ? retvalOrNull : xmlrpc_strsol;
- }
- void
- xmlrpc_strfree(const char * const string) {
- if (string != xmlrpc_strsol)
- free((void *)string);
- }
- const char *
- xmlrpc_strdupnull(const char * const string) {
- if (string)
- return strdup(string);
- else
- return NULL;
- }
- void
- xmlrpc_strfreenull(const char * const string) {
- if (string)
- xmlrpc_strfree(string);
- }
|