Directory: turn functions to methods

This commit is contained in:
Max Kellermann 2013-01-02 23:06:10 +01:00
parent 0c245bc271
commit 0eb05b827f
16 changed files with 274 additions and 302 deletions

View File

@ -128,9 +128,7 @@ db_get_directory(const char *name)
if (name == NULL) if (name == NULL)
return music_root; return music_root;
struct directory *directory = return music_root->LookupDirectory(name);
directory_lookup_directory(music_root, name);
return directory;
} }
struct song * struct song *

View File

@ -41,9 +41,8 @@ extern "C" {
static bool static bool
PrintDirectory(struct client *client, const directory &directory) PrintDirectory(struct client *client, const directory &directory)
{ {
if (!directory_is_root(&directory)) if (!directory.IsRoot())
client_printf(client, "directory: %s\n", client_printf(client, "directory: %s\n", directory.GetPath());
directory_get_path(&directory));
return true; return true;
} }
@ -53,11 +52,11 @@ print_playlist_in_directory(struct client *client,
const directory &directory, const directory &directory,
const char *name_utf8) const char *name_utf8)
{ {
if (directory_is_root(&directory)) if (directory.IsRoot())
client_printf(client, "playlist: %s\n", name_utf8); client_printf(client, "playlist: %s\n", name_utf8);
else else
client_printf(client, "playlist: %s/%s\n", client_printf(client, "playlist: %s/%s\n",
directory_get_path(&directory), name_utf8); directory.GetPath(), name_utf8);
} }
static bool static bool

View File

@ -56,7 +56,7 @@ directory_allocate(const char *path)
} }
struct directory * struct directory *
directory_new(const char *path, struct directory *parent) directory::NewGeneric(const char *path, struct directory *parent)
{ {
assert(path != NULL); assert(path != NULL);
assert((*path == 0) == (parent == NULL)); assert((*path == 0) == (parent == NULL));
@ -69,124 +69,121 @@ directory_new(const char *path, struct directory *parent)
} }
void void
directory_free(struct directory *directory) directory::Free()
{ {
playlist_vector_deinit(&directory->playlists); playlist_vector_deinit(&playlists);
struct song *song, *ns; struct song *song, *ns;
directory_for_each_song_safe(song, ns, directory) directory_for_each_song_safe(song, ns, this)
song_free(song); song_free(song);
struct directory *child, *n; struct directory *child, *n;
directory_for_each_child_safe(child, n, directory) directory_for_each_child_safe(child, n, this)
directory_free(child); child->Free();
g_free(directory); g_free(this);
/* this resets last dir returned */
/*directory_get_path(NULL); */
} }
void void
directory_delete(struct directory *directory) directory::Delete()
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(directory != NULL); assert(parent != nullptr);
assert(directory->parent != NULL);
list_del(&directory->siblings); list_del(&siblings);
directory_free(directory); Free();
} }
const char * const char *
directory_get_name(const struct directory *directory) directory::GetName() const
{ {
assert(!directory_is_root(directory)); assert(!IsRoot());
assert(directory->path != NULL); assert(path != nullptr);
const char *slash = strrchr(directory->path, '/'); const char *slash = strrchr(path, '/');
assert((slash == NULL) == directory_is_root(directory->parent)); assert((slash == nullptr) == parent->IsRoot());
return slash != NULL return slash != NULL
? slash + 1 ? slash + 1
: directory->path; : path;
} }
struct directory * struct directory *
directory_new_child(struct directory *parent, const char *name_utf8) directory::CreateChild(const char *name_utf8)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(parent != NULL);
assert(name_utf8 != NULL); assert(name_utf8 != NULL);
assert(*name_utf8 != 0); assert(*name_utf8 != 0);
char *allocated; char *allocated;
const char *path_utf8; const char *path_utf8;
if (directory_is_root(parent)) { if (IsRoot()) {
allocated = NULL; allocated = NULL;
path_utf8 = name_utf8; path_utf8 = name_utf8;
} else { } else {
allocated = g_strconcat(directory_get_path(parent), allocated = g_strconcat(GetPath(),
"/", name_utf8, NULL); "/", name_utf8, NULL);
path_utf8 = allocated; path_utf8 = allocated;
} }
struct directory *directory = directory_new(path_utf8, parent); directory *child = NewGeneric(path_utf8, this);
g_free(allocated); g_free(allocated);
list_add_tail(&directory->siblings, &parent->children); list_add_tail(&child->siblings, &children);
return directory; return child;
} }
struct directory * const directory *
directory_get_child(const struct directory *directory, const char *name) directory::FindChild(const char *name) const
{ {
assert(holding_db_lock()); assert(holding_db_lock());
struct directory *child; const struct directory *child;
directory_for_each_child(child, directory) directory_for_each_child(child, this)
if (strcmp(directory_get_name(child), name) == 0) if (strcmp(child->GetName(), name) == 0)
return child; return child;
return NULL; return NULL;
} }
void void
directory_prune_empty(struct directory *directory) directory::PruneEmpty()
{ {
assert(holding_db_lock()); assert(holding_db_lock());
struct directory *child, *n; struct directory *child, *n;
directory_for_each_child_safe(child, n, directory) { directory_for_each_child_safe(child, n, this) {
directory_prune_empty(child); child->PruneEmpty();
if (directory_is_empty(child)) if (child->IsEmpty())
directory_delete(child); child->Delete();
} }
} }
struct directory * struct directory *
directory_lookup_directory(struct directory *directory, const char *uri) directory::LookupDirectory(const char *uri)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(uri != NULL); assert(uri != NULL);
if (isRootDirectory(uri)) if (isRootDirectory(uri))
return directory; return this;
char *duplicated = g_strdup(uri), *name = duplicated; char *duplicated = g_strdup(uri), *name = duplicated;
struct directory *d = this;
while (1) { while (1) {
char *slash = strchr(name, '/'); char *slash = strchr(name, '/');
if (slash == name) { if (slash == name) {
directory = NULL; d = NULL;
break; break;
} }
if (slash != NULL) if (slash != NULL)
*slash = '\0'; *slash = '\0';
directory = directory_get_child(directory, name); d = d->FindChild(name);
if (directory == NULL || slash == NULL) if (d == NULL || slash == NULL)
break; break;
name = slash + 1; name = slash + 1;
@ -194,42 +191,38 @@ directory_lookup_directory(struct directory *directory, const char *uri)
g_free(duplicated); g_free(duplicated);
return directory; return d;
} }
void void
directory_add_song(struct directory *directory, struct song *song) directory::AddSong(struct song *song)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(directory != NULL);
assert(song != NULL); assert(song != NULL);
assert(song->parent == directory); assert(song->parent == this);
list_add_tail(&song->siblings, &directory->songs); list_add_tail(&song->siblings, &songs);
} }
void void
directory_remove_song(G_GNUC_UNUSED struct directory *directory, directory::RemoveSong(struct song *song)
struct song *song)
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(directory != NULL);
assert(song != NULL); assert(song != NULL);
assert(song->parent == directory); assert(song->parent == this);
list_del(&song->siblings); list_del(&song->siblings);
} }
struct song * const song *
directory_get_song(const struct directory *directory, const char *name_utf8) directory::FindSong(const char *name_utf8) const
{ {
assert(holding_db_lock()); assert(holding_db_lock());
assert(directory != NULL);
assert(name_utf8 != NULL); assert(name_utf8 != NULL);
struct song *song; struct song *song;
directory_for_each_song(song, directory) { directory_for_each_song(song, this) {
assert(song->parent == directory); assert(song->parent == this);
if (strcmp(song->uri, name_utf8) == 0) if (strcmp(song->uri, name_utf8) == 0)
return song; return song;
@ -239,29 +232,29 @@ directory_get_song(const struct directory *directory, const char *name_utf8)
} }
struct song * struct song *
directory_lookup_song(struct directory *directory, const char *uri) directory::LookupSong(const char *uri)
{ {
char *duplicated, *base; char *duplicated, *base;
assert(holding_db_lock()); assert(holding_db_lock());
assert(directory != NULL);
assert(uri != NULL); assert(uri != NULL);
duplicated = g_strdup(uri); duplicated = g_strdup(uri);
base = strrchr(duplicated, '/'); base = strrchr(duplicated, '/');
struct directory *d = this;
if (base != NULL) { if (base != NULL) {
*base++ = 0; *base++ = 0;
directory = directory_lookup_directory(directory, duplicated); d = d->LookupDirectory(duplicated);
if (directory == NULL) { if (d == nullptr) {
g_free(duplicated); g_free(duplicated);
return NULL; return NULL;
} }
} else } else
base = duplicated; base = duplicated;
struct song *song = directory_get_song(directory, base); struct song *song = d->FindSong(base);
assert(song == NULL || song->parent == directory); assert(song == NULL || song->parent == d);
g_free(duplicated); g_free(duplicated);
return song; return song;
@ -278,16 +271,16 @@ directory_cmp(G_GNUC_UNUSED void *priv,
} }
void void
directory_sort(struct directory *directory) directory::Sort()
{ {
assert(holding_db_lock()); assert(holding_db_lock());
list_sort(NULL, &directory->children, directory_cmp); list_sort(NULL, &children, directory_cmp);
song_list_sort(&directory->songs); song_list_sort(&songs);
struct directory *child; struct directory *child;
directory_for_each_child(child, directory) directory_for_each_child(child, this)
directory_sort(child); child->Sort();
} }
bool bool

View File

@ -90,6 +90,154 @@ struct directory {
bool have_stat; /* not needed if ino_t == dev_t == 0 is impossible */ bool have_stat; /* not needed if ino_t == dev_t == 0 is impossible */
char path[sizeof(long)]; char path[sizeof(long)];
/**
* Generic constructor for #directory object.
*/
gcc_malloc
static directory *NewGeneric(const char *path_utf8, directory *parent);
/**
* Create a new root #directory object.
*/
gcc_malloc
static directory *NewRoot() {
return NewGeneric("", nullptr);
}
/**
* Free this #directory object (and the whole object tree within it),
* assuming it was already removed from the parent.
*/
void Free();
/**
* Remove this #directory object from its parent and free it. This
* must not be called with the root directory.
*
* Caller must lock the #db_mutex.
*/
void Delete();
/**
* Create a new #directory object as a child of the given one.
*
* Caller must lock the #db_mutex.
*
* @param name_utf8 the UTF-8 encoded name of the new sub directory
*/
gcc_malloc
directory *CreateChild(const char *name_utf8);
/**
* Caller must lock the #db_mutex.
*/
gcc_pure
const directory *FindChild(const char *name) const;
gcc_pure
directory *FindChild(const char *name) {
const directory *cthis = this;
return const_cast<directory *>(cthis->FindChild(name));
}
/**
* Look up a sub directory, and create the object if it does not
* exist.
*
* Caller must lock the #db_mutex.
*/
struct directory *MakeChild(const char *name_utf8) {
struct directory *child = FindChild(name_utf8);
if (child == nullptr)
child = CreateChild(name_utf8);
return child;
}
/**
* Looks up a directory by its relative URI.
*
* @param uri the relative URI
* @return the directory, or NULL if none was found
*/
gcc_pure
directory *LookupDirectory(const char *uri);
gcc_pure
bool IsEmpty() const {
return list_empty(&children) &&
list_empty(&songs) &&
list_empty(&playlists);
}
gcc_pure
const char *GetPath() const {
return path;
}
/**
* Returns the base name of the directory.
*/
gcc_pure
const char *GetName() const;
/**
* Is this the root directory of the music database?
*/
gcc_pure
bool IsRoot() const {
return parent == NULL;
}
/**
* Look up a song in this directory by its name.
*
* Caller must lock the #db_mutex.
*/
gcc_pure
const song *FindSong(const char *name_utf8) const;
gcc_pure
song *FindSong(const char *name_utf8) {
const directory *cthis = this;
return const_cast<song *>(cthis->FindSong(name_utf8));
}
/**
* Looks up a song by its relative URI.
*
* Caller must lock the #db_mutex.
*
* @param uri the relative URI
* @return the song, or NULL if none was found
*/
gcc_pure
song *LookupSong(const char *uri);
/**
* Add a song object to this directory. Its "parent" attribute must
* be set already.
*/
void AddSong(song *song);
/**
* Remove a song object from this directory (which effectively
* invalidates the song object, because the "parent" attribute becomes
* stale), but does not free it.
*/
void RemoveSong(song *song);
/**
* Caller must lock the #db_mutex.
*/
void PruneEmpty();
/**
* Sort all directory entries recursively.
*
* Caller must lock the #db_mutex.
*/
void Sort();
/** /**
* Caller must lock #db_mutex. * Caller must lock #db_mutex.
*/ */
@ -105,161 +253,4 @@ isRootDirectory(const char *name)
return name[0] == 0 || (name[0] == '/' && name[1] == 0); return name[0] == 0 || (name[0] == '/' && name[1] == 0);
} }
/**
* Generic constructor for #directory object.
*/
gcc_malloc
struct directory *
directory_new(const char *dirname, struct directory *parent);
/**
* Create a new root #directory object.
*/
gcc_malloc
static inline struct directory *
directory_new_root(void)
{
return directory_new("", NULL);
}
/**
* Free this #directory object (and the whole object tree within it),
* assuming it was already removed from the parent.
*/
void
directory_free(struct directory *directory);
/**
* Remove this #directory object from its parent and free it. This
* must not be called with the root directory.
*
* Caller must lock the #db_mutex.
*/
void
directory_delete(struct directory *directory);
static inline bool
directory_is_empty(const struct directory *directory)
{
return list_empty(&directory->children) &&
list_empty(&directory->songs) &&
list_empty(&directory->playlists);
}
static inline const char *
directory_get_path(const struct directory *directory)
{
return directory->path;
}
/**
* Is this the root directory of the music database?
*/
static inline bool
directory_is_root(const struct directory *directory)
{
return directory->parent == NULL;
}
/**
* Returns the base name of the directory.
*/
gcc_pure
const char *
directory_get_name(const struct directory *directory);
/**
* Caller must lock the #db_mutex.
*/
gcc_pure
struct directory *
directory_get_child(const struct directory *directory, const char *name);
/**
* Create a new #directory object as a child of the given one.
*
* Caller must lock the #db_mutex.
*
* @param parent the parent directory the new one will be added to
* @param name_utf8 the UTF-8 encoded name of the new sub directory
*/
gcc_malloc
struct directory *
directory_new_child(struct directory *parent, const char *name_utf8);
/**
* Look up a sub directory, and create the object if it does not
* exist.
*
* Caller must lock the #db_mutex.
*/
static inline struct directory *
directory_make_child(struct directory *directory, const char *name_utf8)
{
struct directory *child = directory_get_child(directory, name_utf8);
if (child == NULL)
child = directory_new_child(directory, name_utf8);
return child;
}
/**
* Caller must lock the #db_mutex.
*/
void
directory_prune_empty(struct directory *directory);
/**
* Looks up a directory by its relative URI.
*
* @param directory the parent (or grandparent, ...) directory
* @param uri the relative URI
* @return the directory, or NULL if none was found
*/
struct directory *
directory_lookup_directory(struct directory *directory, const char *uri);
/**
* Add a song object to this directory. Its "parent" attribute must
* be set already.
*/
void
directory_add_song(struct directory *directory, struct song *song);
/**
* Remove a song object from this directory (which effectively
* invalidates the song object, because the "parent" attribute becomes
* stale), but does not free it.
*/
void
directory_remove_song(struct directory *directory, struct song *song);
/**
* Look up a song in this directory by its name.
*
* Caller must lock the #db_mutex.
*/
gcc_pure
struct song *
directory_get_song(const struct directory *directory, const char *name_utf8);
/**
* Looks up a song by its relative URI.
*
* Caller must lock the #db_mutex.
*
* @param directory the parent (or grandparent, ...) directory
* @param uri the relative URI
* @return the song, or NULL if none was found
*/
struct song *
directory_lookup_song(struct directory *directory, const char *uri);
/**
* Sort all directory entries recursively.
*
* Caller must lock the #db_mutex.
*/
void
directory_sort(struct directory *directory);
#endif #endif

View File

@ -48,12 +48,11 @@ directory_quark(void)
void void
directory_save(FILE *fp, const struct directory *directory) directory_save(FILE *fp, const struct directory *directory)
{ {
if (!directory_is_root(directory)) { if (!directory->IsRoot()) {
fprintf(fp, DIRECTORY_MTIME "%lu\n", fprintf(fp, DIRECTORY_MTIME "%lu\n",
(unsigned long)directory->mtime); (unsigned long)directory->mtime);
fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, fprintf(fp, "%s%s\n", DIRECTORY_BEGIN, directory->GetPath());
directory_get_path(directory));
} }
struct directory *cur; struct directory *cur;
@ -75,9 +74,8 @@ directory_save(FILE *fp, const struct directory *directory)
playlist_vector_save(fp, &directory->playlists); playlist_vector_save(fp, &directory->playlists);
if (!directory_is_root(directory)) if (!directory->IsRoot())
fprintf(fp, DIRECTORY_END "%s\n", fprintf(fp, DIRECTORY_END "%s\n", directory->GetPath());
directory_get_path(directory));
} }
static struct directory * static struct directory *
@ -87,19 +85,19 @@ directory_load_subdir(FILE *fp, struct directory *parent, const char *name,
const char *line; const char *line;
bool success; bool success;
if (directory_get_child(parent, name) != NULL) { if (parent->FindChild(name) != nullptr) {
g_set_error(error_r, directory_quark(), 0, g_set_error(error_r, directory_quark(), 0,
"Duplicate subdirectory '%s'", name); "Duplicate subdirectory '%s'", name);
return NULL; return NULL;
} }
struct directory *directory = directory_new_child(parent, name); struct directory *directory = parent->CreateChild(name);
line = read_text_line(fp, buffer); line = read_text_line(fp, buffer);
if (line == NULL) { if (line == NULL) {
g_set_error(error_r, directory_quark(), 0, g_set_error(error_r, directory_quark(), 0,
"Unexpected end of file"); "Unexpected end of file");
directory_delete(directory); directory->Delete();
return NULL; return NULL;
} }
@ -112,7 +110,7 @@ directory_load_subdir(FILE *fp, struct directory *parent, const char *name,
if (line == NULL) { if (line == NULL) {
g_set_error(error_r, directory_quark(), 0, g_set_error(error_r, directory_quark(), 0,
"Unexpected end of file"); "Unexpected end of file");
directory_delete(directory); directory->Delete();
return NULL; return NULL;
} }
} }
@ -120,13 +118,13 @@ directory_load_subdir(FILE *fp, struct directory *parent, const char *name,
if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) {
g_set_error(error_r, directory_quark(), 0, g_set_error(error_r, directory_quark(), 0,
"Malformed line: %s", line); "Malformed line: %s", line);
directory_delete(directory); directory->Delete();
return NULL; return NULL;
} }
success = directory_load(fp, directory, buffer, error_r); success = directory_load(fp, directory, buffer, error_r);
if (!success) { if (!success) {
directory_delete(directory); directory->Delete();
return NULL; return NULL;
} }
@ -152,7 +150,7 @@ directory_load(FILE *fp, struct directory *directory,
const char *name = line + sizeof(SONG_BEGIN) - 1; const char *name = line + sizeof(SONG_BEGIN) - 1;
struct song *song; struct song *song;
if (directory_get_song(directory, name) != NULL) { if (directory->FindSong(name) != nullptr) {
g_set_error(error, directory_quark(), 0, g_set_error(error, directory_quark(), 0,
"Duplicate song '%s'", name); "Duplicate song '%s'", name);
return false; return false;
@ -163,7 +161,7 @@ directory_load(FILE *fp, struct directory *directory,
if (song == NULL) if (song == NULL)
return false; return false;
directory_add_song(directory, song); directory->AddSong(song);
} else if (g_str_has_prefix(line, PLAYLIST_META_BEGIN)) { } else if (g_str_has_prefix(line, PLAYLIST_META_BEGIN)) {
/* duplicate the name, because /* duplicate the name, because
playlist_metadata_load() will overwrite the playlist_metadata_load() will overwrite the

View File

@ -186,10 +186,10 @@ map_directory_fs(const struct directory *directory)
assert(music_dir_utf8 != NULL); assert(music_dir_utf8 != NULL);
assert(music_dir_fs != NULL); assert(music_dir_fs != NULL);
if (directory_is_root(directory)) if (directory->IsRoot())
return g_strdup(music_dir_fs); return g_strdup(music_dir_fs);
return map_uri_fs(directory_get_path(directory)); return map_uri_fs(directory->GetPath());
} }
char * char *

View File

@ -161,10 +161,10 @@ song_get_uri(const struct song *song)
assert(song != nullptr); assert(song != nullptr);
assert(*song->uri); assert(*song->uri);
if (!song_in_database(song) || directory_is_root(song->parent)) if (!song_in_database(song) || song->parent->IsRoot())
return g_strdup(song->uri); return g_strdup(song->uri);
else else
return g_strconcat(directory_get_path(song->parent), return g_strconcat(song->parent->GetPath(),
"/", song->uri, nullptr); "/", song->uri, nullptr);
} }

View File

@ -33,9 +33,9 @@ extern "C" {
void void
song_print_uri(struct client *client, struct song *song) song_print_uri(struct client *client, struct song *song)
{ {
if (song_in_database(song) && !directory_is_root(song->parent)) { if (song_in_database(song) && !song->parent->IsRoot()) {
client_printf(client, "%s%s/%s\n", SONG_FILE, client_printf(client, "%s%s/%s\n", SONG_FILE,
directory_get_path(song->parent), song->uri); song->parent->GetPath(), song->uri);
} else { } else {
char *allocated; char *allocated;
const char *uri; const char *uri;

View File

@ -123,14 +123,12 @@ sticker_song_find_cb(const char *uri, const char *value, gpointer user_data)
{ {
struct sticker_song_find_data *data = struct sticker_song_find_data *data =
(struct sticker_song_find_data *)user_data; (struct sticker_song_find_data *)user_data;
struct song *song;
if (memcmp(uri, data->base_uri, data->base_uri_length) != 0) if (memcmp(uri, data->base_uri, data->base_uri_length) != 0)
/* should not happen, ignore silently */ /* should not happen, ignore silently */
return; return;
song = directory_lookup_song(data->directory, song *song = data->directory->LookupSong(uri + data->base_uri_length);
uri + data->base_uri_length);
if (song != NULL) if (song != NULL)
data->func(song, value, data->user_data); data->func(song, value, data->user_data);
} }
@ -147,7 +145,7 @@ sticker_song_find(struct directory *directory, const char *name,
data.user_data = user_data; data.user_data = user_data;
char *allocated; char *allocated;
data.base_uri = directory_get_path(directory); data.base_uri = directory->GetPath();
if (*data.base_uri != 0) if (*data.base_uri != 0)
/* append slash to base_uri */ /* append slash to base_uri */
data.base_uri = allocated = data.base_uri = allocated =

View File

@ -43,7 +43,7 @@ update_archive_tree(struct directory *directory, char *name)
//add dir is not there already //add dir is not there already
db_lock(); db_lock();
struct directory *subdir = struct directory *subdir =
directory_make_child(directory, name); directory->MakeChild(name);
subdir->device = DEVICE_INARCHIVE; subdir->device = DEVICE_INARCHIVE;
db_unlock(); db_unlock();
//create directories first //create directories first
@ -56,18 +56,18 @@ update_archive_tree(struct directory *directory, char *name)
//add file //add file
db_lock(); db_lock();
struct song *song = directory_get_song(directory, name); struct song *song = directory->FindSong(name);
db_unlock(); db_unlock();
if (song == NULL) { if (song == NULL) {
song = song_file_load(name, directory); song = song_file_load(name, directory);
if (song != NULL) { if (song != NULL) {
db_lock(); db_lock();
directory_add_song(directory, song); directory->AddSong(song);
db_unlock(); db_unlock();
modified = true; modified = true;
g_message("added %s/%s", g_message("added %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
} }
} }
} }
@ -87,7 +87,7 @@ update_archive_file2(struct directory *parent, const char *name,
const struct archive_plugin *plugin) const struct archive_plugin *plugin)
{ {
db_lock(); db_lock();
struct directory *directory = directory_get_child(parent, name); directory *directory = parent->FindChild(name);
db_unlock(); db_unlock();
if (directory != NULL && directory->mtime == st->st_mtime && if (directory != NULL && directory->mtime == st->st_mtime &&
@ -114,7 +114,7 @@ update_archive_file2(struct directory *parent, const char *name,
if (directory == NULL) { if (directory == NULL) {
g_debug("creating archive directory: %s", name); g_debug("creating archive directory: %s", name);
db_lock(); db_lock();
directory = directory_new_child(parent, name); directory = parent->CreateChild(name);
/* mark this directory as archive (we use device for /* mark this directory as archive (we use device for
this) */ this) */
directory->device = DEVICE_INARCHIVE; directory->device = DEVICE_INARCHIVE;

View File

@ -46,7 +46,7 @@ static struct directory *
make_directory_if_modified(struct directory *parent, const char *name, make_directory_if_modified(struct directory *parent, const char *name,
const struct stat *st) const struct stat *st)
{ {
struct directory *directory = directory_get_child(parent, name); directory *directory = parent->FindChild(name);
// directory exists already // directory exists already
if (directory != NULL) { if (directory != NULL) {
@ -60,7 +60,7 @@ make_directory_if_modified(struct directory *parent, const char *name,
modified = true; modified = true;
} }
directory = directory_make_child(parent, name); directory = parent->MakeChild(name);
directory->mtime = st->st_mtime; directory->mtime = st->st_mtime;
return directory; return directory;
} }
@ -104,13 +104,12 @@ update_container_file(struct directory *directory,
g_free(child_path_fs); g_free(child_path_fs);
db_lock(); db_lock();
directory_add_song(contdir, song); contdir->AddSong(song);
db_unlock(); db_unlock();
modified = true; modified = true;
g_message("added %s/%s", g_message("added %s/%s", directory->GetPath(), vtrack);
directory_get_path(directory), vtrack);
g_free(vtrack); g_free(vtrack);
} }

View File

@ -34,7 +34,7 @@ delete_song(struct directory *dir, struct song *del)
assert(del->parent == dir); assert(del->parent == dir);
/* first, prevent traversers in main task from getting this */ /* first, prevent traversers in main task from getting this */
directory_remove_song(dir, del); dir->RemoveSong(del);
db_unlock(); /* temporary unlock, because update_remove_song() blocks */ db_unlock(); /* temporary unlock, because update_remove_song() blocks */
@ -74,7 +74,7 @@ delete_directory(struct directory *directory)
clear_directory(directory); clear_directory(directory);
directory_delete(directory); directory->Delete();
} }
bool bool
@ -83,14 +83,14 @@ delete_name_in(struct directory *parent, const char *name)
bool modified = false; bool modified = false;
db_lock(); db_lock();
struct directory *directory = directory_get_child(parent, name); directory *directory = parent->FindChild(name);
if (directory != NULL) { if (directory != NULL) {
delete_directory(directory); delete_directory(directory);
modified = true; modified = true;
} }
struct song *song = directory_get_song(parent, name); struct song *song = parent->FindSong(name);
if (song != NULL) { if (song != NULL) {
delete_song(parent, song); delete_song(parent, song);
modified = true; modified = true;

View File

@ -42,12 +42,12 @@ update_song_file2(struct directory *directory,
const struct decoder_plugin *plugin) const struct decoder_plugin *plugin)
{ {
db_lock(); db_lock();
struct song *song = directory_get_song(directory, name); struct song *song = directory->FindSong(name);
db_unlock(); db_unlock();
if (!directory_child_access(directory, name, R_OK)) { if (!directory_child_access(directory, name, R_OK)) {
g_warning("no read permissions on %s/%s", g_warning("no read permissions on %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
if (song != NULL) { if (song != NULL) {
db_lock(); db_lock();
delete_song(directory, song); delete_song(directory, song);
@ -70,28 +70,27 @@ update_song_file2(struct directory *directory,
} }
if (song == NULL) { if (song == NULL) {
g_debug("reading %s/%s", g_debug("reading %s/%s", directory->GetPath(), name);
directory_get_path(directory), name);
song = song_file_load(name, directory); song = song_file_load(name, directory);
if (song == NULL) { if (song == NULL) {
g_debug("ignoring unrecognized file %s/%s", g_debug("ignoring unrecognized file %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
return; return;
} }
db_lock(); db_lock();
directory_add_song(directory, song); directory->AddSong(song);
db_unlock(); db_unlock();
modified = true; modified = true;
g_message("added %s/%s", g_message("added %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
} else if (st->st_mtime != song->mtime || walk_discard) { } else if (st->st_mtime != song->mtime || walk_discard) {
g_message("updating %s/%s", g_message("updating %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
if (!song_file_update(song)) { if (!song_file_update(song)) {
g_debug("deleting unrecognized file %s/%s", g_debug("deleting unrecognized file %s/%s",
directory_get_path(directory), name); directory->GetPath(), name);
db_lock(); db_lock();
delete_song(directory, song); delete_song(directory, song);
db_unlock(); db_unlock();

View File

@ -102,7 +102,7 @@ remove_excluded_from_directory(struct directory *directory,
struct directory *child, *n; struct directory *child, *n;
directory_for_each_child_safe(child, n, directory) { directory_for_each_child_safe(child, n, directory) {
char *name_fs = utf8_to_fs_charset(directory_get_name(child)); char *name_fs = utf8_to_fs_charset(child->GetName());
if (exclude_list_check(exclude_list, name_fs)) { if (exclude_list_check(exclude_list, name_fs)) {
delete_directory(child); delete_directory(child);
@ -254,8 +254,7 @@ update_directory_child(struct directory *directory,
return; return;
db_lock(); db_lock();
struct directory *subdir = struct directory *subdir = directory->MakeChild(name);
directory_make_child(directory, name);
db_unlock(); db_unlock();
assert(directory == subdir->parent); assert(directory == subdir->parent);
@ -423,7 +422,7 @@ static struct directory *
directory_make_child_checked(struct directory *parent, const char *name_utf8) directory_make_child_checked(struct directory *parent, const char *name_utf8)
{ {
db_lock(); db_lock();
struct directory *directory = directory_get_child(parent, name_utf8); directory *directory = parent->FindChild(name_utf8);
db_unlock(); db_unlock();
if (directory != NULL) if (directory != NULL)
@ -440,11 +439,11 @@ directory_make_child_checked(struct directory *parent, const char *name_utf8)
/* if we're adding directory paths, make sure to delete filenames /* if we're adding directory paths, make sure to delete filenames
with potentially the same name */ with potentially the same name */
db_lock(); db_lock();
struct song *conflicting = directory_get_song(parent, name_utf8); struct song *conflicting = parent->FindSong(name_utf8);
if (conflicting) if (conflicting)
delete_song(parent, conflicting); delete_song(parent, conflicting);
directory = directory_new_child(parent, name_utf8); directory = parent->CreateChild(name_utf8);
db_unlock(); db_unlock();
directory_set_stat(directory, &st); directory_set_stat(directory, &st);

View File

@ -168,7 +168,7 @@ ProxyDatabase::Open(GError **error_r)
return false; return false;
} }
root = directory_new_root(); root = directory::NewRoot();
return true; return true;
} }
@ -178,7 +178,7 @@ ProxyDatabase::Close()
{ {
assert(connection != nullptr); assert(connection != nullptr);
directory_free(root); root->Free();
mpd_connection_free(connection); mpd_connection_free(connection);
} }
@ -241,9 +241,9 @@ Visit(struct mpd_connection *connection,
if (visit_directory) { if (visit_directory) {
struct directory *d = struct directory *d =
directory_new(path, &detached_root); directory::NewGeneric(path, &detached_root);
bool success = visit_directory(*d, error_r); bool success = visit_directory(*d, error_r);
directory_free(d); d->Free();
if (!success) if (!success)
return false; return false;
} }

View File

@ -180,7 +180,7 @@ SimpleDatabase::Load(GError **error_r)
bool bool
SimpleDatabase::Open(GError **error_r) SimpleDatabase::Open(GError **error_r)
{ {
root = directory_new_root(); root = directory::NewRoot();
mtime = 0; mtime = 0;
#ifndef NDEBUG #ifndef NDEBUG
@ -189,7 +189,7 @@ SimpleDatabase::Open(GError **error_r)
GError *error = NULL; GError *error = NULL;
if (!Load(&error)) { if (!Load(&error)) {
directory_free(root); root->Free();
g_warning("Failed to load database: %s", error->message); g_warning("Failed to load database: %s", error->message);
g_error_free(error); g_error_free(error);
@ -197,7 +197,7 @@ SimpleDatabase::Open(GError **error_r)
if (!Check(error_r)) if (!Check(error_r))
return false; return false;
root = directory_new_root(); root = directory::NewRoot();
} }
return true; return true;
@ -209,7 +209,7 @@ SimpleDatabase::Close()
assert(root != NULL); assert(root != NULL);
assert(borrowed_song_count == 0); assert(borrowed_song_count == 0);
directory_free(root); root->Free();
} }
struct song * struct song *
@ -218,7 +218,7 @@ SimpleDatabase::GetSong(const char *uri, GError **error_r) const
assert(root != NULL); assert(root != NULL);
db_lock(); db_lock();
struct song *song = directory_lookup_song(root, uri); song *song = root->LookupSong(uri);
db_unlock(); db_unlock();
if (song == NULL) if (song == NULL)
g_set_error(error_r, db_quark(), DB_NOT_FOUND, g_set_error(error_r, db_quark(), DB_NOT_FOUND,
@ -250,7 +250,7 @@ SimpleDatabase::LookupDirectory(const char *uri) const
assert(uri != NULL); assert(uri != NULL);
ScopeDatabaseLock protect; ScopeDatabaseLock protect;
return directory_lookup_directory(root, uri); return root->LookupDirectory(uri);
} }
bool bool
@ -262,12 +262,10 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
{ {
ScopeDatabaseLock protect; ScopeDatabaseLock protect;
const struct directory *directory = const directory *directory = root->LookupDirectory(selection.uri);
directory_lookup_directory(root, selection.uri);
if (directory == NULL) { if (directory == NULL) {
if (visit_song) { if (visit_song) {
struct song *song = song *song = root->LookupSong(selection.uri);
directory_lookup_song(root, selection.uri);
if (song != nullptr) if (song != nullptr)
return !selection.Match(*song) || return !selection.Match(*song) ||
visit_song(*song, error_r); visit_song(*song, error_r);
@ -310,10 +308,10 @@ SimpleDatabase::Save(GError **error_r)
db_lock(); db_lock();
g_debug("removing empty directories from DB"); g_debug("removing empty directories from DB");
directory_prune_empty(root); root->PruneEmpty();
g_debug("sorting DB"); g_debug("sorting DB");
directory_sort(root); root->Sort();
db_unlock(); db_unlock();