diff options
author | Brad King <brad.king@kitware.com> | 2016-11-09 14:23:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2016-11-09 14:23:18 (GMT) |
commit | 95a97a40e48a0db2b206c4560d6962be3666812c (patch) | |
tree | e7f6f0e6ffca54ee18f8c276735e8a60e45f8833 /Source/kwsys/ConsoleBuf.hxx.in | |
parent | 666bb0e3fa0d212c03f785bd9f6bc05d29925e1f (diff) | |
parent | 773b36e5d4af3ac040625e0ea16bcfd30fcdeb6d (diff) | |
download | CMake-95a97a40e48a0db2b206c4560d6962be3666812c.zip CMake-95a97a40e48a0db2b206c4560d6962be3666812c.tar.gz CMake-95a97a40e48a0db2b206c4560d6962be3666812c.tar.bz2 |
Merge branch 'upstream-KWSys' into update-kwsys
* upstream-KWSys:
KWSys 2016-11-09 (18c65411)
Diffstat (limited to 'Source/kwsys/ConsoleBuf.hxx.in')
-rw-r--r-- | Source/kwsys/ConsoleBuf.hxx.in | 629 |
1 files changed, 320 insertions, 309 deletions
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in index 2496b45..34c69a0 100644 --- a/Source/kwsys/ConsoleBuf.hxx.in +++ b/Source/kwsys/ConsoleBuf.hxx.in @@ -1,354 +1,365 @@ -/*============================================================================ - KWSys - Kitware System Library - Copyright 2000-2016 Kitware, Inc., Insight Software Consortium - - Distributed under the OSI-approved BSD License (the "License"); - see accompanying file Copyright.txt for details. - - This software is distributed WITHOUT ANY WARRANTY; without even the - implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the License for more information. -============================================================================*/ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing#kwsys for details. */ #ifndef @KWSYS_NAMESPACE@_ConsoleBuf_hxx #define @KWSYS_NAMESPACE@_ConsoleBuf_hxx #include <@KWSYS_NAMESPACE@/Configure.hxx> + #include <@KWSYS_NAMESPACE@/Encoding.hxx> -#include <string> + #include <cstring> -#include <sstream> -#include <streambuf> #include <iostream> +#include <sstream> #include <stdexcept> +#include <streambuf> +#include <string> #if defined(_WIN32) -# include <windows.h> -# if __cplusplus >= 201103L -# include <system_error> -# endif +#include <windows.h> +#if __cplusplus >= 201103L +#include <system_error> +#endif #endif -namespace @KWSYS_NAMESPACE@ -{ +namespace @KWSYS_NAMESPACE@ { #if defined(_WIN32) - template<class CharT, class Traits = std::char_traits<CharT> > - class @KWSYS_NAMESPACE@_EXPORT BasicConsoleBuf : - public std::basic_streambuf<CharT, Traits> { - public: - typedef typename Traits::int_type int_type; - typedef typename Traits::char_type char_type; - - class Manager { - public: - Manager(std::basic_ios<CharT, Traits> &ios, const bool err = false) - : m_consolebuf(0) - { - m_ios = &ios; - try { - m_consolebuf = new BasicConsoleBuf<CharT, Traits>(err); - m_streambuf = m_ios->rdbuf(m_consolebuf); - } catch (const std::runtime_error& ex) { - std::cerr << "Failed to create ConsoleBuf!" << std::endl - << ex.what() << std::endl; - }; - } - - ~Manager() - { - if (m_consolebuf) { - delete m_consolebuf; - m_ios->rdbuf(m_streambuf); - } - } +template <class CharT, class Traits = std::char_traits<CharT> > +class @KWSYS_NAMESPACE@_EXPORT BasicConsoleBuf + : public std::basic_streambuf<CharT, Traits> +{ +public: + typedef typename Traits::int_type int_type; + typedef typename Traits::char_type char_type; - private: - std::basic_ios<CharT, Traits> *m_ios; - std::basic_streambuf<CharT, Traits> *m_streambuf; - BasicConsoleBuf<CharT, Traits> *m_consolebuf; + class Manager + { + public: + Manager(std::basic_ios<CharT, Traits>& ios, const bool err = false) + : m_consolebuf(0) + { + m_ios = &ios; + try { + m_consolebuf = new BasicConsoleBuf<CharT, Traits>(err); + m_streambuf = m_ios->rdbuf(m_consolebuf); + } catch (const std::runtime_error& ex) { + std::cerr << "Failed to create ConsoleBuf!" << std::endl + << ex.what() << std::endl; }; + } - BasicConsoleBuf(const bool err = false) : - flush_on_newline(true), - input_pipe_codepage(0), - output_pipe_codepage(0), - input_file_codepage(CP_UTF8), - output_file_codepage(CP_UTF8), - m_consolesCodepage(0) - { - m_hInput = ::GetStdHandle(STD_INPUT_HANDLE); - checkHandle(true, "STD_INPUT_HANDLE"); - if (!setActiveInputCodepage()) { - throw std::runtime_error("setActiveInputCodepage failed!"); - } - m_hOutput = err ? ::GetStdHandle(STD_ERROR_HANDLE) : - ::GetStdHandle(STD_OUTPUT_HANDLE); - checkHandle(false, err ? "STD_ERROR_HANDLE" : "STD_OUTPUT_HANDLE"); - if (!setActiveOutputCodepage()) { - throw std::runtime_error("setActiveOutputCodepage failed!"); - } - _setg(); - _setp(); + ~Manager() + { + if (m_consolebuf) { + delete m_consolebuf; + m_ios->rdbuf(m_streambuf); } + } - ~BasicConsoleBuf() throw() - { - sync(); - } + private: + std::basic_ios<CharT, Traits>* m_ios; + std::basic_streambuf<CharT, Traits>* m_streambuf; + BasicConsoleBuf<CharT, Traits>* m_consolebuf; + }; - bool activateCodepageChange() - { - return setActiveInputCodepage() && setActiveOutputCodepage(); - } + BasicConsoleBuf(const bool err = false) + : flush_on_newline(true) + , input_pipe_codepage(0) + , output_pipe_codepage(0) + , input_file_codepage(CP_UTF8) + , output_file_codepage(CP_UTF8) + , m_consolesCodepage(0) + { + m_hInput = ::GetStdHandle(STD_INPUT_HANDLE); + checkHandle(true, "STD_INPUT_HANDLE"); + if (!setActiveInputCodepage()) { + throw std::runtime_error("setActiveInputCodepage failed!"); + } + m_hOutput = err ? ::GetStdHandle(STD_ERROR_HANDLE) + : ::GetStdHandle(STD_OUTPUT_HANDLE); + checkHandle(false, err ? "STD_ERROR_HANDLE" : "STD_OUTPUT_HANDLE"); + if (!setActiveOutputCodepage()) { + throw std::runtime_error("setActiveOutputCodepage failed!"); + } + _setg(); + _setp(); + } - protected: - virtual int sync() { - bool success = true; - if (m_hInput && m_isConsoleInput && - ::FlushConsoleInputBuffer(m_hInput) == 0) { - success = false; - } - if (m_hOutput && !m_obuffer.empty()) { - const std::wstring wbuffer = getBuffer(m_obuffer); - if (m_isConsoleOutput) { - DWORD charsWritten; - success = ::WriteConsoleW(m_hOutput, wbuffer.c_str(), - (DWORD)wbuffer.size(), &charsWritten, - NULL) == 0 ? false : true; - } else { - DWORD bytesWritten; - std::string buffer; - success = encodeOutputBuffer(wbuffer, buffer); - if (success) { - success = ::WriteFile(m_hOutput, buffer.c_str(), - (DWORD)buffer.size(), &bytesWritten, - NULL) == 0 ? false : true; - } - } + ~BasicConsoleBuf() throw() { sync(); } + + bool activateCodepageChange() + { + return setActiveInputCodepage() && setActiveOutputCodepage(); + } + +protected: + virtual int sync() + { + bool success = true; + if (m_hInput && m_isConsoleInput && + ::FlushConsoleInputBuffer(m_hInput) == 0) { + success = false; + } + if (m_hOutput && !m_obuffer.empty()) { + const std::wstring wbuffer = getBuffer(m_obuffer); + if (m_isConsoleOutput) { + DWORD charsWritten; + success = + ::WriteConsoleW(m_hOutput, wbuffer.c_str(), (DWORD)wbuffer.size(), + &charsWritten, NULL) == 0 + ? false + : true; + } else { + DWORD bytesWritten; + std::string buffer; + success = encodeOutputBuffer(wbuffer, buffer); + if (success) { + success = ::WriteFile(m_hOutput, buffer.c_str(), + (DWORD)buffer.size(), &bytesWritten, NULL) == 0 + ? false + : true; } - m_ibuffer.clear(); - m_obuffer.clear(); - _setg(); - _setp(); - return success ? 0 : -1; } + } + m_ibuffer.clear(); + m_obuffer.clear(); + _setg(); + _setp(); + return success ? 0 : -1; + } - virtual int_type underflow() { - if (this->gptr() >= this->egptr()) { - if (!m_hInput) { - _setg(true); - return Traits::eof(); - } - if (m_isConsoleInput) { - wchar_t wbuffer[128]; - DWORD charsRead; - if (::ReadConsoleW(m_hInput, wbuffer, (sizeof(wbuffer) / sizeof(wbuffer[0])) - 1, - &charsRead, NULL) == 0 || charsRead == 0) { - _setg(true); - return Traits::eof(); - } - wbuffer[charsRead] = L'\0'; - setBuffer(wbuffer, m_ibuffer); - } else { - std::wstring totalBuffer; - std::wstring wbuffer; - char buffer[128]; - DWORD bytesRead; - while (::ReadFile(m_hInput, buffer, (sizeof(buffer) / sizeof(buffer[0])) - 1, - &bytesRead, NULL) == 0) { - if (::GetLastError() == ERROR_MORE_DATA) { - buffer[bytesRead] = '\0'; - if (decodeInputBuffer(buffer, wbuffer)) { - totalBuffer += wbuffer; - continue; - } - } - _setg(true); - return Traits::eof(); - } + virtual int_type underflow() + { + if (this->gptr() >= this->egptr()) { + if (!m_hInput) { + _setg(true); + return Traits::eof(); + } + if (m_isConsoleInput) { + wchar_t wbuffer[128]; + DWORD charsRead; + if (::ReadConsoleW(m_hInput, wbuffer, + (sizeof(wbuffer) / sizeof(wbuffer[0])) - 1, + &charsRead, NULL) == 0 || + charsRead == 0) { + _setg(true); + return Traits::eof(); + } + wbuffer[charsRead] = L'\0'; + setBuffer(wbuffer, m_ibuffer); + } else { + std::wstring totalBuffer; + std::wstring wbuffer; + char buffer[128]; + DWORD bytesRead; + while (::ReadFile(m_hInput, buffer, + (sizeof(buffer) / sizeof(buffer[0])) - 1, &bytesRead, + NULL) == 0) { + if (::GetLastError() == ERROR_MORE_DATA) { buffer[bytesRead] = '\0'; - if (!decodeInputBuffer(buffer, wbuffer)) { - _setg(true); - return Traits::eof(); + if (decodeInputBuffer(buffer, wbuffer)) { + totalBuffer += wbuffer; + continue; } - totalBuffer += wbuffer; - setBuffer(totalBuffer, m_ibuffer); } - _setg(); + _setg(true); + return Traits::eof(); + } + buffer[bytesRead] = '\0'; + if (!decodeInputBuffer(buffer, wbuffer)) { + _setg(true); + return Traits::eof(); } - return Traits::to_int_type(*this->gptr()); + totalBuffer += wbuffer; + setBuffer(totalBuffer, m_ibuffer); } + _setg(); + } + return Traits::to_int_type(*this->gptr()); + } - virtual int_type overflow(int_type ch = Traits::eof()) { - if (!Traits::eq_int_type(ch, Traits::eof())) { - char_type chr = Traits::to_char_type(ch); - m_obuffer += chr; - if ((flush_on_newline && Traits::eq(chr, '\n')) || - Traits::eq_int_type(ch, 0x00)) { - sync(); - } - return ch; - } + virtual int_type overflow(int_type ch = Traits::eof()) + { + if (!Traits::eq_int_type(ch, Traits::eof())) { + char_type chr = Traits::to_char_type(ch); + m_obuffer += chr; + if ((flush_on_newline && Traits::eq(chr, '\n')) || + Traits::eq_int_type(ch, 0x00)) { sync(); - return Traits::eof(); } + return ch; + } + sync(); + return Traits::eof(); + } - public: - bool flush_on_newline; - UINT input_pipe_codepage; - UINT output_pipe_codepage; - UINT input_file_codepage; - UINT output_file_codepage; +public: + bool flush_on_newline; + UINT input_pipe_codepage; + UINT output_pipe_codepage; + UINT input_file_codepage; + UINT output_file_codepage; - private: - HANDLE m_hInput; - HANDLE m_hOutput; - std::basic_string<char_type> m_ibuffer; - std::basic_string<char_type> m_obuffer; - bool m_isConsoleInput; - bool m_isConsoleOutput; - UINT m_activeInputCodepage; - UINT m_activeOutputCodepage; - UINT m_consolesCodepage; - void checkHandle(bool input, std::string handleName) { - if ((input && m_hInput == INVALID_HANDLE_VALUE) || - (!input && m_hOutput == INVALID_HANDLE_VALUE)) { - std::string errmsg = "GetStdHandle(" + handleName + - ") returned INVALID_HANDLE_VALUE"; +private: + HANDLE m_hInput; + HANDLE m_hOutput; + std::basic_string<char_type> m_ibuffer; + std::basic_string<char_type> m_obuffer; + bool m_isConsoleInput; + bool m_isConsoleOutput; + UINT m_activeInputCodepage; + UINT m_activeOutputCodepage; + UINT m_consolesCodepage; + void checkHandle(bool input, std::string handleName) + { + if ((input && m_hInput == INVALID_HANDLE_VALUE) || + (!input && m_hOutput == INVALID_HANDLE_VALUE)) { + std::string errmsg = + "GetStdHandle(" + handleName + ") returned INVALID_HANDLE_VALUE"; #if __cplusplus >= 201103L - throw std::system_error(::GetLastError(), - std::system_category(), errmsg); + throw std::system_error(::GetLastError(), std::system_category(), + errmsg); #else - throw std::runtime_error(errmsg); + throw std::runtime_error(errmsg); #endif - } + } + } + UINT getConsolesCodepage() + { + if (!m_consolesCodepage) { + m_consolesCodepage = GetConsoleCP(); + if (!m_consolesCodepage) { + m_consolesCodepage = GetACP(); } - UINT getConsolesCodepage() { - if (!m_consolesCodepage) { - m_consolesCodepage = GetConsoleCP(); - if (!m_consolesCodepage) { - m_consolesCodepage = GetACP(); - } + } + return m_consolesCodepage; + } + bool setActiveInputCodepage() + { + m_isConsoleInput = false; + switch (GetFileType(m_hInput)) { + case FILE_TYPE_DISK: + m_activeInputCodepage = input_file_codepage; + break; + case FILE_TYPE_CHAR: + // Check for actual console. + DWORD consoleMode; + m_isConsoleInput = + GetConsoleMode(m_hInput, &consoleMode) == 0 ? false : true; + if (m_isConsoleInput) { + break; } - return m_consolesCodepage; - } - bool setActiveInputCodepage() { - m_isConsoleInput = false; - switch (GetFileType(m_hInput)) { - case FILE_TYPE_DISK: - m_activeInputCodepage = input_file_codepage; - break; - case FILE_TYPE_CHAR: - // Check for actual console. - DWORD consoleMode; - m_isConsoleInput = GetConsoleMode(m_hInput, &consoleMode) == 0 ? false : true; - if (m_isConsoleInput) { - break; - } - case FILE_TYPE_PIPE: - m_activeInputCodepage = input_pipe_codepage; - break; - default: - return false; - } - if (!m_isConsoleInput && m_activeInputCodepage == 0) { - m_activeInputCodepage = getConsolesCodepage(); + case FILE_TYPE_PIPE: + m_activeInputCodepage = input_pipe_codepage; + break; + default: + return false; + } + if (!m_isConsoleInput && m_activeInputCodepage == 0) { + m_activeInputCodepage = getConsolesCodepage(); + } + return true; + } + bool setActiveOutputCodepage() + { + m_isConsoleOutput = false; + switch (GetFileType(m_hOutput)) { + case FILE_TYPE_DISK: + m_activeOutputCodepage = output_file_codepage; + break; + case FILE_TYPE_CHAR: + // Check for actual console. + DWORD consoleMode; + m_isConsoleOutput = + GetConsoleMode(m_hOutput, &consoleMode) == 0 ? false : true; + if (m_isConsoleOutput) { + break; } - return true; - } - bool setActiveOutputCodepage() { - m_isConsoleOutput = false; - switch (GetFileType(m_hOutput)) { - case FILE_TYPE_DISK: - m_activeOutputCodepage = output_file_codepage; - break; - case FILE_TYPE_CHAR: - // Check for actual console. - DWORD consoleMode; - m_isConsoleOutput = GetConsoleMode(m_hOutput, &consoleMode) == 0 ? false : true; - if (m_isConsoleOutput) { - break; - } - case FILE_TYPE_PIPE: - m_activeOutputCodepage = output_pipe_codepage; - break; - default: - return false; - } - if (!m_isConsoleOutput && m_activeOutputCodepage == 0) { - m_activeOutputCodepage = getConsolesCodepage(); - } - return true; - } - void _setg(bool empty = false) { - if (!empty) { - this->setg((char_type *)m_ibuffer.data(), - (char_type *)m_ibuffer.data(), - (char_type *)m_ibuffer.data() + m_ibuffer.size()); - } else { - this->setg((char_type *)m_ibuffer.data(), - (char_type *)m_ibuffer.data() + m_ibuffer.size(), - (char_type *)m_ibuffer.data() + m_ibuffer.size()); - } - } - void _setp() { - this->setp((char_type *)m_obuffer.data(), - (char_type *)m_obuffer.data() + m_obuffer.size()); - } - bool encodeOutputBuffer(const std::wstring wbuffer, - std::string &buffer) { - const int length = WideCharToMultiByte(m_activeOutputCodepage, 0, - wbuffer.c_str(), - (int)wbuffer.size(), NULL, 0, - NULL, NULL); - char *buf = new char[length + 1]; - const bool success = WideCharToMultiByte(m_activeOutputCodepage, 0, - wbuffer.c_str(), - (int)wbuffer.size(), buf, - length, NULL, NULL) > 0 - ? true : false; - buf[length] = '\0'; - buffer = buf; - delete[] buf; - return success; - } - bool decodeInputBuffer(const char *buffer, std::wstring &wbuffer) { - int actualCodepage = m_activeInputCodepage; - const char BOM_UTF8[] = { char(0xEF), char(0xBB), char(0xBF) }; - if (std::memcmp(buffer, BOM_UTF8, sizeof(BOM_UTF8)) == 0) { - // PowerShell uses UTF-8 with BOM for pipes - actualCodepage = CP_UTF8; - buffer += sizeof(BOM_UTF8); - } - const int wlength = MultiByteToWideChar(actualCodepage, 0, buffer, - -1, NULL, 0); - wchar_t *wbuf = new wchar_t[wlength]; - const bool success = MultiByteToWideChar(actualCodepage, 0, buffer, - -1, wbuf, wlength) > 0 - ? true : false; - wbuffer = wbuf; - delete[] wbuf; - return success; - } - std::wstring getBuffer(const std::basic_string<char> buffer) { - return Encoding::ToWide(buffer); - } - std::wstring getBuffer(const std::basic_string<wchar_t> buffer) { - return buffer; - } - void setBuffer(const std::wstring wbuffer, - std::basic_string<char> &target) { - target = Encoding::ToNarrow(wbuffer); - } - void setBuffer(const std::wstring wbuffer, - std::basic_string<wchar_t> &target) { - target = wbuffer; - } + case FILE_TYPE_PIPE: + m_activeOutputCodepage = output_pipe_codepage; + break; + default: + return false; + } + if (!m_isConsoleOutput && m_activeOutputCodepage == 0) { + m_activeOutputCodepage = getConsolesCodepage(); + } + return true; + } + void _setg(bool empty = false) + { + if (!empty) { + this->setg((char_type*)m_ibuffer.data(), (char_type*)m_ibuffer.data(), + (char_type*)m_ibuffer.data() + m_ibuffer.size()); + } else { + this->setg((char_type*)m_ibuffer.data(), + (char_type*)m_ibuffer.data() + m_ibuffer.size(), + (char_type*)m_ibuffer.data() + m_ibuffer.size()); + } + } + void _setp() + { + this->setp((char_type*)m_obuffer.data(), + (char_type*)m_obuffer.data() + m_obuffer.size()); + } + bool encodeOutputBuffer(const std::wstring wbuffer, std::string& buffer) + { + const int length = + WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(), + (int)wbuffer.size(), NULL, 0, NULL, NULL); + char* buf = new char[length + 1]; + const bool success = + WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(), + (int)wbuffer.size(), buf, length, NULL, NULL) > 0 + ? true + : false; + buf[length] = '\0'; + buffer = buf; + delete[] buf; + return success; + } + bool decodeInputBuffer(const char* buffer, std::wstring& wbuffer) + { + int actualCodepage = m_activeInputCodepage; + const char BOM_UTF8[] = { char(0xEF), char(0xBB), char(0xBF) }; + if (std::memcmp(buffer, BOM_UTF8, sizeof(BOM_UTF8)) == 0) { + // PowerShell uses UTF-8 with BOM for pipes + actualCodepage = CP_UTF8; + buffer += sizeof(BOM_UTF8); + } + const int wlength = + MultiByteToWideChar(actualCodepage, 0, buffer, -1, NULL, 0); + wchar_t* wbuf = new wchar_t[wlength]; + const bool success = + MultiByteToWideChar(actualCodepage, 0, buffer, -1, wbuf, wlength) > 0 + ? true + : false; + wbuffer = wbuf; + delete[] wbuf; + return success; + } + std::wstring getBuffer(const std::basic_string<char> buffer) + { + return Encoding::ToWide(buffer); + } + std::wstring getBuffer(const std::basic_string<wchar_t> buffer) + { + return buffer; + } + void setBuffer(const std::wstring wbuffer, std::basic_string<char>& target) + { + target = Encoding::ToNarrow(wbuffer); + } + void setBuffer(const std::wstring wbuffer, + std::basic_string<wchar_t>& target) + { + target = wbuffer; + } - }; // BasicConsoleBuf class +}; // BasicConsoleBuf class - typedef BasicConsoleBuf<char> ConsoleBuf; - typedef BasicConsoleBuf<wchar_t> WConsoleBuf; +typedef BasicConsoleBuf<char> ConsoleBuf; +typedef BasicConsoleBuf<wchar_t> WConsoleBuf; #endif } // KWSYS_NAMESPACE |