Commit 3b8bc33a authored by Eric Wong's avatar Eric Wong Committed by Max Kellermann

directory: replace DirectoryList with dirvec

Small memory reduction compared to songvec since most users have much fewer dirs than songs, but still nice to have.
parent 029f607e
...@@ -53,6 +53,7 @@ mpd_headers = \ ...@@ -53,6 +53,7 @@ mpd_headers = \
decoder_api.h \ decoder_api.h \
decoder_internal.h \ decoder_internal.h \
directory.h \ directory.h \
dirvec.h \
gcc.h \ gcc.h \
decoder_list.h \ decoder_list.h \
inputPlugins/_flac_common.h \ inputPlugins/_flac_common.h \
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "song_print.h" #include "song_print.h"
#include "song_save.h" #include "song_save.h"
#include "main_notify.h" #include "main_notify.h"
#include "dirvec.h"
#define DIRECTORY_DIR "directory: " #define DIRECTORY_DIR "directory: "
#define DIRECTORY_MTIME "mtime: " #define DIRECTORY_MTIME "mtime: "
...@@ -60,14 +61,10 @@ static pthread_t update_thr; ...@@ -60,14 +61,10 @@ static pthread_t update_thr;
static int directory_updateJobId; static int directory_updateJobId;
static DirectoryList *newDirectoryList(void);
static enum update_return static enum update_return
addToDirectory(Directory * directory, addToDirectory(Directory * directory,
const char *shortname, const char *name); const char *shortname, const char *name);
static void freeDirectoryList(DirectoryList * list);
static void freeDirectory(Directory * directory); static void freeDirectory(Directory * directory);
static enum update_return exploreDirectory(Directory * directory); static enum update_return exploreDirectory(Directory * directory);
...@@ -188,11 +185,6 @@ static void directory_set_stat(Directory * dir, const struct stat *st) ...@@ -188,11 +185,6 @@ static void directory_set_stat(Directory * dir, const struct stat *st)
dir->stat = 1; dir->stat = 1;
} }
static DirectoryList *newDirectoryList(void)
{
return makeList((ListFreeDataFunc *) freeDirectory, 1);
}
static Directory *newDirectory(const char *dirname, Directory * parent) static Directory *newDirectory(const char *dirname, Directory * parent)
{ {
Directory *directory; Directory *directory;
...@@ -201,13 +193,6 @@ static Directory *newDirectory(const char *dirname, Directory * parent) ...@@ -201,13 +193,6 @@ static Directory *newDirectory(const char *dirname, Directory * parent)
if (dirname && strlen(dirname)) if (dirname && strlen(dirname))
directory->path = xstrdup(dirname); directory->path = xstrdup(dirname);
else
directory->path = NULL;
directory->subDirectories = newDirectoryList();
assert(!directory->songs.base);
directory->stat = 0;
directory->inode = 0;
directory->device = 0;
directory->parent = parent; directory->parent = parent;
return directory; return directory;
...@@ -215,7 +200,7 @@ static Directory *newDirectory(const char *dirname, Directory * parent) ...@@ -215,7 +200,7 @@ static Directory *newDirectory(const char *dirname, Directory * parent)
static void freeDirectory(Directory * directory) static void freeDirectory(Directory * directory)
{ {
freeDirectoryList(directory->subDirectories); dirvec_destroy(&directory->children);
songvec_destroy(&directory->songs); songvec_destroy(&directory->songs);
if (directory->path) if (directory->path)
free(directory->path); free(directory->path);
...@@ -224,11 +209,6 @@ static void freeDirectory(Directory * directory) ...@@ -224,11 +209,6 @@ static void freeDirectory(Directory * directory)
/*getDirectoryPath(NULL); */ /*getDirectoryPath(NULL); */
} }
static void freeDirectoryList(DirectoryList * directoryList)
{
freeList(directoryList);
}
static void removeSongFromDirectory(Directory * directory, const char *shortname) static void removeSongFromDirectory(Directory * directory, const char *shortname)
{ {
Song *song = songvec_find(&directory->songs, shortname); Song *song = songvec_find(&directory->songs, shortname);
...@@ -243,27 +223,22 @@ static void removeSongFromDirectory(Directory * directory, const char *shortname ...@@ -243,27 +223,22 @@ static void removeSongFromDirectory(Directory * directory, const char *shortname
static void deleteEmptyDirectoriesInDirectory(Directory * directory) static void deleteEmptyDirectoriesInDirectory(Directory * directory)
{ {
ListNode *node = directory->subDirectories->firstNode; int i;
ListNode *nextNode; struct dirvec *dv = &directory->children;
Directory *subDir;
for (i = dv->nr; --i >= 0; ) {
while (node) { deleteEmptyDirectoriesInDirectory(dv->base[i]);
subDir = (Directory *) node->data; if (!dv->base[i]->children.nr && !dv->base[i]->songs.nr)
deleteEmptyDirectoriesInDirectory(subDir); dirvec_delete(dv, dv->base[i]);
nextNode = node->nextNode;
if (subDir->subDirectories->numberOfNodes == 0 &&
subDir->songs.nr == 0) {
deleteNodeFromList(directory->subDirectories, node);
}
node = nextNode;
} }
if (!dv->nr)
dirvec_destroy(dv);
} }
static enum update_return updateInDirectory(Directory * directory, static enum update_return updateInDirectory(Directory * directory,
const char *shortname, const char *name) const char *shortname, const char *name)
{ {
Song *song; Song *song;
void *subDir;
struct stat st; struct stat st;
if (myStat(name, &st)) if (myStat(name, &st))
...@@ -280,10 +255,10 @@ static enum update_return updateInDirectory(Directory * directory, ...@@ -280,10 +255,10 @@ static enum update_return updateInDirectory(Directory * directory,
return UPDATE_RETURN_UPDATED; return UPDATE_RETURN_UPDATED;
} }
} else if (S_ISDIR(st.st_mode)) { } else if (S_ISDIR(st.st_mode)) {
if (findInList Directory *subdir = dirvec_find(&directory->children, name);
(directory->subDirectories, shortname, (void **)&subDir)) { if (subdir) {
directory_set_stat((Directory *)subDir, &st); directory_set_stat(subdir, &st);
return updateDirectory((Directory *) subDir); return updateDirectory(subdir);
} else { } else {
return addSubDirectoryToDirectory(directory, shortname, return addSubDirectoryToDirectory(directory, shortname,
name, &st); name, &st);
...@@ -304,29 +279,17 @@ removeDeletedFromDirectory(char *path_max_tmp, Directory * directory) ...@@ -304,29 +279,17 @@ removeDeletedFromDirectory(char *path_max_tmp, Directory * directory)
{ {
const char *dirname = (directory && directory->path) ? const char *dirname = (directory && directory->path) ?
directory->path : NULL; directory->path : NULL;
ListNode *node, *tmpNode;
DirectoryList *subdirs = directory->subDirectories;
enum update_return ret = UPDATE_RETURN_NOUPDATE; enum update_return ret = UPDATE_RETURN_NOUPDATE;
int i; int i;
struct songvec *sv = &directory->songs; struct songvec *sv = &directory->songs;
struct dirvec *dv = &directory->children;
node = subdirs->firstNode; for (i = dv->nr; --i >= 0; ) {
while (node) { if (isDir(dv->base[i]->path))
tmpNode = node->nextNode; continue;
if (node->key) { LOG("removing directory: %s\n", dv->base[i]->path);
if (dirname) dirvec_delete(dv, dv->base[i]);
sprintf(path_max_tmp, "%s/%s", dirname, ret = UPDATE_RETURN_UPDATED;
node->key);
else
strcpy(path_max_tmp, node->key);
if (!isDir(path_max_tmp)) {
LOG("removing directory: %s\n", path_max_tmp);
deleteFromList(subdirs, node->key);
ret = UPDATE_RETURN_UPDATED;
}
}
node = tmpNode;
} }
for (i = sv->nr; --i >= 0; ) { /* cleaner deletes if we go backwards */ for (i = sv->nr; --i >= 0; ) { /* cleaner deletes if we go backwards */
...@@ -354,7 +317,7 @@ static Directory *addDirectoryPathToDB(const char *utf8path, ...@@ -354,7 +317,7 @@ static Directory *addDirectoryPathToDB(const char *utf8path,
char path_max_tmp[MPD_PATH_MAX]; char path_max_tmp[MPD_PATH_MAX];
char *parent; char *parent;
Directory *parentDirectory; Directory *parentDirectory;
void *directory; Directory *directory;
parent = parent_path(path_max_tmp, utf8path); parent = parent_path(path_max_tmp, utf8path);
...@@ -370,16 +333,14 @@ static Directory *addDirectoryPathToDB(const char *utf8path, ...@@ -370,16 +333,14 @@ static Directory *addDirectoryPathToDB(const char *utf8path,
while (*(*shortname) && *(*shortname) == '/') while (*(*shortname) && *(*shortname) == '/')
(*shortname)++; (*shortname)++;
if (!findInList if (!(directory = dirvec_find(&parentDirectory->children, utf8path))) {
(parentDirectory->subDirectories, *shortname, &directory)) {
struct stat st; struct stat st;
if (myStat(utf8path, &st) < 0 || if (myStat(utf8path, &st) < 0 ||
inodeFoundInParent(parentDirectory, st.st_ino, st.st_dev)) inodeFoundInParent(parentDirectory, st.st_ino, st.st_dev))
return NULL; return NULL;
else { else {
directory = newDirectory(utf8path, parentDirectory); directory = newDirectory(utf8path, parentDirectory);
insertInList(parentDirectory->subDirectories, dirvec_add(&parentDirectory->children, directory);
*shortname, directory);
} }
} }
...@@ -387,7 +348,7 @@ static Directory *addDirectoryPathToDB(const char *utf8path, ...@@ -387,7 +348,7 @@ static Directory *addDirectoryPathToDB(const char *utf8path,
with potentially the same name */ with potentially the same name */
removeSongFromDirectory(parentDirectory, *shortname); removeSongFromDirectory(parentDirectory, *shortname);
return (Directory *) directory; return directory;
} }
static Directory *addParentPathToDB(const char *utf8path, const char **shortname) static Directory *addParentPathToDB(const char *utf8path, const char **shortname)
...@@ -446,8 +407,7 @@ static enum update_return updatePath(const char *utf8path) ...@@ -446,8 +407,7 @@ static enum update_return updatePath(const char *utf8path)
/* if updateDirectory fails, means we should delete it */ /* if updateDirectory fails, means we should delete it */
else { else {
LOG("removing directory: %s\n", path); LOG("removing directory: %s\n", path);
deleteFromList(parentDirectory->subDirectories, dirvec_delete(&parentDirectory->children, directory);
shortname);
ret = UPDATE_RETURN_UPDATED; ret = UPDATE_RETURN_UPDATED;
/* don't return, path maybe a song now */ /* don't return, path maybe a song now */
} }
...@@ -623,7 +583,7 @@ static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device) ...@@ -623,7 +583,7 @@ static int inodeFoundInParent(Directory * parent, ino_t inode, dev_t device)
} }
static enum update_return addSubDirectoryToDirectory(Directory * directory, static enum update_return addSubDirectoryToDirectory(Directory * directory,
const char *shortname, mpd_unused const char *shortname,
const char *name, struct stat *st) const char *name, struct stat *st)
{ {
Directory *subDirectory; Directory *subDirectory;
...@@ -639,7 +599,7 @@ static enum update_return addSubDirectoryToDirectory(Directory * directory, ...@@ -639,7 +599,7 @@ static enum update_return addSubDirectoryToDirectory(Directory * directory,
return UPDATE_RETURN_NOUPDATE; return UPDATE_RETURN_NOUPDATE;
} }
insertInList(directory->subDirectories, shortname, subDirectory); dirvec_add(&directory->children, subDirectory);
return UPDATE_RETURN_UPDATED; return UPDATE_RETURN_UPDATED;
} }
...@@ -678,27 +638,6 @@ void closeMp3Directory(void) ...@@ -678,27 +638,6 @@ void closeMp3Directory(void)
freeDirectory(mp3rootDirectory); freeDirectory(mp3rootDirectory);
} }
static Directory *findSubDirectory(Directory * directory, const char *name)
{
void *subDirectory;
char *duplicated = xstrdup(name);
char *key;
key = strtok(duplicated, "/");
if (!key) {
free(duplicated);
return NULL;
}
if (findInList(directory->subDirectories, key, &subDirectory)) {
free(duplicated);
return (Directory *) subDirectory;
}
free(duplicated);
return NULL;
}
int isRootDirectory(const char *name) int isRootDirectory(const char *name)
{ {
if (name == NULL || name[0] == '\0' || strcmp(name, "/") == 0) { if (name == NULL || name[0] == '\0' || strcmp(name, "/") == 0) {
...@@ -710,25 +649,34 @@ int isRootDirectory(const char *name) ...@@ -710,25 +649,34 @@ int isRootDirectory(const char *name)
static Directory *getSubDirectory(Directory * directory, const char *name, static Directory *getSubDirectory(Directory * directory, const char *name,
const char **shortname) const char **shortname)
{ {
Directory *subDirectory; Directory *cur = directory;
int len; Directory *found = NULL;
char *duplicated;
char *locate;
if (isRootDirectory(name)) { if (isRootDirectory(name))
return directory; return directory;
}
if ((subDirectory = findSubDirectory(directory, name)) == NULL) duplicated = xstrdup(name);
return NULL; locate = strchr(duplicated, '/');
while (1) {
if (locate)
*locate = '\0';
if (!(found = dirvec_find(&cur->children, duplicated)))
break;
cur = found;
if (!locate)
break;
*locate = '/';
locate = strchr(locate + 1, '/');
}
*shortname = name; free(duplicated);
len = 0; if (found && (!(*shortname = strrchr(found->path, '/'))))
while (name[len] != '/' && name[len] != '\0') *shortname = found->path;
len++;
while (name[len] == '/')
len++;
return getSubDirectory(subDirectory, &(name[len]), shortname); return found;
} }
static Directory *getDirectoryDetails(const char *name, const char **shortname) static Directory *getDirectoryDetails(const char *name, const char **shortname)
...@@ -745,16 +693,13 @@ static Directory *getDirectory(const char *name) ...@@ -745,16 +693,13 @@ static Directory *getDirectory(const char *name)
return getSubDirectory(mp3rootDirectory, name, &shortname); return getSubDirectory(mp3rootDirectory, name, &shortname);
} }
static int printDirectoryList(struct client *client, DirectoryList * directoryList) static int printDirectoryList(struct client *client, struct dirvec *dv)
{ {
ListNode *node = directoryList->firstNode; size_t i;
Directory *directory;
while (node != NULL) { for (i = 0; i < dv->nr; ++i) {
directory = (Directory *) node->data; client_printf(client, DIRECTORY_DIR "%s\n",
client_printf(client, "%s%s\n", DIRECTORY_DIR, getDirectoryPath(dv->base[i]));
getDirectoryPath(directory));
node = node->nextNode;
} }
return 0; return 0;
...@@ -767,16 +712,17 @@ int printDirectoryInfo(struct client *client, const char *name) ...@@ -767,16 +712,17 @@ int printDirectoryInfo(struct client *client, const char *name)
if ((directory = getDirectory(name)) == NULL) if ((directory = getDirectory(name)) == NULL)
return -1; return -1;
printDirectoryList(client, directory->subDirectories); printDirectoryList(client, &directory->children);
songvec_print(client, &directory->songs); songvec_print(client, &directory->songs);
return 0; return 0;
} }
/* TODO error checking */
static void writeDirectoryInfo(FILE * fp, Directory * directory) static void writeDirectoryInfo(FILE * fp, Directory * directory)
{ {
ListNode *node = (directory->subDirectories)->firstNode; struct dirvec *children = &directory->children;
Directory *subDirectory; size_t i;
int retv; int retv;
if (directory->path) { if (directory->path) {
...@@ -788,15 +734,20 @@ static void writeDirectoryInfo(FILE * fp, Directory * directory) ...@@ -788,15 +734,20 @@ static void writeDirectoryInfo(FILE * fp, Directory * directory)
} }
} }
while (node != NULL) { for (i = 0; i < children->nr; ++i) {
subDirectory = (Directory *) node->data; Directory *cur = children->base[i];
retv = fprintf(fp, "%s%s\n", DIRECTORY_DIR, node->key); const char *base = strrchr(cur->path, '/');
base = base ? base + 1 : cur->path;
assert(*base);
retv = fprintf(fp, DIRECTORY_DIR "%s\n", base);
if (retv < 0) { if (retv < 0) {
ERROR("Failed to write data to database file: %s\n",strerror(errno)); ERROR("Failed to write data to database file: %s\n",
strerror(errno));
return; return;
} }
writeDirectoryInfo(fp, subDirectory); writeDirectoryInfo(fp, cur);
node = node->nextNode;
} }
songvec_save(fp, &directory->songs); songvec_save(fp, &directory->songs);
...@@ -817,10 +768,7 @@ static void readDirectoryInfo(FILE * fp, Directory * directory) ...@@ -817,10 +768,7 @@ static void readDirectoryInfo(FILE * fp, Directory * directory)
int bufferSize = MPD_PATH_MAX * 2; int bufferSize = MPD_PATH_MAX * 2;
char key[MPD_PATH_MAX * 2]; char key[MPD_PATH_MAX * 2];
Directory *subDirectory; Directory *subDirectory;
int strcmpRet;
char *name; char *name;
ListNode *nextDirNode = directory->subDirectories->firstNode;
ListNode *nodeTemp;
while (myFgets(buffer, bufferSize, fp) while (myFgets(buffer, bufferSize, fp)
&& prefixcmp(buffer, DIRECTORY_END)) { && prefixcmp(buffer, DIRECTORY_END)) {
...@@ -836,31 +784,8 @@ static void readDirectoryInfo(FILE * fp, Directory * directory) ...@@ -836,31 +784,8 @@ static void readDirectoryInfo(FILE * fp, Directory * directory)
if (prefixcmp(buffer, DIRECTORY_BEGIN)) if (prefixcmp(buffer, DIRECTORY_BEGIN))
FATAL("Error reading db at line: %s\n", buffer); FATAL("Error reading db at line: %s\n", buffer);
name = &(buffer[strlen(DIRECTORY_BEGIN)]); name = &(buffer[strlen(DIRECTORY_BEGIN)]);
subDirectory = newDirectory(name, directory);
while (nextDirNode && (strcmpRet = dirvec_add(&directory->children, subDirectory);
strcmp(key,
nextDirNode->key)) > 0) {
nodeTemp = nextDirNode->nextNode;
deleteNodeFromList(directory->subDirectories,
nextDirNode);
nextDirNode = nodeTemp;
}
if (NULL == nextDirNode) {
subDirectory = newDirectory(name, directory);
insertInList(directory->subDirectories,
key, (void *)subDirectory);
} else if (strcmpRet == 0) {
subDirectory = (Directory *) nextDirNode->data;
nextDirNode = nextDirNode->nextNode;
} else {
subDirectory = newDirectory(name, directory);
insertInListBeforeNode(directory->
subDirectories,
nextDirNode, -1, key,
(void *)subDirectory);
}
readDirectoryInfo(fp, subDirectory); readDirectoryInfo(fp, subDirectory);
} else if (!prefixcmp(buffer, SONG_BEGIN)) { } else if (!prefixcmp(buffer, SONG_BEGIN)) {
readSongInfoIntoList(fp, &directory->songs, directory); readSongInfoIntoList(fp, &directory->songs, directory);
...@@ -868,27 +793,18 @@ static void readDirectoryInfo(FILE * fp, Directory * directory) ...@@ -868,27 +793,18 @@ static void readDirectoryInfo(FILE * fp, Directory * directory)
FATAL("Unknown line in db: %s\n", buffer); FATAL("Unknown line in db: %s\n", buffer);
} }
} }
while (nextDirNode) {
nodeTemp = nextDirNode->nextNode;
deleteNodeFromList(directory->subDirectories, nextDirNode);
nextDirNode = nodeTemp;
}
} }
static void sortDirectory(Directory * directory) static void sortDirectory(Directory * directory)
{ {
ListNode *node = directory->subDirectories->firstNode; int i;
Directory *subDir; struct dirvec *dv = &directory->children;
sortList(directory->subDirectories); dirvec_sort(dv);
songvec_sort(&directory->songs); songvec_sort(&directory->songs);
while (node != NULL) { for (i = dv->nr; --i >= 0; )
subDir = (Directory *) node->data; sortDirectory(dv->base[i]);
sortDirectory(subDir);
node = node->nextNode;
}
} }
int checkDirectoryDB(void) int checkDirectoryDB(void)
...@@ -1074,9 +990,9 @@ static int traverseAllInSubDirectory(Directory * directory, ...@@ -1074,9 +990,9 @@ static int traverseAllInSubDirectory(Directory * directory,
int (*forEachDir) (Directory *, void *), int (*forEachDir) (Directory *, void *),
void *data) void *data)
{ {
ListNode *node; struct dirvec *dv = &directory->children;
Directory *dir;
int errFlag = 0; int errFlag = 0;
size_t j;
if (forEachDir) { if (forEachDir) {
errFlag = forEachDir(directory, data); errFlag = forEachDir(directory, data);
...@@ -1096,14 +1012,9 @@ static int traverseAllInSubDirectory(Directory * directory, ...@@ -1096,14 +1012,9 @@ static int traverseAllInSubDirectory(Directory * directory,
} }
} }
node = directory->subDirectories->firstNode; for (j = 0; !errFlag && j < dv->nr; ++j)
errFlag = traverseAllInSubDirectory(dv->base[j], forEachSong,
while (node != NULL && !errFlag) {
dir = (Directory *) node->data;
errFlag = traverseAllInSubDirectory(dir, forEachSong,
forEachDir, data); forEachDir, data);
node = node->nextNode;
}
return errFlag; return errFlag;
} }
...@@ -1137,43 +1048,33 @@ void initMp3Directory(void) ...@@ -1137,43 +1048,33 @@ void initMp3Directory(void)
static Song *getSongDetails(const char *file, const char **shortnameRet, static Song *getSongDetails(const char *file, const char **shortnameRet,
Directory ** directoryRet) Directory ** directoryRet)
{ {
Song *song; Song *song = NULL;
Directory *directory; Directory *directory;
char *dir = NULL; char *dir = NULL;
char *duplicated = xstrdup(file); char *duplicated = xstrdup(file);
char *shortname = duplicated; char *shortname = strrchr(duplicated, '/');
char *c = strtok(duplicated, "/");
DEBUG("get song: %s\n", file); DEBUG("get song: %s\n", file);
while (c) { if (!shortname) {
shortname = c; shortname = duplicated;
c = strtok(NULL, "/"); } else {
} *shortname = '\0';
++shortname;
if (shortname != duplicated) {
for (c = duplicated; c < shortname - 1; c++) {
if (*c == '\0')
*c = '/';
}
dir = duplicated; dir = duplicated;
} }
if (!(directory = getDirectory(dir))) { if (!(directory = getDirectory(dir)))
free(duplicated); goto out;
return NULL; if (!(song = songvec_find(&directory->songs, shortname)))
} goto out;
if (!(song = songvec_find(&directory->songs, shortname))) {
free(duplicated);
return NULL;
}
free(duplicated);
if (shortnameRet) if (shortnameRet)
*shortnameRet = shortname; *shortnameRet = song->url;
if (directoryRet) if (directoryRet)
*directoryRet = directory; *directoryRet = directory;
out:
free(duplicated);
return song; return song;
} }
......
...@@ -23,11 +23,14 @@ ...@@ -23,11 +23,14 @@
#include "songvec.h" #include "songvec.h"
#include "list.h" #include "list.h"
typedef List DirectoryList; struct dirvec {
struct _Directory **base;
size_t nr;
};
typedef struct _Directory { typedef struct _Directory {
char *path; char *path;
DirectoryList *subDirectories; struct dirvec children;
struct songvec songs; struct songvec songs;
struct _Directory *parent; struct _Directory *parent;
ino_t inode; ino_t inode;
......
#ifndef DIRVEC_H
#define DIRVEC_H
#include "directory.h"
#include "os_compat.h"
#include "utils.h"
static size_t dv_size(struct dirvec *dv)
{
return dv->nr * sizeof(Directory *);
}
/* Only used for sorting/searching a dirvec, not general purpose compares */
static int dirvec_cmp(const void *d1, const void *d2)
{
const Directory *a = ((const Directory * const *)d1)[0];
const Directory *b = ((const Directory * const *)d2)[0];
return strcmp(a->path, b->path);
}
static void dirvec_sort(struct dirvec *dv)
{
qsort(dv->base, dv->nr, sizeof(Directory *), dirvec_cmp);
}
static Directory *dirvec_find(struct dirvec *dv, const char *path)
{
int i;
for (i = dv->nr; --i >= 0; )
if (!strcmp(dv->base[i]->path, path))
return dv->base[i];
return NULL;
}
static int dirvec_delete(struct dirvec *dv, Directory *del)
{
int i;
for (i = dv->nr; --i >= 0; ) {
if (dv->base[i] != del)
continue;
/* we _don't_ call freeDirectory() here */
if (!--dv->nr) {
free(dv->base);
dv->base = NULL;
} else {
memmove(&dv->base[i], &dv->base[i + 1],
(dv->nr - i + 1) * sizeof(Directory *));
dv->base = xrealloc(dv->base, dv_size(dv));
}
return i;
}
return -1; /* not found */
}
static void dirvec_add(struct dirvec *dv, Directory *add)
{
++dv->nr;
dv->base = xrealloc(dv->base, dv_size(dv));
dv->base[dv->nr - 1] = add;
}
static void dirvec_destroy(struct dirvec *dv)
{
if (dv->base) {
free(dv->base);
dv->base = NULL;
}
dv->nr = 0;
}
#endif /* DIRVEC_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment