make use of std::locale based strings comparison

This commit is contained in:
Andrzej Rybczak
2012-09-08 03:35:52 +02:00
parent a26b1f62f9
commit 057922d2a6
5 changed files with 63 additions and 68 deletions

View File

@@ -71,8 +71,41 @@ void DisplayAlbums(NC::Menu<SearchConstraints> &menu);
void DisplayPrimaryTags(NC::Menu<std::string> &menu); void DisplayPrimaryTags(NC::Menu<std::string> &menu);
bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b); bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b);
bool SortAllTracks(const MPD::Song &a, const MPD::Song &b);
bool SortSearchConstraints(const SearchConstraints &a, const SearchConstraints &b); struct SortAllTracks {
const std::array<MPD::Song::GetFunction, 3> m_gets;
LocaleStringComparison m_cmp;
public:
SortAllTracks() : m_gets({{
&MPD::Song::getDate,
&MPD::Song::getAlbum,
&MPD::Song::getDisc
}}), m_cmp(std::locale(""), Config.ignore_leading_the) { }
bool operator()(const MPD::Song &a, const MPD::Song &b) {
for (auto get = m_gets.begin(); get != m_gets.end(); ++get) {
int ret = m_cmp(a.getTags(*get), b.getTags(*get));
if (ret != 0)
return ret < 0;
}
return a.getTrack() < b.getTrack();
}
};
class SortSearchConstraints {
LocaleStringComparison m_cmp;
public:
SortSearchConstraints() : m_cmp(std::locale(""), Config.ignore_leading_the) { }
bool operator()(const SearchConstraints &a, const SearchConstraints &b) const {
int result;
result = m_cmp(a.PrimaryTag, b.PrimaryTag);
if (result != 0)
return result < 0;
result = m_cmp(a.Date, b.Date);
if (result != 0)
return result < 0;
return m_cmp(a.Album, b.Album) < 0;
}
};
} }
@@ -257,7 +290,7 @@ void MediaLibrary::Update()
Albums->addItem(SearchConstraints(*album, "")); Albums->addItem(SearchConstraints(*album, ""));
} }
if (!Albums->empty()) if (!Albums->empty())
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints); std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
if (Albums->size() > 1) if (Albums->size() > 1)
{ {
Albums->addSeparator(); Albums->addSeparator();
@@ -300,7 +333,7 @@ void MediaLibrary::Update()
} }
Mpd.BlockIdle(0); Mpd.BlockIdle(0);
if (!Albums->empty()) if (!Albums->empty())
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints); std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
Albums->refresh(); Albums->refresh();
} }
@@ -328,7 +361,7 @@ void MediaLibrary::Update()
Songs->addItem(*s, myPlaylist->checkForSong(*s)); Songs->addItem(*s, myPlaylist->checkForSong(*s));
if (Albums->current().value().Date == AllTracksMarker) if (Albums->current().value().Date == AllTracksMarker)
std::sort(Songs->beginV(), Songs->endV(), SortAllTracks); std::sort(Songs->beginV(), Songs->endV(), SortAllTracks());
else else
std::sort(Songs->beginV(), Songs->endV(), SortSongsByTrack); std::sort(Songs->beginV(), Songs->endV(), SortSongsByTrack);
@@ -572,7 +605,7 @@ MPD::SongList MediaLibrary::getSelectedSongs()
Mpd.StartSearch(true); Mpd.StartSearch(true);
Mpd.AddSearch(Config.media_lib_primary_tag, tag); Mpd.AddSearch(Config.media_lib_primary_tag, tag);
auto songs = Mpd.CommitSearchSongs(); auto songs = Mpd.CommitSearchSongs();
std::sort(songs.begin(), songs.end(), SortAllTracks); std::sort(songs.begin(), songs.end(), SortAllTracks());
result.insert(result.end(), songs.begin(), songs.end()); result.insert(result.end(), songs.begin(), songs.end());
}; };
for (auto it = Tags->begin(); it != Tags->end(); ++it) for (auto it = Tags->begin(); it != Tags->end(); ++it)
@@ -915,34 +948,4 @@ bool SortSongsByTrack(const MPD::Song &a, const MPD::Song &b)
return a.getTrack() < b.getTrack(); return a.getTrack() < b.getTrack();
} }
bool SortAllTracks(const MPD::Song &a, const MPD::Song &b)
{
const std::array<MPD::Song::GetFunction, 3> gets = {{
&MPD::Song::getDate,
&MPD::Song::getAlbum,
&MPD::Song::getDisc
}};
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
for (auto get = gets.begin(); get != gets.end(); ++get)
{
int ret = cmp(a.getTags(*get), b.getTags(*get));
if (ret != 0)
return ret < 0;
}
return a.getTrack() < b.getTrack();
}
bool SortSearchConstraints(const SearchConstraints &a, const SearchConstraints &b)
{
int result;
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
result = cmp(a.PrimaryTag, b.PrimaryTag);
if (result != 0)
return result < 0;
result = cmp(a.Date, b.Date);
if (result != 0)
return result < 0;
return cmp(a.Album, b.Album) < 0;
}
} }

View File

@@ -197,9 +197,9 @@ void Playlist::EnterPressed()
for (; begin != end; ++begin) for (; begin != end; ++begin)
playlist.push_back(begin->value()); playlist.push_back(begin->value());
LocaleStringComparison cmp(std::locale(""), Config.ignore_leading_the);
std::function<void(MPD::SongList::iterator, MPD::SongList::iterator)> iter_swap, quick_sort; std::function<void(MPD::SongList::iterator, MPD::SongList::iterator)> iter_swap, quick_sort;
auto song_cmp = [](const MPD::Song &a, const MPD::Song &b) -> bool { auto song_cmp = [&cmp](const MPD::Song &a, const MPD::Song &b) -> bool {
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
for (size_t i = 0; i < SortOptions; ++i) for (size_t i = 0; i < SortOptions; ++i)
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second))) if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second)))
return ret < 0; return ret < 0;

View File

@@ -448,6 +448,7 @@ void SearchEngine::Search()
bool any_found = 1; bool any_found = 1;
bool found = 1; bool found = 1;
LocaleStringComparison cmp(std::locale(""), Config.ignore_leading_the);
for (auto it = list.begin(); it != list.end(); ++it) for (auto it = list.begin(); it != list.end(); ++it)
{ {
if (SearchMode != &SearchModes[2]) // match to pattern if (SearchMode != &SearchModes[2]) // match to pattern
@@ -535,8 +536,6 @@ void SearchEngine::Search()
} }
else // match only if values are equal else // match only if values are equal
{ {
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
if (!itsConstraints[0].empty()) if (!itsConstraints[0].empty())
any_found = any_found =
!cmp(it->getArtist(), itsConstraints[0]) !cmp(it->getArtist(), itsConstraints[0])
@@ -573,10 +572,7 @@ void SearchEngine::Search()
} }
if (found && any_found) if (found && any_found)
{
w->addItem(*it); w->addItem(*it);
list[it-list.begin()] = 0;
}
found = 1; found = 1;
any_found = 1; any_found = 1;
} }

View File

@@ -18,33 +18,37 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/ ***************************************************************************/
#include <locale>
#include "comparators.h" #include "comparators.h"
#include "settings.h" #include "settings.h"
bool CaseInsensitiveStringComparison::hasTheWord(const char *s) const bool LocaleStringComparison::hasTheWord(const std::string &s) const
{ {
return (s[0] == 't' || s[0] == 'T') return s.length() >= 4
&& (s[0] == 't' || s[0] == 'T')
&& (s[1] == 'h' || s[1] == 'H') && (s[1] == 'h' || s[1] == 'H')
&& (s[2] == 'e' || s[2] == 'E') && (s[2] == 'e' || s[2] == 'E')
&& (s[3] == ' '); && (s[3] == ' ');
} }
int CaseInsensitiveStringComparison::operator()(const char *a, const char *b) const int LocaleStringComparison::operator()(const std::string &a, const std::string &b) const
{ {
const char *ac = a.c_str();
const char *bc = b.c_str();
size_t ac_off = 0, bc_off = 0;
if (m_ignore_the) if (m_ignore_the)
{ {
if (hasTheWord(a)) if (hasTheWord(a))
a += 4; ac_off += 4;
if (hasTheWord(b)) if (hasTheWord(b))
b += 4; bc_off += 4;
} }
int dist; return std::use_facet< std::collate<char> >(m_locale).compare(
while (!(dist = tolower(*a)-tolower(*b)) && *b) ac+ac_off, ac+a.length(), bc+bc_off, bc+b.length()
++a, ++b; );
return dist;
} }
CaseInsensitiveSorting::CaseInsensitiveSorting(): cmp(Config.ignore_leading_the) { } CaseInsensitiveSorting::CaseInsensitiveSorting(): cmp(std::locale(""), Config.ignore_leading_the) { }
bool CaseInsensitiveSorting::operator()(const MPD::Item &a, const MPD::Item &b) const bool CaseInsensitiveSorting::operator()(const MPD::Item &a, const MPD::Item &b) const
{ {

View File

@@ -24,31 +24,23 @@
#include <string> #include <string>
#include "mpdpp.h" #include "mpdpp.h"
class CaseInsensitiveStringComparison class LocaleStringComparison
{ {
std::locale m_locale;
bool m_ignore_the; bool m_ignore_the;
bool hasTheWord(const char *s) const; bool hasTheWord(const std::string &s) const;
public: public:
CaseInsensitiveStringComparison(bool ignore_the) : m_ignore_the(ignore_the) { } LocaleStringComparison(const std::locale &loc, bool ignore_the)
: m_locale(loc), m_ignore_the(ignore_the) { }
int operator()(const char *a, const char *b) const; int operator()(const std::string &a, const std::string &b) const;
int operator()(const char *a, const std::string &b) const {
return (*this)(a, b.c_str());
}
int operator()(const std::string &a, const char *b) const {
return (*this)(a.c_str(), b);
}
int operator()(const std::string &a, const std::string &b) const {
return (*this)(a.c_str(), b.c_str());
}
}; };
class CaseInsensitiveSorting class CaseInsensitiveSorting
{ {
CaseInsensitiveStringComparison cmp; LocaleStringComparison cmp;
public: public:
CaseInsensitiveSorting(); CaseInsensitiveSorting();