diff --git a/src/helpers.cpp b/src/helpers.cpp index 4cbaa9b1..fffba71b 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -225,32 +225,6 @@ void ParseArgv(int argc, char **argv) exit(0); } -bool CaseInsensitiveSorting::operator()(std::string a, std::string b) -{ - ToLower(a); - ToLower(b); - if (Config.ignore_leading_the) - { - RemoveTheWord(a); - RemoveTheWord(b); - } - return a < b; -} - -bool CaseInsensitiveSorting::operator()(Song *sa, Song *sb) -{ - std::string a = sa->GetName(); - std::string b = sb->GetName(); - ToLower(a); - ToLower(b); - if (Config.ignore_leading_the) - { - RemoveTheWord(a); - RemoveTheWord(b); - } - return a < b; -} - bool CaseInsensitiveSorting::operator()(const Item &a, const Item &b) { if (a.type == b.type) @@ -258,9 +232,9 @@ bool CaseInsensitiveSorting::operator()(const Item &a, const Item &b) switch (a.type) { case itDirectory: - return operator()(ExtractTopDirectory(a.name), ExtractTopDirectory(b.name)); + return cmp(ExtractTopDirectory(a.name), ExtractTopDirectory(b.name)) < 0; case itPlaylist: - return operator()(a.name, b.name); + return cmp(a.name, b.name) < 0; case itSong: return operator()(a.song, b.song); default: // there's no other type, just silence compiler. @@ -354,13 +328,6 @@ std::string GetLineValue(std::string &line, char a, char b, bool once) return result; } -void RemoveTheWord(std::string &s) -{ - size_t the_pos = s.find("the "); - if (the_pos == 0 && the_pos != std::string::npos) - s = s.substr(4); -} - std::string ExtractTopDirectory(const std::string &s) { size_t slash = s.rfind("/"); diff --git a/src/helpers.h b/src/helpers.h index 0f8a0c21..f559dc65 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -30,21 +30,57 @@ bool ConnectToMPD(); void ParseArgv(int, char **); +class CaseInsensitiveStringComparison +{ + bool hasTheWord(const std::string &s) + { + return (s.length() > 3) + && (s[0] == 't' || s[0] == 'T') + && (s[1] == 'h' || s[1] == 'H') + && (s[2] == 'e' || s[2] == 'E') + && (s[3] == ' '); + } + + public: + int operator()(const std::string &a, const std::string &b) + { + const char *i = a.c_str(); + const char *j = b.c_str(); + if (Config.ignore_leading_the) + { + if (hasTheWord(a)) + i += 4; + if (hasTheWord(b)) + j += 4; + } + int dist; + while (!(dist = tolower(*i)-tolower(*j)) && *j) + ++i, ++j; + return dist; + } +}; + class CaseInsensitiveSorting { + CaseInsensitiveStringComparison cmp; + public: - bool operator()(std::string, std::string); - bool operator()(MPD::Song *, MPD::Song *); - bool operator()(const MPD::Item &, const MPD::Item &); + bool operator()(const std::string &a, const std::string &b) + { + return cmp(a, b) < 0; + } + + bool operator()(MPD::Song *a, MPD::Song *b) + { + return cmp(a->GetName(), b->GetName()) < 0; + } template bool operator()(const std::pair &a, const std::pair &b) { - std::string aa = a.first; - std::string bb = b.first; - ToLower(aa); - ToLower(bb); - return aa < bb; + return cmp(a.first, b.first) < 0; } + + bool operator()(const MPD::Item &, const MPD::Item &); }; template std::string StringPairToString(const std::pair &pair, void *) @@ -115,12 +151,10 @@ std::string FindSharedDir(Menu *); std::string FindSharedDir(const MPD::SongList &); #endif // HAVE_TAGLIB_H std::string FindSharedDir(const std::string &, const std::string &); +std::string ExtractTopDirectory(const std::string &); std::string GetLineValue(std::string &, char = '"', char = '"', bool = 0); -void RemoveTheWord(std::string &s); -std::string ExtractTopDirectory(const std::string &); - #ifdef _UTF8 std::basic_string Scroller(const std::string &str, size_t &pos, size_t width); #endif // _UTF8 diff --git a/src/playlist.cpp b/src/playlist.cpp index 22b2e9da..684c9796 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -323,20 +323,10 @@ void Playlist::EnableHighlighting() bool Playlist::Sorting(MPD::Song *a, MPD::Song *b) { + CaseInsensitiveStringComparison cmp; for (size_t i = 0; i < SortOptions; ++i) - { - std::string sa = (a->*(*SortDialog)[i].second)(); - std::string sb = (b->*(*SortDialog)[i].second)(); - ToLower(sa); - ToLower(sb); - if (Config.ignore_leading_the) - { - RemoveTheWord(sa); - RemoveTheWord(sb); - } - if (sa != sb) - return sa < sb; - } + if (int ret = cmp((a->*(*SortDialog)[i].second)(), (b->*(*SortDialog)[i].second)())) + return ret < 0; return a->GetPosition() < b->GetPosition(); }