Commit b731bbe9 authored by Max Kellermann's avatar Max Kellermann

removed tree.c

This patch makes MPD consume much more memory because string pooling is disabled, but it prepares the next bunch of patches. Replace the code in tagTracker.c with naive algorithms without the tree code. For now, this should do; later we should find better algorithms, especially for getNumberOfTagItems(), which has become wasteful with temporary memory.
parent ad0e09b2
......@@ -84,7 +84,6 @@ mpd_headers = \
tag.h \
tag_id3.h \
tagTracker.h \
tree.h \
utf8.h \
utils.h \
volume.h \
......@@ -147,7 +146,6 @@ mpd_SOURCES = \
tag.c \
tag_id3.c \
tagTracker.c \
tree.c \
utils.c \
volume.c \
utf8.c \
......
......@@ -19,126 +19,110 @@
#include "tagTracker.h"
#include "tag.h"
#include "tree.h"
#include "utils.h"
#include "myfprintf.h"
#include "directory.h"
static Tree *tagTrees[TAG_NUM_OF_ITEM_TYPES];
struct visited {
struct visited *next;
typedef struct tagTrackerItem {
int count;
mpd_sint8 visited;
} TagTrackerItem;
/**
* this is the original pointer passed to visitInTagTracker(),
* i.e. the caller must not invalidate it until he calls
* resetVisitedFlagsInTagTracker().
*/
const char *value;
} mpd_packed;
char *getTagItemString(int type, char *string)
{
TreeIterator iter;
if (tagTrees[type] == NULL)
{
tagTrees[type] = MakeTree((TreeCompareKeyFunction)strcmp,
(TreeFreeFunction)free,
(TreeFreeFunction)free);
}
static struct visited *visited_heads[TAG_NUM_OF_ITEM_TYPES];
static unsigned num_visited[TAG_NUM_OF_ITEM_TYPES];
if (FindInTree(tagTrees[type], string, &iter))
{
((TagTrackerItem *)GetTreeKeyData(&iter)->data)->count++;
return (char *)GetTreeKeyData(&iter)->key;
}
else
{
TagTrackerItem *item = xmalloc(sizeof(TagTrackerItem));
char *key = xstrdup(string);
item->count = 1;
item->visited = 0;
InsertInTree(tagTrees[type], key, item);
return key;
}
char *getTagItemString(int type mpd_unused, char *string)
{
return xstrdup(string);
}
void removeTagItemString(int type, char *string)
void removeTagItemString(int type mpd_unused, char *string)
{
TreeIterator iter;
free(string);
}
assert(string);
static int visit_tag_items(int fd mpd_unused, Song *song, void *data)
{
enum tag_type type = (enum tag_type)(size_t)data;
unsigned i;
assert(tagTrees[type]);
if (tagTrees[type] == NULL)
return;
if (song->tag == NULL)
return 0;
if (FindInTree(tagTrees[type], string, &iter))
{
TagTrackerItem * item =
(TagTrackerItem *)GetTreeKeyData(&iter)->data;
item->count--;
if (item->count <= 0)
RemoveFromTreeByIterator(tagTrees[type], &iter);
for (i = 0; i < (unsigned)song->tag->numOfItems; ++i) {
const struct tag_item *item = song->tag->items[i];
if (item->type == type)
visitInTagTracker(type, item->value);
}
if (GetTreeSize(tagTrees[type]) == 0)
{
FreeTree(tagTrees[type]);
tagTrees[type] = NULL;
}
return 0;
}
int getNumberOfTagItems(int type)
{
if (tagTrees[type] == NULL)
return 0;
int ret;
resetVisitedFlagsInTagTracker(type);
return GetTreeSize(tagTrees[type]);
traverseAllIn(-1, NULL, visit_tag_items, NULL, (void*)(size_t)type);
ret = (int)num_visited[type];
resetVisitedFlagsInTagTracker(type);
return ret;
}
void resetVisitedFlagsInTagTracker(int type)
{
TreeIterator iter;
while (visited_heads[type] != NULL) {
struct visited *v = visited_heads[type];
visited_heads[type] = v->next;
free(v);
}
if (!tagTrees[type])
return;
num_visited[type] = 0;
}
for (SetTreeIteratorToBegin(tagTrees[type], &iter);
!IsTreeIteratorAtEnd(&iter);
IncrementTreeIterator(&iter))
{
((TagTrackerItem *)GetTreeKeyData(&iter)->data)->visited = 0;
}
static struct visited *
find_visit(int type, const char *p)
{
struct visited *v;
for (v = visited_heads[type]; v != NULL; v = v->next)
if (strcmp(v->value, p) == 0)
return v;
return NULL;
}
void visitInTagTracker(int type, const char *str)
{
TreeIterator iter;
if (!tagTrees[type])
return;
struct visited *v = find_visit(type, str);
size_t length;
if (!FindInTree(tagTrees[type], str, &iter))
if (v != NULL)
return;
((TagTrackerItem *)GetTreeKeyData(&iter)->data)->visited = 1;
length = strlen(str);
v = xmalloc(sizeof(*v));
v->value = str;
v->next = visited_heads[type];
visited_heads[type] = v;
++num_visited[type];
}
void printVisitedInTagTracker(int fd, int type)
{
TreeIterator iter;
TagTrackerItem * item;
struct visited *v;
if (!tagTrees[type])
return;
for (SetTreeIteratorToBegin(tagTrees[type], &iter);
!IsTreeIteratorAtEnd(&iter);
IncrementTreeIterator(&iter))
{
item = ((TagTrackerItem *)GetTreeKeyData(&iter)->data);
if (item->visited)
{
fdprintf(fd,
"%s: %s\n",
mpdTagItemKeys[type],
(char *)GetTreeKeyData(&iter)->key);
}
}
for (v = visited_heads[type]; v != NULL; v = v->next)
fdprintf(fd,
"%s: %s\n",
mpdTagItemKeys[type],
v->value);
}
/* the Music Player Daemon (MPD)
* Copyright (C) 2006-2007 by Warren Dukes (warren.dukes@gmail.com)
* This project's homepage is: http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef TREE_H
#define TREE_H
typedef struct _Tree Tree;
typedef struct _TreeNode TreeNode;
typedef struct _TreeIterator TreeIterator;
typedef struct _TreeKeyData TreeKeyData;
struct _TreeIterator
{
Tree * tree;
TreeNode * node;
int which;
};
struct _TreeKeyData
{
void * key;
void * data;
};
typedef int (*TreeCompareKeyFunction)(const void * key1, const void * key2);
typedef void (*TreeFreeFunction)(void * data);
Tree * MakeTree(TreeCompareKeyFunction compareFunc,
TreeFreeFunction freeKey,
TreeFreeFunction freeData);
void FreeTree(Tree * tree);
int GetTreeSize(Tree * tree);
void SetTreeIteratorToBegin(Tree * tree, TreeIterator * iter);
int IsTreeIteratorAtEnd(const TreeIterator * iter);
void IncrementTreeIterator(TreeIterator * iter);
const TreeKeyData *GetTreeKeyData(TreeIterator * iter);
int InsertInTree(Tree * tree, void * key, void * data);
int RemoveFromTreeByKey(Tree * tree, void * key);
void RemoveFromTreeByIterator(Tree * tree, TreeIterator * iter);
int FindInTree(Tree * tree, const void * key,
TreeIterator * iter /* can be NULL */);
#endif
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