2 * Copyright 2005-2007, Ingo Weinhold, bonefish@users.sf.net. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 #ifndef KERNEL_UTIL_DOUBLY_LINKED_LIST_H
6 #define KERNEL_UTIL_DOUBLY_LINKED_LIST_H
9 #include "fssh_types.h"
18 // DoublyLinkedListLink
19 template<typename Element
>
20 class DoublyLinkedListLink
{
22 DoublyLinkedListLink() : next(NULL
), previous(NULL
) {}
23 ~DoublyLinkedListLink() {}
29 // DoublyLinkedListLinkImpl
30 template<typename Element
>
31 class DoublyLinkedListLinkImpl
{
33 typedef DoublyLinkedListLink
<Element
> DLL_Link
;
36 DoublyLinkedListLinkImpl() : fDoublyLinkedListLink() {}
37 ~DoublyLinkedListLinkImpl() {}
39 DLL_Link
*GetDoublyLinkedListLink()
40 { return &fDoublyLinkedListLink
; }
41 const DLL_Link
*GetDoublyLinkedListLink() const
42 { return &fDoublyLinkedListLink
; }
45 DLL_Link fDoublyLinkedListLink
;
48 // DoublyLinkedListStandardGetLink
49 template<typename Element
>
50 class DoublyLinkedListStandardGetLink
{
52 typedef DoublyLinkedListLink
<Element
> Link
;
55 inline Link
*operator()(Element
*element
) const
57 return element
->GetDoublyLinkedListLink();
60 inline const Link
*operator()(const Element
*element
) const
62 return element
->GetDoublyLinkedListLink();
66 // DoublyLinkedListMemberGetLink
67 template<typename Element
,
68 DoublyLinkedListLink
<Element
> Element::* LinkMember
= &Element::fLink
>
69 class DoublyLinkedListMemberGetLink
{
71 typedef DoublyLinkedListLink
<Element
> Link
;
74 inline Link
*operator()(Element
*element
) const
76 return &(element
->*LinkMember
);
79 inline const Link
*operator()(const Element
*element
) const
81 return &(element
->*LinkMember
);
85 // DoublyLinkedListCLink - interface to struct list
86 template<typename Element
>
87 class DoublyLinkedListCLink
{
89 typedef DoublyLinkedListLink
<Element
> Link
;
92 inline Link
*operator()(Element
*element
) const
94 return (Link
*)&element
->link
;
97 inline const Link
*operator()(const Element
*element
) const
99 return (const Link
*)&element
->link
;
104 #define DOUBLY_LINKED_LIST_TEMPLATE_LIST \
105 template<typename Element, typename GetLink>
106 #define DOUBLY_LINKED_LIST_CLASS_NAME DoublyLinkedList<Element, GetLink>
109 template<typename Element
,
110 typename GetLink
= DoublyLinkedListStandardGetLink
<Element
> >
111 class DoublyLinkedList
{
113 typedef DoublyLinkedList
<Element
, GetLink
> List
;
114 typedef DoublyLinkedListLink
<Element
> Link
;
126 Iterator(const Iterator
&other
)
140 fNext
= fList
->GetNext(fNext
);
151 Element
*element
= fCurrent
;
153 fList
->Remove(fCurrent
);
159 Iterator
&operator=(const Iterator
&other
)
162 fCurrent
= other
.fCurrent
;
170 fNext
= fList
->First();
179 class ConstIterator
{
181 ConstIterator(const List
*list
)
188 ConstIterator(const ConstIterator
&other
)
200 Element
*element
= fNext
;
202 fNext
= fList
->GetNext(fNext
);
206 ConstIterator
&operator=(const ConstIterator
&other
)
215 fNext
= fList
->First();
223 class ReverseIterator
{
225 ReverseIterator(List
*list
)
232 ReverseIterator(const ReverseIterator
&other
)
246 fNext
= fList
->GetPrevious(fNext
);
252 Element
*element
= fCurrent
;
254 fList
->Remove(fCurrent
);
260 ReverseIterator
&operator=(const ReverseIterator
&other
)
263 fCurrent
= other
.fCurrent
;
271 fNext
= fList
->Last();
280 class ConstReverseIterator
{
282 ConstReverseIterator(const List
*list
)
289 ConstReverseIterator(const ConstReverseIterator
&other
)
301 Element
*element
= fNext
;
303 fNext
= fList
->GetPrevious(fNext
);
307 ConstReverseIterator
&operator=(const ConstReverseIterator
&other
)
316 fNext
= fList
->Last();
325 DoublyLinkedList() : fFirst(NULL
), fLast(NULL
) {}
326 ~DoublyLinkedList() {}
328 inline bool IsEmpty() const { return (fFirst
== NULL
); }
330 inline void Insert(Element
*element
, bool back
= true);
331 inline void Insert(Element
*before
, Element
*element
);
332 inline void Add(Element
*element
, bool back
= true);
333 inline void Remove(Element
*element
);
335 inline void Swap(Element
*a
, Element
*b
);
337 inline void MoveFrom(DOUBLY_LINKED_LIST_CLASS_NAME
*fromList
);
339 inline void RemoveAll();
340 inline void MakeEmpty() { RemoveAll(); }
342 inline Element
*First() const { return fFirst
; }
343 inline Element
*Last() const { return fLast
; }
345 inline Element
*Head() const { return fFirst
; }
346 inline Element
*Tail() const { return fLast
; }
348 inline Element
*RemoveHead();
350 inline Element
*GetPrevious(Element
*element
) const;
351 inline Element
*GetNext(Element
*element
) const;
353 inline int32_t Size() const;
356 inline Iterator
GetIterator() { return Iterator(this); }
357 inline ConstIterator
GetIterator() const { return ConstIterator(this); }
359 inline ReverseIterator
GetReverseIterator()
360 { return ReverseIterator(this); }
361 inline ConstReverseIterator
GetReverseIterator() const
362 { return ConstReverseIterator(this); }
368 static GetLink sGetLink
;
375 DOUBLY_LINKED_LIST_TEMPLATE_LIST
377 DOUBLY_LINKED_LIST_CLASS_NAME::Insert(Element
*element
, bool back
)
382 Link
*elLink
= sGetLink(element
);
383 elLink
->previous
= fLast
;
386 sGetLink(fLast
)->next
= element
;
392 Link
*elLink
= sGetLink(element
);
393 elLink
->previous
= NULL
;
394 elLink
->next
= fFirst
;
396 sGetLink(fFirst
)->previous
= element
;
405 DOUBLY_LINKED_LIST_TEMPLATE_LIST
407 DOUBLY_LINKED_LIST_CLASS_NAME::Insert(Element
*before
, Element
*element
)
409 if (before
== NULL
) {
416 Link
*beforeLink
= sGetLink(before
);
417 Link
*link
= sGetLink(element
);
420 link
->previous
= beforeLink
->previous
;
421 if (link
->previous
!= NULL
)
422 sGetLink(link
->previous
)->next
= element
;
423 beforeLink
->previous
= element
;
425 if (fFirst
== before
)
430 DOUBLY_LINKED_LIST_TEMPLATE_LIST
432 DOUBLY_LINKED_LIST_CLASS_NAME::Add(Element
*element
, bool back
)
434 Insert(element
, back
);
438 DOUBLY_LINKED_LIST_TEMPLATE_LIST
440 DOUBLY_LINKED_LIST_CLASS_NAME::Remove(Element
*element
)
443 Link
*elLink
= sGetLink(element
);
444 if (elLink
->previous
)
445 sGetLink(elLink
->previous
)->next
= elLink
->next
;
447 fFirst
= elLink
->next
;
449 sGetLink(elLink
->next
)->previous
= elLink
->previous
;
451 fLast
= elLink
->previous
;
452 elLink
->previous
= NULL
;
458 DOUBLY_LINKED_LIST_TEMPLATE_LIST
460 DOUBLY_LINKED_LIST_CLASS_NAME::Swap(Element
*a
, Element
*b
)
462 if (a
&& b
&& a
!= b
) {
463 Element
*aNext
= sGetLink(a
)->next
;
464 Element
*bNext
= sGetLink(b
)->next
;
468 } else if (b
== aNext
) {
481 DOUBLY_LINKED_LIST_TEMPLATE_LIST
483 DOUBLY_LINKED_LIST_CLASS_NAME::MoveFrom(DOUBLY_LINKED_LIST_CLASS_NAME
*fromList
)
485 if (fromList
&& fromList
->fFirst
) {
487 sGetLink(fLast
)->next
= fromList
->fFirst
;
488 sGetLink(fromList
->fFirst
)->previous
= fLast
;
489 fLast
= fromList
->fLast
;
491 fFirst
= fromList
->fFirst
;
492 fLast
= fromList
->fLast
;
494 fromList
->fFirst
= NULL
;
495 fromList
->fLast
= NULL
;
500 DOUBLY_LINKED_LIST_TEMPLATE_LIST
502 DOUBLY_LINKED_LIST_CLASS_NAME::RemoveAll()
504 Element
*element
= fFirst
;
506 Link
*elLink
= sGetLink(element
);
507 element
= elLink
->next
;
508 elLink
->previous
= NULL
;
516 DOUBLY_LINKED_LIST_TEMPLATE_LIST
518 DOUBLY_LINKED_LIST_CLASS_NAME::RemoveHead()
520 Element
*element
= Head();
526 DOUBLY_LINKED_LIST_TEMPLATE_LIST
528 DOUBLY_LINKED_LIST_CLASS_NAME::GetPrevious(Element
*element
) const
530 Element
*result
= NULL
;
532 result
= sGetLink(element
)->previous
;
537 DOUBLY_LINKED_LIST_TEMPLATE_LIST
539 DOUBLY_LINKED_LIST_CLASS_NAME::GetNext(Element
*element
) const
541 Element
*result
= NULL
;
543 result
= sGetLink(element
)->next
;
548 DOUBLY_LINKED_LIST_TEMPLATE_LIST
550 DOUBLY_LINKED_LIST_CLASS_NAME::Size() const
553 for (Element
* element
= First(); element
; element
= GetNext(element
))
559 DOUBLY_LINKED_LIST_TEMPLATE_LIST
560 GetLink
DOUBLY_LINKED_LIST_CLASS_NAME::sGetLink
;
563 } // namespace FSShell
565 using FSShell::DoublyLinkedListLink
;
566 using FSShell::DoublyLinkedListLinkImpl
;
567 using FSShell::DoublyLinkedListStandardGetLink
;
568 using FSShell::DoublyLinkedListMemberGetLink
;
569 using FSShell::DoublyLinkedListCLink
;
570 using FSShell::DoublyLinkedList
;
573 #endif /* __cplusplus */
575 #endif // _KERNEL_UTIL_DOUBLY_LINKED_LIST_H