1
1

Changed directory listings to a doubly linked list

This significantly improves the performance when browsing large
directories. It is somewhat costly on the memory usage, though. :-(
Этот коммит содержится в:
Yorhel 2010-04-27 17:01:43 +02:00
родитель c84e70b627
Коммит eed949d48d
4 изменённых файлов: 40 добавлений и 30 удалений

Просмотреть файл

@ -172,6 +172,8 @@ int calc_item(struct dir *par, char *name) {
d->parent = par;
d->next = par->sub;
par->sub = d;
if(d->next)
d->next->prev = d;
d->name = malloc(strlen(name)+1);
strcpy(d->name, name);
@ -496,15 +498,14 @@ int calc_process() {
/* update references and free original item */
if(orig) {
root->next = orig->next;
if(orig->parent) {
t = orig->parent->sub;
if(t == orig)
orig->parent->sub = root;
else if(t != NULL)
for(; t->next!=NULL; t=t->next)
if(t->next == orig)
t->next = root;
}
root->prev = orig->prev;
if(root->parent && root->parent->sub == orig)
root->parent->sub = root;
if(root->prev)
root->prev->next = root;
if(root->next)
root->next->prev = root;
orig->next = orig->prev = NULL;
freedir(orig);
}
browse_init(root->sub);

Просмотреть файл

@ -122,6 +122,7 @@ struct dir *dirlist_sort(struct dir *list) {
}
if(tail) tail->next = e;
else list = e;
e->prev = tail;
tail = e;
}
p = q;
@ -225,10 +226,22 @@ struct dir *dirlist_next(struct dir *d) {
}
struct dir *dirlist_prev(struct dir *d) {
if(!head || !d)
return NULL;
while((d = d->prev)) {
if(!ISHIDDEN(d))
return d;
}
if(dirlist_parent)
return dirlist_parent;
return NULL;
}
/* this function assumes that 'selected' is valid and points to a visible item */
struct dir *dirlist_get(int i) {
struct dir *t = selected, *d;
int j;
if(!head)
return NULL;
@ -247,15 +260,15 @@ struct dir *dirlist_get(int i) {
return t;
}
/* negative number? start from beginning to get the index of the selected
* item, and then start all over to get the requested item before that.
* XXX: This can obviously be optimized by using a doubly linked list. */
for(j=0,t=NULL; (t=dirlist_next(t)); j++)
if(t == selected)
break;
for(t=NULL,j+=i; (t=dirlist_next(t))&&j>0; j--)
;
return t;
/* otherwise, backward */
while(1) {
d = dirlist_prev(t);
if(!d)
return t;
t = d;
if(!++i)
return t;
}
}

Просмотреть файл

@ -52,7 +52,7 @@
* XXX: probably a good idea to get rid of the custom _t types and use
* fixed-size integers instead, which are much more predictable */
struct dir {
struct dir *parent, *next, *sub, *hlnk;
struct dir *parent, *next, *prev, *sub, *hlnk;
char *name;
off_t size, asize;
unsigned long items;

Просмотреть файл

@ -226,16 +226,12 @@ void freedir(struct dir *dr) {
freedir_rec(dr->sub);
/* update references */
if(dr->parent) {
/* item is at the top of the dir, refer to next item */
if(dr->parent->sub == dr)
dr->parent->sub = dr->next;
/* else, get the previous item and update it's "next"-reference */
else
for(tmp = dr->parent->sub; tmp != NULL; tmp = tmp->next)
if(tmp->next == dr)
tmp->next = dr->next;
}
if(dr->parent && dr->parent->sub == dr)
dr->parent->sub = dr->next;
if(dr->prev)
dr->prev->next = dr->next;
if(dr->next)
dr->next->prev = dr->prev;
freedir_hlnk(dr);