Added new doubly-linked list implementation.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2484 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2003-01-18 14:15:20 +00:00
parent 5afbd29256
commit 8cd0fe6e99

172
src/kernel/core/list.c Normal file
View File

@ -0,0 +1,172 @@
/*
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
#include <list.h>
#define GET_ITEM(list, item) ((void *)((uint8 *)item - list->offset))
#define GET_LINK(list, item) ((list_link *)((uint8 *)item + list->offset))
/** Initializes the list with a specified offset to the link
* structure in the items that will be part of the list.
*/
void
list_init_etc(struct list *list, int32 offset)
{
list->link.next = list->link.prev = (list_link *)list;
list->offset = offset;
}
void
list_init(struct list *list)
{
list_init_etc(list, 0);
}
/** Adds a link to the head of the list
*/
void
list_add_link_to_head(struct list *list, void *_link)
{
list_link *link = (list_link *)_link;
link->next = list->link.next;
link->prev = (list_link *)list;
link->next->prev = link;
if (list->link.prev == (list_link *)list)
list->link.prev = link;
list->link.next = link;
}
/** Adds a link to the tail of the list
*/
void
list_add_link_to_tail(struct list *list, void *_link)
{
list_link *link = (list_link *)_link;
link->next = (list_link *)list;
link->prev = list->link.prev;
if (list->link.next == (list_link *)list)
list->link.next = link;
list->link.prev = link;
}
/** Removes a link from the list it's currently in.
* Note: the link has to be in a list when you call this function.
*/
void
list_remove_link(void *_link)
{
list_link *link = (list_link *)_link;
link->next->prev = link->prev;
link->prev->next = link->next;
}
static inline list_link *
get_next_link(struct list *list, list_link *link)
{
if (link->next == (list_link *)list)
return NULL;
return link->next;
}
static inline list_link *
get_prev_link(struct list *list, list_link *link)
{
if (link->prev == (list_link *)list)
return NULL;
return link->prev;
}
/** Gets the successor for the current item. If the passed
* item is NULL, it returns the first entry in the list,
* if there is one.
* Returns NULL if there aren't any more items in this list.
*/
void *
list_get_next_item(struct list *list, void *item)
{
list_link *link;
if (item == NULL)
return list_is_empty(list) ? NULL : GET_ITEM(list, list->link.next);
link = get_next_link(list, GET_LINK(list, item));
return link != NULL ? GET_ITEM(list, link) : NULL;
}
/** Gets the predecessor for the current item. If the passed
* item is NULL, it returns the last entry in the list,
* if there is one.
* Returns NULL if there aren't any previous items in this list.
*/
void *
list_get_prev_item(struct list *list, void *item)
{
list_link *link;
if (item == NULL)
return list_is_empty(list) ? NULL : GET_ITEM(list, list->link.prev);
link = get_prev_link(list, GET_LINK(list, item));
return link != NULL ? GET_ITEM(list, link) : NULL;
}
/** Removes the first item in the list and returns it.
* Returns NULL if the list is empty.
*/
void *
list_remove_head_item(struct list *list)
{
list_link *link;
if (list_is_empty(list))
return NULL;
list_remove_link(link = list->link.next);
return GET_ITEM(list, link);
}
/** Removes the last item in the list and returns it.
* Returns NULL if the list is empty.
*/
void *
list_remove_tail_item(struct list *list)
{
list_link *link;
if (list_is_empty(list))
return NULL;
list_remove_link(link = list->link.prev);
return GET_ITEM(list, link);
}