PlaylistVector: use std::list

This commit is contained in:
Max Kellermann 2013-01-02 22:16:52 +01:00
parent 83488848e1
commit 9023ba4a81
11 changed files with 79 additions and 108 deletions

View File

@ -1358,7 +1358,7 @@ test_test_pcm_LDADD = \
test_TestQueuePriority_SOURCES = \ test_TestQueuePriority_SOURCES = \
src/queue.c \ src/queue.c \
test/TestQueuePriority.c test/TestQueuePriority.cxx
test_TestQueuePriority_LDADD = \ test_TestQueuePriority_LDADD = \
$(GLIB_LIBS) $(GLIB_LIBS)

View File

@ -55,7 +55,6 @@ Directory::Directory()
{ {
INIT_LIST_HEAD(&children); INIT_LIST_HEAD(&children);
INIT_LIST_HEAD(&songs); INIT_LIST_HEAD(&songs);
INIT_LIST_HEAD(&playlists);
path[0] = 0; path[0] = 0;
} }
@ -64,15 +63,12 @@ Directory::Directory(const char *_path)
{ {
INIT_LIST_HEAD(&children); INIT_LIST_HEAD(&children);
INIT_LIST_HEAD(&songs); INIT_LIST_HEAD(&songs);
INIT_LIST_HEAD(&playlists);
strcpy(path, _path); strcpy(path, _path);
} }
Directory::~Directory() Directory::~Directory()
{ {
playlist_vector_deinit(&playlists);
struct song *song, *ns; struct song *song, *ns;
directory_for_each_song_safe(song, ns, this) directory_for_each_song_safe(song, ns, this)
song_free(song); song_free(song);
@ -318,9 +314,8 @@ Directory::Walk(bool recursive, const SongFilter *filter,
} }
if (visit_playlist) { if (visit_playlist) {
PlaylistInfo *i; for (const PlaylistInfo &p : playlists)
directory_for_each_playlist(i, this) if (!visit_playlist(p, *this, error_r))
if (!visit_playlist(*i, *this, error_r))
return false; return false;
} }

View File

@ -24,6 +24,7 @@
#include "util/list.h" #include "util/list.h"
#include "gcc.h" #include "gcc.h"
#include "DatabaseVisitor.hxx" #include "DatabaseVisitor.hxx"
#include "PlaylistVector.hxx"
#include <glib.h> #include <glib.h>
#include <stdbool.h> #include <stdbool.h>
@ -44,12 +45,6 @@
#define directory_for_each_song_safe(pos, n, directory) \ #define directory_for_each_song_safe(pos, n, directory) \
list_for_each_entry_safe(pos, n, &directory->songs, siblings) 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 song;
struct db_visitor; struct db_visitor;
class SongFilter; class SongFilter;
@ -81,7 +76,7 @@ struct Directory {
*/ */
struct list_head songs; struct list_head songs;
struct list_head playlists; PlaylistVector playlists;
Directory *parent; Directory *parent;
time_t mtime; time_t mtime;
@ -179,7 +174,7 @@ public:
bool IsEmpty() const { bool IsEmpty() const {
return list_empty(&children) && return list_empty(&children) &&
list_empty(&songs) && list_empty(&songs) &&
list_empty(&playlists); playlists.empty();
} }
gcc_pure gcc_pure

View File

@ -72,7 +72,7 @@ directory_save(FILE *fp, const Directory *directory)
directory_for_each_song(song, directory) directory_for_each_song(song, directory)
song_save(fp, song); song_save(fp, song);
playlist_vector_save(fp, &directory->playlists); playlist_vector_save(fp, directory->playlists);
if (!directory->IsRoot()) if (!directory->IsRoot())
fprintf(fp, DIRECTORY_END "%s\n", directory->GetPath()); fprintf(fp, DIRECTORY_END "%s\n", directory->GetPath());
@ -168,7 +168,7 @@ directory_load(FILE *fp, Directory *directory,
buffer */ buffer */
char *name = g_strdup(line + sizeof(PLAYLIST_META_BEGIN) - 1); 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)) { name, buffer, error)) {
g_free(name); g_free(name);
return false; return false;

View File

@ -36,18 +36,17 @@ playlist_database_quark(void)
} }
void void
playlist_vector_save(FILE *fp, const struct list_head *pv) playlist_vector_save(FILE *fp, const PlaylistVector &pv)
{ {
PlaylistInfo *pm; for (const PlaylistInfo &pi : pv)
playlist_vector_for_each(pm, pv)
fprintf(fp, PLAYLIST_META_BEGIN "%s\n" fprintf(fp, PLAYLIST_META_BEGIN "%s\n"
"mtime: %li\n" "mtime: %li\n"
"playlist_end\n", "playlist_end\n",
pm->name.c_str(), (long)pm->mtime); pi.name.c_str(), (long)pi.mtime);
} }
bool 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) GString *buffer, GError **error_r)
{ {
PlaylistInfo pm(name, 0); 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; return true;
} }

View File

@ -27,13 +27,13 @@
#define PLAYLIST_META_BEGIN "playlist_begin: " #define PLAYLIST_META_BEGIN "playlist_begin: "
struct list_head; class PlaylistVector;
void void
playlist_vector_save(FILE *fp, const struct list_head *pv); playlist_vector_save(FILE *fp, const PlaylistVector &pv);
bool 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); GString *buffer, GError **error_r);
#endif #endif

View File

@ -22,6 +22,7 @@
#include "check.h" #include "check.h"
#include "util/list.h" #include "util/list.h"
#include "gcc.h"
#include <string> #include <string>
@ -40,6 +41,18 @@ struct PlaylistInfo {
time_t mtime; 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<typename N> template<typename N>
PlaylistInfo(N &&_name, time_t _mtime) PlaylistInfo(N &&_name, time_t _mtime)
:name(std::forward<N>(_name)), mtime(_mtime) {} :name(std::forward<N>(_name)), mtime(_mtime) {}

View File

@ -21,71 +21,48 @@
#include "PlaylistVector.hxx" #include "PlaylistVector.hxx"
#include "DatabaseLock.hxx" #include "DatabaseLock.hxx"
#include <algorithm>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <glib.h> #include <glib.h>
void PlaylistVector::iterator
playlist_vector_deinit(struct list_head *pv) PlaylistVector::find(const char *name)
{
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)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(pv != NULL);
assert(name != NULL); assert(name != NULL);
PlaylistInfo *pm; return std::find_if(begin(), end(),
playlist_vector_for_each(pm, pv) PlaylistInfo::CompareName(name));
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);
} }
bool bool
playlist_vector_update_or_add(struct list_head *pv, PlaylistInfo &&pi) PlaylistVector::UpdateOrInsert(PlaylistInfo &&pi)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
PlaylistInfo *pm = playlist_vector_find(pv, pi.name.c_str()); auto i = find(pi.name.c_str());
if (pm != NULL) { if (i != end()) {
if (pi.mtime == pm->mtime) if (pi.mtime == i->mtime)
return false; return false;
pm->mtime = pi.mtime; i->mtime = pi.mtime;
} else } else
playlist_vector_add(pv, std::move(pi)); push_back(std::move(pi));
return true; return true;
} }
bool bool
playlist_vector_remove(struct list_head *pv, const char *name) PlaylistVector::erase(const char *name)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
PlaylistInfo *pm = playlist_vector_find(pv, name); auto i = find(name);
if (pm == NULL) if (i == end())
return false; return false;
list_del(&pm->siblings); erase(i);
delete pm;
return true; return true;
} }

View File

@ -21,43 +21,35 @@
#define MPD_PLAYLIST_VECTOR_HXX #define MPD_PLAYLIST_VECTOR_HXX
#include "PlaylistInfo.hxx" #include "PlaylistInfo.hxx"
#include "util/list.h" #include "gcc.h"
#include <sys/time.h> #include <list>
#define playlist_vector_for_each(pos, head) \ class PlaylistVector : protected std::list<PlaylistInfo> {
list_for_each_entry(pos, head, siblings) protected:
/**
#define playlist_vector_for_each_safe(pos, n, head) \
list_for_each_entry_safe(pos, n, head, siblings)
void
playlist_vector_deinit(struct list_head *pv);
/**
* Caller must lock the #db_mutex. * Caller must lock the #db_mutex.
*/ */
PlaylistInfo * gcc_pure
playlist_vector_find(struct list_head *pv, const char *name); iterator find(const char *name);
/** public:
* Caller must lock the #db_mutex. using std::list<PlaylistInfo>::empty;
*/ using std::list<PlaylistInfo>::begin;
void using std::list<PlaylistInfo>::end;
playlist_vector_add(struct list_head *pv, PlaylistInfo &&pi); using std::list<PlaylistInfo>::erase;
/** /**
* Caller must lock the #db_mutex. * Caller must lock the #db_mutex.
* *
* @return true if the vector or one of its items was modified * @return true if the vector or one of its items was modified
*/ */
bool bool UpdateOrInsert(PlaylistInfo &&pi);
playlist_vector_update_or_add(struct list_head *pv, PlaylistInfo &&pi);
/** /**
* Caller must lock the #db_mutex. * Caller must lock the #db_mutex.
*/ */
bool bool erase(const char *name);
playlist_vector_remove(struct list_head *pv, const char *name); };
#endif /* SONGVEC_H */ #endif /* SONGVEC_H */

View File

@ -96,7 +96,7 @@ delete_name_in(Directory *parent, const char *name)
modified = true; modified = true;
} }
playlist_vector_remove(&parent->playlists, name); parent->playlists.erase(name);
db_unlock(); db_unlock();

View File

@ -158,14 +158,15 @@ purge_deleted_from_directory(Directory *directory)
g_free(path); g_free(path);
} }
PlaylistInfo *pm, *np; for (auto i = directory->playlists.begin(),
directory_for_each_playlist_safe(pm, np, directory) { end = directory->playlists.end();
if (!directory_child_is_regular(directory, pm->name.c_str())) { i != end;) {
if (!directory_child_is_regular(directory, i->name.c_str())) {
db_lock(); db_lock();
playlist_vector_remove(&directory->playlists, i = directory->playlists.erase(i);
pm->name.c_str());
db_unlock(); db_unlock();
} } else
++i;
} }
} }
@ -217,8 +218,7 @@ update_playlist_file2(Directory *directory,
PlaylistInfo pi(name, st->st_mtime); PlaylistInfo pi(name, st->st_mtime);
db_lock(); db_lock();
if (playlist_vector_update_or_add(&directory->playlists, if (directory->playlists.UpdateOrInsert(std::move(pi)))
std::move(pi)))
modified = true; modified = true;
db_unlock(); db_unlock();
return true; return true;