1 /*
2 * tList.h
3 * Avida
4 *
5 * Called "tList.hh" prior to 12/7/05.
6 * Copyright 1999-2011 Michigan State University. All rights reserved.
7 * Copyright 1993-2003 California Institute of Technology.
8 *
9 *
10 * This file is part of Avida.
11 *
12 * Avida is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
14 *
15 * Avida is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License along with Avida.
19 * If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 #ifndef tList_h
24 #define tList_h
25
26 #ifndef NULL
27 #define NULL 0
28 #endif
29
30 template<class T> class tList;
31 template<class T> class tBaseIterator;
32 template<class T> class tListIterator;
33 template<class T> class tConstListIterator;
34 template<class T> class tLWConstListIterator;
35
36
37 template <class T> class tListNode
38 {
39 public:
40 T* data;
41 tListNode<T>* next;
42 tListNode<T>* prev;
43
44 // @DMB - Visual Studio doesn't like usage of 'this' in initializers
45 // and throws a lot of useless warnings.
tListNode()46 tListNode() : data(NULL) { next = this; prev = this; }
47 };
48
49
50 template <class T> class tList
51 {
52 friend class tBaseIterator<T>;
53 friend class tListIterator<T>;
54 friend class tConstListIterator<T>;
55 friend class tLWConstListIterator<T>;
56
57 protected:
58 tListNode<T> root; // Data root
59 int size;
60 mutable tListNode<tBaseIterator<T> > it_root; // Iterator root
61 mutable int it_count;
62
RemoveNode(tListNode<T> * out_node)63 T* RemoveNode(tListNode<T>* out_node)
64 {
65 // Make sure we're not trying to delete the root node!
66 if (out_node == &root) return NULL;
67
68 // Adjust any iterators on the deleted node.
69 tListNode< tBaseIterator<T> > * test_it = it_root.next;
70 while (test_it != &it_root) {
71 // If this iterator is on this node, move it back one.
72 if (test_it->data->GetConstNode() == out_node) {
73 test_it->data->PrevConst();
74 }
75 test_it = test_it->next;
76 }
77
78 // Save the data and patch up the linked list.
79 T* out_data = out_node->data;
80 out_node->prev->next = out_node->next;
81 out_node->next->prev = out_node->prev;
82
83 // Cleanup and return
84 size--;
85 delete out_node;
86 return out_data;
87 }
88
89 // To be called from iterator constructor only!
AddIterator(tBaseIterator<T> * new_it)90 void AddIterator(tBaseIterator<T>* new_it) const
91 {
92 tListNode< tBaseIterator<T> >* new_node =
93 new tListNode< tBaseIterator<T> >;
94 new_node->data = new_it;
95 new_node->next = it_root.next;
96 new_node->prev = &it_root;
97 it_root.next->prev = new_node;
98 it_root.next = new_node;
99 it_count++;
100 }
101
102 // To be called from iterator destructor only!
RemoveIterator(tBaseIterator<T> * old_it)103 void RemoveIterator(tBaseIterator<T>* old_it) const
104 {
105 tListNode< tBaseIterator<T> >* test_it = it_root.next;
106 while (test_it->data != old_it) test_it = test_it->next;
107 test_it->prev->next = test_it->next;
108 test_it->next->prev = test_it->prev;
109 delete test_it;
110 it_count--;
111 }
112
113
114 public:
tList()115 tList() : size(0), it_count(0) { }
tList(const tList & in_list)116 explicit tList(const tList& in_list) : size(0), it_count(0) { Append(in_list); }
~tList()117 ~tList() { Clear(); }
118
Pop()119 inline T* Pop() { return RemoveNode(root.next); }
PopRear()120 inline T* PopRear() { return RemoveNode(root.prev); }
121
Clear()122 void Clear() { while (size > 0) Pop(); }
123
Append(const tList<T> & in_list)124 void Append(const tList<T>& in_list)
125 {
126 tListNode<T>* cur_node = in_list.root.next;
127 while (cur_node != &(in_list.root)) {
128 PushRear(cur_node->data);
129 cur_node = cur_node->next;
130 }
131 }
132
Copy(const tList<T> & in_list)133 void Copy(const tList<T> & in_list) {
134 Clear();
135 Append(in_list);
136 }
137
138 inline tList& operator=(const tList& list) { Copy(list); return *this; }
139
Push(T * _in)140 void Push(T* _in) {
141 tListNode<T>* new_node = new tListNode<T>;
142 new_node->data = _in;
143 new_node->next = root.next;
144 new_node->prev = &root;
145 root.next->prev = new_node;
146 root.next = new_node;
147 size++;
148 }
149
PushRear(T * _in)150 tListNode<T>* PushRear(T* _in) {
151 tListNode<T>* new_node = new tListNode<T>;
152 new_node->data = _in;
153 new_node->next = &root;
154 new_node->prev = root.prev;
155 root.prev->next = new_node;
156 root.prev = new_node;
157 size++;
158 return new_node;
159 }
160
GetFirst()161 inline const T* GetFirst() const { return root.next->data; }
GetLast()162 inline const T* GetLast() const { return root.prev->data; }
GetFirst()163 inline T* GetFirst() { return root.next->data; }
GetLast()164 inline T* GetLast() { return root.prev->data; }
165
GetPos(int pos)166 T* GetPos(int pos)
167 {
168 if (pos >= GetSize()) return NULL;
169 tListNode<T>* test_node = root.next;
170 for (int i = 0; i < pos; i++) test_node = test_node->next;
171 return test_node->data;
172 }
173
GetPos(int pos)174 const T* GetPos(int pos) const
175 {
176 if (pos >= GetSize()) return NULL;
177 tListNode<T>* test_node = root.next;
178 for (int i = 0; i < pos; i++) test_node = test_node->next;
179 return test_node->data;
180 }
181
CircNext()182 inline void CircNext() { if (size > 0) PushRear(Pop()); }
CircPrev()183 inline void CircPrev() { if (size > 0) Push(PopRear()); }
184
Insert(tListIterator<T> & list_it,T * in_data)185 T* Insert(tListIterator<T>& list_it, T* in_data)
186 {
187 tListNode<T>* cur_node = list_it.node;
188
189 // Build the new node for the list...
190 tListNode<T>* new_node = new tListNode<T>;
191 new_node->data = in_data;
192
193 // Insert the new node before the iterator...
194 new_node->next = cur_node;
195 new_node->prev = cur_node->prev;
196 cur_node->prev->next = new_node;
197 cur_node->prev = new_node;
198 size++;
199
200 return in_data;
201 }
202
203
Remove(tListIterator<T> & other)204 T* Remove(tListIterator<T>& other)
205 {
206 if (&(other.list) != this) return NULL; // @CAO make this an assert?
207 return RemoveNode(other.node);
208 }
209
210
Remove(T * other)211 T* Remove(T* other)
212 {
213 tListNode<T>* test = root.next;
214 while (test != &root) {
215 if (test->data == other) {
216 RemoveNode(test);
217 return other;
218 }
219 test = test->next;
220 }
221
222 return NULL;
223 }
224
GetSize()225 inline int GetSize() const { return size; }
226
227
228 // Empty out another list, transferring its contents to the end of this one.
Transfer(tList<T> & other_list)229 void Transfer(tList<T>& other_list)
230 {
231 // If the other list is empty, stop here.
232 if (other_list.GetSize() == 0) return;
233
234 // Hook this list into the other one.
235 other_list.root.next->prev = root.prev;
236 other_list.root.prev->next = &root;
237 root.prev->next = other_list.root.next;
238 root.prev = other_list.root.prev;
239
240 // Clean up the other list so it has no entries.
241 other_list.root.next = &(other_list.root);
242 other_list.root.prev = &(other_list.root);
243
244 // Update the size
245 size += other_list.size;
246 other_list.size = 0;
247
248 // Update all iterators in the other list to point at the root.
249 tListNode< tBaseIterator<T> > * test_it = other_list.it_root.next;
250 while (test_it != &other_list.it_root) {
251 test_it->data->Reset();
252 test_it = test_it->next;
253 }
254 }
255
256 // Find by value
Find(T * _in)257 T* Find(T* _in) const
258 {
259 if (size == 0) return NULL;
260 tListNode<T>* test = root.next;
261 while (test != &root) {
262 if ( *(test->data) == *(_in) ) return test->data;
263 test = test->next;
264 }
265 return NULL;
266 }
267
268 // Find by Pointer
FindPtr(T * _in)269 T* FindPtr(T* _in) const
270 {
271 tListNode<T>* test = root.next;
272 while (test != &root) {
273 if ( test->data == _in ) return test->data;
274 test = test->next;
275 }
276 return NULL;
277 }
278
279 // Find the position of the node by its pointer
FindPosPtr(T * _in)280 int FindPosPtr(T* _in) const
281 {
282 tListNode<T>* test = root.next;
283 int pos = 0;
284 while (test != &root) {
285 if ( test->data == _in ) return pos;
286 test = test->next;
287 pos++;
288 }
289 return 0;
290 }
291
292
293 // Remove by position
PopPos(int pos)294 T* PopPos(int pos)
295 {
296 if (pos >= GetSize()) return NULL;
297 tListNode<T>* test_node = root.next;
298 for (int i = 0; i < pos; i++) test_node = test_node->next;
299 return RemoveNode(test_node);
300 }
301
302 };
303
304
305
306 // This is an extended version of tList that contains extra functions to
307 // allow method pointers associated with the object type being listed.
308 template <class T> class tListPlus : public tList<T>
309 {
310 public:
tListPlus()311 tListPlus() : tList<T>() { ; }
tListPlus(const tList<T> & in_list)312 explicit tListPlus(const tList<T>& in_list) : tList<T>(in_list) { ; }
tListPlus(const tListPlus & in_list)313 explicit tListPlus(const tListPlus& in_list) : tList<T>(in_list) { ; }
314
315
316
FindValue(V (T::* fun)()const,V value)317 template<typename V> T* FindValue(V (T::*fun)() const, V value) const
318 {
319 tListNode<T>* node;
320 if (FindNode(fun, value, node)) return node->data;
321 return NULL;
322 }
323
PopValue(V (T::* fun)()const,V value)324 template<typename V> T* PopValue(V (T::*fun)() const, V value)
325 {
326 tListNode<T>* node;
327 if (FindNode(fun, value, node)) return tList<T>::RemoveNode(node);
328 return NULL;
329 }
330
FindMax(V (T::* fun)()const)331 template<typename V> T* FindMax(V (T::*fun)() const) const
332 {
333 tListNode<T>* node;
334 if (FindMax(fun, node)) return node->data;
335 return NULL;
336 }
337
PopMax(V (T::* fun)()const)338 template<typename V> T* PopMax(V (T::*fun)() const)
339 {
340 tListNode<T>* node;
341 if (FindMax(fun, node)) return tList<T>::RemoveNode(node);
342 return NULL;
343 }
344
345
346 // Find by summing values until a specified total is reached.
FindSummedValue(int sum,int (T::* fun)()const)347 T* FindSummedValue(int sum, int (T::*fun)() const) const
348 {
349 if (this->size == 0) return NULL;
350
351 int total = 0;
352 tListNode<T>* test = this->root.next;
353 while (test != &(this->root) && total < sum) {
354 total += (test->data->*fun)();
355 test = test->next;
356 }
357 return test->data;
358 }
359
360
Count(int (T::* fun)()const)361 int Count(int (T::*fun)() const) const
362 {
363 int total = 0;
364 tListNode<T> * test = this->root.next;
365 while (test != &(this->root)) {
366 total += (test->data->*fun)();
367 test = test->next;
368 }
369 return total;
370 }
371
372
373
374 private:
FindNode(V (T::* fun)()const,V value,tListNode<T> * & node)375 template<typename V> bool FindNode(V (T::*fun)() const, V value, tListNode<T>*& node) const
376 {
377 node = this->root.next;
378 while (node != &(this->root)) {
379 if ((node->data->*fun)() == value) return true;
380 node = node->next;
381 }
382
383 return false;
384 }
385
386
FindMax(V (T::* fun)()const,tListNode<T> * & best)387 template<typename V> bool FindMax(V (T::*fun)() const, tListNode<T>*& best) const
388 {
389 if (this->size == 0) return false;
390
391 tListNode<T>* test = this->root.next;
392 best = test;
393 V max_val = (test->data->*fun)();
394 while (test != &(this->root)) {
395 const V cur_val = (test->data->*fun)();
396 if (cur_val > max_val) {
397 max_val = cur_val;
398 best = test;
399 }
400 test = test->next;
401 }
402
403 return true;
404 }
405 };
406
407
408
409
410
411
412
413
414
415 template <class T> class tBaseIterator
416 {
417 friend class tList<T>;
418
419 protected:
420 virtual const tList<T>& GetConstList() = 0;
421 virtual const tListNode<T>* GetConstNode() = 0;
422
423 public:
tBaseIterator()424 tBaseIterator() { ; }
~tBaseIterator()425 virtual ~tBaseIterator() { ; }
426
427 virtual void Set(tListNode<T>* in_node) = 0;
428 virtual void Reset() = 0;
429
430 virtual const T* GetConst() = 0;
431 virtual const T* NextConst() = 0;
432 virtual const T* PrevConst() = 0;
433
434 virtual bool AtRoot() const = 0;
435 virtual bool AtEnd() const = 0;
436 };
437
438
439
440 template <class T> class tListIterator : public tBaseIterator<T>
441 {
442 friend class tList<T>;
443
444 private:
445 tList<T>& list;
446 tListNode<T>* node;
447
GetConstList()448 const tList<T>& GetConstList() { return list; }
GetConstNode()449 const tListNode<T>* GetConstNode() { return node; }
450
451 public:
tListIterator(tList<T> & _list)452 explicit inline tListIterator(tList<T>& _list) : list(_list), node(&(_list.root)) { list.AddIterator(this); }
tListIterator(tList<T> & _list,tListNode<T> * start)453 explicit inline tListIterator(tList<T>& _list, tListNode<T>* start) : list(_list), node(start) { list.AddIterator(this); }
tListIterator(const tListIterator<T> & _tli)454 inline tListIterator(const tListIterator<T>& _tli) : tBaseIterator<T>(), list(_tli.list), node(_tli.node)
455 {
456 list.AddIterator(this);
457 }
458
~tListIterator()459 inline ~tListIterator() { list.RemoveIterator(this); }
460
Set(tListNode<T> * in_node)461 void Set(tListNode<T>* in_node) { node = in_node; }
Reset()462 void Reset() { node = &(list.root); }
GetPos()463 tListNode<T>* GetPos() { return node; }
464
Get()465 T* Get() { return node->data; }
Next()466 T* Next() { node = node->next; return node->data; }
Prev()467 T* Prev() { node = node->prev; return node->data; }
468
GetConst()469 const T* GetConst() { return Get(); }
NextConst()470 const T* NextConst() { return Next(); }
PrevConst()471 const T* PrevConst() { return Prev(); }
472
473 bool Find(T* test_data);
474
AtRoot()475 bool AtRoot() const { return (node == &(list.root)); }
AtEnd()476 bool AtEnd() const { return (node->next == &(list.root)); }
477
478 // Unique methods...
Remove()479 T* Remove() { return list.RemoveNode(node); }
480 };
481
482
483 template <class T> class tConstListIterator : public tBaseIterator<T>
484 {
485 friend class tList<T>;
486
487 private:
488 const tList<T>& list;
489 const tListNode<T>* node;
490
GetConstList()491 const tList<T>& GetConstList() { return list; }
GetConstNode()492 const tListNode<T>* GetConstNode() { return node; }
493
494 public:
tConstListIterator(const tList<T> & _list)495 explicit tConstListIterator(const tList<T>& _list) : list(_list), node(&(_list.root)) { list.AddIterator(this); }
tConstListIterator(const tList<T> & _list,const tListNode<T> * start_node)496 explicit tConstListIterator(const tList<T>& _list, const tListNode<T>* start_node)
497 : list(_list), node(start_node) { list.AddIterator(this); }
~tConstListIterator()498 ~tConstListIterator() { list.RemoveIterator(this); }
499
Set(tListNode<T> * in_node)500 void Set(tListNode<T>* in_node) { node = in_node; }
Reset()501 void Reset() { node = &(list.root); }
502
Get()503 T* Get() { return node->data; }
Next()504 T* Next() { node = node->next; return node->data; }
Prev()505 T* Prev() { node = node->prev; return node->data; }
506
GetConst()507 const T* GetConst() { return Get(); }
NextConst()508 const T* NextConst() { return Next(); }
PrevConst()509 const T* PrevConst() { return Prev(); }
510 bool Find(const T * test_data);
511
AtRoot()512 bool AtRoot() const { return (node == &(list.root)); }
AtEnd()513 bool AtEnd() const { return (node->next == &(list.root)); }
514 };
515
516
517 template <class T> class tLWConstListIterator : public tBaseIterator<T>
518 {
519 friend class tList<T>;
520
521 private:
522 const tList<T>& list;
523 const tListNode<T>* node;
524
GetConstList()525 const tList<T>& GetConstList() { return list; }
GetConstNode()526 const tListNode<T>* GetConstNode() { return node; }
527
528 public:
tLWConstListIterator(const tList<T> & _list)529 explicit tLWConstListIterator(const tList<T>& _list) : list(_list), node(&(_list.root)) { ; }
tLWConstListIterator(const tList<T> & _list,const tListNode<T> * start_node)530 explicit tLWConstListIterator(const tList<T>& _list, const tListNode<T>* start_node) : list(_list), node(start_node) { ; }
~tLWConstListIterator()531 ~tLWConstListIterator() { ; }
532
Set(tListNode<T> * in_node)533 void Set(tListNode<T>* in_node) { node = in_node; }
Reset()534 void Reset() { node = &(list.root); }
535
Get()536 T* Get() { return node->data; }
Next()537 T* Next() { node = node->next; return node->data; }
Prev()538 T* Prev() { node = node->prev; return node->data; }
539
GetConst()540 const T* GetConst() { return Get(); }
NextConst()541 const T* NextConst() { return Next(); }
PrevConst()542 const T* PrevConst() { return Prev(); }
543 bool Find(const T* test_data);
544
AtRoot()545 bool AtRoot() const { return (node == &(list.root)); }
AtEnd()546 bool AtEnd() const { return (node->next == &(list.root)); }
547 };
548
549
550
551
Find(T * test_data)552 template <class T> bool tListIterator<T>::Find(T* test_data)
553 {
554 for (node = list.root.next; node != &(list.root); node = node->next) if (node->data == test_data) return true;
555 return false;
556 }
557
558
559
Find(const T * test_data)560 template <class T> bool tConstListIterator<T>::Find(const T* test_data)
561 {
562 for (node = list.root.next; node != &(list.root); node = node->next) if (node->data == test_data) return true;
563 return false;
564 }
565
566
567
Find(const T * test_data)568 template <class T> bool tLWConstListIterator<T>::Find(const T* test_data)
569 {
570 for (node = list.root.next; node != &(list.root); node = node->next) if (node->data == test_data) return true;
571 return false;
572 }
573
574 #endif
575