[libc-commits] [libc] [libc] Refactor static polymorphism in WriteBuffer (NFC). (PR #169089)
Alexey Samsonov via libc-commits
libc-commits at lists.llvm.org
Fri Nov 21 11:55:20 PST 2025
https://github.com/vonosmas created https://github.com/llvm/llvm-project/pull/169089
There are three flavors of WriteBuffer currently, all of which could be passed into `printf_core::Writer` class. It's a tricky class, since it chooses a flavor-specific logic either based on runtime dispatch (to save code size and prevent generating three versions of the entirety of printf_core), or based on template arguments (to avoid dealing with function pointers in codegen for `FILL_BUFF_AND_DROP_OVERFLOW` path).
Refactor this somewhat convoluted logic to have three concrete subclasses inheriting from the templated base class, and use static polymorphism with `reinterpret_cast` to implement dispatching above. Now we can actually have flavor-specific fields, constructors, and methods (e.g. `flush_to_stream` is now a method of `FlushingBuffer`), and the code on the user side is cleaner: the complexity of enabling/disabling runtime-dispatch and using proper template arguments is now localized in `writer.h`.
This code will need to be further templatized to support buffers of type `wchar_t` to implement `swprintf()` and friends. This change would make it (ever so slightly) easier.
>From f6522d891d8f9a855bd87e0ab0889156946233db Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Fri, 21 Nov 2025 19:45:34 +0000
Subject: [PATCH] [libc] Refactor static polymorphism in WriteBuffer (NFC).
There are three flavors of WriteBuffer currently, all of which
could be passed into printf_core::Writer class. It's a tricky
class, since it chooses a flavor-specific logic either based
on runtime dispatch (to save code size and prevent
generating three versions of the entirety of printf_core),
or based on template arguments (to avoid dealing with
function pointers in codegen for FILL_BUFF_AND_DROP_OVERFLOW path.
Refactor this somewhat convoluted logic to have three
concrete subclasses inheriting from the templated base
class, and use static polymorphism with reinterpret_cast
to implement dispatching above. Now we can actually
have flavor-specific fields, constructors, and methods
(e.g. "flush_to_stream" is now a method of FlushingBuffer),
and the code on the user side is cleaner: the complexity
of enabling/disabling runtime-dispatch and using proper
template arguments is now localized in writer.h.
This code will need to be further templatized to support
buffers of type wchar_t to implement swprintf() and
friends. This change would make it (ever so slightly) easier.
---
libc/src/__support/RPC/rpc_server.h | 12 +-
libc/src/stdio/baremetal/printf.cpp | 8 +-
libc/src/stdio/baremetal/vprintf.cpp | 8 +-
.../stdio/printf_core/vasprintf_internal.h | 10 +-
.../src/stdio/printf_core/vfprintf_internal.h | 6 +-
libc/src/stdio/printf_core/writer.h | 154 +++++++++++-------
libc/src/stdio/snprintf.cpp | 4 +-
libc/src/stdio/sprintf.cpp | 5 +-
libc/src/stdio/vsnprintf.cpp | 4 +-
libc/src/stdio/vsprintf.cpp | 5 +-
libc/src/stdlib/strfromd.cpp | 4 +-
libc/src/stdlib/strfromf.cpp | 4 +-
libc/src/stdlib/strfroml.cpp | 4 +-
libc/src/time/strftime.cpp | 4 +-
libc/src/time/strftime_l.cpp | 4 +-
.../src/stdio/printf_core/converter_test.cpp | 16 +-
.../src/stdio/printf_core/writer_test.cpp | 64 ++++----
17 files changed, 162 insertions(+), 154 deletions(-)
diff --git a/libc/src/__support/RPC/rpc_server.h b/libc/src/__support/RPC/rpc_server.h
index abd604ae48146..98dc40ecd0a89 100644
--- a/libc/src/__support/RPC/rpc_server.h
+++ b/libc/src/__support/RPC/rpc_server.h
@@ -169,9 +169,7 @@ LIBC_INLINE static void handle_printf(rpc::Server::Port &port,
if (!format[lane])
continue;
- printf_core::WriteBuffer<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
- wb(nullptr, 0);
+ printf_core::DropOverflowBuffer wb(nullptr, 0);
printf_core::Writer writer(wb);
internal::DummyArgList<packed> printf_args;
@@ -198,9 +196,7 @@ LIBC_INLINE static void handle_printf(rpc::Server::Port &port,
if (!format[lane])
continue;
- printf_core::WriteBuffer<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
- wb(nullptr, 0);
+ printf_core::DropOverflowBuffer wb(nullptr, 0);
printf_core::Writer writer(wb);
internal::StructArgList<packed> printf_args(args[lane], args_sizes[lane]);
@@ -262,9 +258,7 @@ LIBC_INLINE static void handle_printf(rpc::Server::Port &port,
continue;
char *buffer = temp_storage.alloc(buffer_size[lane]);
- printf_core::WriteBuffer<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
- wb(buffer, buffer_size[lane]);
+ printf_core::DropOverflowBuffer wb(buffer, buffer_size[lane]);
printf_core::Writer writer(wb);
internal::StructArgList<packed> printf_args(args[lane], args_sizes[lane]);
diff --git a/libc/src/stdio/baremetal/printf.cpp b/libc/src/stdio/baremetal/printf.cpp
index 5a9b19ff20471..2fa9cf7c9f3cd 100644
--- a/libc/src/stdio/baremetal/printf.cpp
+++ b/libc/src/stdio/baremetal/printf.cpp
@@ -41,9 +41,9 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
static constexpr size_t BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
- printf_core::WriteBuffer<printf_core::WriteMode::FLUSH_TO_STREAM> wb(
- buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
- printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);
+ printf_core::FlushingBuffer wb(buffer, BUFF_SIZE, &stdout_write_hook,
+ nullptr);
+ printf_core::Writer writer(wb);
auto retval = printf_core::printf_main(&writer, format, args);
if (!retval.has_value()) {
@@ -51,7 +51,7 @@ LLVM_LIBC_FUNCTION(int, printf, (const char *__restrict format, ...)) {
return -1;
}
- int flushval = wb.overflow_write("");
+ int flushval = wb.flush_to_stream();
if (flushval != printf_core::WRITE_OK) {
libc_errno = printf_core::internal_error_to_errno(-flushval);
return -1;
diff --git a/libc/src/stdio/baremetal/vprintf.cpp b/libc/src/stdio/baremetal/vprintf.cpp
index c172b368d15f3..d89f26cd72b0a 100644
--- a/libc/src/stdio/baremetal/vprintf.cpp
+++ b/libc/src/stdio/baremetal/vprintf.cpp
@@ -39,9 +39,9 @@ LLVM_LIBC_FUNCTION(int, vprintf,
static constexpr size_t BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
- printf_core::WriteBuffer<printf_core::WriteMode::FLUSH_TO_STREAM> wb(
- buffer, BUFF_SIZE, &stdout_write_hook, nullptr);
- printf_core::Writer<printf_core::WriteMode::FLUSH_TO_STREAM> writer(wb);
+ printf_core::FlushingBuffer wb(buffer, BUFF_SIZE, &stdout_write_hook,
+ nullptr);
+ printf_core::Writer writer(wb);
auto retval = printf_core::printf_main(&writer, format, args);
if (!retval.has_value()) {
@@ -49,7 +49,7 @@ LLVM_LIBC_FUNCTION(int, vprintf,
return -1;
}
- int flushval = wb.overflow_write("");
+ int flushval = wb.flush_to_stream();
if (flushval != printf_core::WRITE_OK) {
libc_errno = printf_core::internal_error_to_errno(-flushval);
return -1;
diff --git a/libc/src/stdio/printf_core/vasprintf_internal.h b/libc/src/stdio/printf_core/vasprintf_internal.h
index 41df17b67f35b..db6b95d49aaca 100644
--- a/libc/src/stdio/printf_core/vasprintf_internal.h
+++ b/libc/src/stdio/printf_core/vasprintf_internal.h
@@ -18,10 +18,8 @@
namespace LIBC_NAMESPACE_DECL {
namespace printf_core {
-LIBC_INLINE int resize_overflow_hook(cpp::string_view new_str, void *target) {
- WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> *wb =
- reinterpret_cast<
- WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> *>(target);
+LIBC_INLINE int resize_overflow_hook(cpp::string_view new_str,
+ ResizingBuffer *wb) {
size_t new_size = new_str.size() + wb->buff_cur;
const bool isBuffOnStack = (wb->buff == wb->init_buff);
char *new_buff = static_cast<char *>(
@@ -47,8 +45,8 @@ LIBC_INLINE ErrorOr<size_t> vasprintf_internal(char **ret,
const char *__restrict format,
internal::ArgList args) {
char init_buff_on_stack[DEFAULT_BUFFER_SIZE];
- printf_core::WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> wb(
- init_buff_on_stack, DEFAULT_BUFFER_SIZE, resize_overflow_hook);
+ printf_core::ResizingBuffer wb(init_buff_on_stack, DEFAULT_BUFFER_SIZE,
+ resize_overflow_hook);
printf_core::Writer writer(wb);
auto ret_val = printf_core::printf_main(&writer, format, args);
diff --git a/libc/src/stdio/printf_core/vfprintf_internal.h b/libc/src/stdio/printf_core/vfprintf_internal.h
index c47a03d741f98..321b0693ad339 100644
--- a/libc/src/stdio/printf_core/vfprintf_internal.h
+++ b/libc/src/stdio/printf_core/vfprintf_internal.h
@@ -86,8 +86,8 @@ LIBC_INLINE ErrorOr<size_t> vfprintf_internal(::FILE *__restrict stream,
internal::ArgList &args) {
constexpr size_t BUFF_SIZE = 1024;
char buffer[BUFF_SIZE];
- printf_core::WriteBuffer<Mode<WriteMode::FLUSH_TO_STREAM>::value> wb(
- buffer, BUFF_SIZE, &file_write_hook, reinterpret_cast<void *>(stream));
+ printf_core::FlushingBuffer wb(buffer, BUFF_SIZE, &file_write_hook,
+ reinterpret_cast<void *>(stream));
Writer writer(wb);
internal::flockfile(stream);
auto retval = printf_main(&writer, format, args);
@@ -95,7 +95,7 @@ LIBC_INLINE ErrorOr<size_t> vfprintf_internal(::FILE *__restrict stream,
internal::funlockfile(stream);
return retval;
}
- int flushval = wb.overflow_write("");
+ int flushval = wb.flush_to_stream();
if (flushval != WRITE_OK)
retval = Error(-flushval);
internal::funlockfile(stream);
diff --git a/libc/src/stdio/printf_core/writer.h b/libc/src/stdio/printf_core/writer.h
index 9de108ece510f..cb45b105597d1 100644
--- a/libc/src/stdio/printf_core/writer.h
+++ b/libc/src/stdio/printf_core/writer.h
@@ -38,36 +38,65 @@ template <WriteMode write_mode> struct Mode {
#endif
};
+template <WriteMode write_mode> class Writer;
+
template <WriteMode write_mode> struct WriteBuffer {
- using StreamWriter = int (*)(cpp::string_view, void *);
char *buff;
- const char *init_buff; // for checking when resize.
size_t buff_len;
size_t buff_cur = 0;
-
- // The stream writer will be called when the buffer is full. It will be passed
- // string_views to write to the stream.
- const StreamWriter stream_writer;
- void *output_target;
-
// The current writing mode in case the user wants runtime dispatch of the
// stream writer with function pointers.
[[maybe_unused]] WriteMode write_mode_;
- LIBC_INLINE WriteBuffer(char *buff, size_t buff_len, StreamWriter hook,
- void *target)
- : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(hook),
- output_target(target), write_mode_(WriteMode::FLUSH_TO_STREAM) {}
+protected:
+ LIBC_INLINE WriteBuffer(char *buff, size_t buff_len, WriteMode mode)
+ : buff(buff), buff_len(buff_len), write_mode_(mode) {}
+
+private:
+ friend class Writer<write_mode>;
+ // The overflow_write method will handle the case when adding new_str to
+ // the buffer would overflow it. Specific actions will depend on the buffer
+ // type / write_mode.
+ LIBC_INLINE int overflow_write(cpp::string_view new_str);
+};
+
+// Buffer variant that discards characters that don't fit into the buffer.
+struct DropOverflowBuffer
+ : public WriteBuffer<Mode<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value> {
+ LIBC_INLINE DropOverflowBuffer(char *buff, size_t buff_len)
+ : WriteBuffer<Mode<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>(
+ buff, buff_len, WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) {}
+
+ LIBC_INLINE int fill_remaining_to_buff(cpp::string_view new_str) {
+ if (buff_cur < buff_len) {
+ size_t bytes_to_write = buff_len - buff_cur;
+ if (bytes_to_write > new_str.size()) {
+ bytes_to_write = new_str.size();
+ }
+ inline_memcpy(buff + buff_cur, new_str.data(), bytes_to_write);
+ buff_cur += bytes_to_write;
+ }
+ return WRITE_OK;
+ }
+};
- LIBC_INLINE WriteBuffer(char *buff, size_t buff_len)
- : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(nullptr),
- output_target(nullptr),
- write_mode_(WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) {}
+// Buffer variant that flushes to stream when it gets full.
+struct FlushingBuffer
+ : public WriteBuffer<Mode<WriteMode::FLUSH_TO_STREAM>::value> {
+ // The stream writer will be called when the buffer is full. It will be passed
+ // string_views to write to the stream.
+ using StreamWriter = int (*)(cpp::string_view, void *);
+ const StreamWriter stream_writer;
+ void *output_target;
- LIBC_INLINE WriteBuffer(char *buff, size_t buff_len, StreamWriter hook)
- : buff(buff), init_buff(buff), buff_len(buff_len), stream_writer(hook),
- output_target(this), write_mode_(WriteMode::RESIZE_AND_FILL_BUFF) {}
+ LIBC_INLINE FlushingBuffer(char *buff, size_t buff_len, StreamWriter hook,
+ void *target)
+ : WriteBuffer<Mode<WriteMode::FLUSH_TO_STREAM>::value>(
+ buff, buff_len, WriteMode::FLUSH_TO_STREAM),
+ stream_writer(hook), output_target(target) {}
+ // Flushes the entire current buffer to stream, followed by the new_str (if
+ // non-empty).
LIBC_INLINE int flush_to_stream(cpp::string_view new_str) {
if (buff_cur > 0) {
int retval = stream_writer({buff, buff_cur}, output_target);
@@ -83,48 +112,61 @@ template <WriteMode write_mode> struct WriteBuffer {
return WRITE_OK;
}
- LIBC_INLINE int fill_remaining_to_buff(cpp::string_view new_str) {
- if (buff_cur < buff_len) {
- size_t bytes_to_write = buff_len - buff_cur;
- if (bytes_to_write > new_str.size()) {
- bytes_to_write = new_str.size();
- }
- inline_memcpy(buff + buff_cur, new_str.data(), bytes_to_write);
- buff_cur += bytes_to_write;
- }
- return WRITE_OK;
- }
+ LIBC_INLINE int flush_to_stream() { return flush_to_stream({}); }
+};
- LIBC_INLINE int resize_and_write(cpp::string_view new_str) {
- return stream_writer(new_str, output_target);
- }
+// Buffer variant that calls a resizing callback when it gets full.
+struct ResizingBuffer
+ : public WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value> {
+ using ResizeWriter = int (*)(cpp::string_view, ResizingBuffer *);
+ const ResizeWriter resize_writer;
+ const char *init_buff; // for checking when resize.
- // The overflow_write method is intended to be called to write the contents of
- // the buffer and new_str to the stream_writer if it exists. If a resizing
- // hook is provided, it will resize the buffer and write the contents. If
- // neither a stream_writer nor a resizing hook is provided, it will fill the
- // remaining space in the buffer with new_str and drop the overflow. Calling
- // this with an empty string will flush the buffer if relevant.
-
- LIBC_INLINE int overflow_write(cpp::string_view new_str) {
- if constexpr (write_mode == WriteMode::RUNTIME_DISPATCH) {
- if (write_mode_ == WriteMode::FILL_BUFF_AND_DROP_OVERFLOW)
- return fill_remaining_to_buff(new_str);
- else if (write_mode_ == WriteMode::FLUSH_TO_STREAM)
- return flush_to_stream(new_str);
- else if (write_mode_ == WriteMode::RESIZE_AND_FILL_BUFF)
- return resize_and_write(new_str);
- } else if constexpr (write_mode == WriteMode::FILL_BUFF_AND_DROP_OVERFLOW) {
- return fill_remaining_to_buff(new_str);
- } else if constexpr (write_mode == WriteMode::FLUSH_TO_STREAM) {
- return flush_to_stream(new_str);
- } else if constexpr (write_mode == WriteMode::RESIZE_AND_FILL_BUFF) {
- return resize_and_write(new_str);
- }
- __builtin_unreachable();
+ LIBC_INLINE ResizingBuffer(char *buff, size_t buff_len, ResizeWriter hook)
+ : WriteBuffer<Mode<WriteMode::RESIZE_AND_FILL_BUFF>::value>(
+ buff, buff_len, WriteMode::RESIZE_AND_FILL_BUFF),
+ resize_writer(hook), init_buff(buff) {}
+
+ // Invokes the callback that is supposed to resize the buffer and make
+ // it large enough to fit the new_str addition.
+ LIBC_INLINE int resize_and_write(cpp::string_view new_str) {
+ return resize_writer(new_str, this);
}
};
+template <>
+LIBC_INLINE int WriteBuffer<WriteMode::RUNTIME_DISPATCH>::overflow_write(
+ cpp::string_view new_str) {
+ if (write_mode_ == WriteMode::FILL_BUFF_AND_DROP_OVERFLOW)
+ return reinterpret_cast<DropOverflowBuffer *>(this)->fill_remaining_to_buff(
+ new_str);
+ else if (write_mode_ == WriteMode::FLUSH_TO_STREAM)
+ return reinterpret_cast<FlushingBuffer *>(this)->flush_to_stream(new_str);
+ else if (write_mode_ == WriteMode::RESIZE_AND_FILL_BUFF)
+ return reinterpret_cast<ResizingBuffer *>(this)->resize_and_write(new_str);
+ __builtin_unreachable();
+}
+
+template <>
+LIBC_INLINE int
+WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::overflow_write(
+ cpp::string_view new_str) {
+ return reinterpret_cast<DropOverflowBuffer *>(this)->fill_remaining_to_buff(
+ new_str);
+}
+
+template <>
+LIBC_INLINE int WriteBuffer<WriteMode::FLUSH_TO_STREAM>::overflow_write(
+ cpp::string_view new_str) {
+ return reinterpret_cast<FlushingBuffer *>(this)->flush_to_stream(new_str);
+}
+
+template <>
+LIBC_INLINE int WriteBuffer<WriteMode::RESIZE_AND_FILL_BUFF>::overflow_write(
+ cpp::string_view new_str) {
+ return reinterpret_cast<ResizingBuffer *>(this)->resize_and_write(new_str);
+}
+
template <WriteMode write_mode> class Writer final {
WriteBuffer<write_mode> &wb;
size_t chars_written = 0;
diff --git a/libc/src/stdio/snprintf.cpp b/libc/src/stdio/snprintf.cpp
index d95195f6f485f..8364e8d59b278 100644
--- a/libc/src/stdio/snprintf.cpp
+++ b/libc/src/stdio/snprintf.cpp
@@ -31,9 +31,7 @@ LLVM_LIBC_FUNCTION(int, snprintf,
// and pointer semantics, as well as handling
// destruction automatically.
va_end(vlist);
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
+ printf_core::DropOverflowBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
auto ret_val = printf_core::printf_main(&writer, format, args);
diff --git a/libc/src/stdio/sprintf.cpp b/libc/src/stdio/sprintf.cpp
index 2a9b6ea7c5e50..d340096bb6d2b 100644
--- a/libc/src/stdio/sprintf.cpp
+++ b/libc/src/stdio/sprintf.cpp
@@ -31,9 +31,8 @@ LLVM_LIBC_FUNCTION(int, sprintf,
// destruction automatically.
va_end(vlist);
- printf_core::WriteBuffer<
- printf_core::Mode<printf_core::WriteMode::RESIZE_AND_FILL_BUFF>::value>
- wb(buffer, cpp::numeric_limits<size_t>::max());
+ printf_core::DropOverflowBuffer wb(buffer,
+ cpp::numeric_limits<size_t>::max());
printf_core::Writer writer(wb);
auto ret_val = printf_core::printf_main(&writer, format, args);
diff --git a/libc/src/stdio/vsnprintf.cpp b/libc/src/stdio/vsnprintf.cpp
index 5d936360c0857..b65343dfefc75 100644
--- a/libc/src/stdio/vsnprintf.cpp
+++ b/libc/src/stdio/vsnprintf.cpp
@@ -28,9 +28,7 @@ LLVM_LIBC_FUNCTION(int, vsnprintf,
internal::ArgList args(vlist); // This holder class allows for easier copying
// and pointer semantics, as well as handling
// destruction automatically.
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
+ printf_core::DropOverflowBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
auto ret_val = printf_core::printf_main(&writer, format, args);
diff --git a/libc/src/stdio/vsprintf.cpp b/libc/src/stdio/vsprintf.cpp
index f9cf8118534f6..8affb88d2b807 100644
--- a/libc/src/stdio/vsprintf.cpp
+++ b/libc/src/stdio/vsprintf.cpp
@@ -28,9 +28,8 @@ LLVM_LIBC_FUNCTION(int, vsprintf,
// and pointer semantics, as well as handling
// destruction automatically.
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(buffer, cpp::numeric_limits<size_t>::max());
+ printf_core::DropOverflowBuffer wb(buffer,
+ cpp::numeric_limits<size_t>::max());
printf_core::Writer writer(wb);
auto ret_val = printf_core::printf_main(&writer, format, args);
diff --git a/libc/src/stdlib/strfromd.cpp b/libc/src/stdlib/strfromd.cpp
index 71e257f08645b..5409a57c722d4 100644
--- a/libc/src/stdlib/strfromd.cpp
+++ b/libc/src/stdlib/strfromd.cpp
@@ -22,9 +22,7 @@ LLVM_LIBC_FUNCTION(int, strfromd,
printf_core::FormatSection section =
internal::parse_format_string(format, fp);
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(s, (n > 0 ? n - 1 : 0));
+ printf_core::DropOverflowBuffer wb(s, (n > 0 ? n - 1 : 0));
printf_core::Writer writer(wb);
int result = 0;
diff --git a/libc/src/stdlib/strfromf.cpp b/libc/src/stdlib/strfromf.cpp
index 65f242b200f18..e68e50210dd4d 100644
--- a/libc/src/stdlib/strfromf.cpp
+++ b/libc/src/stdlib/strfromf.cpp
@@ -22,9 +22,7 @@ LLVM_LIBC_FUNCTION(int, strfromf,
printf_core::FormatSection section =
internal::parse_format_string(format, fp);
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(s, (n > 0 ? n - 1 : 0));
+ printf_core::DropOverflowBuffer wb(s, (n > 0 ? n - 1 : 0));
printf_core::Writer writer(wb);
int result = 0;
diff --git a/libc/src/stdlib/strfroml.cpp b/libc/src/stdlib/strfroml.cpp
index 31668a0323c93..4be21677f7f13 100644
--- a/libc/src/stdlib/strfroml.cpp
+++ b/libc/src/stdlib/strfroml.cpp
@@ -27,9 +27,7 @@ LLVM_LIBC_FUNCTION(int, strfroml,
// the length modifier has to be set to LenghtModifier::L
section.length_modifier = printf_core::LengthModifier::L;
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(s, (n > 0 ? n - 1 : 0));
+ printf_core::DropOverflowBuffer wb(s, (n > 0 ? n - 1 : 0));
printf_core::Writer writer(wb);
int result = 0;
diff --git a/libc/src/time/strftime.cpp b/libc/src/time/strftime.cpp
index ff8c05a0b07da..af0f438d22cab 100644
--- a/libc/src/time/strftime.cpp
+++ b/libc/src/time/strftime.cpp
@@ -19,9 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(size_t, strftime,
(char *__restrict buffer, size_t buffsz,
const char *__restrict format, const tm *timeptr)) {
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
+ printf_core::DropOverflowBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
auto ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
diff --git a/libc/src/time/strftime_l.cpp b/libc/src/time/strftime_l.cpp
index 2ec90634ea347..7a70d2c5418ee 100644
--- a/libc/src/time/strftime_l.cpp
+++ b/libc/src/time/strftime_l.cpp
@@ -22,9 +22,7 @@ LLVM_LIBC_FUNCTION(size_t, strftime_l,
(char *__restrict buffer, size_t buffsz,
const char *__restrict format, const tm *timeptr,
locale_t)) {
- printf_core::WriteBuffer<printf_core::Mode<
- printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::value>
- wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
+ printf_core::DropOverflowBuffer wb(buffer, (buffsz > 0 ? buffsz - 1 : 0));
printf_core::Writer writer(wb);
auto ret = strftime_core::strftime_main(&writer, format, timeptr);
if (buffsz > 0) // if the buffsz is 0 the buffer may be a null pointer.
diff --git a/libc/test/src/stdio/printf_core/converter_test.cpp b/libc/test/src/stdio/printf_core/converter_test.cpp
index 2dae2a22c864c..68e2fdac89d47 100644
--- a/libc/test/src/stdio/printf_core/converter_test.cpp
+++ b/libc/test/src/stdio/printf_core/converter_test.cpp
@@ -14,18 +14,14 @@
class LlvmLibcPrintfConverterTest : public LIBC_NAMESPACE::testing::Test {
protected:
- // void SetUp() override {}
- // void TearDown() override {}
+ LlvmLibcPrintfConverterTest() : wb(str, sizeof(str) - 1), writer(wb) {}
char str[60];
- LIBC_NAMESPACE::printf_core::WriteBuffer<
- LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
- wb = LIBC_NAMESPACE::printf_core::WriteBuffer<
- LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>(
- str, sizeof(str) - 1);
- LIBC_NAMESPACE::printf_core::Writer<
- LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
- writer = LIBC_NAMESPACE::printf_core::Writer(wb);
+ LIBC_NAMESPACE::printf_core::DropOverflowBuffer wb;
+ LIBC_NAMESPACE::printf_core::Writer<LIBC_NAMESPACE::printf_core::Mode<
+ LIBC_NAMESPACE::printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>::
+ value>
+ writer;
};
TEST_F(LlvmLibcPrintfConverterTest, SimpleRawConversion) {
diff --git a/libc/test/src/stdio/printf_core/writer_test.cpp b/libc/test/src/stdio/printf_core/writer_test.cpp
index d263cf55aa474..e0128505b2766 100644
--- a/libc/test/src/stdio/printf_core/writer_test.cpp
+++ b/libc/test/src/stdio/printf_core/writer_test.cpp
@@ -15,20 +15,21 @@
namespace {
using LIBC_NAMESPACE::cpp::string_view;
-using LIBC_NAMESPACE::printf_core::WriteBuffer;
+using LIBC_NAMESPACE::printf_core::DropOverflowBuffer;
+using LIBC_NAMESPACE::printf_core::FlushingBuffer;
using LIBC_NAMESPACE::printf_core::WriteMode;
using LIBC_NAMESPACE::printf_core::Writer;
TEST(LlvmLibcPrintfWriterTest, Constructor) {
char str[10];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
(void)writer;
}
TEST(LlvmLibcPrintfWriterTest, Write) {
char str[4] = {'D', 'E', 'F', 'G'};
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write({"abc", 3});
@@ -44,7 +45,7 @@ TEST(LlvmLibcPrintfWriterTest, Write) {
TEST(LlvmLibcPrintfWriterTest, WriteMultipleTimes) {
char str[10];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write({"abc", 3});
writer.write({"DEF", 3});
@@ -58,7 +59,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteMultipleTimes) {
TEST(LlvmLibcPrintfWriterTest, WriteChars) {
char str[4] = {'D', 'E', 'F', 'G'};
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('a', 3);
@@ -71,7 +72,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteChars) {
TEST(LlvmLibcPrintfWriterTest, WriteCharsMultipleTimes) {
char str[10];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('a', 3);
writer.write('D', 3);
@@ -85,7 +86,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsMultipleTimes) {
TEST(LlvmLibcPrintfWriterTest, WriteManyChars) {
char str[100];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('Z', 99);
@@ -107,7 +108,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteManyChars) {
TEST(LlvmLibcPrintfWriterTest, MixedWrites) {
char str[13];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('a', 3);
writer.write({"DEF", 3});
@@ -122,7 +123,7 @@ TEST(LlvmLibcPrintfWriterTest, MixedWrites) {
TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLength) {
char str[11];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write({"abcDEF123456", 12});
@@ -134,7 +135,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLength) {
TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLength) {
char str[11];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('1', 15);
@@ -146,7 +147,7 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLength) {
TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLength) {
char str[11];
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, sizeof(str) - 1);
+ DropOverflowBuffer wb(str, sizeof(str) - 1);
Writer writer(wb);
writer.write('a', 3);
@@ -164,7 +165,7 @@ TEST(LlvmLibcPrintfWriterTest, StringWithMaxLengthOne) {
char str[1];
// This is because the max length should be at most 1 less than the size of
// the buffer it's writing to.
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(str, 0);
+ DropOverflowBuffer wb(str, 0);
Writer writer(wb);
writer.write('a', 3);
@@ -179,7 +180,7 @@ TEST(LlvmLibcPrintfWriterTest, StringWithMaxLengthOne) {
}
TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLength) {
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb(nullptr, 0);
+ DropOverflowBuffer wb(nullptr, 0);
Writer writer(wb);
writer.write('a', 3);
@@ -215,14 +216,12 @@ TEST(LlvmLibcPrintfWriterTest, WriteWithMaxLengthWithCallback) {
OutBuff out_buff = {str, 0};
char wb_buff[8];
- WriteBuffer<WriteMode::FLUSH_TO_STREAM> wb(
- wb_buff, sizeof(wb_buff), ©_to_out,
- reinterpret_cast<void *>(&out_buff));
+ FlushingBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out,
+ reinterpret_cast<void *>(&out_buff));
Writer writer(wb);
writer.write({"abcDEF123456", 12});
- // Flush the buffer
- wb.overflow_write("");
+ wb.flush_to_stream();
str[out_buff.cur_pos] = '\0';
ASSERT_STREQ("abcDEF123456", str);
@@ -235,14 +234,12 @@ TEST(LlvmLibcPrintfWriterTest, WriteCharsWithMaxLengthWithCallback) {
OutBuff out_buff = {str, 0};
char wb_buff[8];
- WriteBuffer<WriteMode::FLUSH_TO_STREAM> wb(
- wb_buff, sizeof(wb_buff), ©_to_out,
- reinterpret_cast<void *>(&out_buff));
+ FlushingBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out,
+ reinterpret_cast<void *>(&out_buff));
Writer writer(wb);
writer.write('1', 15);
- // Flush the buffer
- wb.overflow_write("");
+ wb.flush_to_stream();
str[out_buff.cur_pos] = '\0';
ASSERT_STREQ("111111111111111", str);
@@ -255,17 +252,15 @@ TEST(LlvmLibcPrintfWriterTest, MixedWriteWithMaxLengthWithCallback) {
OutBuff out_buff = {str, 0};
char wb_buff[8];
- WriteBuffer<WriteMode::FLUSH_TO_STREAM> wb(
- wb_buff, sizeof(wb_buff), ©_to_out,
- reinterpret_cast<void *>(&out_buff));
+ FlushingBuffer wb(wb_buff, sizeof(wb_buff), ©_to_out,
+ reinterpret_cast<void *>(&out_buff));
Writer writer(wb);
writer.write('a', 3);
writer.write({"DEF", 3});
writer.write('1', 3);
writer.write({"456", 3});
- // Flush the buffer
- wb.overflow_write("");
+ wb.flush_to_stream();
str[out_buff.cur_pos] = '\0';
ASSERT_STREQ("aaaDEF111456", str);
@@ -278,8 +273,8 @@ TEST(LlvmLibcPrintfWriterTest, ZeroLengthBufferWithCallback) {
OutBuff out_buff = {str, 0};
char wb_buff[1];
- WriteBuffer<WriteMode::FLUSH_TO_STREAM> wb(
- wb_buff, 0, ©_to_out, reinterpret_cast<void *>(&out_buff));
+ FlushingBuffer wb(wb_buff, 0, ©_to_out,
+ reinterpret_cast<void *>(&out_buff));
Writer writer(wb);
writer.write('a', 3);
@@ -287,8 +282,7 @@ TEST(LlvmLibcPrintfWriterTest, ZeroLengthBufferWithCallback) {
writer.write('1', 3);
writer.write({"456", 3});
- // Flush the buffer
- wb.overflow_write("");
+ wb.flush_to_stream();
str[out_buff.cur_pos] = '\0';
ASSERT_STREQ("aaaDEF111456", str);
@@ -300,8 +294,8 @@ TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLengthWithCallback) {
OutBuff out_buff = {str, 0};
- WriteBuffer<WriteMode::FLUSH_TO_STREAM> wb(
- nullptr, 0, ©_to_out, reinterpret_cast<void *>(&out_buff));
+ FlushingBuffer wb(nullptr, 0, ©_to_out,
+ reinterpret_cast<void *>(&out_buff));
Writer writer(wb);
writer.write('a', 3);
@@ -309,7 +303,7 @@ TEST(LlvmLibcPrintfWriterTest, NullStringWithZeroMaxLengthWithCallback) {
writer.write('1', 3);
writer.write({"456", 3});
- wb.overflow_write("");
+ wb.flush_to_stream();
str[out_buff.cur_pos] = '\0';
ASSERT_EQ(writer.get_chars_written(), size_t{12});
More information about the libc-commits
mailing list