]> mj.ucw.cz Git - libucw.git/commitdiff
Fastbuf: Rewritten bprintf()
authorMartin Mares <mj@ucw.cz>
Thu, 17 Oct 2013 14:00:16 +0000 (16:00 +0200)
committerMartin Mares <mj@ucw.cz>
Thu, 17 Oct 2013 14:00:16 +0000 (16:00 +0200)
The new version prints directly to the stream buffer, avoiding
unnecessary copies in the common case. Also, only small buffers
are allocated on the stack.

ucw/ff-printf.c

index 8e59f2ffbf1ff191e848fb086eda2c71c1e9b042..903508cfa10c8d43e7de569d16adbc4dfacf01be 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     UCW Library -- Printf on Fastbuf Streams
  *
- *     (c) 2002--2005 Martin Mares <mj@ucw.cz>
+ *     (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/fastbuf.h>
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <alloca.h>
 
 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;
     }
-  else
-    len = 256;
 
-  while (1)
+  int bufsize = len + 1;
+  bool need_free = 0;
+  if (bufsize <= 256)
+    buf = alloca(bufsize);
+  else
     {
-      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;
+      buf = xmalloc(bufsize);
+      need_free = 1;
     }
+
+  vsnprintf(buf, bufsize, msg, args);
+  bwrite(b, buf, len);
+
+  if (need_free)
+    xfree(buf);
+  return len;
 }
 
 int