btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / private / kernel / util / SinglyLinkedList.h
blob9598a83d97baf42e30fbf872bcb94ce1d2c0ce45
1 /*
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.
6 */
7 #ifndef KERNEL_UTIL_SINGLY_LINKED_LIST_H
8 #define KERNEL_UTIL_SINGLY_LINKED_LIST_H
11 #include <SupportDefs.h>
14 #ifdef __cplusplus
16 // SinglyLinkedListLink
17 template<typename Element>
18 class SinglyLinkedListLink {
19 public:
20 SinglyLinkedListLink() : next(NULL) {}
21 ~SinglyLinkedListLink() {}
23 Element* next;
26 // SinglyLinkedListLinkImpl
27 template<typename Element>
28 class SinglyLinkedListLinkImpl {
29 private:
30 typedef SinglyLinkedListLink<Element> SLL_Link;
32 public:
33 SinglyLinkedListLinkImpl() : fSinglyLinkedListLink() {}
34 ~SinglyLinkedListLinkImpl() {}
36 SLL_Link* GetSinglyLinkedListLink()
37 { return &fSinglyLinkedListLink; }
38 const SLL_Link* GetSinglyLinkedListLink() const
39 { return &fSinglyLinkedListLink; }
41 private:
42 SLL_Link fSinglyLinkedListLink;
45 // SinglyLinkedListStandardGetLink
46 template<typename Element>
47 class SinglyLinkedListStandardGetLink {
48 private:
49 typedef SinglyLinkedListLink<Element> Link;
51 public:
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 {
67 private:
68 typedef SinglyLinkedListLink<Element> Link;
70 public:
71 inline Link* operator()(Element* element) const
73 return &(element->*LinkMember);
76 inline const Link* operator()(const Element* element) const
78 return &(element->*LinkMember);
83 // for convenience
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 {
92 private:
93 typedef SinglyLinkedList<Element, GetLink> List;
94 typedef SinglyLinkedListLink<Element> Link;
96 public:
97 class Iterator {
98 public:
99 Iterator(const List* list)
101 fList(list)
103 Rewind();
106 Iterator(const Iterator& other)
108 *this = other;
111 bool HasNext() const
113 return fNext;
116 Element* Next()
118 Element* element = fNext;
119 if (fNext)
120 fNext = fList->GetNext(fNext);
121 return element;
124 Iterator& operator=(const Iterator& other)
126 fList = other.fList;
127 fNext = other.fNext;
128 return* this;
131 void Rewind()
133 fNext = fList->First();
136 private:
137 const List* fList;
138 Element* fNext;
141 public:
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;
165 // O(n)!
167 inline Iterator GetIterator() const { return Iterator(this); }
169 private:
170 Element *fFirst;
172 static GetLink sGetLink;
176 // inline methods
178 // Add
179 SINGLY_LINKED_LIST_TEMPLATE_LIST
180 void
181 SINGLY_LINKED_LIST_CLASS_NAME::Add(Element* element)
183 if (element != NULL) {
184 sGetLink(element)->next = fFirst;
185 fFirst = element;
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
192 in the list.
193 \param element The element to be removed.
194 \return \c true, if the element was in the list and has been removed,
195 \c false otherwise.
197 SINGLY_LINKED_LIST_TEMPLATE_LIST
198 bool
199 SINGLY_LINKED_LIST_CLASS_NAME::Remove(Element* element)
201 if (element == NULL)
202 return false;
204 Element* next = fFirst;
205 Element* last = NULL;
206 while (element != next) {
207 if (next == NULL)
208 return false;
209 last = next;
210 next = sGetLink(next)->next;
213 Link* elementLink = sGetLink(element);
214 if (last == NULL)
215 fFirst = elementLink->next;
216 else
217 sGetLink(last)->next = elementLink->next;
219 elementLink->next = NULL;
220 return true;
224 SINGLY_LINKED_LIST_TEMPLATE_LIST
225 void
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;
234 else
235 sGetLink(previous)->next = elementLink->next;
237 elementLink->next = NULL;
241 SINGLY_LINKED_LIST_TEMPLATE_LIST
242 void
243 SINGLY_LINKED_LIST_CLASS_NAME::MoveFrom(SINGLY_LINKED_LIST_CLASS_NAME* fromList)
245 if (fromList->fFirst == NULL)
246 return;
248 if (fFirst == NULL) {
249 // This list is empty -- just transfer the head.
250 fFirst = fromList->fFirst;
251 fromList->fFirst = NULL;
252 return;
255 // Neither list is empty -- find the tail of this list.
256 Element* tail = fFirst;
257 while (Element* next = sGetLink(tail)->next)
258 tail = next;
260 sGetLink(tail)->next = fromList->fFirst;
261 fromList->fFirst = NULL;
265 // RemoveAll
266 SINGLY_LINKED_LIST_TEMPLATE_LIST
267 void
268 SINGLY_LINKED_LIST_CLASS_NAME::RemoveAll()
270 Element* element = fFirst;
271 while (element) {
272 Link* elLink = sGetLink(element);
273 element = elLink->next;
274 elLink->next = NULL;
276 fFirst = NULL;
279 // RemoveHead
280 SINGLY_LINKED_LIST_TEMPLATE_LIST
281 Element*
282 SINGLY_LINKED_LIST_CLASS_NAME::RemoveHead()
284 Element* element = Head();
285 Remove(element);
286 return element;
289 // GetNext
290 SINGLY_LINKED_LIST_TEMPLATE_LIST
291 Element*
292 SINGLY_LINKED_LIST_CLASS_NAME::GetNext(Element* element) const
294 Element* result = NULL;
295 if (element)
296 result = sGetLink(element)->next;
297 return result;
300 // Size
301 SINGLY_LINKED_LIST_TEMPLATE_LIST
302 int32
303 SINGLY_LINKED_LIST_CLASS_NAME::Size() const
305 int32 count = 0;
306 for (Element* element = First(); element; element = GetNext(element))
307 count++;
308 return count;
311 // sGetLink
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