X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=inline;f=ucw%2Fff-printf.c;h=09a6d432943ee5534cdffba9fdb3bca2e38b6030;hb=cc0f9b973f4a16a6228249f17f6fce209a0f56c4;hp=8e59f2ffbf1ff191e848fb086eda2c71c1e9b042;hpb=fa7aa6d9457616ce28f97c83eaa616d0ff276870;p=libucw.git diff --git a/ucw/ff-printf.c b/ucw/ff-printf.c index 8e59f2ff..09a6d432 100644 --- a/ucw/ff-printf.c +++ b/ucw/ff-printf.c @@ -1,7 +1,7 @@ /* * UCW Library -- Printf on Fastbuf Streams * - * (c) 2002--2005 Martin Mares + * (c) 2002--2013 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -9,52 +9,57 @@ #include #include +#include #include +#include #include int vbprintf(struct fastbuf *b, const char *msg, va_list args) { byte *buf; - int len, r; + int remains, len; va_list args2; - len = bdirect_write_prepare(b, &buf); - if (len >= 16) + va_copy(args2, args); + remains = bdirect_write_prepare(b, &buf); + len = vsnprintf(buf, remains, msg, args2); + va_end(args2); + + if (len <= remains) { - va_copy(args2, args); - r = vsnprintf(buf, len, msg, args2); - va_end(args2); - if (r < 0) - len = 256; - else if (r < len) - { - bdirect_write_commit(b, buf+r); - return r; - } - else - len = r+1; + bdirect_write_commit(b, buf + len); + return len; } + + /* + * We need a temporary buffer. If it is small, let's use stack. + * Otherwise, we malloc it, but we have to be careful, since we + * might be running inside a transaction and bwrite() could + * throw an exception. + * + * FIXME: This deserves a more systematic solution, the same + * problem is likely to happen at other places, too. + */ + int bufsize = len + 1; + struct resource *res = NULL; + byte *extra_buffer = NULL; + if (bufsize <= 256) + buf = alloca(bufsize); + else if (rp_current()) + buf = res_malloc(bufsize, &res); else - len = 256; + buf = extra_buffer = xmalloc(bufsize); - while (1) - { - buf = alloca(len); - va_copy(args2, args); - r = vsnprintf(buf, len, msg, args2); - va_end(args2); - if (r < 0) - len += len; - else if (r < len) - { - bwrite(b, buf, r); - return r; - } - else - len = r+1; - } + vsnprintf(buf, bufsize, msg, args); + bwrite(b, buf, len); + + if (res) + res_free(res); + else if (extra_buffer) + xfree(extra_buffer); + return len; } int