diff --git a/Makefile.in b/Makefile.in
index ad54720e..d923d507 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -101,6 +101,7 @@ C_SRCS := $(srcroot)src/jemalloc.c \
$(srcroot)src/bin.c \
$(srcroot)src/bin_info.c \
$(srcroot)src/bitmap.c \
+ $(srcroot)src/buf_writer.c \
$(srcroot)src/ckh.c \
$(srcroot)src/ctl.c \
$(srcroot)src/div.c \
diff --git a/include/jemalloc/internal/buf_writer.h b/include/jemalloc/internal/buf_writer.h
new file mode 100644
index 00000000..013bbf5d
--- /dev/null
+++ b/include/jemalloc/internal/buf_writer.h
@@ -0,0 +1,24 @@
+#ifndef JEMALLOC_INTERNAL_BUF_WRITER_H
+#define JEMALLOC_INTERNAL_BUF_WRITER_H
+
+/*
+ * Note: when using the buffered writer, cbopaque is passed to write_cb only
+ * when the buffer is flushed. It would make a difference if cbopaque points
+ * to something that's changing for each write_cb call, or something that
+ * affects write_cb in a way dependent on the content of the output string.
+ * However, the most typical usage case in practice is that cbopaque points to
+ * some "option like" content for the write_cb, so it doesn't matter.
+ */
+
+typedef struct {
+ void (*write_cb)(void *, const char *);
+ void *cbopaque;
+ char *buf;
+ size_t buf_size; /* must be one less than the capacity of buf array */
+ size_t buf_end;
+} buf_write_arg_t;
+
+void buf_write_flush(buf_write_arg_t *arg);
+void buf_write_cb(void *buf_write_arg, const char *s);
+
+#endif /* JEMALLOC_INTERNAL_BUF_WRITER_H */
diff --git a/include/jemalloc/internal/malloc_io.h b/include/jemalloc/internal/malloc_io.h
index dabcb198..fac63612 100644
--- a/include/jemalloc/internal/malloc_io.h
+++ b/include/jemalloc/internal/malloc_io.h
@@ -40,6 +40,7 @@
*/
#define MALLOC_PRINTF_BUFSIZE 4096
+void wrtmessage(void *cbopaque, const char *s);
int buferror(int err, char *buf, size_t buflen);
uintmax_t malloc_strtoumax(const char *restrict nptr, char **restrict endptr,
int base);
@@ -99,29 +100,4 @@ malloc_read_fd(int fd, void *buf, size_t count) {
return (ssize_t)result;
}
-/******************************************************************************/
-
-/*
- * The rest is buffered writing utility.
- *
- * The only difference when using the buffered writer is that cbopaque is
- * passed to write_cb only when the buffer is flushed. It would make a
- * difference if cbopaque points to something that's changing for each write_cb
- * call, or something that affects write_cb in a way dependent on the content
- * of the output string. However, the most typical usage case in practice is
- * that cbopaque points to some "option like" content for the write_cb, so it
- * doesn't matter.
- */
-
-typedef struct {
- void (*write_cb)(void *, const char *);
- void *cbopaque;
- char *buf;
- size_t buf_size; /* must be one less than the capacity of buf array */
- size_t buf_end;
-} buf_write_arg_t;
-
-void buf_write_flush(buf_write_arg_t *arg);
-void buf_write_cb(void *buf_write_arg, const char *s);
-
#endif /* JEMALLOC_INTERNAL_MALLOC_IO_H */
diff --git a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj
index f9af3ddd..4b25b856 100644
--- a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj
+++ b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj
@@ -41,6 +41,7 @@
+
diff --git a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters
index 90f8831d..73ee8d1d 100644
--- a/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters
+++ b/msvc/projects/vc2015/jemalloc/jemalloc.vcxproj.filters
@@ -22,6 +22,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj
index 4ca484ac..ed6f618d 100644
--- a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj
+++ b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj
@@ -41,6 +41,7 @@
+
diff --git a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters
index 90f8831d..73ee8d1d 100644
--- a/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters
+++ b/msvc/projects/vc2017/jemalloc/jemalloc.vcxproj.filters
@@ -22,6 +22,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/src/buf_writer.c b/src/buf_writer.c
new file mode 100644
index 00000000..41065946
--- /dev/null
+++ b/src/buf_writer.c
@@ -0,0 +1,36 @@
+#define JEMALLOC_BUF_WRITER_C_
+#include "jemalloc/internal/jemalloc_preamble.h"
+#include "jemalloc/internal/jemalloc_internal_includes.h"
+
+#include "jemalloc/internal/buf_writer.h"
+#include "jemalloc/internal/malloc_io.h"
+
+void
+buf_write_flush(buf_write_arg_t *arg) {
+ assert(arg->buf_end <= arg->buf_size);
+ arg->buf[arg->buf_end] = '\0';
+ if (arg->write_cb == NULL) {
+ arg->write_cb = je_malloc_message != NULL ?
+ je_malloc_message : wrtmessage;
+ }
+ arg->write_cb(arg->cbopaque, arg->buf);
+ arg->buf_end = 0;
+}
+
+void
+buf_write_cb(void *buf_write_arg, const char *s) {
+ buf_write_arg_t *arg = (buf_write_arg_t *)buf_write_arg;
+ size_t i, slen, n, s_remain, buf_remain;
+ assert(arg->buf_end <= arg->buf_size);
+ for (i = 0, slen = strlen(s); i < slen; i += n) {
+ if (arg->buf_end == arg->buf_size) {
+ buf_write_flush(arg);
+ }
+ s_remain = slen - i;
+ buf_remain = arg->buf_size - arg->buf_end;
+ n = s_remain < buf_remain ? s_remain : buf_remain;
+ memcpy(arg->buf + arg->buf_end, s + i, n);
+ arg->buf_end += n;
+ }
+ assert(i == slen);
+}
diff --git a/src/jemalloc.c b/src/jemalloc.c
index 0a95b3b1..e54c49b0 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -4,6 +4,7 @@
#include "jemalloc/internal/assert.h"
#include "jemalloc/internal/atomic.h"
+#include "jemalloc/internal/buf_writer.h"
#include "jemalloc/internal/ctl.h"
#include "jemalloc/internal/extent_dss.h"
#include "jemalloc/internal/extent_mmap.h"
diff --git a/src/malloc_io.c b/src/malloc_io.c
index cfefcacb..4b7d2e4a 100644
--- a/src/malloc_io.c
+++ b/src/malloc_io.c
@@ -53,7 +53,6 @@
/******************************************************************************/
/* Function prototypes for non-inline static functions. */
-static void wrtmessage(void *cbopaque, const char *s);
#define U2S_BUFSIZE ((1U << (LG_SIZEOF_INTMAX_T + 3)) + 1)
static char *u2s(uintmax_t x, unsigned base, bool uppercase, char *s,
size_t *slen_p);
@@ -68,7 +67,7 @@ static char *x2s(uintmax_t x, bool alt_form, bool uppercase, char *s,
/******************************************************************************/
/* malloc_message() setup. */
-static void
+void
wrtmessage(void *cbopaque, const char *s) {
malloc_write_fd(STDERR_FILENO, s, strlen(s));
}
@@ -664,36 +663,6 @@ malloc_printf(const char *format, ...) {
va_end(ap);
}
-void
-buf_write_flush(buf_write_arg_t *arg) {
- assert(arg->buf_end <= arg->buf_size);
- arg->buf[arg->buf_end] = '\0';
- if (arg->write_cb == NULL) {
- arg->write_cb = je_malloc_message != NULL ?
- je_malloc_message : wrtmessage;
- }
- arg->write_cb(arg->cbopaque, arg->buf);
- arg->buf_end = 0;
-}
-
-void
-buf_write_cb(void *buf_write_arg, const char *s) {
- buf_write_arg_t *arg = (buf_write_arg_t *)buf_write_arg;
- size_t i, slen, n, s_remain, buf_remain;
- assert(arg->buf_end <= arg->buf_size);
- for (i = 0, slen = strlen(s); i < slen; i += n) {
- if (arg->buf_end == arg->buf_size) {
- buf_write_flush(arg);
- }
- s_remain = slen - i;
- buf_remain = arg->buf_size - arg->buf_end;
- n = s_remain < buf_remain ? s_remain : buf_remain;
- memcpy(arg->buf + arg->buf_end, s + i, n);
- arg->buf_end += n;
- }
- assert(i == slen);
-}
-
/*
* Restore normal assertion macros, in order to make it possible to compile all
* C files as a single concatenation.
diff --git a/src/prof_log.c b/src/prof_log.c
index e3d21af2..d0b798de 100644
--- a/src/prof_log.c
+++ b/src/prof_log.c
@@ -3,6 +3,7 @@
#include "jemalloc/internal/jemalloc_internal_includes.h"
#include "jemalloc/internal/assert.h"
+#include "jemalloc/internal/buf_writer.h"
#include "jemalloc/internal/ckh.h"
#include "jemalloc/internal/emitter.h"
#include "jemalloc/internal/hash.h"
diff --git a/src/prof_recent.c b/src/prof_recent.c
index f4cad097..a1f71ea1 100644
--- a/src/prof_recent.c
+++ b/src/prof_recent.c
@@ -3,6 +3,7 @@
#include "jemalloc/internal/jemalloc_internal_includes.h"
#include "jemalloc/internal/assert.h"
+#include "jemalloc/internal/buf_writer.h"
#include "jemalloc/internal/emitter.h"
#include "jemalloc/internal/prof_data.h"
#include "jemalloc/internal/prof_recent.h"
diff --git a/test/unit/buf_writer.c b/test/unit/buf_writer.c
index 5051f76a..bbdb657e 100644
--- a/test/unit/buf_writer.c
+++ b/test/unit/buf_writer.c
@@ -1,5 +1,7 @@
#include "test/jemalloc_test.h"
+#include "jemalloc/internal/buf_writer.h"
+
#define TEST_BUF_SIZE 16
#define UNIT_MAX (TEST_BUF_SIZE * 3)