On 11 April 2011 19:59, River Tarnell <river.tarn...@wikimedia.de> wrote: > -----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.
Thanks River, that's really helpful! Andrew Dunbar (hippietrail) > - river. > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.11 (SunOS) > > iEYEARECAAYFAk2i0QcACgkQIXd7fCuc5vI1ewCfTdlavg0rr56l7JzwAe5Oea9x > 55sAnA4MIosJLfOnD/O3z/nkq0yqD5CE > =AGMe > -----END PGP SIGNATURE----- > > _______________________________________________ > Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org) > https://lists.wikimedia.org/mailman/listinfo/toolserver-l > Posting guidelines for this list: > https://wiki.toolserver.org/view/Mailing_list_etiquette > _______________________________________________ Toolserver-l mailing list (Toolserver-l@lists.wikimedia.org) https://lists.wikimedia.org/mailman/listinfo/toolserver-l Posting guidelines for this list: https://wiki.toolserver.org/view/Mailing_list_etiquette