Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions libc/src/__support/RPC/rpc_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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]);
Expand Down Expand Up @@ -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]);
Expand Down
8 changes: 4 additions & 4 deletions libc/src/stdio/baremetal/printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ 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()) {
libc_errno = printf_core::internal_error_to_errno(retval.error());
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;
Expand Down
8 changes: 4 additions & 4 deletions libc/src/stdio/baremetal/vprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ 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()) {
libc_errno = printf_core::internal_error_to_errno(retval.error());
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;
Expand Down
10 changes: 4 additions & 6 deletions libc/src/stdio/printf_core/vasprintf_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *>(
Expand All @@ -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);
Expand Down
6 changes: 3 additions & 3 deletions libc/src/stdio/printf_core/vfprintf_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,16 +86,16 @@ 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);
if (!retval.has_value()) {
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);
Expand Down
154 changes: 98 additions & 56 deletions libc/src/stdio/printf_core/writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions libc/src/stdio/snprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions libc/src/stdio/sprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions libc/src/stdio/vsnprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 2 additions & 3 deletions libc/src/stdio/vsprintf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 1 addition & 3 deletions libc/src/stdlib/strfromd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions libc/src/stdlib/strfromf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions libc/src/stdlib/strfroml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions libc/src/time/strftime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading
Loading