From b747062e09334b80e16f6dac5330b5a9b9744137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Heusipp?= Date: Mon, 23 Sep 2024 17:58:52 +0000 Subject: [PATCH] [Ref] openmpt123: Split textout buffer handling from textout backends. [Ref] openmpt123: Move platform-specific textout backend selection into textout_wrapper. [Ref] openmpt123: Avoid pushing cursor_up() through redundant transcoding. [Ref] openmpt123: Simplify platform-specific initialization in main(). [Ref] openmpt123: Cleanup FILE_mode_guard. git-svn-id: https://source.openmpt.org/svn/openmpt/trunk/OpenMPT@21704 56274372-70c3-4bfc-bfc3-4c3a0b034d27 --- openmpt123/openmpt123.cpp | 81 +++++++++-------------- openmpt123/openmpt123.hpp | 136 +++++++++++++++++++++++--------------- 2 files changed, 113 insertions(+), 104 deletions(-) diff --git a/openmpt123/openmpt123.cpp b/openmpt123/openmpt123.cpp index dce66686c1e..742f656c709 100644 --- a/openmpt123/openmpt123.cpp +++ b/openmpt123/openmpt123.cpp @@ -45,6 +45,7 @@ static const char * const license = #include #endif +#include "mpt/base/algorithm.hpp" #include "mpt/base/detect.hpp" #include "mpt/main/main.hpp" @@ -2078,8 +2079,7 @@ static void parse_openmpt123( commandlineflags & flags, const std::vector args ) { - FILE_mode_guard stdin_utf8_guard( stdin, FILE_mode::utf8 ); - FILE_mode_guard stdout_utf8_guard( stdout, FILE_mode::utf8 ); - FILE_mode_guard stderr_utf8_guard( stderr, FILE_mode::utf8 ); + FILE_mode_guard stdin_text_guard( stdin, FILE_mode::text ); + FILE_mode_guard stdout_text_guard( stdout, FILE_mode::text ); + FILE_mode_guard stderr_text_guard( stderr, FILE_mode::text ); + textout_dummy dummy_log; -#if MPT_OS_WINDOWS && !MPT_WINRT_BEFORE(MPT_WIN_10) -#if defined(UNICODE) - textout_ostream_console std_out( std::wcout, STD_OUTPUT_HANDLE ); - textout_ostream_console std_err( std::wclog, STD_ERROR_HANDLE ); -#else - textout_ostream_console std_out( std::cout, STD_OUTPUT_HANDLE ); - textout_ostream_console std_err( std::clog, STD_ERROR_HANDLE ); -#endif -#elif MPT_OS_WINDOWS -#if defined(UNICODE) - textout_wostream std_out( std::wcout ); - textout_wostream std_err( std::wclog ); -#else - textout_ostream std_out( std::cout ); - textout_ostream std_err( std::clog ); -#endif -#else - textout_ostream std_out( std::cout ); - textout_ostream std_err( std::clog ); -#endif + textout_wrapper std_out; + textout_wrapper std_err; commandlineflags flags; @@ -2274,29 +2261,23 @@ static mpt::uint8 main( std::vector args ) { try { - bool stdin_can_ui = true; - for ( const auto & filename : flags.filenames ) { - if ( filename == MPT_NATIVE_PATH("-") ) { - stdin_can_ui = false; - break; - } - } + const FILE_mode stdin_mode = mpt::contains( flags.filenames, MPT_NATIVE_PATH("-") ) ? FILE_mode::binary : FILE_mode::text; + const FILE_mode stdout_mode = flags.use_stdout ? FILE_mode::binary : FILE_mode::text; - bool stdout_can_ui = true; - if ( flags.use_stdout ) { - stdout_can_ui = false; - } + [[maybe_unused]] const bool stdin_text = ( stdin_mode == FILE_mode::text ); + [[maybe_unused]] const bool stdin_data = ( stdin_mode == FILE_mode::binary ); + [[maybe_unused]] const bool stdout_text = ( stdout_mode == FILE_mode::text ); + [[maybe_unused]] const bool stdout_data = ( stdout_mode == FILE_mode::binary ); - // set stdin binary - FILE_mode_guard stdin_guard( stdin, stdin_can_ui ? FILE_mode::unchanged : FILE_mode::binary ); + // set stdin/stdout to binary for data input/output + std::optional stdin_guard{ stdin_data ? std::make_optional( stdin, FILE_mode::binary ) : std::nullopt }; + std::optional stdout_guard{ stdout_data ? std::make_optional( stdout, FILE_mode::binary ) : std::nullopt }; - // set stdout binary - FILE_mode_guard stdout_guard( stdout, stdout_can_ui ? FILE_mode::unchanged : FILE_mode::binary ); + // setup terminal + std::optional input_guard{ stdin_text && ( flags.mode == Mode::UI ) ? std::make_optional() : std::nullopt }; - // setup terminal for ui mode - std::optional input_guard{ ( stdin_can_ui && ( flags.mode == Mode::UI ) ? std::make_optional() : std::nullopt ) }; - - textout & log = flags.quiet ? static_cast( dummy_log ) : static_cast( stdout_can_ui ? std_out : std_err ); + // choose text output between quiet/stdout/stderr + textout & log = flags.quiet ? static_cast( dummy_log ) : stdout_text ? static_cast( std_out ) : static_cast( std_err ); show_banner( log, flags.banner ); diff --git a/openmpt123/openmpt123.hpp b/openmpt123/openmpt123.hpp index 0a6e8287512..9107671cf58 100644 --- a/openmpt123/openmpt123.hpp +++ b/openmpt123/openmpt123.hpp @@ -174,13 +174,10 @@ inline bool IsTerminal( int fd ) { class textout : public string_concat_stream { +protected: + textout() = default; public: - textout() { - return; - } - virtual ~textout() { - return; - } + virtual ~textout() = default; protected: mpt::ustring pop() { mpt::ustring text = str(); @@ -189,26 +186,44 @@ class textout : public string_concat_stream { } public: virtual void writeout() = 0; - virtual void cursor_up( std::size_t lines ) { - static_cast( lines ); - } + virtual void cursor_up( std::size_t lines ) = 0; }; + + class textout_dummy : public textout { public: - textout_dummy() { - return; - } - virtual ~textout_dummy() { - return; - } + textout_dummy() = default; + ~textout_dummy() final = default; public: - void writeout() override { + void writeout() final { static_cast( pop() ); } + void cursor_up( std::size_t lines ) final { + static_cast( lines ); + } }; -class textout_ostream : public textout { + + +enum class textout_destination { + destination_stdout, + destination_stderr, +}; + +class textout_backend { +protected: + textout_backend() = default; +public: + virtual ~textout_backend() = default; +public: + virtual void write( const mpt::ustring & text ) = 0; + virtual void cursor_up(std::size_t lines) = 0; +}; + + + +class textout_ostream : public textout_backend { private: std::ostream & s; #if MPT_OS_DJGPP @@ -226,12 +241,9 @@ class textout_ostream : public textout { #endif return; } - virtual ~textout_ostream() { - writeout_impl(); - } -private: - void writeout_impl() { - mpt::ustring text = pop(); + ~textout_ostream() final = default; +public: + void write( const mpt::ustring & text ) final { if ( text.length() > 0 ) { #if MPT_OS_DJGPP s << mpt::transcode( codepage, text ); @@ -243,21 +255,17 @@ class textout_ostream : public textout { s.flush(); } } -public: - void writeout() override { - writeout_impl(); - } - void cursor_up( std::size_t lines ) override { + void cursor_up( std::size_t lines ) final { s.flush(); for ( std::size_t line = 0; line < lines; ++line ) { - *this << MPT_USTRING("\x1b[1A"); + s << std::string("\x1b[1A"); } } }; #if MPT_OS_WINDOWS && defined(UNICODE) -class textout_wostream : public textout { +class textout_wostream : public textout_backend { private: std::wostream & s; public: @@ -266,25 +274,18 @@ class textout_wostream : public textout { { return; } - virtual ~textout_wostream() { - writeout_impl(); - } -private: - void writeout_impl() { - mpt::ustring text = pop(); + ~textout_wostream() final = default; +public: + void write( const mpt::ustring & text ) final { if ( text.length() > 0 ) { s << mpt::transcode( text ); s.flush(); } } -public: - void writeout() override { - writeout_impl(); - } - void cursor_up( std::size_t lines ) override { + void cursor_up( std::size_t lines ) final { s.flush(); for ( std::size_t line = 0; line < lines; ++line ) { - *this << MPT_USTRING("\x1b[1A"); + s << std::wstring(L"\x1b[1A"); } } }; @@ -293,7 +294,7 @@ class textout_wostream : public textout { #if MPT_OS_WINDOWS && !MPT_WINRT_BEFORE(MPT_WIN_10) -class textout_ostream_console : public textout { +class textout_ostream_console : public textout_backend { private: #if defined(UNICODE) std::wostream & s; @@ -314,12 +315,9 @@ class textout_ostream_console : public textout { { return; } - virtual ~textout_ostream_console() { - writeout_impl(); - } -private: - void writeout_impl() { - mpt::ustring text = pop(); + ~textout_ostream_console() final = default; +public: + void write( const mpt::ustring & text ) final { if ( text.length() > 0 ) { if ( console ) { DWORD chars_written = 0; @@ -340,11 +338,7 @@ class textout_ostream_console : public textout { } } } -public: - void writeout() override { - writeout_impl(); - } - void cursor_up( std::size_t lines ) override { + void cursor_up( std::size_t lines ) final { if ( console ) { s.flush(); CONSOLE_SCREEN_BUFFER_INFO csbi; @@ -362,6 +356,40 @@ class textout_ostream_console : public textout { #endif // MPT_OS_WINDOWS && !MPT_WINRT_BEFORE(MPT_WIN_10) + + +template +class textout_wrapper : public textout { +private: +#if MPT_OS_WINDOWS && !MPT_WINRT_BEFORE(MPT_WIN_10) +#if defined(UNICODE) + textout_ostream_console out{ dest == textout_destination::destination_stdout ? std::wcout : std::wclog, dest == textout_destination::destination_stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE }; +#else + textout_ostream_console out{ dest == textout_destination::destination_stdout ? std::cout : std::clog, dest == textout_destination::destination_stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE }; +#endif +#elif MPT_OS_WINDOWS +#if defined(UNICODE) + textout_wostream out{ dest == textout_destination::destination_stdout ? std::wcout : std::wclog }; +#else + textout_wostream out{ dest == textout_destination::destination_stdout ? std::cout : std::clog }; +#endif +#else + textout_wostream out{ dest == textout_destination::destination_stdout ? std::cout : std::clog }; +#endif +public: + textout_wrapper() = default; + ~textout_wrapper() final = default; +public: + void writeout() final { + out.write( pop() ); + } + void cursor_up(std::size_t lines) final { + out.cursor_up( lines ); + } +}; + + + inline mpt::ustring append_software_tag( mpt::ustring software ) { mpt::ustring openmpt123 = mpt::ustring() + MPT_USTRING("openmpt123 ")