Update copyright notices.
[mpd-mk.git] / src / directory.c
blob0ace67dde9e02825368921563eef47bb717e7c83
1 /*
2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
21 #include "directory.h"
22 #include "song.h"
23 #include "path.h"
25 #include <glib.h>
27 #include <assert.h>
28 #include <string.h>
29 #include <stdlib.h>
31 struct directory *
32 directory_new(const char *path, struct directory *parent)
34 struct directory *directory;
35 size_t pathlen = strlen(path);
37 assert(path != NULL);
38 assert((*path == 0) == (parent == NULL));
40 directory = g_malloc0(sizeof(*directory) -
41 sizeof(directory->path) + pathlen + 1);
42 directory->parent = parent;
43 memcpy(directory->path, path, pathlen + 1);
45 return directory;
48 void
49 directory_free(struct directory *directory)
51 for (unsigned i = 0; i < directory->songs.nr; ++i)
52 song_free(directory->songs.base[i]);
54 for (unsigned i = 0; i < directory->children.nr; ++i)
55 directory_free(directory->children.base[i]);
57 dirvec_destroy(&directory->children);
58 songvec_destroy(&directory->songs);
59 g_free(directory);
60 /* this resets last dir returned */
61 /*directory_get_path(NULL); */
64 const char *
65 directory_get_name(const struct directory *directory)
67 return g_basename(directory->path);
70 void
71 directory_prune_empty(struct directory *directory)
73 int i;
74 struct dirvec *dv = &directory->children;
76 for (i = dv->nr; --i >= 0; ) {
77 struct directory *child = dv->base[i];
79 directory_prune_empty(child);
81 if (directory_is_empty(child)) {
82 dirvec_delete(dv, child);
83 directory_free(child);
86 if (!dv->nr)
87 dirvec_destroy(dv);
90 struct directory *
91 directory_lookup_directory(struct directory *directory, const char *uri)
93 struct directory *cur = directory;
94 struct directory *found = NULL;
95 char *duplicated;
96 char *locate;
98 assert(uri != NULL);
100 if (isRootDirectory(uri))
101 return directory;
103 duplicated = g_strdup(uri);
104 locate = strchr(duplicated, '/');
105 while (1) {
106 if (locate)
107 *locate = '\0';
108 if (!(found = directory_get_child(cur, duplicated)))
109 break;
110 assert(cur == found->parent);
111 cur = found;
112 if (!locate)
113 break;
114 *locate = '/';
115 locate = strchr(locate + 1, '/');
118 g_free(duplicated);
120 return found;
123 struct song *
124 directory_lookup_song(struct directory *directory, const char *uri)
126 char *duplicated, *base;
127 struct song *song;
129 assert(directory != NULL);
130 assert(uri != NULL);
132 duplicated = g_strdup(uri);
133 base = strrchr(duplicated, '/');
135 if (base != NULL) {
136 *base++ = 0;
137 directory = directory_lookup_directory(directory, duplicated);
138 if (directory == NULL) {
139 g_free(duplicated);
140 return NULL;
142 } else
143 base = duplicated;
145 song = songvec_find(&directory->songs, base);
146 assert(song == NULL || song->parent == directory);
148 g_free(duplicated);
149 return song;
153 void
154 directory_sort(struct directory *directory)
156 int i;
157 struct dirvec *dv = &directory->children;
159 dirvec_sort(dv);
160 songvec_sort(&directory->songs);
162 for (i = dv->nr; --i >= 0; )
163 directory_sort(dv->base[i]);
167 directory_walk(struct directory *directory,
168 int (*forEachSong)(struct song *, void *),
169 int (*forEachDir)(struct directory *, void *),
170 void *data)
172 struct dirvec *dv = &directory->children;
173 int err = 0;
174 size_t j;
176 if (forEachDir && (err = forEachDir(directory, data)) < 0)
177 return err;
179 if (forEachSong) {
180 err = songvec_for_each(&directory->songs, forEachSong, data);
181 if (err < 0)
182 return err;
185 for (j = 0; err >= 0 && j < dv->nr; ++j)
186 err = directory_walk(dv->base[j], forEachSong,
187 forEachDir, data);
189 return err;