[libc-commits] [libc] [wip] [libc] Implement vasprintf (PR #98824)
Michael Jones via libc-commits
libc-commits at lists.llvm.org
Fri Jul 19 11:11:16 PDT 2024
================
@@ -23,60 +23,73 @@ namespace printf_core {
struct WriteBuffer {
using StreamWriter = int (*)(cpp::string_view, void *);
+ using OverflowWriter = int (WriteBuffer::*)(cpp::string_view);
char *buff;
- const size_t buff_len;
+ 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.
StreamWriter stream_writer;
void *output_target;
+ OverflowWriter overflowWriter{nullptr};
LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len, StreamWriter hook,
void *target)
: buff(Buff), buff_len(Buff_len), stream_writer(hook),
- output_target(target) {}
+ output_target(target), overflowWriter(&WriteBuffer::flush_to_stream) {}
LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len)
: buff(Buff), buff_len(Buff_len), stream_writer(nullptr),
- output_target(nullptr) {}
+ output_target(nullptr),
+ overflowWriter(&WriteBuffer::fill_remaining_to_buff) {}
- // 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, else it will
- // write as much of new_str to the buffer as it can. The current position in
- // the buffer will be reset iff stream_writer is called. Calling this with an
- // empty string will flush the buffer if relevant.
- LIBC_INLINE int overflow_write(cpp::string_view new_str) {
- // If there is a stream_writer, write the contents of the buffer, then
- // new_str, then clear the buffer.
- if (stream_writer != nullptr) {
- if (buff_cur > 0) {
- int retval = stream_writer({buff, buff_cur}, output_target);
- if (retval < 0) {
- return retval;
- }
+ LIBC_INLINE WriteBuffer(char *Buff, size_t Buff_len, StreamWriter hook)
+ : buff(Buff), buff_len(Buff_len), stream_writer(hook),
+ output_target(this), overflowWriter(&WriteBuffer::resize_and_write) {}
+
+ LIBC_INLINE int flush_to_stream(cpp::string_view new_str) {
+ if (buff_cur > 0) {
+ int retval = stream_writer({buff, buff_cur}, output_target);
+ if (retval < 0) {
+ return retval;
}
- if (new_str.size() > 0) {
- int retval = stream_writer(new_str, output_target);
- if (retval < 0) {
- return retval;
- }
+ }
+ if (new_str.size() > 0) {
+ int retval = stream_writer(new_str, output_target);
+ if (retval < 0) {
+ return retval;
}
- buff_cur = 0;
- return WRITE_OK;
- } else {
- // We can't flush to the stream, so fill the rest of the buffer, then drop
- // the overflow.
- 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;
+ }
+ buff_cur = 0;
+ 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();
}
- return WRITE_OK;
+ inline_memcpy(buff + buff_cur, new_str.data(), bytes_to_write);
+ buff_cur += bytes_to_write;
}
+ return WRITE_OK;
+ }
+
+ LIBC_INLINE int resize_and_write(cpp::string_view new_str) {
+ return stream_writer(new_str, output_target);
+ }
+
+ // 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) {
+ return (this->*overflowWriter)(new_str);
----------------
michaelrj-google wrote:
I'm not certain on how the branch predictor will act (and it will vary by CPU), but I would assume that since the type enum isn't changing it will be able to correctly guess the branch (especially on a second pass).
https://github.com/llvm/llvm-project/pull/98824
More information about the libc-commits
mailing list