2 * Copyright (C) 2010-2011 Max Kellermann <max@duempel.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 * OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef XCSOAR_UTIL_LIST_HEAD_HPP
31 #define XCSOAR_UTIL_LIST_HEAD_HPP
40 * A doubly linked list implementation, similar to linux/list.h. It
41 * is very cheap at runtime, because the prev/next pointers are
42 * included in each item, instead of doing a separate allocation. To
43 * use it, derive your class/struct from this one.
46 ListHead
*next
, *prev
;
59 * Cheap non-initializing constructor.
71 * Initialize an empty list.
74 :next(this), prev(this)
80 const ListHead
*GetPrevious() const {
81 assert(type
== CONNECTED
|| type
== HEAD
);
86 ListHead
*GetPrevious() {
87 assert(type
== CONNECTED
|| type
== HEAD
);
92 const ListHead
*GetNext() const {
93 assert(type
== CONNECTED
|| type
== HEAD
);
99 assert(type
== CONNECTED
|| type
== HEAD
);
104 bool IsEmpty() const {
105 assert(type
== HEAD
);
106 assert((prev
== this) == (next
== this));
111 * Is the specified item the first one in the list?
113 bool IsFirst(const ListHead
&item
) const {
114 assert(type
== HEAD
);
116 return item
.prev
== this;
120 * Is the specified item the last one in the list?
122 bool IsLast(const ListHead
&item
) const {
123 assert(type
== HEAD
);
125 return item
.next
== this;
129 * Is the specified item the first or the last one in the list?
131 bool IsEdge(const ListHead
&item
) const {
132 return IsFirst(item
) || IsLast(item
);
136 * Count the number of items in this list, not including the current
140 unsigned Count() const {
141 assert(type
== HEAD
);
144 for (const ListHead
*p
= next
; p
!= this; p
= p
->next
)
150 * Turns this object into an empty list.
154 assert(type
== UNKNOWN
|| type
== HEAD
);
165 * Remove this item from the linked list.
168 assert(type
== CONNECTED
);
169 assert(prev
->next
== this);
170 assert(next
->prev
== this);
181 * Remove this item from the linked list. This variant allows
182 * removing a const object from the list. Debug information is not
183 * updated, this object must not ever be used again. Use with care!
185 void RemoveConst() const {
186 assert(type
== CONNECTED
);
187 assert(prev
->next
== this);
188 assert(next
->prev
== this);
195 * Insert this item after the specified one. It must not be in the
196 * list already (or in another list).
198 void InsertAfter(ListHead
&other
) {
199 assert(type
== UNKNOWN
|| type
== DISCONNECTED
);
200 assert(&other
!= this);
201 assert(&other
!= this);
202 assert(other
.type
== HEAD
|| other
.type
== CONNECTED
);
203 assert(other
.prev
->next
== &other
);
204 assert(other
.next
->prev
== &other
);
217 * Insert this item before the specified one. It must not be in the
218 * list already (or in another list).
220 void InsertBefore(ListHead
&other
) {
221 assert(type
== UNKNOWN
|| type
== DISCONNECTED
);
222 assert(&other
!= this);
223 assert(&other
!= this);
224 assert(other
.type
== HEAD
|| other
.type
== CONNECTED
);
225 assert(other
.prev
->next
== &other
);
226 assert(other
.next
->prev
== &other
);
239 * Move this item from its current position in the list after the
242 void MoveAfter(ListHead
&other
) {
243 assert(type
== CONNECTED
);
244 assert(other
.type
== HEAD
|| other
.type
== CONNECTED
);
246 if (prev
== &other
) {
247 assert(other
.next
== this);
256 * Insert this item with the specified one.
258 void Replace(ListHead
&other
) {
259 assert(type
== CONNECTED
);
260 assert(&other
!= this);
261 assert(prev
->next
== this);
262 assert(next
->prev
== this);
263 assert(other
.type
== UNKNOWN
|| other
.type
== DISCONNECTED
);
273 other
.type
= CONNECTED
;
278 * Changes the type from CONNECTED to DISCONNECTED. Call this on
279 * the copy of an existing object.
281 void SetDisconnected() {
283 assert(type
== CONNECTED
);
288 class const_iterator
{
289 friend class ListHead
;
291 const ListHead
*current
;
294 const_iterator(const ListHead
*_current
):current(_current
) {}
297 typedef std::bidirectional_iterator_tag iterator_category
;
298 typedef ptrdiff_t difference_type
;
299 typedef const ListHead value_type
;
300 typedef const ListHead
*pointer
;
301 typedef const ListHead
&reference
;
303 const_iterator() = default;
305 reference
operator*() const {
309 pointer
operator->() const {
313 const_iterator
&operator++() {
314 current
= current
->next
;
318 const_iterator
operator++(int) {
319 const_iterator old
= *this;
320 current
= current
->next
;
324 const_iterator
&operator--() {
325 current
= current
->prev
;
329 const_iterator
operator--(int) {
330 const_iterator old
= *this;
331 current
= current
->prev
;
335 bool operator==(const const_iterator
&other
) const {
336 return current
== other
.current
;
339 bool operator!=(const const_iterator
&other
) const {
340 return current
!= other
.current
;
344 const_iterator
begin() const {
345 assert(type
== HEAD
);
350 const_iterator
end() const {
351 assert(type
== HEAD
);
356 class const_reverse_iterator
{
357 friend class ListHead
;
359 const ListHead
*current
;
362 const_reverse_iterator(const ListHead
*_current
):current(_current
) {}
365 typedef std::bidirectional_iterator_tag iterator_category
;
366 typedef ptrdiff_t difference_type
;
367 typedef const ListHead value_type
;
368 typedef const ListHead
*pointer
;
369 typedef const ListHead
&reference
;
371 const_reverse_iterator() = default;
373 reference
operator*() const {
377 pointer
operator->() const {
381 const_reverse_iterator
&operator++() {
382 current
= current
->prev
;
386 const_reverse_iterator
operator++(int) {
387 const_reverse_iterator old
= *this;
388 current
= current
->prev
;
392 const_reverse_iterator
&operator--() {
393 current
= current
->next
;
397 const_reverse_iterator
operator--(int) {
398 const_reverse_iterator old
= *this;
399 current
= current
->next
;
403 bool operator==(const const_reverse_iterator
&other
) const {
404 return current
== other
.current
;
407 bool operator!=(const const_reverse_iterator
&other
) const {
408 return current
!= other
.current
;
412 const_reverse_iterator
rbegin() const {
413 assert(type
== HEAD
);
418 const_reverse_iterator
rend() const {
419 assert(type
== HEAD
);