2 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Copyright 2005-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
5 * Distributed under the terms of the MIT License.
7 #ifndef KERNEL_UTIL_SINGLY_LINKED_LIST_H
8 #define KERNEL_UTIL_SINGLY_LINKED_LIST_H
11 #include <SupportDefs.h>
16 // SinglyLinkedListLink
17 template<typename Element
>
18 class SinglyLinkedListLink
{
20 SinglyLinkedListLink() : next(NULL
) {}
21 ~SinglyLinkedListLink() {}
26 // SinglyLinkedListLinkImpl
27 template<typename Element
>
28 class SinglyLinkedListLinkImpl
{
30 typedef SinglyLinkedListLink
<Element
> SLL_Link
;
33 SinglyLinkedListLinkImpl() : fSinglyLinkedListLink() {}
34 ~SinglyLinkedListLinkImpl() {}
36 SLL_Link
* GetSinglyLinkedListLink()
37 { return &fSinglyLinkedListLink
; }
38 const SLL_Link
* GetSinglyLinkedListLink() const
39 { return &fSinglyLinkedListLink
; }
42 SLL_Link fSinglyLinkedListLink
;
45 // SinglyLinkedListStandardGetLink
46 template<typename Element
>
47 class SinglyLinkedListStandardGetLink
{
49 typedef SinglyLinkedListLink
<Element
> Link
;
52 inline Link
* operator()(Element
* element
) const
54 return element
->GetSinglyLinkedListLink();
57 inline const Link
* operator()(const Element
* element
) const
59 return element
->GetSinglyLinkedListLink();
63 // SinglyLinkedListMemberGetLink
64 template<typename Element
,
65 SinglyLinkedListLink
<Element
> Element::* LinkMember
= &Element::fLink
>
66 class SinglyLinkedListMemberGetLink
{
68 typedef SinglyLinkedListLink
<Element
> Link
;
71 inline Link
* operator()(Element
* element
) const
73 return &(element
->*LinkMember
);
76 inline const Link
* operator()(const Element
* element
) const
78 return &(element
->*LinkMember
);
84 #define SINGLY_LINKED_LIST_TEMPLATE_LIST \
85 template<typename Element, typename GetLink>
86 #define SINGLY_LINKED_LIST_CLASS_NAME SinglyLinkedList<Element, GetLink>
89 template<typename Element
,
90 typename GetLink
= SinglyLinkedListStandardGetLink
<Element
> >
91 class SinglyLinkedList
{
93 typedef SinglyLinkedList
<Element
, GetLink
> List
;
94 typedef SinglyLinkedListLink
<Element
> Link
;
99 Iterator(const List
* list
)
106 Iterator(const Iterator
& other
)
118 Element
* element
= fNext
;
120 fNext
= fList
->GetNext(fNext
);
124 Iterator
& operator=(const Iterator
& other
)
133 fNext
= fList
->First();
142 SinglyLinkedList() : fFirst(NULL
) {}
143 ~SinglyLinkedList() {}
145 inline bool IsEmpty() const { return (fFirst
== NULL
); }
147 inline void Add(Element
* element
);
148 inline bool Remove(Element
* element
);
149 inline void Remove(Element
* previous
, Element
* element
);
151 inline void MoveFrom(SINGLY_LINKED_LIST_CLASS_NAME
* fromList
);
152 // O(1) if either list is empty, otherwise O(n).
154 inline void RemoveAll();
155 inline void MakeEmpty() { RemoveAll(); }
157 inline Element
* First() const { return fFirst
; }
158 inline Element
* Head() const { return fFirst
; }
160 inline Element
* RemoveHead();
162 inline Element
* GetNext(Element
* element
) const;
164 inline int32
Size() const;
167 inline Iterator
GetIterator() const { return Iterator(this); }
172 static GetLink sGetLink
;
179 SINGLY_LINKED_LIST_TEMPLATE_LIST
181 SINGLY_LINKED_LIST_CLASS_NAME::Add(Element
* element
)
183 if (element
!= NULL
) {
184 sGetLink(element
)->next
= fFirst
;
190 /*! Removes \a element from the list.
191 It is safe to call the list with a \c NULL element or an element that isn't
193 \param element The element to be removed.
194 \return \c true, if the element was in the list and has been removed,
197 SINGLY_LINKED_LIST_TEMPLATE_LIST
199 SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element
* element
)
204 Element
* next
= fFirst
;
205 Element
* last
= NULL
;
206 while (element
!= next
) {
210 next
= sGetLink(next
)->next
;
213 Link
* elementLink
= sGetLink(element
);
215 fFirst
= elementLink
->next
;
217 sGetLink(last
)->next
= elementLink
->next
;
219 elementLink
->next
= NULL
;
224 SINGLY_LINKED_LIST_TEMPLATE_LIST
226 SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element
* previous
, Element
* element
)
228 // ASSERT(previous == NULL
229 // ? fFirst == element : sGetLink(previous)->next == element);
231 Link
* elementLink
= sGetLink(element
);
232 if (previous
== NULL
)
233 fFirst
= elementLink
->next
;
235 sGetLink(previous
)->next
= elementLink
->next
;
237 elementLink
->next
= NULL
;
241 SINGLY_LINKED_LIST_TEMPLATE_LIST
243 SINGLY_LINKED_LIST_CLASS_NAME::MoveFrom(SINGLY_LINKED_LIST_CLASS_NAME
* fromList
)
245 if (fromList
->fFirst
== NULL
)
248 if (fFirst
== NULL
) {
249 // This list is empty -- just transfer the head.
250 fFirst
= fromList
->fFirst
;
251 fromList
->fFirst
= NULL
;
255 // Neither list is empty -- find the tail of this list.
256 Element
* tail
= fFirst
;
257 while (Element
* next
= sGetLink(tail
)->next
)
260 sGetLink(tail
)->next
= fromList
->fFirst
;
261 fromList
->fFirst
= NULL
;
266 SINGLY_LINKED_LIST_TEMPLATE_LIST
268 SINGLY_LINKED_LIST_CLASS_NAME::RemoveAll()
270 Element
* element
= fFirst
;
272 Link
* elLink
= sGetLink(element
);
273 element
= elLink
->next
;
280 SINGLY_LINKED_LIST_TEMPLATE_LIST
282 SINGLY_LINKED_LIST_CLASS_NAME::RemoveHead()
284 Element
* element
= Head();
290 SINGLY_LINKED_LIST_TEMPLATE_LIST
292 SINGLY_LINKED_LIST_CLASS_NAME::GetNext(Element
* element
) const
294 Element
* result
= NULL
;
296 result
= sGetLink(element
)->next
;
301 SINGLY_LINKED_LIST_TEMPLATE_LIST
303 SINGLY_LINKED_LIST_CLASS_NAME::Size() const
306 for (Element
* element
= First(); element
; element
= GetNext(element
))
312 SINGLY_LINKED_LIST_TEMPLATE_LIST
313 GetLink
SINGLY_LINKED_LIST_CLASS_NAME::sGetLink
;
315 #endif /* __cplusplus */
317 #endif // _KERNEL_UTIL_SINGLY_LINKED_LIST_H