]> mj.ucw.cz Git - libucw.git/blob - ucw/ff-printf.c
Maint: Moved ABI tools to maint/
[libucw.git] / ucw / ff-printf.c
1 /*
2  *      UCW Library -- Printf on Fastbuf Streams
3  *
4  *      (c) 2002--2013 Martin Mares <mj@ucw.cz>
5  *
6  *      This software may be freely distributed and used according to the terms
7  *      of the GNU Lesser General Public License.
8  */
9
10 #include <ucw/lib.h>
11 #include <ucw/fastbuf.h>
12 #include <ucw/resource.h>
13
14 #include <stdio.h>
15 #include <alloca.h>
16
17 int
18 vbprintf(struct fastbuf *b, const char *msg, va_list args)
19 {
20   byte *buf;
21   int remains, len;
22   va_list args2;
23
24   va_copy(args2, args);
25   remains = bdirect_write_prepare(b, &buf);
26   len = vsnprintf(buf, remains, msg, args2);
27   va_end(args2);
28
29   if (len <= remains)
30     {
31       bdirect_write_commit(b, buf + len);
32       return len;
33     }
34
35   /*
36    *  We need a temporary buffer. If it is small, let's use stack.
37    *  Otherwise, we malloc it, but we have to be careful, since we
38    *  might be running inside a transaction and bwrite() could
39    *  throw an exception.
40    *
41    *  FIXME: This deserves a more systematic solution, the same
42    *  problem is likely to happen at other places, too.
43    */
44   int bufsize = len + 1;
45   struct resource *res = NULL;
46   byte *extra_buffer = NULL;
47   if (bufsize <= 256)
48     buf = alloca(bufsize);
49   else if (rp_current())
50     buf = res_malloc(bufsize, &res);
51   else
52     buf = extra_buffer = xmalloc(bufsize);
53
54   vsnprintf(buf, bufsize, msg, args);
55   bwrite(b, buf, len);
56
57   if (res)
58     res_free(res);
59   else if (extra_buffer)
60     xfree(extra_buffer);
61   return len;
62 }
63
64 int
65 bprintf(struct fastbuf *b, const char *msg, ...)
66 {
67   va_list args;
68   int res;
69
70   va_start(args, msg);
71   res = vbprintf(b, msg, args);
72   va_end(args);
73   return res;
74 }
75
76 #ifdef TEST
77
78 int main(void)
79 {
80   struct fastbuf *b = bfdopen_shared(1, 65536);
81   for (int i=0; i<10000; i++)
82     bprintf(b, "13=%d str=<%s> msg=%m\n", 13, "str");
83   bclose(b);
84   return 0;
85 }
86
87 #endif