From a7dddd9f3b506959667cfc818858d4179fb48bc4 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 21 Oct 2017 22:06:08 +0200 Subject: [PATCH] Refactor wxLog and wxMessageOutput classes to avoid duplication Add wxMessageOutputWithConv mix-in class to avoid duplicating the same code in wxLogStream and wxMessageOutputStderr. Also derive wxLogStderr from wxMessageOutputStderr to reuse its code without having to create a temporary object of this type (which will be more expensive now that doing it involves creating a heap-allocated conversion object copy). --- include/wx/log.h | 17 ++++++++-------- include/wx/msgout.h | 46 +++++++++++++++++++++++++++++++++---------- src/common/log.cpp | 41 ++++++-------------------------------- src/common/msgout.cpp | 42 ++++++++++++++++++++------------------- 4 files changed, 72 insertions(+), 74 deletions(-) diff --git a/include/wx/log.h b/include/wx/log.h index e83c2fcea8..fa2efb5ee0 100644 --- a/include/wx/log.h +++ b/include/wx/log.h @@ -61,6 +61,7 @@ class WXDLLIMPEXP_FWD_BASE wxObject; #include "wx/dynarray.h" #include "wx/hashmap.h" +#include "wx/msgout.h" #if wxUSE_THREADS #include "wx/thread.h" @@ -716,34 +717,31 @@ private: // log everything to a "FILE *", stderr by default -class WXDLLIMPEXP_BASE wxLogStderr : public wxLog +class WXDLLIMPEXP_BASE wxLogStderr : public wxLog, + private wxMessageOutputStderr { public: // redirect log output to a FILE wxLogStderr(FILE *fp = NULL, const wxMBConv &conv = wxConvWhateverWorks); - virtual ~wxLogStderr(); protected: // implement sink function virtual void DoLogText(const wxString& msg) wxOVERRIDE; - FILE *m_fp; - const wxMBConv *m_conv; - wxDECLARE_NO_COPY_CLASS(wxLogStderr); }; #if wxUSE_STD_IOSTREAM // log everything to an "ostream", cerr by default -class WXDLLIMPEXP_BASE wxLogStream : public wxLog +class WXDLLIMPEXP_BASE wxLogStream : public wxLog, + private wxMessageOutputWithConv { public: // redirect log output to an ostream wxLogStream(wxSTD ostream *ostr = (wxSTD ostream *) NULL, - const wxMBConv &conv = wxConvWhateverWorks); - virtual ~wxLogStream(); + const wxMBConv& conv = wxConvWhateverWorks); protected: // implement sink function @@ -751,7 +749,8 @@ protected: // using ptr here to avoid including from this file wxSTD ostream *m_ostr; - const wxMBConv *m_conv; + + wxDECLARE_NO_COPY_CLASS(wxLogStream); }; #endif // wxUSE_STD_IOSTREAM diff --git a/include/wx/msgout.h b/include/wx/msgout.h index 8f0aa85757..c687661c41 100644 --- a/include/wx/msgout.h +++ b/include/wx/msgout.h @@ -58,25 +58,51 @@ private: }; // ---------------------------------------------------------------------------- -// implementation which sends output to stderr or specified file +// helper mix-in for output targets that can use difference encodings // ---------------------------------------------------------------------------- -class WXDLLIMPEXP_BASE wxMessageOutputStderr : public wxMessageOutput +class WXDLLIMPEXP_BASE wxMessageOutputWithConv { -public: - wxMessageOutputStderr(FILE *fp = stderr, - const wxMBConv &conv = wxConvWhateverWorks); - virtual ~wxMessageOutputStderr(); - - virtual void Output(const wxString& str) wxOVERRIDE; - protected: + explicit wxMessageOutputWithConv(const wxMBConv& conv) + : m_conv(conv.Clone()) + { + } + + ~wxMessageOutputWithConv() + { + delete m_conv; + } + // return the string with "\n" appended if it doesn't already terminate // with it (in which case it's returned unchanged) wxString AppendLineFeedIfNeeded(const wxString& str); + // Prepare the given string for output by appending a new line to it, if + // necessary, and converting it to a narrow string using our conversion + // object. + wxCharBuffer PrepareForOutput(const wxString& str); + + const wxMBConv* const m_conv; +}; + +// ---------------------------------------------------------------------------- +// implementation which sends output to stderr or specified file +// ---------------------------------------------------------------------------- + +class WXDLLIMPEXP_BASE wxMessageOutputStderr : public wxMessageOutput, + protected wxMessageOutputWithConv +{ +public: + wxMessageOutputStderr(FILE *fp = stderr, + const wxMBConv &conv = wxConvWhateverWorks); + + virtual void Output(const wxString& str) wxOVERRIDE; + +protected: FILE *m_fp; - const wxMBConv *m_conv; + + wxDECLARE_NO_COPY_CLASS(wxMessageOutputStderr); }; // ---------------------------------------------------------------------------- diff --git a/src/common/log.cpp b/src/common/log.cpp index ca627a0cb7..d5a59ff502 100644 --- a/src/common/log.cpp +++ b/src/common/log.cpp @@ -839,18 +839,9 @@ void wxLogBuffer::DoLogTextAtLevel(wxLogLevel level, const wxString& msg) // wxLogStderr class implementation // ---------------------------------------------------------------------------- -wxLogStderr::wxLogStderr(FILE *fp, const wxMBConv &conv): -m_conv(conv.Clone()) +wxLogStderr::wxLogStderr(FILE *fp, const wxMBConv& conv) + : wxMessageOutputStderr(fp ? fp : stderr, conv) { - if ( fp == NULL ) - m_fp = stderr; - else - m_fp = fp; -} - -wxLogStderr::~wxLogStderr() -{ - delete m_conv; } void wxLogStderr::DoLogText(const wxString& msg) @@ -858,7 +849,7 @@ void wxLogStderr::DoLogText(const wxString& msg) // First send it to stderr, even if we don't have it (e.g. in a Windows GUI // application under) it's not a problem to try to use it and it's easier // than determining whether we do have it or not. - wxMessageOutputStderr(m_fp, *m_conv).Output(msg); + wxMessageOutputStderr::Output(msg); // under GUI systems such as Windows or Mac, programs usually don't have // stderr at all, so show the messages also somewhere else, typically in @@ -880,8 +871,8 @@ void wxLogStderr::DoLogText(const wxString& msg) #if wxUSE_STD_IOSTREAM #include "wx/ioswrap.h" -wxLogStream::wxLogStream(wxSTD ostream *ostr, const wxMBConv &conv): -m_conv(conv.Clone()) +wxLogStream::wxLogStream(wxSTD ostream *ostr, const wxMBConv& conv) + : wxMessageOutputWithConv(conv) { if ( ostr == NULL ) m_ostr = &wxSTD cerr; @@ -889,29 +880,9 @@ m_conv(conv.Clone()) m_ostr = ostr; } -wxLogStream::~wxLogStream() -{ - delete m_conv; -} - void wxLogStream::DoLogText(const wxString& msg) { - wxString msgLF(msg); - if ( msgLF.empty() || *msgLF.rbegin() != '\n' ) - msgLF += '\n'; - -#if defined(__WINDOWS__) - // Determine whether the encoding is UTF-16. In that case, the file - // should have been opened in "wb" mode, and EOL-style must be handled - // here. - - if (m_conv->GetMBNulLen() == 2) - { - msgLF.Replace("\n", "\r\n"); - } -#endif - - const wxCharBuffer buf = m_conv->cWX2MB(msgLF.c_str()); + const wxCharBuffer& buf = PrepareForOutput(msg); m_ostr->write(buf, buf.length()); } #endif // wxUSE_STD_IOSTREAM diff --git a/src/common/msgout.cpp b/src/common/msgout.cpp index b20346d62b..1be492f520 100644 --- a/src/common/msgout.cpp +++ b/src/common/msgout.cpp @@ -133,21 +133,10 @@ void wxMessageOutputBest::Output(const wxString& str) } // ---------------------------------------------------------------------------- -// wxMessageOutputStderr +// wxMessageOutputWithConv // ---------------------------------------------------------------------------- -wxMessageOutputStderr::wxMessageOutputStderr(FILE *fp, - const wxMBConv &conv): -m_fp(fp), m_conv(conv.Clone()) -{ -} - -wxMessageOutputStderr::~wxMessageOutputStderr() -{ - delete m_conv; -} - -wxString wxMessageOutputStderr::AppendLineFeedIfNeeded(const wxString& str) +wxString wxMessageOutputWithConv::AppendLineFeedIfNeeded(const wxString& str) { wxString strLF(str); if ( strLF.empty() || *strLF.rbegin() != '\n' ) @@ -156,23 +145,36 @@ wxString wxMessageOutputStderr::AppendLineFeedIfNeeded(const wxString& str) return strLF; } -void wxMessageOutputStderr::Output(const wxString& str) +wxCharBuffer wxMessageOutputWithConv::PrepareForOutput(const wxString& str) { wxString strWithLF = AppendLineFeedIfNeeded(str); #if defined(__WINDOWS__) // Determine whether the encoding is UTF-16. In that case, the file - // should have been opened in "wb" mode, and EOL-style must be handled - // here. - - if (m_conv->GetMBNulLen() == 2) + // should have been opened in "wb" mode, and EOL conversion must be done + // here as it won't be done at stdio level. + if ( m_conv->GetMBNulLen() == 2 ) { strWithLF.Replace("\n", "\r\n"); } -#endif +#endif // __WINDOWS__ - const wxCharBuffer buf = m_conv->cWX2MB(strWithLF.c_str()); + return m_conv->cWX2MB(strWithLF.c_str()); +} +// ---------------------------------------------------------------------------- +// wxMessageOutputStderr +// ---------------------------------------------------------------------------- + +wxMessageOutputStderr::wxMessageOutputStderr(FILE *fp, const wxMBConv& conv) + : wxMessageOutputWithConv(conv), + m_fp(fp) +{ +} + +void wxMessageOutputStderr::Output(const wxString& str) +{ + const wxCharBuffer& buf = PrepareForOutput(str); fwrite(buf, buf.length(), 1, m_fp); fflush(m_fp); }