2 * Copyright 2001 Adrian Thurston <thurston@cs.queensu.ca>
5 /* This file is part of Aapl.
7 * Aapl is free software; you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free
9 * Software Foundation; either version 2.1 of the License, or (at your option)
12 * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
19 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 /* This header is not wrapped in ifndef becuase it is not intended to
23 * be included by the user. */
29 #if defined( DOUBLELIST_VALUE )
31 * \brief Double list element for DListVal.
33 * DListValEl stores the type T of DListVal by value.
35 template <class T
> struct DListValEl
38 * \brief Construct a DListValEl with a given value.
40 * The only constructor available initializes the value element. This
41 * enforces that DListVal elements are never created without having their
42 * value intialzed by the user. T's copy constructor is used to copy the
45 DListValEl( const T
&val
) : value(val
) { }
48 * \brief Value stored by the list element.
50 * Value is always copied into new list elements using the copy
56 * \brief List previous pointer.
58 * Points to the previous item in the list. If this is the first item in
59 * the list, then prev is NULL. If this element is not in a list then
65 * \brief List next pointer.
67 * Points to the next item in the list. If this is the list item in the
68 * list, then next is NULL. If this element is not in a list then next is
75 #ifndef __AAPL_DOUBLE_LIST_EL
76 #define __AAPL_DOUBLE_LIST_EL
78 * \brief Double list element properties.
80 * This class can be inherited to make a class suitable to be a double list
81 * element. It simply provides the next and previous pointers. An alternative
82 * is to put the next and previous pointers in the class directly.
84 template <class Element
> struct DListEl
87 * \brief List previous pointer.
89 * Points to the previous item in the list. If this is the first item in
90 * the list, then prev is NULL. If this element is not in a list then
96 * \brief List next pointer.
98 * Points to the next item in the list. If this is the list item in the
99 * list, then next is NULL. If this element is not in a list then next is
104 #endif /* __AAPL_DOUBLE_LIST_EL */
108 /* Doubly Linked List */
109 template <DLMEL_TEMPDEF
> class DList
112 /** \brief Initialize an empty list. */
113 DList() : head(0), tail(0), listLen(0) {}
116 * \brief Perform a deep copy of the list.
118 * The elements of the other list are duplicated and put into this list.
119 * Elements are copied using the copy constructor.
121 DList(const DList
&other
);
123 #ifdef DOUBLELIST_VALUE
125 * \brief Clear the double list contents.
127 * All elements are deleted.
129 ~DList() { empty(); }
132 * \brief Assign another list into this list using a deep copy.
134 * The elements of the other list are duplicated and put into this list.
135 * Each list item is created using the copy constructor. If this list
136 * contains any elements before the copy, they are deleted first.
138 * \returns A reference to this.
140 DList
&operator=(const DList
&other
);
143 * \brief Transfer the contents of another list into this list.
145 * The elements of the other list moved in. The other list will be empty
146 * afterwards. If this list contains any elements before the copy, then
149 void transfer(DList
&other
);
152 * \brief Abandon all elements in the list.
154 * List elements are not deleted.
159 * \brief Perform a deep copy of the list.
161 * The elements of the other list are duplicated and put into this list.
162 * Each list item is created using the copy constructor. If this list
163 * contains any elements before the copy, they are abandoned.
165 * \returns A reference to this.
167 DList
&operator=(const DList
&other
);
170 * \brief Transfer the contents of another list into this list.
172 * The elements of the other list moved in. The other list will be empty
173 * afterwards. If this list contains any elements before the copy, they
176 void transfer(DList
&other
);
180 #ifdef DOUBLELIST_VALUE
182 * \brief Make a new element and prepend it to the front of the list.
184 * The item is copied into the new element using the copy constructor.
185 * Equivalent to list.addBefore(list.head, item).
187 void prepend(const T
&item
);
190 * \brief Make a new element and append it to the end of the list.
192 * The item is copied into the new element using the copy constructor.
193 * Equivalent to list.addAfter(list.tail, item).
195 void append(const T
&item
);
198 * \brief Make a new element and insert it immediately after an element in
201 * The item is copied into the new element using the copy constructor. If
202 * prev_el is NULL then the new element is prepended to the front of the
203 * list. If prev_el is not already in the list then undefined behaviour
204 * results. Equivalent to list.addAfter(prev_el, new DListValEl(item)).
206 void addAfter(Element
*prev_el
, const T
&item
);
209 * \brief Make a new element and insert it immediately before an element
212 * The item is copied into the new element using the copy construcotor. If
213 * next_el is NULL then the new element is appended to the end of the
214 * list. If next_el is not already in the list then undefined behaviour
215 * results. Equivalent to list.addBefore(next_el, new DListValEl(item)).
217 void addBefore(Element
*next_el
, const T
&item
);
221 * \brief Prepend a single element to the front of the list.
223 * If new_el is already an element of some list, then undefined behaviour
224 * results. Equivalent to list.addBefore(list.head, new_el).
226 void prepend(Element
*new_el
) { addBefore(head
, new_el
); }
229 * \brief Append a single element to the end of the list.
231 * If new_el is alreay an element of some list, then undefined behaviour
232 * results. Equivalent to list.addAfter(list.tail, new_el).
234 void append(Element
*new_el
) { addAfter(tail
, new_el
); }
237 * \brief Prepend an entire list to the beginning of this list.
239 * All items are moved, not copied. Afterwards, the other list is emtpy.
240 * All items are prepended at once, so this is an O(1) operation.
241 * Equivalent to list.addBefore(list.head, dl).
243 void prepend(DList
&dl
) { addBefore(head
, dl
); }
246 * \brief Append an entire list to the end of the list.
248 * All items are moved, not copied. Afterwards, the other list is empty.
249 * All items are appened at once, so this is an O(1) operation.
250 * Equivalent to list.addAfter(list.tail, dl).
252 void append(DList
&dl
) { addAfter(tail
, dl
); }
254 void addAfter(Element
*prev_el
, Element
*new_el
);
255 void addBefore(Element
*next_el
, Element
*new_el
);
257 void addAfter(Element
*prev_el
, DList
&dl
);
258 void addBefore(Element
*next_el
, DList
&dl
);
261 * \brief Detach the head of the list
263 * The element detached is not deleted. If there is no head of the list
264 * (the list is empty) then undefined behaviour results. Equivalent to
265 * list.detach(list.head).
267 * \returns The element detached.
269 Element
*detachFirst() { return detach(head
); }
272 * \brief Detach the tail of the list
274 * The element detached is not deleted. If there is no tail of the list
275 * (the list is empty) then undefined behaviour results. Equivalent to
276 * list.detach(list.tail).
278 * \returns The element detached.
280 Element
*detachLast() { return detach(tail
); }
282 /* Detaches an element from the list. Does not free any memory. */
283 Element
*detach(Element
*el
);
286 * \brief Detach and delete the first element in the list.
288 * If there is no first element (the list is empty) then undefined
289 * behaviour results. Equivalent to delete list.detach(list.head);
291 void removeFirst() { delete detach( head
); }
294 * \brief Detach and delete the last element in the list.
296 * If there is no last element (the list is emtpy) then undefined
297 * behaviour results. Equivalent to delete list.detach(list.tail);
299 void removeLast() { delete detach( tail
); }
302 * \brief Detach and delete an element from the list.
304 * If the element is not in the list, then undefined behaviour results.
305 * Equivalent to delete list.detach(el);
307 void remove(Element
*el
) { delete detach( el
); }
312 /** \brief The number of elements in the list. */
313 long length() const { return listLen
; }
315 /** \brief Head and tail of the linked list. */
316 Element
*head
, *tail
;
318 /** \brief The number of element in the list. */
321 /* Convenience access. */
322 long size() const { return listLen
; }
324 /* Forward this so a ref can be used. */
327 /* Class for setting the iterator. */
328 struct IterFirst
{ IterFirst( const DList
&l
) : l(l
) { } const DList
&l
; };
329 struct IterLast
{ IterLast( const DList
&l
) : l(l
) { } const DList
&l
; };
330 struct IterNext
{ IterNext( const Iter
&i
) : i(i
) { } const Iter
&i
; };
331 struct IterPrev
{ IterPrev( const Iter
&i
) : i(i
) { } const Iter
&i
; };
334 * \brief Double List Iterator.
339 /* Default construct. */
342 /* Construct from a double list. */
343 Iter( const DList
&dl
) : ptr(dl
.head
) { }
344 Iter( Element
*el
) : ptr(el
) { }
345 Iter( const IterFirst
&dlf
) : ptr(dlf
.l
.head
) { }
346 Iter( const IterLast
&dll
) : ptr(dll
.l
.tail
) { }
347 Iter( const IterNext
&dln
) : ptr(dln
.i
.ptr
->BASE_EL(next
)) { }
348 Iter( const IterPrev
&dlp
) : ptr(dlp
.i
.ptr
->BASE_EL(prev
)) { }
350 /* Assign from a double list. */
351 Iter
&operator=( const DList
&dl
) { ptr
= dl
.head
; return *this; }
352 Iter
&operator=( Element
*el
) { ptr
= el
; return *this; }
353 Iter
&operator=( const IterFirst
&af
) { ptr
= af
.l
.head
; return *this; }
354 Iter
&operator=( const IterLast
&al
) { ptr
= al
.l
.tail
; return *this; }
355 Iter
&operator=( const IterNext
&an
) { ptr
= an
.i
.ptr
->BASE_EL(next
); return *this; }
356 Iter
&operator=( const IterPrev
&ap
) { ptr
= ap
.i
.ptr
->BASE_EL(prev
); return *this; }
358 /** \brief Less than end? */
359 bool lte() const { return ptr
!= 0; }
361 /** \brief At end? */
362 bool end() const { return ptr
== 0; }
364 /** \brief Greater than beginning? */
365 bool gtb() const { return ptr
!= 0; }
367 /** \brief At beginning? */
368 bool beg() const { return ptr
== 0; }
370 /** \brief At first element? */
371 bool first() const { return ptr
&& ptr
->BASE_EL(prev
) == 0; }
373 /** \brief At last element? */
374 bool last() const { return ptr
&& ptr
->BASE_EL(next
) == 0; }
376 /** \brief Implicit cast to Element*. */
377 operator Element
*() const { return ptr
; }
379 /** \brief Dereference operator returns Element&. */
380 Element
&operator *() const { return *ptr
; }
382 /** \brief Arrow operator returns Element*. */
383 Element
*operator->() const { return ptr
; }
385 /** \brief Move to next item. */
386 inline Element
*operator++() { return ptr
= ptr
->BASE_EL(next
); }
388 /** \brief Move to next item. */
389 inline Element
*increment() { return ptr
= ptr
->BASE_EL(next
); }
391 /** \brief Move to next item. */
392 inline Element
*operator++(int);
394 /** \brief Move to previous item. */
395 inline Element
*operator--() { return ptr
= ptr
->BASE_EL(prev
); }
397 /** \brief Move to previous item. */
398 inline Element
*decrement() { return ptr
= ptr
->BASE_EL(prev
); }
400 /** \brief Move to previous item. */
401 inline Element
*operator--(int);
403 /** \brief Return the next item. Does not modify this. */
404 inline IterNext
next() const { return IterNext(*this); }
406 /** \brief Return the prev item. Does not modify this. */
407 inline IterPrev
prev() const { return IterPrev(*this); }
409 /** \brief The iterator is simply a pointer. */
413 /** \brief Return first element. */
414 IterFirst
first() { return IterFirst(*this); }
416 /** \brief Return last element. */
417 IterLast
last() { return IterLast(*this); }
420 /* Copy constructor, does a deep copy of other. */
421 template <DLMEL_TEMPDEF
> DList
<DLMEL_TEMPUSE
>::
422 DList(const DList
<DLMEL_TEMPUSE
> &other
) :
423 head(0), tail(0), listLen(0)
425 Element
*el
= other
.head
;
427 append( new Element(*el
) );
428 el
= el
->BASE_EL(next
);
432 #ifdef DOUBLELIST_VALUE
434 /* Assignement operator does deep copy. */
435 template <DLMEL_TEMPDEF
> DList
<DLMEL_TEMPUSE
> &DList
<DLMEL_TEMPUSE
>::
436 operator=(const DList
&other
)
438 /* Free the old list. The value list assumes items were allocated on the
442 Element
*el
= other
.head
;
444 append( new Element(*el
) );
445 el
= el
->BASE_EL(next
);
450 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
451 transfer(DList
&other
)
453 /* Free the old list. The value list assumes items were allocated on the
459 listLen
= other
.listLen
;
466 /* Assignement operator does deep copy. */
467 template <DLMEL_TEMPDEF
> DList
<DLMEL_TEMPUSE
> &DList
<DLMEL_TEMPUSE
>::
468 operator=(const DList
&other
)
470 Element
*el
= other
.head
;
472 append( new Element(*el
) );
473 el
= el
->BASE_EL(next
);
478 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
479 transfer(DList
&other
)
483 listLen
= other
.listLen
;
490 #ifdef DOUBLELIST_VALUE
492 /* Prepend a new item. Inlining this bloats the caller with new overhead. */
493 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
494 prepend(const T
&item
)
496 addBefore(head
, new Element(item
));
499 /* Append a new item. Inlining this bloats the caller with the new overhead. */
500 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
501 append(const T
&item
)
503 addAfter(tail
, new Element(item
));
506 /* Add a new item after a prev element. Inlining this bloats the caller with
507 * the new overhead. */
508 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
509 addAfter(Element
*prev_el
, const T
&item
)
511 addAfter(prev_el
, new Element(item
));
514 /* Add a new item before a next element. Inlining this bloats the caller with
515 * the new overhead. */
516 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
517 addBefore(Element
*next_el
, const T
&item
)
519 addBefore(next_el
, new Element(item
));
525 * The larger iterator operators.
529 template <DLMEL_TEMPDEF
> Element
*DList
<DLMEL_TEMPUSE
>::Iter::
533 ptr
= ptr
->BASE_EL(next
);
538 template <DLMEL_TEMPDEF
> Element
*DList
<DLMEL_TEMPUSE
>::Iter::
542 ptr
= ptr
->BASE_EL(prev
);
547 * \brief Insert an element immediately after an element in the list.
549 * If prev_el is NULL then new_el is prepended to the front of the list. If
550 * prev_el is not in the list or if new_el is already in a list, then
551 * undefined behaviour results.
553 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
554 addAfter(Element
*prev_el
, Element
*new_el
)
556 /* Set the previous pointer of new_el to prev_el. We do
557 * this regardless of the state of the list. */
558 new_el
->BASE_EL(prev
) = prev_el
;
560 /* Set forward pointers. */
562 /* There was no prev_el, we are inserting at the head. */
563 new_el
->BASE_EL(next
) = head
;
567 /* There was a prev_el, we can access previous next. */
568 new_el
->BASE_EL(next
) = prev_el
->BASE_EL(next
);
569 prev_el
->BASE_EL(next
) = new_el
;
572 /* Set reverse pointers. */
573 if (new_el
->BASE_EL(next
) == 0) {
574 /* There is no next element. Set the tail pointer. */
578 /* There is a next element. Set it's prev pointer. */
579 new_el
->BASE_EL(next
)->BASE_EL(prev
) = new_el
;
582 /* Update list length. */
587 * \brief Insert an element immediatly before an element in the list.
589 * If next_el is NULL then new_el is appended to the end of the list. If
590 * next_el is not in the list or if new_el is already in a list, then
591 * undefined behaviour results.
593 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
594 addBefore(Element
*next_el
, Element
*new_el
)
596 /* Set the next pointer of the new element to next_el. We do
597 * this regardless of the state of the list. */
598 new_el
->BASE_EL(next
) = next_el
;
600 /* Set reverse pointers. */
602 /* There is no next elememnt. We are inserting at the tail. */
603 new_el
->BASE_EL(prev
) = tail
;
607 /* There is a next element and we can access next's previous. */
608 new_el
->BASE_EL(prev
) = next_el
->BASE_EL(prev
);
609 next_el
->BASE_EL(prev
) = new_el
;
612 /* Set forward pointers. */
613 if (new_el
->BASE_EL(prev
) == 0) {
614 /* There is no previous element. Set the head pointer.*/
618 /* There is a previous element, set it's next pointer to new_el. */
619 new_el
->BASE_EL(prev
)->BASE_EL(next
) = new_el
;
622 /* Update list length. */
627 * \brief Insert an entire list immediatly after an element in this list.
629 * Elements are moved, not copied. Afterwards, the other list is empty. If
630 * prev_el is NULL then the elements are prepended to the front of the list.
631 * If prev_el is not in the list then undefined behaviour results. All
632 * elements are inserted into the list at once, so this is an O(1) operation.
634 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
635 addAfter( Element
*prev_el
, DList
<DLMEL_TEMPUSE
> &dl
)
637 /* Do not bother if dl has no elements. */
638 if ( dl
.listLen
== 0 )
641 /* Set the previous pointer of dl.head to prev_el. We do
642 * this regardless of the state of the list. */
643 dl
.head
->BASE_EL(prev
) = prev_el
;
645 /* Set forward pointers. */
647 /* There was no prev_el, we are inserting at the head. */
648 dl
.tail
->BASE_EL(next
) = head
;
652 /* There was a prev_el, we can access previous next. */
653 dl
.tail
->BASE_EL(next
) = prev_el
->BASE_EL(next
);
654 prev_el
->BASE_EL(next
) = dl
.head
;
657 /* Set reverse pointers. */
658 if (dl
.tail
->BASE_EL(next
) == 0) {
659 /* There is no next element. Set the tail pointer. */
663 /* There is a next element. Set it's prev pointer. */
664 dl
.tail
->BASE_EL(next
)->BASE_EL(prev
) = dl
.tail
;
667 /* Update the list length. */
668 listLen
+= dl
.listLen
;
671 dl
.head
= dl
.tail
= 0;
676 * \brief Insert an entire list immediately before an element in this list.
678 * Elements are moved, not copied. Afterwards, the other list is empty. If
679 * next_el is NULL then the elements are appended to the end of the list. If
680 * next_el is not in the list then undefined behaviour results. All elements
681 * are inserted at once, so this is an O(1) operation.
683 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::
684 addBefore( Element
*next_el
, DList
<DLMEL_TEMPUSE
> &dl
)
686 /* Do not bother if dl has no elements. */
687 if ( dl
.listLen
== 0 )
690 /* Set the next pointer of dl.tail to next_el. We do
691 * this regardless of the state of the list. */
692 dl
.tail
->BASE_EL(next
) = next_el
;
694 /* Set reverse pointers. */
696 /* There is no next elememnt. We are inserting at the tail. */
697 dl
.head
->BASE_EL(prev
) = tail
;
701 /* There is a next element and we can access next's previous. */
702 dl
.head
->BASE_EL(prev
) = next_el
->BASE_EL(prev
);
703 next_el
->BASE_EL(prev
) = dl
.tail
;
706 /* Set forward pointers. */
707 if (dl
.head
->BASE_EL(prev
) == 0) {
708 /* There is no previous element. Set the head pointer.*/
712 /* There is a previous element, set it's next pointer to new_el. */
713 dl
.head
->BASE_EL(prev
)->BASE_EL(next
) = dl
.head
;
716 /* Update list length. */
717 listLen
+= dl
.listLen
;
720 dl
.head
= dl
.tail
= 0;
726 * \brief Detach an element from the list.
728 * The element is not deleted. If the element is not in the list, then
729 * undefined behaviour results.
731 * \returns The element detached.
733 template <DLMEL_TEMPDEF
> Element
*DList
<DLMEL_TEMPUSE
>::
736 /* Set forward pointers to skip over el. */
737 if (el
->BASE_EL(prev
) == 0)
738 head
= el
->BASE_EL(next
);
740 el
->BASE_EL(prev
)->BASE_EL(next
) =
744 /* Set reverse pointers to skip over el. */
745 if (el
->BASE_EL(next
) == 0)
746 tail
= el
->BASE_EL(prev
);
748 el
->BASE_EL(next
)->BASE_EL(prev
) =
752 /* Update List length and return element we detached. */
758 * \brief Clear the list by deleting all elements.
760 * Each item in the list is deleted. The list is reset to its initial state.
762 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::empty()
764 Element
*nextToGo
= 0, *cur
= head
;
768 nextToGo
= cur
->BASE_EL(next
);
777 * \brief Clear the list by forgetting all elements.
779 * All elements are abandoned, not deleted. The list is reset to it's initial
782 template <DLMEL_TEMPDEF
> void DList
<DLMEL_TEMPUSE
>::abandon()
788 #ifdef AAPL_NAMESPACE