318 lines
6.4 KiB
C++
318 lines
6.4 KiB
C++
/*
|
|||
|
|
* 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
|
||
|
|
|
||
|
|||
#include <SupportDefs.h>
|
|||
|
|
|
||
|
|
|
||
#ifdef __cplusplus
|
|||
|
|||
// SinglyLinkedListLink
|
|||
|
|
template<typename Element>
|
||
|
|
class SinglyLinkedListLink {
|
||
public:
|
|||
SinglyLinkedListLink() : next(NULL) {}
|
|||
|
|
~SinglyLinkedListLink() {}
|
||
|
|
|
||
Element* next;
|
|||
};
|
|||
|
|
|
||
// SinglyLinkedListLinkImpl
|
|||
|
|
template<typename Element>
|
||
|
|
class SinglyLinkedListLinkImpl {
|
||
|
|
private:
|
||
|
|
typedef SinglyLinkedListLink<Element> SLL_Link;
|
||
|
|
|
||
public:
|
|||
SinglyLinkedListLinkImpl() : fSinglyLinkedListLink() {}
|
|||
|
|
~SinglyLinkedListLinkImpl() {}
|
||
|
|
|
||
|
|
SLL_Link* GetSinglyLinkedListLink()
|
||
|
|
{ return &fSinglyLinkedListLink; }
|
||
|
|
const SLL_Link* GetSinglyLinkedListLink() const
|
||
|
|
{ return &fSinglyLinkedListLink; }
|
||
|
|
|
||
private:
|
|||
SLL_Link fSinglyLinkedListLink;
|
|||
};
|
|||
|
|||
// SinglyLinkedListStandardGetLink
|
|||
|
|
template<typename Element>
|
||
|
|
class SinglyLinkedListStandardGetLink {
|
||
|
|
private:
|
||
|
|
typedef SinglyLinkedListLink<Element> Link;
|
||
|
|||
public:
|
|||
|
|
inline Link* operator()(Element* element) const
|
||
|
|
{
|
||
|
|
return element->GetSinglyLinkedListLink();
|
||
|
|
}
|
||
|
|||
inline const Link* operator()(const Element* element) const
|
|||
|
|
{
|
||
|
|
return element->GetSinglyLinkedListLink();
|
||
|
|
}
|
||
|
|
};
|
||
|
|||
// SinglyLinkedListMemberGetLink
|
|||
|
|
template<typename Element,
|
||
|
|
SinglyLinkedListLink<Element> Element::* LinkMember = &Element::fLink>
|
||
|
|
class SinglyLinkedListMemberGetLink {
|
||
|
|
private:
|
||
|
|
typedef SinglyLinkedListLink<Element> Link;
|
||
|
|||
public:
|
|||
|
|
inline Link* operator()(Element* element) const
|
||
|
|
{
|
||
|
|
return &(element->*LinkMember);
|
||
|
|
}
|
||
|
|||
inline const Link* operator()(const Element* element) const
|
|||
|
|
{
|
||
|
|
return &(element->*LinkMember);
|
||
}
|
|||
};
|
|||
|
|||
|
|
|
||
// for convenience
|
|||
|
|
#define SINGLY_LINKED_LIST_TEMPLATE_LIST \
|
||
|
|
template<typename Element, typename GetLink>
|
||
|
|
#define SINGLY_LINKED_LIST_CLASS_NAME SinglyLinkedList<Element, GetLink>
|
||
|
|||
|
|
|
||
template<typename Element,
|
|||
|
|
typename GetLink = SinglyLinkedListStandardGetLink<Element> >
|
||
|
|
class SinglyLinkedList {
|
||
|
|
private:
|
||
|
|
typedef SinglyLinkedList<Element, GetLink> List;
|
||
|
|
typedef SinglyLinkedListLink<Element> Link;
|
||
|
|||
public:
|
|||
class ConstIterator {
|
|||
public:
|
|||
ConstIterator(const List* list)
|
|||
:
|
|||
|
|
fList(list)
|
||
|
|
{
|
||
|
|
Rewind();
|
||
|
|
}
|
||
|
|||
ConstIterator(const ConstIterator& other)
|
|||
{
|
|||
|
|
*this = other;
|
||
|
|
}
|
||
|
|||
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); }
|
||
|
|||
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);
|
|||
// 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;
|
||
|
|
|
||
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
|
||
void
|
|||
SINGLY_LINKED_LIST_CLASS_NAME::Add(Element* element)
|
|||
{
|
|||
if (element != NULL) {
|
|||
sGetLink(element)->next = fFirst;
|
|||
fFirst = element;
|
|||
|
|
}
|
||
}
|
|||
|
|
|
||
|
|||
/*! 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)
|
|||
{
|
|||
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;
|
||
|
|
}
|
||
|
|||
Link* elementLink = sGetLink(element);
|
|||
|
|
if (last == NULL)
|
||
|
|
fFirst = elementLink->next;
|
||
|
|
else
|
||
|
|
sGetLink(last)->next = elementLink->next;
|
||
|
|||
elementLink->next = NULL;
|
|||
return true;
|
|||
}
|
|||
|
|
|
||
|
|||
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;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
SINGLY_LINKED_LIST_TEMPLATE_LIST
|
|||
|
|
void
|
||
SINGLY_LINKED_LIST_CLASS_NAME::TakeFrom(SINGLY_LINKED_LIST_CLASS_NAME* fromList)
|
|||
{
|
|||
|
|
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()
|
||
{
|
|||
Element* element = fFirst;
|
|||
|
|
while (element) {
|
||
|
|
Link* elLink = sGetLink(element);
|
||
|
|
element = elLink->next;
|
||
|
|
elLink->next = NULL;
|
||
|
|
}
|
||
|
|
fFirst = NULL;
|
||
}
|
|||
|
|
|
||
// RemoveHead
|
|||
|
|
SINGLY_LINKED_LIST_TEMPLATE_LIST
|
||
|
|
Element*
|
||
|
|
SINGLY_LINKED_LIST_CLASS_NAME::RemoveHead()
|
||
{
|
|||
Element* element = Head();
|
|||
|
|
Remove(element);
|
||
|
|
return element;
|
||
}
|
|||
|
|
|
||
// GetNext
|
|||
|
|
SINGLY_LINKED_LIST_TEMPLATE_LIST
|
||
|
|
Element*
|
||
|
|
SINGLY_LINKED_LIST_CLASS_NAME::GetNext(Element* element) const
|
||
{
|
|||
Element* result = NULL;
|
|||
|
|
if (element)
|
||
|
|
result = sGetLink(element)->next;
|
||
|
|
return result;
|
||
}
|
|||
|
|
|
||
// Size
|
|||
|
|
SINGLY_LINKED_LIST_TEMPLATE_LIST
|
||
|
|
int32
|
||
SINGLY_LINKED_LIST_CLASS_NAME::Count() const
|
|||
{
|
|||
int32 count = 0;
|
|||
|
|
for (Element* element = First(); element; element = GetNext(element))
|
||
|
|
count++;
|
||
return count;
|
|||
|
|
}
|
||
|
|
|
||
// sGetLink
|
|||
|
|
SINGLY_LINKED_LIST_TEMPLATE_LIST
|
||
|
|
GetLink SINGLY_LINKED_LIST_CLASS_NAME::sGetLink;
|
||
|
|||
#endif /* __cplusplus */
|
|||
|
|||
#endif // _KERNEL_UTIL_SINGLY_LINKED_LIST_H
|