mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-23 15:16:40 +08:00
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'
This commit is contained in:
parent
369890cdd9
commit
5b9331ade0
25
src/exec.cpp
25
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<io_buffer_t *>(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();
|
||||
|
||||
|
|
11
src/io.cpp
11
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]);
|
||||
|
||||
|
|
10
src/io.h
10
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<char> 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(); }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user