88 lines
1.8 KiB
88 lines
1.8 KiB
3 months ago
|
/*
|
||
|
* UCW Library -- Printf on Fastbuf Streams
|
||
|
*
|
||
|
* (c) 2002--2013 Martin Mares <mj@ucw.cz>
|
||
|
*
|
||
|
* 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 <ucw/resource.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <alloca.h>
|
||
|
|
||
|
int
|
||
|
vbprintf(struct fastbuf *b, const char *msg, va_list args)
|
||
|
{
|
||
|
byte *buf;
|
||
|
int remains, len;
|
||
|
va_list args2;
|
||
|
|
||
|
va_copy(args2, args);
|
||
|
remains = bdirect_write_prepare(b, &buf);
|
||
|
len = vsnprintf(buf, remains, msg, args2);
|
||
|
va_end(args2);
|
||
|
|
||
|
if (len < remains)
|
||
|
{
|
||
|
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
|
||
|
buf = extra_buffer = xmalloc(bufsize);
|
||
|
|
||
|
vsnprintf(buf, bufsize, msg, args);
|
||
|
bwrite(b, buf, len);
|
||
|
|
||
|
if (res)
|
||
|
res_free(res);
|
||
|
else if (extra_buffer)
|
||
|
xfree(extra_buffer);
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
bprintf(struct fastbuf *b, const char *msg, ...)
|
||
|
{
|
||
|
va_list args;
|
||
|
int res;
|
||
|
|
||
|
va_start(args, msg);
|
||
|
res = vbprintf(b, msg, args);
|
||
|
va_end(args);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
#ifdef TEST
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
struct fastbuf *b = bfdopen_shared(1, 65536);
|
||
|
for (int i=0; i<10000; i++)
|
||
|
bprintf(b, "13=%d str=<%s> msg=%m\n", 13, "str");
|
||
|
bclose(b);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif
|