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