diff options
author | Eric Wong <normalperson@yhbt.net> | 2008-09-23 20:48:39 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-09-23 20:48:39 +0200 |
commit | 0bec1d38078c88d07939a4c210b7cdeb9c8eb59c (patch) | |
tree | 9ec91df91017224ef643060533a657db3c1c53dd /src/songvec.c | |
parent | afe6ce7210be330eefb0e8f18f2b6787bf052087 (diff) | |
download | mpd-0bec1d38078c88d07939a4c210b7cdeb9c8eb59c.tar.gz mpd-0bec1d38078c88d07939a4c210b7cdeb9c8eb59c.tar.xz mpd-0bec1d38078c88d07939a4c210b7cdeb9c8eb59c.zip |
Replace SongList with struct songvec
Our linked-list implementation is wasteful and the
SongList isn't modified enough to benefit from being a linked
list. So use a more compact array of song pointers which
saves ~200K on a library with ~9K songs (on x86-32).
Diffstat (limited to 'src/songvec.c')
-rw-r--r-- | src/songvec.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/songvec.c b/src/songvec.c new file mode 100644 index 000000000..620338781 --- /dev/null +++ b/src/songvec.c @@ -0,0 +1,89 @@ +#include "songvec.h" +#include "utils.h" + +/* Only used for sorting/searchin a songvec, not general purpose compares */ +static int songvec_cmp(const void *s1, const void *s2) +{ + const Song *a = ((const Song * const *)s1)[0]; + const Song *b = ((const Song * const *)s2)[0]; + return strcmp(a->url, b->url); +} + +static size_t sv_size(struct songvec *sv) +{ + return sv->nr * sizeof(Song *); +} + +void songvec_sort(struct songvec *sv) +{ + qsort(sv->base, sv->nr, sizeof(Song *), songvec_cmp); +} + +Song *songvec_find(struct songvec *sv, const char *url) +{ + int i; + + for (i = sv->nr; --i >= 0; ) + if (!strcmp(sv->base[i]->url, url)) + return sv->base[i]; + return NULL; +} + +int songvec_delete(struct songvec *sv, Song *del) +{ + int i; + + for (i = sv->nr; --i >= 0; ) { + if (sv->base[i] != del) + continue; + /* we _don't_ call freeSong() here */ + if (!--sv->nr) { + free(sv->base); + sv->base = NULL; + } else { + memmove(&sv->base[i], &sv->base[i + 1], + (sv->nr - i + 1) * sizeof(Song *)); + sv->base = xrealloc(sv->base, sv_size(sv)); + } + return i; + } + + return -1; /* not found */ +} + +void songvec_add(struct songvec *sv, Song *add) +{ + ++sv->nr; + sv->base = xrealloc(sv->base, sv_size(sv)); + sv->base[sv->nr - 1] = add; +} + +void songvec_free(struct songvec *sv) +{ + free(sv->base); + sv->base = NULL; + sv->nr = 0; +} + +/* + * Removes missing songs from a songvec. This function is only temporary + * as updating will be moved into a thread and updating shared memory... + */ +#include "path.h" +#include "ls.h" +void songvec_prune(struct songvec *sv) +{ + int i; + char tmp[MPD_PATH_MAX]; + struct stat sb; + + for (i = sv->nr; --i >= 0; ) { + Song *song = sv->base[i]; + assert(song); + if (!myStat(get_song_url(tmp, song), &sb)) + continue; + songvec_delete(sv, song); + freeSong(song); + i = sv->nr; + } +} |