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

Reply via email to