Files
haiku-beta6/headers/private/util/SinglyLinkedList.h
T

318 lines
6.4 KiB
C++
Raw Normal View History

/*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2010, Ingo Weinhold, [email protected].
*
* Distributed under the terms of the MIT License.
*/
#ifndef KERNEL_UTIL_SINGLY_LINKED_LIST_H
#define KERNEL_UTIL_SINGLY_LINKED_LIST_H
2003-06-23 05:54:53 +00:00
2013-11-20 14:06:32 +01:00
#include <SupportDefs.h>
#ifdef __cplusplus
2003-06-23 05:54:53 +00:00
// SinglyLinkedListLink
template<typename Element>
class SinglyLinkedListLink {
2003-06-23 05:54:53 +00:00
public:
SinglyLinkedListLink() : next(NULL) {}
~SinglyLinkedListLink() {}
2008-08-01 09:57:14 +00:00
Element* next;
2003-06-23 05:54:53 +00:00
};
// SinglyLinkedListLinkImpl
template<typename Element>
class SinglyLinkedListLinkImpl {
private:
typedef SinglyLinkedListLink<Element> SLL_Link;
2003-06-23 05:54:53 +00:00
public:
SinglyLinkedListLinkImpl() : fSinglyLinkedListLink() {}
~SinglyLinkedListLinkImpl() {}
SLL_Link* GetSinglyLinkedListLink()
{ return &fSinglyLinkedListLink; }
const SLL_Link* GetSinglyLinkedListLink() const
{ return &fSinglyLinkedListLink; }
2003-06-23 05:54:53 +00:00
private:
SLL_Link fSinglyLinkedListLink;
2003-06-23 05:54:53 +00:00
};
// SinglyLinkedListStandardGetLink
template<typename Element>
class SinglyLinkedListStandardGetLink {
private:
typedef SinglyLinkedListLink<Element> Link;
2003-06-23 05:54:53 +00:00
public:
inline Link* operator()(Element* element) const
{
return element->GetSinglyLinkedListLink();
}
inline const Link* operator()(const Element* element) const
{
return element->GetSinglyLinkedListLink();
}
};
2003-06-23 05:54:53 +00:00
// SinglyLinkedListMemberGetLink
template<typename Element,
SinglyLinkedListLink<Element> Element::* LinkMember = &Element::fLink>
class SinglyLinkedListMemberGetLink {
private:
typedef SinglyLinkedListLink<Element> Link;
2003-06-23 05:54:53 +00:00
public:
inline Link* operator()(Element* element) const
{
return &(element->*LinkMember);
}
inline const Link* operator()(const Element* element) const
{
return &(element->*LinkMember);
2003-06-23 05:54:53 +00:00
}
};
2003-06-23 05:54:53 +00:00
// for convenience
#define SINGLY_LINKED_LIST_TEMPLATE_LIST \
template<typename Element, typename GetLink>
#define SINGLY_LINKED_LIST_CLASS_NAME SinglyLinkedList<Element, GetLink>
2003-06-23 05:54:53 +00:00
template<typename Element,
typename GetLink = SinglyLinkedListStandardGetLink<Element> >
class SinglyLinkedList {
private:
typedef SinglyLinkedList<Element, GetLink> List;
typedef SinglyLinkedListLink<Element> Link;
2003-06-23 05:54:53 +00:00
public:
class ConstIterator {
public:
ConstIterator(const List* list)
:
fList(list)
{
Rewind();
}
2003-06-23 05:54:53 +00:00
ConstIterator(const ConstIterator& other)
{
*this = other;
}
2003-06-23 05:54:53 +00:00
bool HasNext() const
{
return fNext;
}
Element* Next()
{
Element* element = fNext;
if (fNext)
fNext = fList->GetNext(fNext);
return element;
}
ConstIterator& operator=(const ConstIterator& other)
{
fList = other.fList;
fNext = other.fNext;
return* this;
}
void Rewind()
{
fNext = fList->First();
}
private:
const List* fList;
Element* fNext;
};
public:
SinglyLinkedList() : fFirst(NULL) {}
~SinglyLinkedList() {}
inline bool IsEmpty() const { return (fFirst == NULL); }
2003-06-23 05:54:53 +00:00
inline void Add(Element* element);
inline bool Remove(Element* element);
inline void Remove(Element* previous, Element* element);
inline void TakeFrom(SINGLY_LINKED_LIST_CLASS_NAME* fromList);
2008-10-22 14:43:46 +00:00
// O(1) if either list is empty, otherwise O(n).
inline void RemoveAll();
inline void MakeEmpty() { RemoveAll(); }
inline Element* First() const { return fFirst; }
inline Element* Head() const { return fFirst; }
inline Element* RemoveHead();
inline Element* GetNext(Element* element) const;
2024-09-04 14:04:46 -04:00
inline int32 Count() const;
// O(n)!
inline ConstIterator GetIterator() const { return ConstIterator(this); }
private:
Element *fFirst;
static GetLink sGetLink;
};
// inline methods
// Add
SINGLY_LINKED_LIST_TEMPLATE_LIST
2003-06-23 05:54:53 +00:00
void
SINGLY_LINKED_LIST_CLASS_NAME::Add(Element* element)
2003-06-23 05:54:53 +00:00
{
if (element != NULL) {
2008-08-01 09:57:14 +00:00
sGetLink(element)->next = fFirst;
fFirst = element;
}
2003-06-23 05:54:53 +00:00
}
/*! Removes \a element from the list.
It is safe to call the list with a \c NULL element or an element that isn't
in the list.
\param element The element to be removed.
\return \c true, if the element was in the list and has been removed,
\c false otherwise.
*/
SINGLY_LINKED_LIST_TEMPLATE_LIST
bool
SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element* element)
2003-06-23 05:54:53 +00:00
{
if (element == NULL)
return false;
Element* next = fFirst;
Element* last = NULL;
while (element != next) {
if (next == NULL)
return false;
last = next;
next = sGetLink(next)->next;
}
2003-06-23 05:54:53 +00:00
Link* elementLink = sGetLink(element);
if (last == NULL)
fFirst = elementLink->next;
else
sGetLink(last)->next = elementLink->next;
2003-06-23 05:54:53 +00:00
elementLink->next = NULL;
return true;
2003-06-23 05:54:53 +00:00
}
2008-10-22 14:43:46 +00:00
SINGLY_LINKED_LIST_TEMPLATE_LIST
void
SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element* previous, Element* element)
{
// ASSERT(previous == NULL
// ? fFirst == element : sGetLink(previous)->next == element);
Link* elementLink = sGetLink(element);
if (previous == NULL)
fFirst = elementLink->next;
else
sGetLink(previous)->next = elementLink->next;
elementLink->next = NULL;
}
2008-10-22 14:43:46 +00:00
SINGLY_LINKED_LIST_TEMPLATE_LIST
void
SINGLY_LINKED_LIST_CLASS_NAME::TakeFrom(SINGLY_LINKED_LIST_CLASS_NAME* fromList)
2008-10-22 14:43:46 +00:00
{
if (fromList->fFirst == NULL)
return;
if (fFirst == NULL) {
// This list is empty -- just transfer the head.
fFirst = fromList->fFirst;
fromList->fFirst = NULL;
return;
}
// Neither list is empty -- find the tail of this list.
Element* tail = fFirst;
while (Element* next = sGetLink(tail)->next)
tail = next;
sGetLink(tail)->next = fromList->fFirst;
fromList->fFirst = NULL;
}
// RemoveAll
SINGLY_LINKED_LIST_TEMPLATE_LIST
void
SINGLY_LINKED_LIST_CLASS_NAME::RemoveAll()
2003-06-23 05:54:53 +00:00
{
Element* element = fFirst;
while (element) {
Link* elLink = sGetLink(element);
element = elLink->next;
elLink->next = NULL;
}
fFirst = NULL;
2003-06-23 05:54:53 +00:00
}
// RemoveHead
SINGLY_LINKED_LIST_TEMPLATE_LIST
Element*
SINGLY_LINKED_LIST_CLASS_NAME::RemoveHead()
2003-06-23 05:54:53 +00:00
{
Element* element = Head();
Remove(element);
return element;
2003-06-23 05:54:53 +00:00
}
// GetNext
SINGLY_LINKED_LIST_TEMPLATE_LIST
Element*
SINGLY_LINKED_LIST_CLASS_NAME::GetNext(Element* element) const
2003-06-23 05:54:53 +00:00
{
Element* result = NULL;
if (element)
result = sGetLink(element)->next;
return result;
2003-06-23 05:54:53 +00:00
}
// Size
SINGLY_LINKED_LIST_TEMPLATE_LIST
int32
2024-09-04 14:04:46 -04:00
SINGLY_LINKED_LIST_CLASS_NAME::Count() const
2003-06-23 05:54:53 +00:00
{
int32 count = 0;
for (Element* element = First(); element; element = GetNext(element))
count++;
2003-06-23 05:54:53 +00:00
return count;
}
// sGetLink
SINGLY_LINKED_LIST_TEMPLATE_LIST
GetLink SINGLY_LINKED_LIST_CLASS_NAME::sGetLink;
2003-06-23 05:54:53 +00:00
#endif /* __cplusplus */
2003-06-23 05:54:53 +00:00
#endif // _KERNEL_UTIL_SINGLY_LINKED_LIST_H