PlaylistVector: use std::list
This commit is contained in:
parent
83488848e1
commit
9023ba4a81
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "util/list.h"
|
||||
#include "gcc.h"
|
||||
#include "DatabaseVisitor.hxx"
|
||||
#include "PlaylistVector.hxx"
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdbool.h>
|
||||
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "check.h"
|
||||
#include "util/list.h"
|
||||
#include "gcc.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -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<typename N>
|
||||
PlaylistInfo(N &&_name, time_t _mtime)
|
||||
:name(std::forward<N>(_name)), mtime(_mtime) {}
|
||||
|
@ -21,71 +21,48 @@
|
||||
#include "PlaylistVector.hxx"
|
||||
#include "DatabaseLock.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <glib.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -21,43 +21,35 @@
|
||||
#define MPD_PLAYLIST_VECTOR_HXX
|
||||
|
||||
#include "PlaylistInfo.hxx"
|
||||
#include "util/list.h"
|
||||
#include "gcc.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <list>
|
||||
|
||||
#define playlist_vector_for_each(pos, head) \
|
||||
list_for_each_entry(pos, head, siblings)
|
||||
class PlaylistVector : protected std::list<PlaylistInfo> {
|
||||
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<PlaylistInfo>::empty;
|
||||
using std::list<PlaylistInfo>::begin;
|
||||
using std::list<PlaylistInfo>::end;
|
||||
using std::list<PlaylistInfo>::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 */
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user