make use of std::locale based strings comparison
This commit is contained in:
@@ -71,8 +71,41 @@ void DisplayAlbums(NC::Menu<SearchConstraints> &menu);
|
||||
void DisplayPrimaryTags(NC::Menu<std::string> &menu);
|
||||
|
||||
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, ""));
|
||||
}
|
||||
if (!Albums->empty())
|
||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints);
|
||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
|
||||
if (Albums->size() > 1)
|
||||
{
|
||||
Albums->addSeparator();
|
||||
@@ -300,7 +333,7 @@ void MediaLibrary::Update()
|
||||
}
|
||||
Mpd.BlockIdle(0);
|
||||
if (!Albums->empty())
|
||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints);
|
||||
std::sort(Albums->beginV(), Albums->endV(), SortSearchConstraints());
|
||||
Albums->refresh();
|
||||
}
|
||||
|
||||
@@ -328,7 +361,7 @@ void MediaLibrary::Update()
|
||||
Songs->addItem(*s, myPlaylist->checkForSong(*s));
|
||||
|
||||
if (Albums->current().value().Date == AllTracksMarker)
|
||||
std::sort(Songs->beginV(), Songs->endV(), SortAllTracks);
|
||||
std::sort(Songs->beginV(), Songs->endV(), SortAllTracks());
|
||||
else
|
||||
std::sort(Songs->beginV(), Songs->endV(), SortSongsByTrack);
|
||||
|
||||
@@ -572,7 +605,7 @@ MPD::SongList MediaLibrary::getSelectedSongs()
|
||||
Mpd.StartSearch(true);
|
||||
Mpd.AddSearch(Config.media_lib_primary_tag, tag);
|
||||
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());
|
||||
};
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -197,9 +197,9 @@ void Playlist::EnterPressed()
|
||||
for (; begin != end; ++begin)
|
||||
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;
|
||||
auto song_cmp = [](const MPD::Song &a, const MPD::Song &b) -> bool {
|
||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
||||
auto song_cmp = [&cmp](const MPD::Song &a, const MPD::Song &b) -> bool {
|
||||
for (size_t i = 0; i < SortOptions; ++i)
|
||||
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second)))
|
||||
return ret < 0;
|
||||
|
||||
@@ -448,6 +448,7 @@ void SearchEngine::Search()
|
||||
bool any_found = 1;
|
||||
bool found = 1;
|
||||
|
||||
LocaleStringComparison cmp(std::locale(""), Config.ignore_leading_the);
|
||||
for (auto it = list.begin(); it != list.end(); ++it)
|
||||
{
|
||||
if (SearchMode != &SearchModes[2]) // match to pattern
|
||||
@@ -535,8 +536,6 @@ void SearchEngine::Search()
|
||||
}
|
||||
else // match only if values are equal
|
||||
{
|
||||
CaseInsensitiveStringComparison cmp(Config.ignore_leading_the);
|
||||
|
||||
if (!itsConstraints[0].empty())
|
||||
any_found =
|
||||
!cmp(it->getArtist(), itsConstraints[0])
|
||||
@@ -573,10 +572,7 @@ void SearchEngine::Search()
|
||||
}
|
||||
|
||||
if (found && any_found)
|
||||
{
|
||||
w->addItem(*it);
|
||||
list[it-list.begin()] = 0;
|
||||
}
|
||||
found = 1;
|
||||
any_found = 1;
|
||||
}
|
||||
|
||||
@@ -18,33 +18,37 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <locale>
|
||||
#include "comparators.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[2] == 'e' || s[2] == 'E')
|
||||
&& (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 (hasTheWord(a))
|
||||
a += 4;
|
||||
ac_off += 4;
|
||||
if (hasTheWord(b))
|
||||
b += 4;
|
||||
bc_off += 4;
|
||||
}
|
||||
int dist;
|
||||
while (!(dist = tolower(*a)-tolower(*b)) && *b)
|
||||
++a, ++b;
|
||||
return dist;
|
||||
return std::use_facet< std::collate<char> >(m_locale).compare(
|
||||
ac+ac_off, ac+a.length(), bc+bc_off, bc+b.length()
|
||||
);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
@@ -24,31 +24,23 @@
|
||||
#include <string>
|
||||
#include "mpdpp.h"
|
||||
|
||||
class CaseInsensitiveStringComparison
|
||||
class LocaleStringComparison
|
||||
{
|
||||
std::locale m_locale;
|
||||
bool m_ignore_the;
|
||||
|
||||
bool hasTheWord(const char *s) const;
|
||||
bool hasTheWord(const std::string &s) const;
|
||||
|
||||
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 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());
|
||||
}
|
||||
int operator()(const std::string &a, const std::string &b) const;
|
||||
};
|
||||
|
||||
class CaseInsensitiveSorting
|
||||
{
|
||||
CaseInsensitiveStringComparison cmp;
|
||||
LocaleStringComparison cmp;
|
||||
|
||||
public:
|
||||
CaseInsensitiveSorting();
|
||||
|
||||
Reference in New Issue
Block a user