PlaylistVector: use std::list
This commit is contained in:
parent
83488848e1
commit
9023ba4a81
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue