Skip to content

Commit

Permalink
Improve buffering
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaut authored and happymonkey1 committed Apr 6, 2024
1 parent 88ab1ba commit 60d0bbb
Showing 1 changed file with 22 additions and 28 deletions.
50 changes: 22 additions & 28 deletions include/fmt/format-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1467,6 +1467,8 @@ template <typename F> class file_base {
if (ungetc(c, file_) == EOF)
FMT_THROW(system_error(errno, FMT_STRING("ungetc failed")));
}

void flush() { fflush(this->file_); }
};

// A FILE wrapper for glibc.
Expand All @@ -1477,10 +1479,6 @@ template <typename F> class glibc_file : public file_base<F> {
unbuffered = 2 // _IO_UNBUFFERED
};

auto available_space() const -> ptrdiff_t {
return this->file_->_IO_buf_end - this->file_->_IO_write_ptr;
}

public:
using file_base<F>::file_base;

Expand All @@ -1495,16 +1493,16 @@ template <typename F> class glibc_file : public file_base<F> {
--this->file_->_IO_write_ptr;
}

// Returns the file's read buffer as a string_view.
// Returns the file's read buffer.
auto get_read_buffer() const -> span<const char> {
return {this->file_->_IO_read_ptr,
to_unsigned(this->file_->_IO_read_end - this->file_->_IO_read_ptr)};
auto ptr = this->file_->_IO_read_ptr;
return {ptr, to_unsigned(this->file_->_IO_read_end - ptr)};
}

// Returns the file's write buffer.
auto get_write_buffer() const -> span<char> {
if (available_space() == 0) fflush_unlocked(this->file_);
FMT_ASSERT(available_space() > 0, "");
return {this->file_->_IO_write_ptr, static_cast<size_t>(available_space())};
auto ptr = this->file_->_IO_write_ptr;
return {ptr, to_unsigned(this->file_->_IO_buf_end - ptr)};
}

void advance_write_buffer(size_t size) { this->file_->_IO_write_ptr += size; }
Expand All @@ -1514,6 +1512,8 @@ template <typename F> class glibc_file : public file_base<F> {
char* end = this->file_->_IO_write_end;
return memchr(end, '\n', to_unsigned(this->file_->_IO_write_ptr - end));
}

void flush() { fflush_unlocked(this->file_); }
};

// A FILE wrapper for Apple's libc.
Expand All @@ -1524,10 +1524,6 @@ template <typename F> class apple_file : public file_base<F> {
unbuffered = 2 // __SLBF
};

auto available_space() const -> ptrdiff_t {
return this->file_->_bf._base + this->file_->_bf._size - this->file_->_p;
}

public:
using file_base<F>::file_base;

Expand All @@ -1549,10 +1545,9 @@ template <typename F> class apple_file : public file_base<F> {
}

auto get_write_buffer() const -> span<char> {
if (available_space() == 0) fflush(this->file_);
FMT_ASSERT(available_space() > 0, "");
return {reinterpret_cast<char*>(this->file_->_p),
static_cast<size_t>(available_space())};
to_unsigned(this->file_->_bf._base + this->file_->_bf._size -
this->file_->_p)};
}

void advance_write_buffer(size_t size) {
Expand Down Expand Up @@ -1586,6 +1581,8 @@ template <typename F> class fallback_file : public file_base<F> {

auto get_write_buffer() const -> span<char> { return {nullptr, 0}; }

void advance_write_buffer(size_t) {}

auto get() -> int {
has_next_ = false;
return file_base<F>::get();
Expand All @@ -1596,8 +1593,6 @@ template <typename F> class fallback_file : public file_base<F> {
next_ = c;
has_next_ = true;
}

void advance_write_buffer(size_t) {}
};

template <typename F, FMT_ENABLE_IF(sizeof(F::_p) != 0)>
Expand All @@ -1616,23 +1611,22 @@ class file_print_buffer : public buffer<char> {
private:
file_ref file_;

void set_buffer() {
auto buf = file_.get_write_buffer();
this->set(buf.data, buf.size);
}

static void grow(buffer<char>& buf, size_t) {
auto& self = static_cast<file_print_buffer&>(buf);
static void grow(buffer<char>& base, size_t) {
auto& self = static_cast<file_print_buffer&>(base);
self.file_.advance_write_buffer(self.size());
self.set_buffer();
if (self.file_.get_write_buffer().size == 0) self.file_.flush();
auto buf = self.file_.get_write_buffer();
FMT_ASSERT(buf.size > 0, "");
self.set(buf.data, buf.size);
self.clear();
}

public:
explicit file_print_buffer(FILE* f) : buffer(grow, size_t()), file_(f) {
flockfile(f);
file_.init_buffer();
set_buffer();
auto buf = file_.get_write_buffer();
set(buf.data, buf.size);
}
~file_print_buffer() {
file_.advance_write_buffer(size());
Expand Down

0 comments on commit 60d0bbb

Please sign in to comment.