X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ucw%2Fff-printf.c;h=f2ef8f3244b33ae5888af7f78e128b15b9043d82;hb=564be9c0adf9f5796b60f2727cecc9c7274f86ff;hp=ad80e413d58ebef9281689b1cd4e81faed621c36;hpb=a4fe009d3366b0a3e119713b0ecc7fc0070efdfa;p=libucw.git diff --git a/ucw/ff-printf.c b/ucw/ff-printf.c index ad80e413..f2ef8f32 100644 --- a/ucw/ff-printf.c +++ b/ucw/ff-printf.c @@ -1,14 +1,15 @@ /* * 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. */ -#include "ucw/lib.h" -#include "ucw/fastbuf.h" +#include +#include +#include #include #include @@ -17,44 +18,47 @@ 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