mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 09:39:52 +08:00
61686aff34
Rewrite IO chains to be a vector of pointers, instead of a linked list Removed io_transmogrify
185 lines
5.2 KiB
C++
185 lines
5.2 KiB
C++
#ifndef FISH_IO_H
|
|
#define FISH_IO_H
|
|
|
|
#include <vector>
|
|
#include <tr1/memory>
|
|
using std::tr1::shared_ptr;
|
|
|
|
/**
|
|
Describes what type of IO operation an io_data_t represents
|
|
*/
|
|
enum io_mode
|
|
{
|
|
IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE
|
|
};
|
|
|
|
/** Represents an FD redirection */
|
|
class io_data_t
|
|
{
|
|
private:
|
|
/** buffer to save output in for IO_BUFFER. Note that in the original fish, the buffer was a pointer to a buffer_t stored in the param2 union down below, and when an io_data_t was duplicated the pointer was copied so that two io_data_ts referenced the same buffer. It's not clear to me how this was ever cleaned up correctly. But it's important that they share the same buffer for reasons I don't yet understand either. We can get correct sharing and cleanup with shared_ptr. */
|
|
shared_ptr<std::vector<char> > out_buffer;
|
|
|
|
/* No assignment allowed */
|
|
void operator=(const io_data_t &rhs);
|
|
|
|
public:
|
|
/** Type of redirect */
|
|
int io_mode;
|
|
/** FD to redirect */
|
|
int fd;
|
|
|
|
/**
|
|
Type-specific parameter for redirection
|
|
*/
|
|
union
|
|
{
|
|
/** Fds for IO_PIPE and for IO_BUFFER */
|
|
int pipe_fd[2];
|
|
/** fd to redirect specified fd to, for IO_FD */
|
|
int old_fd;
|
|
} param1;
|
|
|
|
|
|
/** Second type-specific paramter for redirection */
|
|
union
|
|
{
|
|
/** file creation flags to send to open for IO_FILE */
|
|
int flags;
|
|
/** Whether to close old_fd for IO_FD */
|
|
int close_old;
|
|
} param2;
|
|
|
|
/** Filename IO_FILE. malloc'd. This needs to be used after fork, so don't use wcstring here. */
|
|
const char *filename_cstr;
|
|
|
|
/** Convenience to set filename_cstr via wcstring */
|
|
void set_filename(const wcstring &str) {
|
|
free((void *)filename_cstr);
|
|
filename_cstr = wcs2str(str.c_str());
|
|
}
|
|
|
|
/** Function to create the output buffer */
|
|
void out_buffer_create() {
|
|
out_buffer.reset(new std::vector<char>);
|
|
}
|
|
|
|
/** Function to append to the buffer */
|
|
void out_buffer_append(const char *ptr, size_t count) {
|
|
assert(out_buffer.get() != NULL);
|
|
out_buffer->insert(out_buffer->end(), ptr, ptr + count);
|
|
}
|
|
|
|
/** Function to get a pointer to the buffer */
|
|
char *out_buffer_ptr(void) {
|
|
assert(out_buffer.get() != NULL);
|
|
return out_buffer->empty() ? NULL : &out_buffer->at(0);
|
|
}
|
|
|
|
const char *out_buffer_ptr(void) const {
|
|
assert(out_buffer.get() != NULL);
|
|
return out_buffer->empty() ? NULL : &out_buffer->at(0);
|
|
}
|
|
|
|
/** Function to get the size of the buffer */
|
|
size_t out_buffer_size(void) const {
|
|
assert(out_buffer.get() != NULL);
|
|
return out_buffer->size();
|
|
}
|
|
|
|
/** Set to true if this is an input io redirection */
|
|
bool is_input;
|
|
|
|
io_data_t() :
|
|
out_buffer(),
|
|
io_mode(0),
|
|
fd(0),
|
|
param1(),
|
|
param2(),
|
|
filename_cstr(NULL),
|
|
is_input(0)
|
|
{
|
|
}
|
|
|
|
io_data_t(const io_data_t &rhs) :
|
|
out_buffer(rhs.out_buffer),
|
|
io_mode(rhs.io_mode),
|
|
fd(rhs.fd),
|
|
param1(rhs.param1),
|
|
param2(rhs.param2),
|
|
filename_cstr(rhs.filename_cstr ? strdup(rhs.filename_cstr) : NULL),
|
|
is_input(rhs.is_input)
|
|
{
|
|
}
|
|
|
|
~io_data_t() {
|
|
free((void *)filename_cstr);
|
|
}
|
|
};
|
|
|
|
class io_chain_t : public std::vector<io_data_t *> {
|
|
public:
|
|
io_chain_t();
|
|
io_chain_t(io_data_t *);
|
|
|
|
void remove(const io_data_t *element);
|
|
io_chain_t duplicate() const;
|
|
void duplicate_append(const io_chain_t &src);
|
|
void destroy();
|
|
|
|
const io_data_t *get_io_for_fd(int fd) const;
|
|
io_data_t *get_io_for_fd(int fd);
|
|
|
|
|
|
};
|
|
|
|
/**
|
|
Remove the specified io redirection from the chain
|
|
*/
|
|
void io_remove(io_chain_t &list, const io_data_t *element);
|
|
|
|
/** Make a copy of the specified chain of redirections. Uses operator new. */
|
|
io_chain_t io_duplicate(const io_chain_t &chain);
|
|
|
|
/** Return a shallow copy of the specified chain of redirections that contains only the applicable redirections. That is, if there's multiple redirections for the same fd, only the second one is included. */
|
|
io_chain_t io_unique(const io_chain_t &chain);
|
|
|
|
/** Appends a copy of the specified 'src' chain of redirections to 'dst.' Uses operator new. */
|
|
void io_duplicate_append( const io_chain_t &src, io_chain_t &dst );
|
|
|
|
/** Destroys an io_chain */
|
|
void io_chain_destroy(io_chain_t &chain);
|
|
|
|
/**
|
|
Return the last io redirection in the chain for the specified file descriptor.
|
|
*/
|
|
const io_data_t *io_chain_get(const io_chain_t &src, int fd);
|
|
io_data_t *io_chain_get(io_chain_t &src, int fd);
|
|
|
|
|
|
/**
|
|
Free all resources used by a IO_BUFFER type io redirection.
|
|
*/
|
|
void io_buffer_destroy( io_data_t *io_buffer );
|
|
|
|
/**
|
|
Create a IO_BUFFER type io redirection, complete with a pipe and a
|
|
vector<char> for output. The default file descriptor used is 1 for
|
|
output buffering and 0 for input buffering.
|
|
|
|
\param is_input set this parameter to zero if the buffer should be
|
|
used to buffer the output of a command, or non-zero to buffer the
|
|
input to a command.
|
|
*/
|
|
io_data_t *io_buffer_create( bool is_input );
|
|
|
|
/**
|
|
Close output pipe, and read from input pipe until eof.
|
|
*/
|
|
void io_buffer_read( io_data_t *d );
|
|
|
|
/** Print debug information about the specified IO redirection chain to stderr. */
|
|
void io_print( const io_chain_t &chain );
|
|
|
|
#endif
|