-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Andrew Dunbar:
Hmm currently I'm using _vscprintf / vsprintf on
Windows/MSVC inside
#ifdef _WIN32
and vasprintf Ubuntu/gcc inside #else
But my C-fu is to puny to figure out what #ifdefs to
use to detect
what combination of C compiler and libc I'm compiling under.
Apparently it's important with snprintf since some
implementations
return "an unspecified return value less than 1" with size=0.
That's true, but no current Unix implementation should do that, since
the return value of snprintf() is standardised in the current POSIX
standard (IEEE 1003.1-2004) and in the C99 standard (ISO/IEC 9899:1999).
The following code should handle Windows and both old and new Unix,
although it's completely untested and comes with no warranty:
/* Compile with "-D_XOPEN_SOURCE=600 -std=c99" */
int
my_vasprintf(char **res, char const *fmt, va_list args)
{
int sz, r;
#ifdef _WIN32
sz = _vscprintf(fmt, args);
#else
sz = snprintf(NULL, 0, fmt, args);
#endif
#if defined(_WIN32) || (defined(__STDC__) && __STDC__ >= 199901L) \
|| (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 600))
if (sz < 0)
return sz;
if (sz >= 0) {
#else
if (sz >= 1) {
#endif
if ((*res = malloc(sz + 1)) == NULL)
return -1;
if ((sz = sprintf(*res, fmt, args)) < 0) {
free(*res);
*res = NULL;
}
return sz;
}
#define MAXLN 65535
*res = NULL;
for (sz = 128; sz <= MAXLN; sz *= 2) {
if ((*res = realloc(*res, sz)) == NULL)
return -1;
r = vsnprintf(*res, sz, fmt, args);
if (r > 0 && r < sz)
return r;
}
errno = ENOMEM;
if (*res) {
free(*res);
*res = NULL;
}
return -1;
}
Obviously, this will be slower than the modern implementation, and you
may want to tune the initial buffer size for the expected string length.
- river.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (SunOS)
iEYEARECAAYFAk2i0QcACgkQIXd7fCuc5vI1ewCfTdlavg0rr56l7JzwAe5Oea9x
55sAnA4MIosJLfOnD/O3z/nkq0yqD5CE
=AGMe
-----END PGP SIGNATURE-----