/* * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de. * * Distributed under the terms of the MIT License. */ #ifndef KERNEL_UTIL_SINGLY_LINKED_LIST_H #define KERNEL_UTIL_SINGLY_LINKED_LIST_H #ifdef __cplusplus // SinglyLinkedListLink template class SinglyLinkedListLink { public: SinglyLinkedListLink() : next(NULL) {} ~SinglyLinkedListLink() {} Element* next; }; // SinglyLinkedListLinkImpl template class SinglyLinkedListLinkImpl { private: typedef SinglyLinkedListLink SLL_Link; public: SinglyLinkedListLinkImpl() : fSinglyLinkedListLink() {} ~SinglyLinkedListLinkImpl() {} SLL_Link* GetSinglyLinkedListLink() { return &fSinglyLinkedListLink; } const SLL_Link* GetSinglyLinkedListLink() const { return &fSinglyLinkedListLink; } private: SLL_Link fSinglyLinkedListLink; }; // SinglyLinkedListStandardGetLink template class SinglyLinkedListStandardGetLink { private: typedef SinglyLinkedListLink Link; public: inline Link* operator()(Element* element) const { return element->GetSinglyLinkedListLink(); } inline const Link* operator()(const Element* element) const { return element->GetSinglyLinkedListLink(); } }; // SinglyLinkedListMemberGetLink template Element::* LinkMember = &Element::fLink> class SinglyLinkedListMemberGetLink { private: typedef SinglyLinkedListLink 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 #define SINGLY_LINKED_LIST_CLASS_NAME SinglyLinkedList template > class SinglyLinkedList { private: typedef SinglyLinkedList List; typedef SinglyLinkedListLink Link; public: class Iterator { public: Iterator(const List* list) : fList(list) { Rewind(); } Iterator(const Iterator& other) { *this = other; } bool HasNext() const { return fNext; } Element* Next() { Element* element = fNext; if (fNext) fNext = fList->GetNext(fNext); return element; } Iterator& operator=(const Iterator& 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 void Remove(Element* element); inline void MoveFrom(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 Size() const; // O(n)! inline Iterator GetIterator() const { return Iterator(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; } } // Remove SINGLY_LINKED_LIST_TEMPLATE_LIST void SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element* element) { if (element == NULL) return; Element* next = fFirst; Element* last = NULL; while (next != NULL && element != next) { 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; } SINGLY_LINKED_LIST_TEMPLATE_LIST void SINGLY_LINKED_LIST_CLASS_NAME::MoveFrom(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::Size() 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