commit 80831e50b967c8475f1fcc0e19e3aa992f9eb242
parent 0079ec774a6e79b417a1f2daa1220d1c5df6e5b8
Author: Oswald Buddenhagen <ossi@users.sf.net>
Date: Thu, 9 Jun 2022 14:25:39 +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.
Diffstat:
3 files changed, 46 insertions(+), 4 deletions(-)
diff --git 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
@@ -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
@@ -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 )
{