This repository has been archived on 2019-08-01. You can view files and clone it, but cannot push or open issues or pull requests.
ncurses-poll/src/ncurses-poll.hpp

134 lines
3.2 KiB
C++

//
// ncurses-poll.hpp
//
// A header for performing asynchronous I/O with ncurses using Boost.Asio.
//
// @author CismonX <admin@cismon.net>
//
#ifndef NCURSES_POLL_HPP_
#define NCURSES_POLL_HPP_
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <curses.h>
template <typename Session>
class ncurses_poll {
using stream_descriptor_t = boost::asio::posix::stream_descriptor;
/// Provides asynchronous I/O functionalities for this ncurses instance.
stream_descriptor_t sd_;
/// I/O context used by the stream descriptor.
boost::asio::io_context *context_;
/// File pointer of this tty.
FILE *file_ = nullptr;
/// Screen pointer of this ncurses instance.
SCREEN *screen_ = nullptr;
/// User-defined session for this ncurses instance.
Session session_;
public:
/// Provides support for stackless coroutines.
boost::asio::coroutine coro;
/**
* Constructor.
*
* @param io_context The I/O context used for dispatching handlers.
*/
explicit ncurses_poll(boost::asio::io_context& io_context) :
sd_(io_context), context_(&io_context), session_(this) {}
/**
* Deleted default constructor.
*/
ncurses_poll() = delete;
/**
* Initialize ncurses instance.
*
* @param path File path. e.g. "/dev/pts/0". Empty for current tty.
*/
int init(const std::string& path = ttyname(STDIN_FILENO)) {
file_ = fopen(path.c_str(), "r+");
if (file_ == nullptr) {
return errno;
}
screen_ = newterm(nullptr, file_, file_);
boost::system::error_code ec;
sd_.assign(fileno(file_), ec);
return ec.value();
}
/**
* Invoke the given callback once the terminal is readable.
*
* @param read_cb The callback to be invoked.
*/
template <typename F>
void on_readable(F&& read_cb) {
sd_.async_wait(stream_descriptor_t::wait_read, boost::bind<void>(
[this, read_cb](const boost::system::error_code& ec) {
set_term(screen_);
read_cb(ec, this);
}, boost::asio::placeholders::error));
}
/**
* Invoke the given callback once the terminal is writable.
*
* @param write_cb The callback to be invoked.
*/
template <typename F>
void on_writable(F&& write_cb) {
sd_.async_wait(stream_descriptor_t::wait_write, boost::bind<void>(
[this, write_cb](const boost::system::error_code& ec) {
set_term(screen_);
write_cb(ec, this);
}, boost::asio::placeholders::error));
}
/**
* Get current session.
*/
Session *session() {
return &session_;
}
/**
* Get screen pointer of this ncurses instance.
*/
SCREEN *screen() const {
return screen_;
}
/**
* Get current I/O context.
*/
boost::asio::io_context *get_io_context() {
return context_;
}
/**
* Destructor.
*/
~ncurses_poll() {
if (screen_) {
set_term(screen_);
endwin();
delscreen(screen_);
}
if (file_) {
fclose(file_);
}
}
};
#endif