Skip to content

Commit

Permalink
[Ref] openmpt123: Split textout buffer handling from textout backends.
Browse files Browse the repository at this point in the history
[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
  • Loading branch information
manxorist committed Sep 23, 2024
1 parent 5aa1672 commit b747062
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 104 deletions.
81 changes: 31 additions & 50 deletions openmpt123/openmpt123.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ static const char * const license =
#include <sys/types.h>
#endif

#include "mpt/base/algorithm.hpp"
#include "mpt/base/detect.hpp"
#include "mpt/main/main.hpp"

Expand Down Expand Up @@ -2078,8 +2079,7 @@ static void parse_openmpt123( commandlineflags & flags, const std::vector<mpt::u
}

enum class FILE_mode {
unchanged,
utf8,
text,
binary,
};

Expand All @@ -2095,7 +2095,7 @@ class FILE_mode_guard {
, old_mode(-1)
{
switch (new_mode) {
case FILE_mode::utf8:
case FILE_mode::text:
fflush( file );
#if defined(UNICODE)
old_mode = _setmode( _fileno( file ), _O_U8TEXT );
Expand All @@ -2113,11 +2113,12 @@ class FILE_mode_guard {
throw exception( MPT_USTRING("failed to set binary mode on file descriptor") );
}
break;
default:
// nothing
break;
}
}
FILE_mode_guard( const FILE_mode_guard & ) = delete;
FILE_mode_guard( FILE_mode_guard && ) = default;
FILE_mode_guard & operator=( const FILE_mode_guard & ) = delete;
FILE_mode_guard & operator=( FILE_mode_guard && ) = default;
~FILE_mode_guard() {
if ( old_mode != -1 ) {
fflush( file );
Expand All @@ -2140,10 +2141,13 @@ class terminal_ui_guard {

class FILE_mode_guard {
public:
FILE_mode_guard( FILE * /* file */, FILE_mode /* new_mode */ )
{
FILE_mode_guard( FILE * /* file */, FILE_mode /* new_mode */ ) {
return;
}
FILE_mode_guard( const FILE_mode_guard & ) = delete;
FILE_mode_guard( FILE_mode_guard && ) = default;
FILE_mode_guard & operator=( const FILE_mode_guard & ) = delete;
FILE_mode_guard & operator=( FILE_mode_guard && ) = default;
~FILE_mode_guard() = default;
};

Expand Down Expand Up @@ -2180,30 +2184,13 @@ class terminal_ui_guard {

static mpt::uint8 main( std::vector<mpt::ustring> 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<textout_destination::destination_stdout> std_out;
textout_wrapper<textout_destination::destination_stderr> std_err;

commandlineflags flags;

Expand Down Expand Up @@ -2274,29 +2261,23 @@ static mpt::uint8 main( std::vector<mpt::ustring> 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<FILE_mode_guard> stdin_guard{ stdin_data ? std::make_optional<FILE_mode_guard>( stdin, FILE_mode::binary ) : std::nullopt };
std::optional<FILE_mode_guard> stdout_guard{ stdout_data ? std::make_optional<FILE_mode_guard>( 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<terminal_ui_guard> input_guard{ stdin_text && ( flags.mode == Mode::UI ) ? std::make_optional<terminal_ui_guard>() : std::nullopt };

// setup terminal for ui mode
std::optional<terminal_ui_guard> input_guard{ ( stdin_can_ui && ( flags.mode == Mode::UI ) ? std::make_optional<terminal_ui_guard>() : std::nullopt ) };

textout & log = flags.quiet ? static_cast<textout&>( dummy_log ) : static_cast<textout&>( stdout_can_ui ? std_out : std_err );
// choose text output between quiet/stdout/stderr
textout & log = flags.quiet ? static_cast<textout&>( dummy_log ) : stdout_text ? static_cast<textout&>( std_out ) : static_cast<textout&>( std_err );

show_banner( log, flags.banner );

Expand Down
136 changes: 82 additions & 54 deletions openmpt123/openmpt123.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,10 @@ inline bool IsTerminal( int fd ) {


class textout : public string_concat_stream<mpt::ustring> {
protected:
textout() = default;
public:
textout() {
return;
}
virtual ~textout() {
return;
}
virtual ~textout() = default;
protected:
mpt::ustring pop() {
mpt::ustring text = str();
Expand All @@ -189,26 +186,44 @@ class textout : public string_concat_stream<mpt::ustring> {
}
public:
virtual void writeout() = 0;
virtual void cursor_up( std::size_t lines ) {
static_cast<void>( 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<void>( pop() );
}
void cursor_up( std::size_t lines ) final {
static_cast<void>( 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
Expand All @@ -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<std::string>( codepage, text );
Expand All @@ -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:
Expand All @@ -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<std::wstring>( 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");
}
}
};
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -362,6 +356,40 @@ class textout_ostream_console : public textout {

#endif // MPT_OS_WINDOWS && !MPT_WINRT_BEFORE(MPT_WIN_10)



template <textout_destination dest>
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 ")
Expand Down

0 comments on commit b747062

Please sign in to comment.