2003-10-13 05:57:05 +04:00
|
|
|
/*
|
|
|
|
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
|
|
|
** Distributed under the terms of the OpenBeOS License.
|
|
|
|
*/
|
|
|
|
#ifndef KERNEL_UTIL_DOUBLY_LINKED_LIST_H
|
|
|
|
#define KERNEL_UTIL_DOUBLY_LINKED_LIST_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <SupportDefs.h>
|
2004-03-03 03:50:01 +03:00
|
|
|
#include <util/kernel_cpp.h>
|
2003-10-13 05:57:05 +04:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
|
|
|
/* This header defines a doubly-linked list. It differentiates between a link
|
|
|
|
* and an item.
|
|
|
|
* It's the C++ version of <util/list.h> it's very small and efficient, but
|
|
|
|
* has not been perfectly C++-ified yet.
|
|
|
|
* The link must be part of the item, it cannot be allocated on demand yet.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace DoublyLinked {
|
|
|
|
|
|
|
|
class Link {
|
|
|
|
public:
|
|
|
|
Link *next;
|
|
|
|
Link *prev;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class Item, Link Item::* LinkMember = &Item::fLink> class Iterator;
|
|
|
|
|
|
|
|
template<class Item, Link Item::* LinkMember = &Item::fLink>
|
|
|
|
class List {
|
|
|
|
public:
|
|
|
|
//typedef typename Item ValueType;
|
|
|
|
typedef Iterator<Item, LinkMember> IteratorType;
|
|
|
|
|
|
|
|
List()
|
|
|
|
{
|
|
|
|
fLink.next = fLink.prev = &fLink;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Add(Item *item)
|
|
|
|
{
|
|
|
|
//Link *link = &item->*LinkMember;
|
|
|
|
(item->*LinkMember).next = &fLink;
|
|
|
|
(item->*LinkMember).prev = fLink.prev;
|
|
|
|
|
|
|
|
fLink.prev->next = &(item->*LinkMember);
|
|
|
|
fLink.prev = &(item->*LinkMember);
|
|
|
|
}
|
|
|
|
|
2004-03-03 03:50:01 +03:00
|
|
|
static void Remove(Item *item)
|
2003-10-13 05:57:05 +04:00
|
|
|
{
|
|
|
|
(item->*LinkMember).next->prev = (item->*LinkMember).prev;
|
|
|
|
(item->*LinkMember).prev->next = (item->*LinkMember).next;
|
|
|
|
}
|
|
|
|
|
|
|
|
Item *RemoveHead()
|
|
|
|
{
|
|
|
|
if (IsEmpty())
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Item *item = GetItem(fLink.next);
|
|
|
|
Remove(item);
|
|
|
|
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
|
|
|
IteratorType Iterator()
|
|
|
|
{
|
2003-10-13 07:19:21 +04:00
|
|
|
return IteratorType(this);
|
2003-10-13 05:57:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsEmpty()
|
|
|
|
{
|
|
|
|
return fLink.next == &fLink;
|
|
|
|
}
|
|
|
|
|
|
|
|
Link *Head()
|
|
|
|
{
|
|
|
|
return fLink.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static inline size_t Offset()
|
|
|
|
{
|
|
|
|
return (size_t)&(((Item *)1)->*LinkMember) - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline Item *GetItem(Link *link)
|
|
|
|
{
|
|
|
|
return (Item *)((uint8 *)link - Offset());
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2003-10-13 07:19:21 +04:00
|
|
|
friend class IteratorType;
|
2003-10-13 05:57:05 +04:00
|
|
|
Link fLink;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class Item, Link Item::* LinkMember>
|
|
|
|
class Iterator {
|
|
|
|
public:
|
|
|
|
typedef List<Item, LinkMember> ListType;
|
|
|
|
|
|
|
|
Iterator() : fCurrent(NULL) {}
|
2004-03-03 03:50:01 +03:00
|
|
|
Iterator(ListType &list) : fList(list), fCurrent(list.Head()) {}
|
2003-10-13 05:57:05 +04:00
|
|
|
|
|
|
|
Item *Next()
|
|
|
|
{
|
2004-03-03 03:50:01 +03:00
|
|
|
if (fCurrent == &fList.fLink)
|
2003-10-13 05:57:05 +04:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
Link *current = fCurrent;
|
|
|
|
fCurrent = fCurrent->next;
|
|
|
|
|
|
|
|
return ListType::GetItem(current);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2004-03-03 03:50:01 +03:00
|
|
|
ListType &fList;
|
|
|
|
Link *fCurrent;
|
2003-10-13 05:57:05 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace DoublyLinked
|
|
|
|
|
|
|
|
#endif /* __cplusplus */
|
|
|
|
|
|
|
|
#endif /* KERNEL_UTIL_DOUBLY_LINKED_LIST_H */
|