From 5b9331ade0b6c2944ec92a71416e2cf63d27fb11 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sun, 27 May 2018 23:56:20 -0700 Subject: [PATCH] Teach io_buffer_t to append from output_stream_t directly This will simplify logic when we teach output_stream_t about explicitly split outputs, i.e. for 'string split0' --- src/exec.cpp | 25 ++++++++++--------------- src/io.cpp | 11 +++++++++++ src/io.h | 10 +++++++--- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/exec.cpp b/src/exec.cpp index a3e9ce456..a12c33c9e 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -925,8 +925,8 @@ void exec_job(parser_t &parser, job_t *j) { process_net_io_chain.get_io_for_fd(STDERR_FILENO); assert(builtin_io_streams.get() != NULL); - const wcstring &stdout_buffer = builtin_io_streams->out.buffer(); - const wcstring &stderr_buffer = builtin_io_streams->err.buffer(); + const output_stream_t &stdout_stream = builtin_io_streams->out; + const output_stream_t &stderr_stream = builtin_io_streams->err; // If we are outputting to a file, we have to actually do it, even if we have no // output, so that we can truncate the file. Does not apply to /dev/null. @@ -936,9 +936,9 @@ void exec_job(parser_t &parser, job_t *j) { // We are handling reads directly in the main loop. Note that we may still end // up forking. const bool stdout_is_to_buffer = stdout_io && stdout_io->io_mode == IO_BUFFER; - const bool no_stdout_output = stdout_buffer.empty(); - const bool no_stderr_output = stderr_buffer.empty(); - const bool stdout_discarded = builtin_io_streams->out.output_discarded(); + const bool no_stdout_output = stdout_stream.empty(); + const bool no_stderr_output = stderr_stream.empty(); + const bool stdout_discarded = stdout_stream.output_discarded(); if (!stdout_discarded && no_stdout_output && no_stderr_output) { // The builtin produced no output and is not inside of a pipeline. No @@ -954,19 +954,14 @@ void exec_job(parser_t &parser, job_t *j) { p->argv0()); io_buffer_t *io_buffer = static_cast(stdout_io.get()); - if (stdout_discarded) { - io_buffer->set_discard(); - } else { - const std::string res = wcs2string(builtin_io_streams->out.buffer()); - io_buffer->out_buffer_append(res.data(), res.size()); - } + io_buffer->append_from_stream(stdout_stream); fork_was_skipped = true; } else if (stdout_io.get() == NULL && stderr_io.get() == NULL) { // We are writing to normal stdout and stderr. Just do it - no need to fork. debug(3, L"Skipping fork: ordinary output for internal builtin '%ls'", p->argv0()); - const std::string outbuff = wcs2string(stdout_buffer); - const std::string errbuff = wcs2string(stderr_buffer); + const std::string outbuff = wcs2string(stdout_stream.buffer()); + const std::string errbuff = wcs2string(stderr_stream.buffer()); bool builtin_io_done = do_builtin_io(outbuff.data(), outbuff.size(), errbuff.data(), errbuff.size()); if (!builtin_io_done && errno != EPIPE) { @@ -995,11 +990,11 @@ void exec_job(parser_t &parser, job_t *j) { // in the child. // // These strings may contain embedded nulls, so don't treat them as C strings. - const std::string outbuff_str = wcs2string(stdout_buffer); + const std::string outbuff_str = wcs2string(stdout_stream.buffer()); const char *outbuff = outbuff_str.data(); size_t outbuff_len = outbuff_str.size(); - const std::string errbuff_str = wcs2string(stderr_buffer); + const std::string errbuff_str = wcs2string(stderr_stream.buffer()); const char *errbuff = errbuff_str.data(); size_t errbuff_len = errbuff_str.size(); diff --git a/src/io.cpp b/src/io.cpp index 995877a19..e18be8f75 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -31,6 +31,17 @@ void io_buffer_t::print() const { is_input ? "yes" : "no", (unsigned long)out_buffer_size()); } +void io_buffer_t::append_from_stream(const output_stream_t &stream) { + if (output_discarded()) + return; + if (stream.output_discarded()) { + set_discard(); + return; + } + const std::string str = wcs2string(stream.buffer()); + out_buffer_append(str.data(), str.size()); +} + void io_buffer_t::read() { exec_close(pipe_fd[1]); diff --git a/src/io.h b/src/io.h index 3d54679c0..7b789fb67 100644 --- a/src/io.h +++ b/src/io.h @@ -98,6 +98,7 @@ class io_pipe_t : public io_data_t { }; class io_chain_t; +class output_stream_t; class io_buffer_t : public io_pipe_t { private: /// True if we're discarding input. @@ -121,8 +122,7 @@ class io_buffer_t : public io_pipe_t { void out_buffer_append(const char *ptr, size_t count) { if (discard) return; if (buffer_limit && out_buffer.size() + count > buffer_limit) { - discard = true; - out_buffer.clear(); + set_discard(); return; } out_buffer.insert(out_buffer.end(), ptr, ptr + count); @@ -153,6 +153,10 @@ class io_buffer_t : public io_pipe_t { /// Close output pipe, and read from input pipe until eof. void read(); + /// Appends data from a given output_stream_t. + /// Marks the receiver as discarded if the stream was discarded. + void append_from_stream(const output_stream_t &stream); + /// Create a IO_BUFFER type io redirection, complete with a pipe and a vector for output. /// The default file descriptor used is STDOUT_FILENO for buffering. /// @@ -258,7 +262,7 @@ class output_stream_t { const wcstring &buffer() const { return buffer_; } /// Function that returns true if we discarded the input because there was too much data. - bool output_discarded() { return discard; } + bool output_discarded() const { return discard; } bool empty() const { return buffer_.empty(); } };