fish-shell/io.h

220 lines
5 KiB
C++

#ifndef FISH_IO_H
#define FISH_IO_H
#include <vector>
// Note that we have to include something to get any _LIBCPP_VERSION defined so we can detect libc++
// So it's key that vector go above. If we didn't need vector for other reasons, we might include ciso646, which does nothing
#if defined(_LIBCPP_VERSION) || __cplusplus > 199711L
// C++11 or libc++ (which is a C++11-only library, but the memory header works OK in C++03)
#include <memory>
using std::shared_ptr;
#else
// C++03 or libstdc++
#include <tr1/memory>
using std::tr1::shared_ptr;
#endif
/**
Describes what type of IO operation an io_data_t represents
*/
enum io_mode_t
{
IO_FILE, IO_PIPE, IO_FD, IO_BUFFER, IO_CLOSE
};
/** Represents an FD redirection */
class io_data_t
{
private:
/* No assignment or copying allowed */
io_data_t(const io_data_t &rhs);
void operator=(const io_data_t &rhs);
protected:
io_data_t(io_mode_t m, int f) :
io_mode(m),
fd(f)
{
}
public:
/** Type of redirect */
const io_mode_t io_mode;
/** FD to redirect */
const int fd;
virtual void print() const = 0;
virtual ~io_data_t() = 0;
};
class io_close_t : public io_data_t
{
public:
io_close_t(int f) :
io_data_t(IO_CLOSE, f)
{
}
virtual void print() const;
};
class io_fd_t : public io_data_t
{
public:
/** fd to redirect specified fd to */
const int old_fd;
/** Whether to close old_fd */
const bool close_old;
virtual void print() const;
io_fd_t(int f, int old, bool close = false) :
io_data_t(IO_FD, f),
old_fd(old),
close_old(close)
{
}
};
class io_file_t : public io_data_t
{
public:
/** Filename, malloc'd. This needs to be used after fork, so don't use wcstring here. */
const char * const filename_cstr;
/** file creation flags to send to open */
const int flags;
virtual void print() const;
io_file_t(int f, const wcstring &fname, int fl = 0) :
io_data_t(IO_FILE, f),
filename_cstr(wcs2str(fname)),
flags(fl)
{
}
virtual ~io_file_t()
{
free((void *)filename_cstr);
}
};
class io_pipe_t : public io_data_t
{
protected:
io_pipe_t(io_mode_t m, int f, bool i):
io_data_t(m, f),
is_input(i)
{
pipe_fd[0] = pipe_fd[1] = -1;
}
public:
int pipe_fd[2];
const bool is_input;
virtual void print() const;
io_pipe_t(int f, bool i):
io_data_t(IO_PIPE, f),
is_input(i)
{
pipe_fd[0] = pipe_fd[1] = -1;
}
};
class io_buffer_t : public io_pipe_t
{
private:
/** buffer to save output in */
std::vector<char> out_buffer;
io_buffer_t(int f, bool i):
io_pipe_t(IO_BUFFER, f, i),
out_buffer()
{
}
public:
virtual void print() const;
virtual ~io_buffer_t();
/** Function to append to the buffer */
void out_buffer_append(const char *ptr, size_t count)
{
out_buffer.insert(out_buffer.end(), ptr, ptr + count);
}
/** Function to get a pointer to the buffer */
char *out_buffer_ptr(void)
{
return out_buffer.empty() ? NULL : &out_buffer.at(0);
}
const char *out_buffer_ptr(void) const
{
return out_buffer.empty() ? NULL : &out_buffer.at(0);
}
/** Function to get the size of the buffer */
size_t out_buffer_size(void) const
{
return out_buffer.size();
}
/**
Close output pipe, and read from input pipe until eof.
*/
void read();
/**
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.
\param fd when -1, determined from is_input.
*/
static io_buffer_t *create(bool is_input, int fd = -1);
};
class io_chain_t : public std::vector<shared_ptr<io_data_t> >
{
public:
io_chain_t();
io_chain_t(const shared_ptr<io_data_t> &);
void remove(const shared_ptr<const io_data_t> &element);
void push_back(const shared_ptr<io_data_t> &element);
void push_front(const shared_ptr<io_data_t> &element);
void append(const io_chain_t &chain);
shared_ptr<const io_data_t> get_io_for_fd(int fd) const;
shared_ptr<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 shared_ptr<const io_data_t> &element);
/** 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.
*/
shared_ptr<const io_data_t> io_chain_get(const io_chain_t &src, int fd);
shared_ptr<io_data_t> io_chain_get(io_chain_t &src, int fd);
/** Print debug information about the specified IO redirection chain to stderr. */
void io_print(const io_chain_t &chain);
#endif