From 1b0f127931b54bd9ae43ccbf8fd8c7d7f55aad19 Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Sat, 8 May 2021 02:16:21 +0800 Subject: [PATCH 1/2] `onError` for common error-processing logic --- terminal/src/terminal.cpp | 65 ++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/terminal/src/terminal.cpp b/terminal/src/terminal.cpp index 7c2c2b7..3ae9d3a 100644 --- a/terminal/src/terminal.cpp +++ b/terminal/src/terminal.cpp @@ -20,6 +20,31 @@ #include #include #include +#include + +namespace { +struct charSpan { + const char *content; + unsigned len; + charSpan(const char *content, const unsigned len): + content(content), len(len) {} + template + charSpan(const char (&content)[N]): charSpan(content, N) {} +}; +void onError(int return_code, const charSpan error_prefix) { + if (return_code < 0) { + std::string error_message{error_prefix.content, error_prefix.len}; + error_message += strerror(errno); + throw std::runtime_error(std::move(error_message)); + } +} +void write(int term, const charSpan content, const charSpan error_prefix) { + onError( + ::write(term, content.content, content.len) != content.len ? -1 : 0, + error_prefix + ); +} +} namespace hacktile { namespace terminal { @@ -31,12 +56,8 @@ initializedTerminal::initializedTerminal(int term): term(term) { // Retrieve the original flag of terminal, so that they // could be recovered once the program has exit. - if(tcgetattr(term, &terminalMode) < 0) { - std::stringstream error; - error << "cannot fetch terminal attribute: " - << strerror(errno); - throw std::runtime_error(error.str()); - } + onError(tcgetattr(term, &terminalMode), + "cannot fetch terminal attribute: "); } initializedTerminal::~initializedTerminal() { // Reset the screen display mode. @@ -53,29 +74,19 @@ newTerminal::newTerminal(int term): initializedTerminal(term) { newTerminalMode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); newTerminalMode.c_cc[VMIN] = 1; newTerminalMode.c_cc[VTIME] = 0; - if(tcsetattr(term, TCSANOW, &newTerminalMode) < 0) { - std::stringstream error; - error << "cannot initialize terminal: " - << strerror(errno); - throw std::runtime_error(error.str()); - } + onError(tcsetattr(term, TCSANOW, &newTerminalMode), + "cannot initialize terminal: "); } clearScreen::clearScreen(int term): newTerminal(term) { // Initialize the current screen for printing. - char initScreen[] = control "2J" control "0;0H" control "?25l"; - size_t lenInitScreen = sizeof(initScreen); - if(write(term, initScreen, lenInitScreen) != lenInitScreen) { - std::stringstream error; - error << "cannot setup terminal screen: " - << strerror(errno); - throw std::runtime_error(error.str()); - } + write(term, control "2J" control "0;0H" control "?25l", + "cannot setup terminal screen: "); } clearScreen::~clearScreen() { // Clear screen data and reset the pointer. - char resetPointer[] = control "0;0H" control "?25h" control "2J"; - write(term, resetPointer, sizeof(resetPointer)); + write(term, control "0;0H" control "?25h" control "2J", + "cannot reset pointer: "); } } @@ -191,13 +202,9 @@ void terminal::append(const char* s, size_t length) { } void terminal::flush() { - if(write(term, buffer.data(), buffer.size()) != buffer.size()) { - std::stringstream error; - error << "cannot write to terminal: " << strerror(errno); - throw std::runtime_error(error.str()); - } else { - buffer = std::vector(); - } + write(term, charSpan{buffer.data(), buffer.size()}, + "cannot write to terminal: "); + buffer = std::vector(); } } // namespace hacktile::terminal From d2fa12034062f729102988f630b84d08e5958a3a Mon Sep 17 00:00:00 2001 From: Imple Lee <80144331+ImpleLee@users.noreply.github.com> Date: Sat, 8 May 2021 02:33:11 +0800 Subject: [PATCH 2/2] `unsigned` -> `size_t` for array length --- terminal/src/terminal.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terminal/src/terminal.cpp b/terminal/src/terminal.cpp index 3ae9d3a..49526d3 100644 --- a/terminal/src/terminal.cpp +++ b/terminal/src/terminal.cpp @@ -25,10 +25,10 @@ namespace { struct charSpan { const char *content; - unsigned len; - charSpan(const char *content, const unsigned len): + std::size_t len; + charSpan(const char *content, const std::size_t len): content(content), len(len) {} - template + template charSpan(const char (&content)[N]): charSpan(content, N) {} }; void onError(int return_code, const charSpan error_prefix) {