diff options
Diffstat (limited to 'base/dbl_list.hh')
-rw-r--r-- | base/dbl_list.hh | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/base/dbl_list.hh b/base/dbl_list.hh new file mode 100644 index 000000000..4f6d61a45 --- /dev/null +++ b/base/dbl_list.hh @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DBL_LIST_HH__ +#define __DBL_LIST_HH__ + +class DblListEl { + DblListEl *next; + DblListEl *prev; + + // remove this from list + void remove() { + prev->next = next; + next->prev = prev; + } + + // insert this before old_el + void insertBefore(DblListEl *old_el) { + prev = old_el->prev; + next = old_el; + prev->next = this; + next->prev = this; + } + + // insert this after old_el + void insertAfter(DblListEl *old_el) { + next = old_el->next; + prev = old_el; + next->prev = this; + prev->next = this; + } + + friend class DblListBase; +}; + + +// +// doubly-linked list of DblListEl objects +// +class DblListBase { + // dummy list head element: dummy.next is head, dummy.prev is tail + DblListEl dummy; + + // length counter + unsigned length; + + DblListEl *valid_or_null(DblListEl *el) { + // make sure users never see the dummy element + return (el == &dummy) ? NULL : el; + } + + public: + + DblListEl *head() { + return valid_or_null(dummy.next); + } + + DblListEl *tail() { + return valid_or_null(dummy.prev); + } + + DblListEl *next(DblListEl *el) { + return valid_or_null(el->next); + } + + DblListEl *prev(DblListEl *el) { + return valid_or_null(el->prev); + } + + bool is_empty() { + return (dummy.next == &dummy); + } + + void remove(DblListEl *el) { + el->remove(); + --length; + } + + void insertBefore(DblListEl *new_el, DblListEl *old_el) { + new_el->insertBefore(old_el); + ++length; + } + + void insertAfter(DblListEl *new_el, DblListEl *old_el) { + new_el->insertAfter(old_el); + ++length; + } + + // append to end of list, i.e. as dummy.prev + void append(DblListEl *el) { + insertBefore(el, &dummy); + } + + // prepend to front of list (push), i.e. as dummy.next + void prepend(DblListEl *el) { + insertAfter(el, &dummy); + } + + DblListEl *pop() { + DblListEl *hd = head(); + if (hd != NULL) + remove(hd); + return hd; + } + + // constructor + DblListBase() { + dummy.next = dummy.prev = &dummy; + length = 0; + } +}; + + +// +// Template class serves solely to cast args & return values +// to appropriate type (T *) +// +template<class T> class DblList : private DblListBase { + + public: + + T *head() { return (T *)DblListBase::head(); } + T *tail() { return (T *)DblListBase::tail(); } + + T *next(T *el) { return (T *)DblListBase::next(el); } + T *prev(T *el) { return (T *)DblListBase::prev(el); } + + bool is_empty() { return DblListBase::is_empty(); } + + void remove(T *el) { DblListBase::remove(el); } + + void append(T *el) { DblListBase::append(el); } + void prepend(T *el) { DblListBase::prepend(el); } + + T *pop() { return (T *)DblListBase::pop(); } + + DblList<T>() { } +}; + +#endif // __DBL_LIST_HH__ |