diff --git a/Makefile.am b/Makefile.am index e7a9ffb24..2e9efd15c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1358,7 +1358,7 @@ test_test_pcm_LDADD = \ test_TestQueuePriority_SOURCES = \ src/queue.c \ - test/TestQueuePriority.c + test/TestQueuePriority.cxx test_TestQueuePriority_LDADD = \ $(GLIB_LIBS) diff --git a/src/Directory.cxx b/src/Directory.cxx index dec772c01..f27b3d474 100644 --- a/src/Directory.cxx +++ b/src/Directory.cxx @@ -55,7 +55,6 @@ Directory::Directory() { INIT_LIST_HEAD(&children); INIT_LIST_HEAD(&songs); - INIT_LIST_HEAD(&playlists); path[0] = 0; } @@ -64,15 +63,12 @@ Directory::Directory(const char *_path) { INIT_LIST_HEAD(&children); INIT_LIST_HEAD(&songs); - INIT_LIST_HEAD(&playlists); strcpy(path, _path); } Directory::~Directory() { - playlist_vector_deinit(&playlists); - struct song *song, *ns; directory_for_each_song_safe(song, ns, this) song_free(song); @@ -318,9 +314,8 @@ Directory::Walk(bool recursive, const SongFilter *filter, } if (visit_playlist) { - PlaylistInfo *i; - directory_for_each_playlist(i, this) - if (!visit_playlist(*i, *this, error_r)) + for (const PlaylistInfo &p : playlists) + if (!visit_playlist(p, *this, error_r)) return false; } diff --git a/src/Directory.hxx b/src/Directory.hxx index ab23a6922..710f47921 100644 --- a/src/Directory.hxx +++ b/src/Directory.hxx @@ -24,6 +24,7 @@ #include "util/list.h" #include "gcc.h" #include "DatabaseVisitor.hxx" +#include "PlaylistVector.hxx" #include #include @@ -44,12 +45,6 @@ #define directory_for_each_song_safe(pos, n, directory) \ list_for_each_entry_safe(pos, n, &directory->songs, siblings) -#define directory_for_each_playlist(pos, directory) \ - list_for_each_entry(pos, &directory->playlists, siblings) - -#define directory_for_each_playlist_safe(pos, n, directory) \ - list_for_each_entry_safe(pos, n, &directory->playlists, siblings) - struct song; struct db_visitor; class SongFilter; @@ -81,7 +76,7 @@ struct Directory { */ struct list_head songs; - struct list_head playlists; + PlaylistVector playlists; Directory *parent; time_t mtime; @@ -179,7 +174,7 @@ public: bool IsEmpty() const { return list_empty(&children) && list_empty(&songs) && - list_empty(&playlists); + playlists.empty(); } gcc_pure diff --git a/src/DirectorySave.cxx b/src/DirectorySave.cxx index 6fcc9ccc0..cd750c9b2 100644 --- a/src/DirectorySave.cxx +++ b/src/DirectorySave.cxx @@ -72,7 +72,7 @@ directory_save(FILE *fp, const Directory *directory) directory_for_each_song(song, directory) song_save(fp, song); - playlist_vector_save(fp, &directory->playlists); + playlist_vector_save(fp, directory->playlists); if (!directory->IsRoot()) fprintf(fp, DIRECTORY_END "%s\n", directory->GetPath()); @@ -168,7 +168,7 @@ directory_load(FILE *fp, Directory *directory, buffer */ char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1); - if (!playlist_metadata_load(fp, &directory->playlists, + if (!playlist_metadata_load(fp, directory->playlists, name, buffer, error)) { g_free(name); return false; diff --git a/src/PlaylistDatabase.cxx b/src/PlaylistDatabase.cxx index bbfdf7481..4604a8956 100644 --- a/src/PlaylistDatabase.cxx +++ b/src/PlaylistDatabase.cxx @@ -36,18 +36,17 @@ playlist_database_quark(void) } void -playlist_vector_save(FILE *fp, const struct list_head *pv) +playlist_vector_save(FILE *fp, const PlaylistVector &pv) { - PlaylistInfo *pm; - playlist_vector_for_each(pm, pv) + for (const PlaylistInfo &pi : pv) fprintf(fp, PLAYLIST_META_BEGIN "%s\n" "mtime: %li\n" "playlist_end\n", - pm->name.c_str(), (long)pm->mtime); + pi.name.c_str(), (long)pi.mtime); } bool -playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, +playlist_metadata_load(FILE *fp, PlaylistVector &pv, const char *name, GString *buffer, GError **error_r) { PlaylistInfo pm(name, 0); @@ -76,6 +75,6 @@ playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, } } - playlist_vector_update_or_add(pv, std::move(pm)); + pv.UpdateOrInsert(std::move(pm)); return true; } diff --git a/src/PlaylistDatabase.hxx b/src/PlaylistDatabase.hxx index 0b4cd3f3a..da2bb6b97 100644 --- a/src/PlaylistDatabase.hxx +++ b/src/PlaylistDatabase.hxx @@ -27,13 +27,13 @@ #define PLAYLIST_META_BEGIN "playlist_begin: " -struct list_head; +class PlaylistVector; void -playlist_vector_save(FILE *fp, const struct list_head *pv); +playlist_vector_save(FILE *fp, const PlaylistVector &pv); bool -playlist_metadata_load(FILE *fp, struct list_head *pv, const char *name, +playlist_metadata_load(FILE *fp, PlaylistVector &pv, const char *name, GString *buffer, GError **error_r); #endif diff --git a/src/PlaylistInfo.hxx b/src/PlaylistInfo.hxx index fffafd819..e4cf0f4ef 100644 --- a/src/PlaylistInfo.hxx +++ b/src/PlaylistInfo.hxx @@ -22,6 +22,7 @@ #include "check.h" #include "util/list.h" +#include "gcc.h" #include @@ -40,6 +41,18 @@ struct PlaylistInfo { time_t mtime; + class CompareName { + const char *const name; + + public: + constexpr CompareName(const char *_name):name(_name) {} + + gcc_pure + bool operator()(const PlaylistInfo &pi) const { + return pi.name.compare(name) == 0; + } + }; + template PlaylistInfo(N &&_name, time_t _mtime) :name(std::forward(_name)), mtime(_mtime) {} diff --git a/src/PlaylistVector.cxx b/src/PlaylistVector.cxx index f1f13567f..06c7b9ff0 100644 --- a/src/PlaylistVector.cxx +++ b/src/PlaylistVector.cxx @@ -21,71 +21,48 @@ #include "PlaylistVector.hxx" #include "DatabaseLock.hxx" +#include + #include #include #include -void -playlist_vector_deinit(struct list_head *pv) -{ - assert(pv != NULL); - - PlaylistInfo *pm, *n; - playlist_vector_for_each_safe(pm, n, pv) - delete pm; -} - -PlaylistInfo * -playlist_vector_find(struct list_head *pv, const char *name) +PlaylistVector::iterator +PlaylistVector::find(const char *name) { assert(holding_db_lock()); - assert(pv != NULL); assert(name != NULL); - PlaylistInfo *pm; - playlist_vector_for_each(pm, pv) - if (pm->name.compare(name) == 0) - return pm; - - return NULL; -} - -void -playlist_vector_add(struct list_head *pv, PlaylistInfo &&pi) -{ - assert(holding_db_lock()); - - PlaylistInfo *pm = new PlaylistInfo(std::move(pi)); - list_add_tail(&pm->siblings, pv); + return std::find_if(begin(), end(), + PlaylistInfo::CompareName(name)); } bool -playlist_vector_update_or_add(struct list_head *pv, PlaylistInfo &&pi) +PlaylistVector::UpdateOrInsert(PlaylistInfo &&pi) { assert(holding_db_lock()); - PlaylistInfo *pm = playlist_vector_find(pv, pi.name.c_str()); - if (pm != NULL) { - if (pi.mtime == pm->mtime) + auto i = find(pi.name.c_str()); + if (i != end()) { + if (pi.mtime == i->mtime) return false; - pm->mtime = pi.mtime; + i->mtime = pi.mtime; } else - playlist_vector_add(pv, std::move(pi)); + push_back(std::move(pi)); return true; } bool -playlist_vector_remove(struct list_head *pv, const char *name) +PlaylistVector::erase(const char *name) { assert(holding_db_lock()); - PlaylistInfo *pm = playlist_vector_find(pv, name); - if (pm == NULL) + auto i = find(name); + if (i == end()) return false; - list_del(&pm->siblings); - delete pm; + erase(i); return true; } diff --git a/src/PlaylistVector.hxx b/src/PlaylistVector.hxx index 14445315c..0a4cd95b3 100644 --- a/src/PlaylistVector.hxx +++ b/src/PlaylistVector.hxx @@ -21,43 +21,35 @@ #define MPD_PLAYLIST_VECTOR_HXX #include "PlaylistInfo.hxx" -#include "util/list.h" +#include "gcc.h" -#include +#include -#define playlist_vector_for_each(pos, head) \ - list_for_each_entry(pos, head, siblings) +class PlaylistVector : protected std::list { +protected: + /** + * Caller must lock the #db_mutex. + */ + gcc_pure + iterator find(const char *name); -#define playlist_vector_for_each_safe(pos, n, head) \ - list_for_each_entry_safe(pos, n, head, siblings) +public: + using std::list::empty; + using std::list::begin; + using std::list::end; + using std::list::erase; -void -playlist_vector_deinit(struct list_head *pv); + /** + * Caller must lock the #db_mutex. + * + * @return true if the vector or one of its items was modified + */ + bool UpdateOrInsert(PlaylistInfo &&pi); -/** - * Caller must lock the #db_mutex. - */ -PlaylistInfo * -playlist_vector_find(struct list_head *pv, const char *name); - -/** - * Caller must lock the #db_mutex. - */ -void -playlist_vector_add(struct list_head *pv, PlaylistInfo &&pi); - -/** - * Caller must lock the #db_mutex. - * - * @return true if the vector or one of its items was modified - */ -bool -playlist_vector_update_or_add(struct list_head *pv, PlaylistInfo &&pi); - -/** - * Caller must lock the #db_mutex. - */ -bool -playlist_vector_remove(struct list_head *pv, const char *name); + /** + * Caller must lock the #db_mutex. + */ + bool erase(const char *name); +}; #endif /* SONGVEC_H */ diff --git a/src/UpdateDatabase.cxx b/src/UpdateDatabase.cxx index 50697511c..984fb1be8 100644 --- a/src/UpdateDatabase.cxx +++ b/src/UpdateDatabase.cxx @@ -96,7 +96,7 @@ delete_name_in(Directory *parent, const char *name) modified = true; } - playlist_vector_remove(&parent->playlists, name); + parent->playlists.erase(name); db_unlock(); diff --git a/src/UpdateWalk.cxx b/src/UpdateWalk.cxx index 4923f083a..eb0565832 100644 --- a/src/UpdateWalk.cxx +++ b/src/UpdateWalk.cxx @@ -158,14 +158,15 @@ purge_deleted_from_directory(Directory *directory) g_free(path); } - PlaylistInfo *pm, *np; - directory_for_each_playlist_safe(pm, np, directory) { - if (!directory_child_is_regular(directory, pm->name.c_str())) { + for (auto i = directory->playlists.begin(), + end = directory->playlists.end(); + i != end;) { + if (!directory_child_is_regular(directory, i->name.c_str())) { db_lock(); - playlist_vector_remove(&directory->playlists, - pm->name.c_str()); + i = directory->playlists.erase(i); db_unlock(); - } + } else + ++i; } } @@ -217,8 +218,7 @@ update_playlist_file2(Directory *directory, PlaylistInfo pi(name, st->st_mtime); db_lock(); - if (playlist_vector_update_or_add(&directory->playlists, - std::move(pi))) + if (directory->playlists.UpdateOrInsert(std::move(pi))) modified = true; db_unlock(); return true;