commit 80831e50b967c8475f1fcc0e19e3aa992f9eb242
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Thu Jun 9 14:25:39 2022 +0200

    add xprintf()
    
    this introduces a "commit" callback to the xprintf kernel, to avoid
    pointlessly assembling a temporary output string prior to printing it.
    
    one could lift the buffer limitations by introducing a "segment"
    callback instead, but that would slow down xvasprintf() due to the
    higher callback rate, for no good reason.

 configure.ac |  2 +-
 src/common.h |  1 +
 src/util.c   | 47 ++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5922126b..3b9b145d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -83,7 +83,7 @@ if test "x$ob_cv_strftime_z" = x"no"; then
 fi
 
 AC_CHECK_HEADERS(poll.h sys/select.h)
-AC_CHECK_FUNCS(vasprintf strnlen memrchr timegm)
+AC_CHECK_FUNCS(vasprintf strnlen memrchr timegm fwrite_unlocked)
 
 AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"])
 AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
diff --git a/src/common.h b/src/common.h
index f4810604..c7ad08c5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -166,6 +166,7 @@ void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... );
 void flushn( void );
 
 char *xvasprintf( const char *fmt, va_list ap );
+void xprintf( const char *fmt, ... );
 
 #if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0
 # define fdatasync fsync
diff --git a/src/util.c b/src/util.c
index 9e5af7e3..aa8f28a2 100644
--- a/src/util.c
+++ b/src/util.c
@@ -198,8 +198,10 @@ sys_error( const char *msg, ... )
 #define QPRINTF_SEGS 16
 #define QPRINTF_BUFF 1000
 
-char *
-xvasprintf( const char *fmt, va_list ap )
+typedef void (*printf_cb)( const char **segs, uint *segls, int nsegs, uint 
totlen, void *aux );
+
+static void
+xvprintf_core( const char *fmt, va_list ap, printf_cb cb, void *cb_aux )
 {
        int nsegs = 0;
        uint totlen = 0;
@@ -320,15 +322,54 @@ xvasprintf( const char *fmt, va_list ap )
                        fmt++;
                }
        }
-       char *out = d = nfmalloc( totlen + 1 );
+       cb( segs, segls, nsegs, totlen, cb_aux );
+}
+
+static void
+xasprintf_cb( const char **segs, uint *segls, int nsegs, uint totlen, void 
*aux )
+{
+       char *d = nfmalloc( totlen + 1 );
+       *(char **)aux = d;
        for (int i = 0; i < nsegs; i++) {
                memcpy( d, segs[i], segls[i] );
                d += segls[i];
        }
        *d = 0;
+}
+
+char *
+xvasprintf( const char *fmt, va_list ap )
+{
+       char *out;
+       xvprintf_core( fmt, ap, xasprintf_cb, &out );
        return out;
 }
 
+#ifndef HAVE_FWRITE_UNLOCKED
+# define flockfile(f)
+# define funlockfile(f)
+# define fwrite_unlocked(b, l, n, f) fwrite(b, l, n, f)
+#endif
+
+static void
+xprintf_cb( const char **segs, uint *segls, int nsegs, uint totlen 
ATTR_UNUSED, void *aux ATTR_UNUSED )
+{
+       flockfile( stdout );
+       for (int i = 0; i < nsegs; i++)
+               fwrite_unlocked( segs[i], 1, segls[i], stdout );
+       funlockfile( stdout );
+}
+
+void
+xprintf( const char *fmt, ... )
+{
+       va_list va;
+
+       va_start( va, fmt );
+       xvprintf_core( fmt, va, xprintf_cb, NULL );
+       va_end( va );
+}
+
 void
 vFprintf( FILE *f, const char *msg, va_list va )
 {


_______________________________________________
isync-devel mailing list
isync-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/isync-devel

Reply via email to