From b910ce38be0a2ad2eb06d0399c6308b328d1e258 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Tue, 28 Aug 2012 07:12:31 +0200 Subject: [PATCH] restrict conversions being done in strbuffer --- src/help.cpp | 34 ++++++------ src/helpers.h | 33 ++++++++---- src/lastfm.cpp | 4 +- src/lyrics.cpp | 10 ++-- src/search_engine.cpp | 10 ++-- src/song_info.cpp | 17 +++--- src/strbuffer.h | 119 +++++++++++++++++++++++++++--------------- 7 files changed, 139 insertions(+), 88 deletions(-) diff --git a/src/help.cpp b/src/help.cpp index 2619c10b..a20021f8 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -94,23 +94,25 @@ std::string Help::DisplayKeys(const ActionType at) void Help::Section(const char *type, const char *title) { - *w << "\n " << fmtBold << type << " - " << title << fmtBoldEnd << "\n\n"; + *w << U("\n ") << fmtBold << TO_WSTRING(type) << U(" - "); + *w << TO_WSTRING(title) << fmtBoldEnd << '\n' << '\n'; } void Help::KeyDesc(const ActionType at, const char *desc) { - *w << " " << DisplayKeys(at) << " : " << desc << "\n"; + *w << U(" ") << DisplayKeys(at) << U(" : ") << TO_WSTRING(desc) << '\n'; } void Help::MouseDesc(std::string action, const char *desc, bool indent) { action.resize(31 - (indent ? 2 : 0), ' '); - *w << " " << (indent ? " " : "") << action << ": " << desc << "\n"; + *w << U(" ") << (indent ? U(" ") : U("")) << TO_WSTRING(action); + *w << U(": ") << TO_WSTRING(desc) << '\n'; } void Help::MouseColumn(const char *column) { - *w << fmtBold << " " << column << " column:\n" << fmtBoldEnd; + *w << fmtBold << U(" ") << TO_WSTRING(column) << U(" column:\n") << fmtBoldEnd; } void Help::GetKeybindings() @@ -126,7 +128,7 @@ void Help::GetKeybindings() KeyDesc(aPageDown, "Page down"); KeyDesc(aMoveHome, "Home"); KeyDesc(aMoveEnd, "End"); - *w << "\n"; + *w << '\n'; if (Config.screen_switcher_previous) { KeyDesc(aNextScreen, "Switch between current and last screen"); @@ -155,7 +157,7 @@ void Help::GetKeybindings() # ifdef ENABLE_CLOCK KeyDesc(aShowClock, "Show clock"); # endif // ENABLE_CLOCK - *w << "\n"; + *w << '\n'; KeyDesc(aShowServerInfo, "Show server info"); KeysSection("Global"); @@ -168,7 +170,7 @@ void Help::GetKeybindings() KeyDesc(aSeekBackward, "Seek backward in playing song"); KeyDesc(aVolumeDown, "Decrease volume by 2%"); KeyDesc(aVolumeUp, "Increase volume by 2%"); - *w << "\n"; + *w << '\n'; KeyDesc(aToggleSpaceMode, "Toggle space mode (select/add)"); KeyDesc(aToggleAddMode, "Toggle add mode (add or remove/always add)"); KeyDesc(aToggleMouse, "Toggle mouse support"); @@ -177,7 +179,7 @@ void Help::GetKeybindings() KeyDesc(aSelectAlbum, "Select songs of album around the cursor"); KeyDesc(aAddSelectedItems, "Add selected items to playlist"); KeyDesc(aAddRandomItems, "Add random items to playlist"); - *w << "\n"; + *w << '\n'; KeyDesc(aToggleRepeat, "Toggle repeat mode"); KeyDesc(aToggleRandom, "Toggle random mode"); KeyDesc(aToggleSingle, "Toggle single mode"); @@ -188,7 +190,7 @@ void Help::GetKeybindings() KeyDesc(aToggleCrossfade, "Toggle crossfade mode"); KeyDesc(aSetCrossfade, "Set crossfade"); KeyDesc(aUpdateDatabase, "Start music database update"); - *w << "\n"; + *w << '\n'; KeyDesc(aApplyFilter, "Apply filter"); KeyDesc(aDisableFilter, "Disable filter"); KeyDesc(aFindItemForward, "Find item forward"); @@ -215,7 +217,7 @@ void Help::GetKeybindings() KeyDesc(aToggleFetchingLyricsInBackground, "Toggle fetching lyrics for playing songs in background"); # endif // HAVE_CURL_CURL_H KeyDesc(aShowLyrics, "Show/hide song lyrics"); - *w << "\n"; + *w << '\n'; KeyDesc(aQuit, "Quit"); KeysSection("Playlist"); @@ -324,7 +326,7 @@ void Help::GetKeybindings() MouseSection("Global"); MouseDesc("Left click on \"Playing/Paused\"", "Play/pause"); MouseDesc("Left click on progressbar", "Jump to pointed position in playing song"); - *w << "\n"; + *w << '\n'; MouseDesc("Mouse wheel on \"Volume: xx\"", "Play/pause"); MouseDesc("Mouse wheel on main window", "Scroll"); @@ -335,7 +337,7 @@ void Help::GetKeybindings() MouseSection("Browser"); MouseDesc("Left click on directory", "Enter pointed directory"); MouseDesc("Right click on directory", "Add pointed directory to playlist"); - *w << "\n"; + *w << '\n'; MouseDesc("Left click on song/playlist", "Add pointed item to playlist"); MouseDesc("Right click on song/playlist", "Add pointed item to playlist and play it"); @@ -347,7 +349,7 @@ void Help::GetKeybindings() MouseColumn("Left/middle"); MouseDesc("Left click", "Select pointed item", true); MouseDesc("Right click", "Add item to playlist", true); - *w << "\n"; + *w << '\n'; MouseColumn("Right"); MouseDesc("Left Click", "Add pointed item to playlist", true); MouseDesc("Right Click", "Add pointed item to playlist and play it", true); @@ -356,7 +358,7 @@ void Help::GetKeybindings() MouseColumn("Left"); MouseDesc("Left click", "Select pointed item", true); MouseDesc("Right click", "Add item to playlist", true); - *w << "\n"; + *w << '\n'; MouseColumn("Right"); MouseDesc("Left click", "Add pointed item to playlist", true); MouseDesc("Right click", "Add pointed item to playlist and play it", true); @@ -370,11 +372,11 @@ void Help::GetKeybindings() MouseColumn("Left"); MouseDesc("Left click", "Enter pointed directory/select pointed album", true); MouseDesc("Right click", "Toggle view (directories/albums)", true); - *w << "\n"; + *w << '\n'; MouseColumn("Middle"); MouseDesc("Left click", "Select option", true); MouseDesc("Right click", "Set value/execute", true); - *w << "\n"; + *w << '\n'; MouseColumn("Right"); MouseDesc("Left click", "Select pointed item", true); MouseDesc("Right click", "Set value", true); diff --git a/src/helpers.h b/src/helpers.h index 48b34c8f..e23474d8 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -73,8 +73,19 @@ template std::string StringPairToString(const std::pair return pair.first; } +template struct StringConverter { + const char *operator()(const char *s) { return s; } +}; +template <> struct StringConverter< basic_buffer > { + std::wstring operator()(const char *s) { return ToWString(s); } +}; +template <> struct StringConverter { + std::basic_string operator()(const char *s) { return TO_WSTRING(s); } +}; + template void String2Buffer(const std::basic_string &s, basic_buffer &buf) { + StringConverter< basic_buffer > cnv; for (typename std::basic_string::const_iterator it = s.begin(); it != s.end(); ++it) { if (*it == '$') @@ -107,7 +118,7 @@ template void String2Buffer(const std::basic_string &s, basic_bu case '/': if (++it == s.end()) { - buf << "$/"; + buf << cnv("$/"); break; } switch (*it) @@ -149,6 +160,8 @@ template void String2Buffer(const std::basic_string &s, basic_bu template void ShowTime(T &buf, size_t length, bool short_names) { + StringConverter cnv; + const unsigned MINUTE = 60; const unsigned HOUR = 60*MINUTE; const unsigned DAY = 24*HOUR; @@ -157,37 +170,37 @@ template void ShowTime(T &buf, size_t length, bool short_names) unsigned years = length/YEAR; if (years) { - buf << years << (short_names ? "y" : (years == 1 ? " year" : " years")); + buf << years << cnv(short_names ? "y" : (years == 1 ? " year" : " years")); length -= years*YEAR; if (length) - buf << ", "; + buf << cnv(", "); } unsigned days = length/DAY; if (days) { - buf << days << (short_names ? "d" : (days == 1 ? " day" : " days")); + buf << days << cnv(short_names ? "d" : (days == 1 ? " day" : " days")); length -= days*DAY; if (length) - buf << ", "; + buf << cnv(", "); } unsigned hours = length/HOUR; if (hours) { - buf << hours << (short_names ? "h" : (hours == 1 ? " hour" : " hours")); + buf << hours << cnv(short_names ? "h" : (hours == 1 ? " hour" : " hours")); length -= hours*HOUR; if (length) - buf << ", "; + buf << cnv(", "); } unsigned minutes = length/MINUTE; if (minutes) { - buf << minutes << (short_names ? "m" : (minutes == 1 ? " minute" : " minutes")); + buf << minutes << cnv(short_names ? "m" : (minutes == 1 ? " minute" : " minutes")); length -= minutes*MINUTE; if (length) - buf << ", "; + buf << cnv(", "); } if (length) - buf << length << (short_names ? "s" : (length == 1 ? " second" : " seconds")); + buf << length << cnv(short_names ? "s" : (length == 1 ? " second" : " seconds")); } template void ShowTag(T &buf, const std::string &tag) diff --git a/src/lastfm.cpp b/src/lastfm.cpp index 179a5ca5..27db93cc 100644 --- a/src/lastfm.cpp +++ b/src/lastfm.cpp @@ -143,7 +143,7 @@ void Lastfm::Load() while (getline(input, line)) { if (!first) - *w << "\n"; + *w << '\n'; utf_to_locale(line); *w << line; first = 0; @@ -153,7 +153,7 @@ void Lastfm::Load() } else { - *w << "Fetching informations... "; + *w << U("Fetching informations... "); pthread_create(&itsDownloader, 0, DownloadWrapper, this); isDownloadInProgress = 1; } diff --git a/src/lyrics.cpp b/src/lyrics.cpp index d5b993c7..a55aa5f4 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -249,10 +249,10 @@ void *Lyrics::Download() bool fetcher_defined = itsFetcher && *itsFetcher; for (LyricsFetcher **plugin = fetcher_defined ? itsFetcher : lyricsPlugins; *plugin != 0; ++plugin) { - *w << "Fetching lyrics from " << fmtBold << (*plugin)->name() << fmtBoldEnd << "... "; + *w << U("Fetching lyrics from ") << fmtBold << TO_WSTRING((*plugin)->name()) << fmtBoldEnd << U("... "); result = (*plugin)->fetch(artist, title); if (result.first == false) - *w << clRed << result.second << clEnd << "\n"; + *w << clRed << TO_WSTRING(result.second) << clEnd << '\n'; else break; if (fetcher_defined) @@ -268,7 +268,7 @@ void *Lyrics::Download() *w << result.second; } else - *w << "\nLyrics weren't found."; + *w << '\n' << U("Lyrics weren't found."); isReadyToTake = 1; pthread_exit(0); @@ -338,7 +338,7 @@ void Lyrics::Load() while (getline(input, line)) { if (!first) - *w << "\n"; + *w << '\n'; utf_to_locale(line); *w << line; first = 0; @@ -353,7 +353,7 @@ void Lyrics::Load() pthread_create(&itsDownloader, 0, DownloadWrapper, this); isDownloadInProgress = 1; # else - *w << "Local lyrics not found. As ncmpcpp has been compiled without curl support, you can put appropriate lyrics into " << Config.lyrics_directory << " directory (file syntax is \"$ARTIST - $TITLE.txt\") or recompile ncmpcpp with curl support."; + *w << U("Local lyrics not found. As ncmpcpp has been compiled without curl support, you can put appropriate lyrics into ") << TO_WSTRING(Config.lyrics_directory) << U(" directory (file syntax is \"$ARTIST - $TITLE.txt\") or recompile ncmpcpp with curl support."); w->Flush(); # endif } diff --git a/src/search_engine.cpp b/src/search_engine.cpp index 0e39438a..73229e75 100644 --- a/src/search_engine.cpp +++ b/src/search_engine.cpp @@ -137,10 +137,12 @@ void SearchEngine::EnterPressed() if (option < ConstraintsNumber) { - Statusbar() << fmtBold << ConstraintsNames[option] << fmtBoldEnd << ": "; + std::string constraint = ConstraintsNames[option]; + Statusbar() << fmtBold << constraint << fmtBoldEnd << ": "; itsConstraints[option] = Global::wFooter->GetString(itsConstraints[option]); w->Current().buffer().Clear(); - w->Current().buffer() << fmtBold << std::setw(13) << std::left << ConstraintsNames[option] << fmtBoldEnd << ": "; + constraint.resize(13, ' '); + w->Current().buffer() << fmtBold << constraint << fmtBoldEnd << ": "; ShowTag(w->Current().buffer(), itsConstraints[option]); } else if (option == ConstraintsNumber+1) @@ -324,7 +326,9 @@ void SearchEngine::Prepare() for (size_t i = 0; i < ConstraintsNumber; ++i) { - (*w)[i].mkBuffer() << fmtBold << std::setw(13) << std::left << ConstraintsNames[i] << fmtBoldEnd << ": "; + std::string constraint = ConstraintsNames[i]; + constraint.resize(13, ' '); + (*w)[i].mkBuffer() << fmtBold << constraint << fmtBoldEnd << ": "; ShowTag((*w)[i].buffer(), itsConstraints[i]); } diff --git a/src/song_info.cpp b/src/song_info.cpp index 71c34ea8..beff130a 100644 --- a/src/song_info.cpp +++ b/src/song_info.cpp @@ -109,25 +109,24 @@ void SongInfo::PrepareSong(MPD::Song &s) s.SetComment(f.tag()->comment().to8Bit(1)); # endif // HAVE_TAGLIB_H - *w << fmtBold << Config.color1 << "Filename: " << fmtBoldEnd << Config.color2 << s.getName() << "\n" << clEnd; - *w << fmtBold << "Directory: " << fmtBoldEnd << Config.color2; + *w << fmtBold << Config.color1 << U("Filename: ") << fmtBoldEnd << Config.color2 << s.getName() << '\n' << clEnd; + *w << fmtBold << U("Directory: ") << fmtBoldEnd << Config.color2; ShowTag(*w, s.getDirectory()); - *w << "\n\n" << clEnd; - *w << fmtBold << "Length: " << fmtBoldEnd << Config.color2 << s.getLength() << "\n" << clEnd; + *w << U("\n\n") << clEnd; + *w << fmtBold << U("Length: ") << fmtBoldEnd << Config.color2 << s.getLength() << '\n' << clEnd; # ifdef HAVE_TAGLIB_H if (!f.isNull()) { - *w << fmtBold << "Bitrate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->bitrate() << " kbps\n" << clEnd; - *w << fmtBold << "Sample rate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->sampleRate() << " Hz\n" << clEnd; - *w << fmtBold << "Channels: " << fmtBoldEnd << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << "\n" << clDefault; + *w << fmtBold << U("Bitrate: ") << fmtBoldEnd << Config.color2 << f.audioProperties()->bitrate() << U(" kbps\n") << clEnd; + *w << fmtBold << U("Sample rate: ") << fmtBoldEnd << Config.color2 << f.audioProperties()->sampleRate() << U(" Hz\n") << clEnd; + *w << fmtBold << U("Channels: ") << fmtBoldEnd << Config.color2 << (f.audioProperties()->channels() == 1 ? U("Mono") : U("Stereo")) << '\n' << clDefault; } # endif // HAVE_TAGLIB_H *w << clDefault; for (const Metadata *m = Tags; m->Name; ++m) { - *w << fmtBold << "\n" << m->Name << ": " << fmtBoldEnd; + *w << fmtBold << '\n' << TO_WSTRING(m->Name) << U(": ") << fmtBoldEnd; ShowTag(*w, s.getTags(m->Get)); } } - diff --git a/src/strbuffer.h b/src/strbuffer.h index f932964c..6d31467e 100644 --- a/src/strbuffer.h +++ b/src/strbuffer.h @@ -136,12 +136,51 @@ namespace NCurses /// void Clear(); - /// @param t any object that has defined ostream &operator<<() - /// @return reference to itself - /// - template basic_buffer &operator<<(const T &t) + basic_buffer &operator<<(int n) { - itsString << t; + itsString << n; + return *this; + } + + basic_buffer &operator<<(long int n) + { + itsString << n; + return *this; + } + + basic_buffer &operator<<(unsigned int n) + { + itsString << n; + return *this; + } + + basic_buffer &operator<<(long unsigned int n) + { + itsString << n; + return *this; + } + + basic_buffer &operator<<(char c) + { + itsString << c; + return *this; + } + + basic_buffer &operator<<(wchar_t c) + { + itsString << c; + return *this; + } + + basic_buffer &operator<<(const C *s) + { + itsString << s; + return *this; + } + + basic_buffer &operator<<(const std::basic_string &s) + { + itsString << s; return *this; } @@ -161,9 +200,37 @@ namespace NCurses /// basic_buffer &operator<<(const basic_buffer &buf); - /// Friend operator, that handles printing + /// Friend operator that handles printing /// the content of buffer to window object - friend Window &operator<< <>(Window &, const basic_buffer &); + friend Window &operator<<(Window &w, const basic_buffer &buf) + { + const std::basic_string &s = buf.itsTempString ? *buf.itsTempString : buf.itsString.str(); + if (buf.itsFormat.empty()) + w << s; + else + { + std::basic_string tmp; + auto b = buf.itsFormat.begin(), e = buf.itsFormat.end(); + for (size_t i = 0; i < s.length() || b != e; ++i) + { + while (b != e && i == b->Position) + { + if (!tmp.empty()) + { + w << tmp; + tmp.clear(); + } + buf.LoadAttribute(w, b->Value); + b++; + } + if (i < s.length()) + tmp += s[i]; + } + if (!tmp.empty()) + w << tmp; + } + return w; + } private: /// Loads an attribute to given window object @@ -281,7 +348,7 @@ template void NCurses::basic_buffer::Write( Window &w, s += separator; len = 0; - typename std::list::FormatPos>::const_iterator lb = itsFormat.begin(); + auto lb = itsFormat.begin(); if (itsFormat.back().Position > start_pos) // if there is no attributes from current position, don't load them { // load all attributes that are before start position @@ -358,44 +425,10 @@ template NCurses::basic_buffer &NCurses::basic_buffer::operat itsString << buf.itsString.str(); std::list tmp = buf.itsFormat; if (len) - for (typename std::list::FormatPos>::iterator it = tmp.begin(); it != tmp.end(); ++it) + for (auto it = tmp.begin(); it != tmp.end(); ++it) it->Position += len; itsFormat.merge(tmp); return *this; } -template NCurses::Window &operator<<(NCurses::Window &w, const NCurses::basic_buffer &buf) -{ - const std::basic_string &s = buf.itsTempString ? *buf.itsTempString : buf.itsString.str(); - if (buf.itsFormat.empty()) - { - w << s; - } - else - { - std::basic_string tmp; - typename std::list::FormatPos>::const_iterator b = buf.itsFormat.begin(); - typename std::list::FormatPos>::const_iterator e = buf.itsFormat.end(); - for (size_t i = 0; i < s.length() || b != e; ++i) - { - while (b != e && i == b->Position) - { - if (!tmp.empty()) - { - w << tmp; - tmp.clear(); - } - buf.LoadAttribute(w, b->Value); - b++; - } - if (i < s.length()) - tmp += s[i]; - } - if (!tmp.empty()) - w << tmp; - } - return w; -} - #endif -