From 0c5413156be50810ce4be970650113bbe6986b17 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Thu, 14 Jul 2016 00:29:31 +0200 Subject: [PATCH] added tty + mior changes --- src/uvw.hpp | 1 + src/uvw/handle.hpp | 4 +- src/uvw/tcp.hpp | 12 ++++-- src/uvw/tty.hpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++ src/uvw/util.hpp | 7 +++- test/main.cpp | 4 +- 6 files changed, 117 insertions(+), 8 deletions(-) create mode 100644 src/uvw/tty.hpp diff --git a/src/uvw.hpp b/src/uvw.hpp index b932f132..8870260f 100644 --- a/src/uvw.hpp +++ b/src/uvw.hpp @@ -11,4 +11,5 @@ #include "uvw/stream.hpp" #include "uvw/tcp.hpp" #include "uvw/timer.hpp" +#include "uvw/tty.hpp" #include "uvw/util.hpp" diff --git a/src/uvw/handle.hpp b/src/uvw/handle.hpp index c5f4a6c6..7d5c6925 100644 --- a/src/uvw/handle.hpp +++ b/src/uvw/handle.hpp @@ -21,6 +21,7 @@ template<> struct HandleType { }; template<> struct HandleType { }; template<> struct HandleType { }; template<> struct HandleType { }; +template<> struct HandleType { }; template @@ -87,9 +88,10 @@ protected: } template - void invoke(F &&f, Args&&... args) { + auto invoke(F &&f, Args&&... args) { auto err = std::forward(f)(std::forward(args)...); if(err) { Emitter::publish(ErrorEvent{err}); } + return err; } public: diff --git a/src/uvw/tcp.hpp b/src/uvw/tcp.hpp index 51c9a1d7..ec31b91c 100644 --- a/src/uvw/tcp.hpp +++ b/src/uvw/tcp.hpp @@ -31,7 +31,7 @@ class Tcp final: public Stream { sockaddr_storage ssto; int len = sizeof(ssto); char name[sizeof(ssto)]; - Addr addr{ "", 0 }; + std::pair addr{ "", 0 }; int err = std::forward(f)(get(), reinterpret_cast(&ssto), &len); @@ -44,7 +44,11 @@ class Tcp final: public Stream { } } - return addr; + /** + * See Boost/Mutant idiom: + * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant + */ + return reinterpret_cast(addr); } public: @@ -78,7 +82,7 @@ public: template> void bind(Addr addr, bool ipv6only = false) noexcept { - bind(addr.first, addr.second, ipv6only); + bind(addr.ip, addr.port, ipv6only); } template> @@ -100,7 +104,7 @@ public: template> void connect(Addr addr) noexcept { - connect(addr.first, addr.second); + connect(addr.ip, addr.port); } void accept(Tcp &tcp) noexcept { diff --git a/src/uvw/tty.hpp b/src/uvw/tty.hpp new file mode 100644 index 00000000..2a7ecc24 --- /dev/null +++ b/src/uvw/tty.hpp @@ -0,0 +1,97 @@ +#pragma once + + +#include +#include +#include +#include +#include "event.hpp" +#include "stream.hpp" +#include "util.hpp" + + +namespace uvw { + + +namespace details { + + +template +struct FileDescriptor; + +template<> struct FileDescriptor<0> { }; +template<> struct FileDescriptor<1> { }; +template<> struct FileDescriptor<2> { }; + +} + + +class TTY final: public Stream { + template + explicit TTY(std::shared_ptr ref, + details::FileDescriptor, + bool readable) + : Stream{HandleType{}, std::move(ref)}, + fd{FD}, + rw{readable ? 1 : 0} + { } + +public: + static constexpr auto STDIN = details::FileDescriptor<0>{}; + static constexpr auto STDOUT = details::FileDescriptor<1>{}; + static constexpr auto STDERR = details::FileDescriptor<2>{}; + + enum class Mode: unsigned short int { NORMAL, RAW, IO }; + + template + static std::shared_ptr create(Args&&... args) { + return std::shared_ptr{new TTY{std::forward(args)...}}; + } + + bool init() { return initialize(&uv_tty_init, fd, rw); } + + void mode(TTY::Mode m) { + // uv_tty_set_mode is inline, cannot be used with invoke directly + auto wrap = [](auto *handle, auto m) { + return uv_tty_set_mode(handle, m); + }; + + switch(m) { + case TTY::Mode::NORMAL: + invoke(std::move(wrap), get(), UV_TTY_MODE_NORMAL); + break; + case TTY::Mode::RAW: + invoke(std::move(wrap), get(), UV_TTY_MODE_RAW); + break; + case TTY::Mode::IO: + invoke(std::move(wrap), get(), UV_TTY_MODE_IO); + break; + } + } + + void reset() { invoke(&uv_tty_reset_mode); } + + WinSize getWinSize() { + std::pair size{0, 0}; + int width; + int height; + + if(0 == invoke(&uv_tty_get_winsize, get(), &width, &height)) { + size.first = width; + size.second = height; + } + + /** + * See Boost/Mutant idiom: + * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant + */ + return reinterpret_cast(size); + } + +private: + uv_file fd; + int rw; +}; + + +} diff --git a/src/uvw/util.hpp b/src/uvw/util.hpp index 665fdec1..86e09fd5 100644 --- a/src/uvw/util.hpp +++ b/src/uvw/util.hpp @@ -67,7 +67,12 @@ private: }; -using Addr = std::pair; +/** + * See Boost/Mutant idiom: + * https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Boost_mutant + */ +struct Addr { std::string ip; unsigned int port; }; +struct WinSize { int width; int height; }; } diff --git a/test/main.cpp b/test/main.cpp index 2b64e819..b085f446 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -31,10 +31,10 @@ void listen(uvw::Loop &loop) { srv.accept(*client); uvw::Addr local = srv.address(); - std::cout << "local: " << local.first << " " << local.second << std::endl; + std::cout << "local: " << local.ip << " " << local.port << std::endl; uvw::Addr remote = client->remote(); - std::cout << "remote: " << remote.first << " " << remote.second << std::endl; + std::cout << "remote: " << remote.ip << " " << remote.port << std::endl; client->on([](const uvw::DataEvent &event, uvw::Tcp &) { std::cout.write(event.data(), event.length()) << std::endl;