Do not buffer builtin output if avoidable

builtins output to stdout and stderr via io_streams_t. Prior to this fix, it
contained an output_stream_t which just wraps a buffer. So all builtin output
went to this buffer (except for eval).

Switch output_stream_t to become a new abstract class which can output to a
buffer, file descriptor, or nowhere. This allows for example `string` to stream
its output as it is produced, instead of buffering it.
This commit is contained in:
ridiculousfish
2020-07-29 16:03:29 -07:00
parent 68092c5d21
commit bcfc54fdaa
7 changed files with 174 additions and 51 deletions

View File

@@ -57,8 +57,7 @@ void io_bufferfill_t::print() const {
std::fwprintf(stderr, L"bufferfill %d -> %d\n", write_fd_.fd(), fd);
}
void io_buffer_t::append_from_stream(const output_stream_t &stream) {
const separated_buffer_t<wcstring> &input = stream.buffer();
void io_buffer_t::append_from_wide_buffer(const separated_buffer_t<wcstring> &input) {
if (input.elements().empty() && !input.discarded()) return;
scoped_lock locker(append_lock_);
if (buffer_.discarded()) return;
@@ -349,6 +348,32 @@ shared_ptr<const io_data_t> io_chain_t::io_for_fd(int fd) const {
void output_stream_t::append_narrow_buffer(const separated_buffer_t<std::string> &buffer) {
for (const auto &rhs_elem : buffer.elements()) {
buffer_.append(str2wcstring(rhs_elem.contents), rhs_elem.separation);
append_with_separation(str2wcstring(rhs_elem.contents), rhs_elem.separation);
}
}
void output_stream_t::append_with_separation(const wchar_t *s, size_t len, separation_type_t type) {
append(s, len);
if (type == separation_type_t::explicitly) {
append(L'\n');
}
}
void fd_output_stream_t::append(const wchar_t *s, size_t amt) {
if (errored_) return;
int res = wwrite_to_fd(s, amt, this->fd_);
if (res < 0) {
// TODO: this error is too aggressive, e.g. if we got SIGINT we should not complain.
wperror(L"write");
errored_ = true;
}
}
void null_output_stream_t::append(const wchar_t *, size_t) {}
void buffered_output_stream_t::append(const wchar_t *s, size_t amt) { buffer_.append(s, s + amt); }
void buffered_output_stream_t::append_with_separation(const wchar_t *s, size_t len,
separation_type_t type) {
buffer_.append(s, s + len, type);
}