00001 /*
00002 Copyright (c) 2000-2003 Lee Thomason (www.grinninglizard.com)
00003
00004 Grinning Lizard Utilities. Note that software that uses the
00005 utility package (including Lilith3D and Kyra) have more restrictive
00006 licences which applies to code outside of the utility package.
00007
00008
00009 This software is provided 'as-is', without any express or implied
00010 warranty. In no event will the authors be held liable for any
00011 damages arising from the use of this software.
00012
00013 Permission is granted to anyone to use this software for any
00014 purpose, including commercial applications, and to alter it and
00015 redistribute it freely, subject to the following restrictions:
00016
00017 1. The origin of this software must not be misrepresented; you must
00018 not claim that you wrote the original software. If you use this
00019 software in a product, an acknowledgment in the product documentation
00020 would be appreciated but is not required.
00021
00022 2. Altered source versions must be plainly marked as such, and
00023 must not be misrepresented as being the original software.
00024
00025 3. This notice may not be removed or altered from any source
00026 distribution.
00027 */
00028
00029
00030 #ifndef KYRA_CIRCLELIST_INCLUDED
00031 #define KYRA_CIRCLELIST_INCLUDED
00032
00033 #include "../util/gldebug.h"
00034
00035 // OPT improvements:
00036 // - add memory allocator
00037 // - remove the 'data' from circle node, so the overhead isn't in
00038 // the sentinels.
00039
00040 template <class T>
00041 struct GlCircleNode
00042 {
00043 T data;
00044
00045 GlCircleNode<T>* next;
00046 GlCircleNode<T>* prev;
00047 };
00048
00049 /*
00050 A circular, double linked list.
00051 */
00052 template <class T>
00053 class GlCircleList
00054 {
00055 public:
00056 GlCircleList() { sentinel.next = &sentinel; sentinel.prev = &sentinel; }
00057 ~GlCircleList() { Clear(); }
00058
00059 bool Empty() const { return sentinel.next == &sentinel; }
00060 T& Front() const { return sentinel.next->data; }
00061 T& Back() const { return sentinel.prev->data; }
00062 GlCircleNode<T>* FrontNode() const { return sentinel.next; }
00063 GlCircleNode<T>* BackNode() const { return sentinel.prev; }
00064
00065 void Clear() { GlCircleNode<T>* temp;
00066 while( sentinel.next != &sentinel )
00067 {
00068 temp = sentinel.next;
00069 sentinel.next = sentinel.next->next;
00070 delete temp;
00071 }
00072 sentinel.prev = &sentinel;
00073 }
00074 void PushFront( const T& insert ) {
00075 GlCircleNode<T>* node = new GlCircleNode<T>;
00076 node->data = insert;
00077
00078 node->prev = &sentinel;
00079 node->next = sentinel.next;
00080 sentinel.next->prev = node;
00081 sentinel.next = node;
00082 }
00083 void PushBack( const T& insert ) {
00084 GlCircleNode<T>* node = new GlCircleNode<T>;
00085 node->data = insert;
00086
00087 node->prev = sentinel.prev;
00088 node->next = &sentinel;
00089 sentinel.prev->next = node;
00090 sentinel.prev = node;
00091 }
00092 void PopFront() {
00093 GLASSERT( sentinel.next != &sentinel );
00094 GlCircleNode<T>* node = sentinel.next;
00095 // node->prev->next = node->next;
00096 // node->next->prev = node->prev;
00097 // delete node;
00098 Delete( node );
00099 }
00100 void PopBack() {
00101 GLASSERT( sentinel.prev != &sentinel );
00102 GlCircleNode<T>* node = sentinel.prev;
00103 // node->prev->next = node->next;
00104 // node->next->prev = node->prev;
00105 // delete node;
00106 Delete( node );
00107 }
00108
00109 void Delete( GlCircleNode<T>* node ) {
00110 GLASSERT( node != &sentinel );
00111 node->prev->next = node->next;
00112 node->next->prev = node->prev;
00113 delete node;
00114 }
00115 GlCircleNode<T>* Find( T value ) {
00116 GlCircleNode<T>* node = sentinel.next;
00117 while ( node != &sentinel )
00118 {
00119 if ( node->data == value )
00120 return node;
00121 node = node->next;
00122 }
00123 return 0;
00124 }
00125
00126 // Scoping problems. Pretend this is private.
00127 GlCircleNode<T> sentinel;
00128 };
00129
00130
00131 template <class T>
00132 class GlCircleListIterator
00133 {
00134 public:
00135 GlCircleListIterator( GlCircleList<T>& _list ) : current( 0 ), list( &_list ) {}
00136
00137 void Begin() { current = list->sentinel.next; }
00138 void Next() { current = current->next; }
00139 void Prev() { current = current->prev; }
00140 bool Done() { return ( current == &(list->sentinel) ); }
00141
00143 T& Current() { return (current->data); }
00144
00145 void InsertBefore( const T& addMe )
00146 {
00147 GlCircleNode<T>* node = new GlCircleNode<T>;
00148 node->data = addMe;
00149
00150 node->prev = current->prev;
00151 node->next = current;
00152 current->prev->next = node;
00153 current->prev = node;
00154 }
00155
00156 void InsertAfter( const T& addMe )
00157 {
00158 GlCircleNode<T>* node = new GlCircleNode<T>;
00159 node->data = addMe;
00160
00161 node->prev = current;
00162 node->next = current->next;
00163 current->next->prev = node;
00164 current->next = node;
00165 }
00166
00167 void Remove()
00168 {
00169 GLASSERT( current != &(list->sentinel) );
00170
00171 GlCircleNode<T>* temp = current;
00172 current = current->next;
00173
00174 temp->prev->next = temp->next;
00175 temp->next->prev = temp->prev;
00176 delete temp;
00177 }
00178
00179 private:
00180 GlCircleNode<T>* current;
00181 GlCircleList<T>* list;
00182 };
00183
00184
00185 #endif
1.2.11.1 written by Dimitri van Heesch,
© 1997-2001