-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[libc] Refactor static polymorphism in WriteBuffer (NFC). #169089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
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.
|
@llvm/pr-subscribers-libc Author: Alexey Samsonov (vonosmas) ChangesThere are three flavors of WriteBuffer currently, all of which could be passed into Refactor this somewhat convoluted logic to have three concrete subclasses inheriting from the templated base class, and use static polymorphism with This code will need to be further templatized to support buffers of type Patch is 29.36 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169089.diff 17 Files Affected:
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 buff...
[truncated]
|
🐧 Linux x64 Test ResultsThe build succeeded and no tests ran. This is expected in some build configurations. |
There are three flavors of WriteBuffer currently, all of which could be passed into
printf_core::Writerclass. 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 forFILL_BUFF_AND_DROP_OVERFLOWpath).Refactor this somewhat convoluted logic to have three concrete subclasses inheriting from the templated base class, and use static polymorphism with
reinterpret_castto implement dispatching above. Now we can actually have flavor-specific fields, constructors, and methods (e.g.flush_to_streamis now a method ofFlushingBuffer), and the code on the user side is cleaner: the complexity of enabling/disabling runtime-dispatch and using proper template arguments is now localized inwriter.h.This code will need to be further templatized to support buffers of type
wchar_tto implementswprintf()and friends. This change would make it (ever so slightly) easier.