Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/util/list.h @ 5402

Last change on this file since 5402 was 5400, checked in by bensch, 20 years ago

orxonox/trunk: a new Function to List.
This gives the ability to remove entities from the end of the List.
This is good, if you have an entity just added, and then deleted right afterwards

File size: 13.3 KB
RevLine 
[4486]1/*!
[5068]2 * @file list.h
3 * a File that includes a List-template
4 */
[2636]5
[3224]6#ifndef _LIST_H
7#define _LIST_H
[2036]8
[3860]9#include "compiler.h"
10#ifndef NULL
[4499]11#define NULL 0                                       //!< this will define NULL
[3860]12#endif
[2036]13
[5115]14template<class T> class tIterator;
[2036]15
[4574]16//! a list element of the tList,
[3652]17template<class T> struct listElement
[2077]18{
[4488]19  listElement*        prev;                          //!< pointer to the previous listElement in the list
20  T*                  curr;                          //!< pointer to the list payload/container
21  listElement*        next;                          //!< pointer to the next listElement
[3652]22};
[2077]23
[4488]24/**
[4836]25 *  the list template class
[4497]26
27   you will use this as a generic list for all type of objects
[5229]28 */
[4574]29template<class T> class tList
[2822]30{
[5115]31  friend class tIterator<T>;
32
[5229]33  public:
34    tList ();
35    ~tList ();
[2822]36
[5229]37    void add(T* entity);
38    void addAtBeginning(T* entity); //!< @todo This should be made with an ENUM
39    void remove(const T* entity);
[5400]40    void removeFromLast(const T* entity);
[5229]41    void removeLast();
42    void flush();
43    T* firstElement() const;
44    T* lastElement() const;
45    bool isEmpty() const;
46    unsigned int getSize() const;
47    bool inList(T* entity) const;
48    tIterator<T>* getIterator() const;
49    T* nextElement(T* toEntity);
50    T* toArray();
[3652]51
[5229]52  private:
53    unsigned int       size;             //!< the size (lenght) of the list
54    listElement<T>*    first;            //!< pointer to the first element
55    listElement<T>*    last;             //!< pointer to the last element
56    listElement<T>*    currentEl;        //!< pointer to the current element
[2822]57};
58
59
[4497]60/**
[4836]61 *  the constructor
[5229]62 */
[2822]63template<class T>
[5229]64    inline tList<T>::tList ()
[2822]65{
[5229]66  this->currentEl = NULL;
[2822]67  this->first = NULL;
68  this->last = NULL;
69  this->size = 0;
70}
71
[4497]72
73/**
[4836]74 *  the deconstructor
[4497]75
[5229]76   this will delete only the list. ATTENTION: the list is deleted, but the objects in the list will remain
77 */
[2822]78template<class T>
[5229]79    inline tList<T>::~tList ()
[3553]80{
81  this->currentEl = this->first;
[5229]82  listElement<T>* le;
[3553]83  while(this->currentEl != NULL)
[5229]84  {
85    le = this->currentEl->next;
86    delete this->currentEl;
87    this->currentEl = le;
88  }
[3553]89  this->first = NULL;
90  this->last = NULL;
[5229]91  this->currentEl = NULL;
[3553]92  this->size = 0;
93}
[2822]94
[3553]95
[4497]96/**
[4836]97 *  add an entity to the list
98 * @param entity: the entity to add
[5229]99 */
[2822]100template<class T>
[5229]101    inline void tList<T>::add(T* entity)
[2822]102{
[3860]103  if( unlikely(entity == NULL)) return;
[3652]104  listElement<T>* el = new listElement<T>;
[2822]105  el->prev = this->last;
106  el->curr = entity;
107  el->next = NULL;
108
109  this->last = el;
110
[3860]111  if( unlikely(el->prev == NULL)) this->first = el; /* if first element */
[2822]112  else el->prev->next = el;
113  this->size++;
114}
115
[5073]116/**
117 *  add an entity to the list
118 * @param entity: the entity to add
119 */
120template<class T>
[5074]121    inline void tList<T>::addAtBeginning(T* entity)
[5073]122{
123  if( unlikely(entity == NULL)) return;
124  listElement<T>* el = new listElement<T>;
125  el->next = this->first;
126  el->curr = entity;
127  el->prev = NULL;
[2822]128
[5073]129  this->first = el;
130
[5229]131  if( unlikely(el->next == NULL)) this->last = el; /* if first element */
[5073]132  else el->next->prev = el;
133  this->size++;
134}
135
136
[4497]137/**
[5285]138 * remove an entity from the list
[4836]139 * @param entity: the entity to be removed
[5229]140 */
[2822]141template<class T>
[5229]142    inline void tList<T>::remove(const T* entity)
[2822]143{
144  this->currentEl = this->first;
145  while( this->currentEl != NULL)
[5229]146  {
147    if( unlikely(this->currentEl->curr == entity))
[2822]148    {
[5229]149      // erstes element?
150      if( unlikely(this->currentEl->prev == NULL)) this->first = this->currentEl->next;
151      else this->currentEl->prev->next = this->currentEl->next;
[2822]152
[5229]153      // letztes element?
154      if( unlikely(this->currentEl->next == NULL)) this->last = this->currentEl->prev;
155      else this->currentEl->next->prev = this->currentEl->prev;
[2822]156
[5229]157      delete this->currentEl;
158      this->size--;
159      return;
[2822]160    }
[5229]161    this->currentEl = this->currentEl->next;
162  }
[2822]163}
164
[5400]165/**
166 * remove an entity from the list
167 * @param entity: the entity to be removed
168 *
169 * this algorithm starts at the end of the List, working its way to the front
170 * for finding the right entity.
171 */
172template<class T>
173    inline void tList<T>::removeFromLast(const T* entity)
174{
175  this->currentEl = this->last;
176  while( this->currentEl != NULL)
177  {
178    if( unlikely(this->currentEl->curr == entity))
179    {
180      // erstes element?
181      if( unlikely(this->currentEl->prev == NULL)) this->first = this->currentEl->next;
182      else this->currentEl->prev->next = this->currentEl->next;
[5229]183
[5400]184      // letztes element?
185      if( unlikely(this->currentEl->next == NULL)) this->last = this->currentEl->prev;
186      else this->currentEl->next->prev = this->currentEl->prev;
187
188      delete this->currentEl;
189      this->size--;
190      return;
191    }
192    this->currentEl = this->currentEl->prev;
193  }
194}
195
196
[5068]197/**
198 * removes the Last Element of the List
199 */
200 template<class T>
201     inline void tList<T>::removeLast()
202{
[5229]203  if( unlikely(this->last == NULL))
[5068]204    return;
[5229]205
206  // only one element in the list (and its not NULL :D )
207  if( unlikely(this->last == this->first))
[5068]208  {
209    delete this->first;
210    this->first = NULL;
211    this->last = NULL;
212    this->size--;
213  }
214  else
215  {
216    listElement<T>* delLast = this->last;
217    this->last->prev->next = NULL;
218    this->last = this->last->prev;
219    delete delLast;
220  }
221}
[2822]222
[5229]223
[4497]224/**
[5229]225 *  this will delete all objects from the list, this can be very dangerous if there are ghost objects in the list.
226 */
[2822]227template<class T>
[5229]228    inline void tList<T>::flush()
[2822]229{
230  this->currentEl = this->first;
[5229]231
232  listElement<T>* le;
233  while( this->currentEl != NULL)
234  {
235    le = this->currentEl->next;
236    delete this->currentEl->curr;
237    delete this->currentEl;
238    this->currentEl = le;
239  }
[2822]240  this->first = NULL;
241  this->last = NULL;
[5230]242  this->currentEl = NULL;
[2822]243  this->size = 0;
244}
245
246
[4497]247/**
[4836]248 *  returns the first element of the list
249 * @returns first element
[5229]250 */
[2822]251template<class T>
[5229]252    inline T* tList<T>::firstElement() const
[2822]253{
254  return this->first->curr;
255}
256
[3832]257
[4497]258/**
[4836]259 *  function returns the last element of the list
260 * @returns the last element
[5229]261 */
[3790]262template<class T>
[5229]263    inline T* tList<T>::lastElement() const
[3790]264{
265  return this->last->curr;
266}
[2822]267
[3790]268
[4497]269/**
[4836]270 *  returns true if the list is empty
271 * @returns true if the list is empty
[5229]272 */
[2822]273template<class T>
[5229]274    inline bool tList<T>::isEmpty() const
[2822]275{
[5229]276  return (this->size == 0)?true:false;
[2822]277}
278
[5229]279
[4508]280/**
[5229]281 *  checks if an entity is in the List.
[4836]282 * @param entity The entity to check for in the entire List.
283 * @returns true if it is, false otherwise
[5229]284 */
[4508]285template<class T>
[5229]286    inline bool tList<T>::inList(T* entity) const
[4574]287{
[4508]288  // pre checks
[5229]289  if( unlikely(entity == NULL)) return false;
[2822]290
[4508]291  // search in the List
[5229]292  listElement<T>* el = this->first;
293  while( this->currentEl != NULL)
294  {
295    if( this->currentEl->curr == entity)
296      return true;
[4508]297
[5229]298    el = this->currentEl->next;
299  }
[4508]300}
301
[5229]302
[4497]303/**
[4836]304 *  this returns the number of elements in the list
305 * @returns number of elements
[5229]306 */
[2822]307template<class T>
[5229]308    inline unsigned int tList<T>::getSize() const
[2822]309{
310  return this->size;
311}
312
313
[4497]314/**
[4836]315 *  creates an itereator object and returns it
316 * @returns the iterator object to this list
[4497]317
318   You will use this, if you want to iterate through the list
[5229]319 */
[2822]320template<class T>
[5229]321    inline tIterator<T>* tList<T>::getIterator() const
[3652]322{
[5115]323  return new tIterator<T>(this);
[3652]324}
325
326
[2822]327
[3585]328/**
[4836]329 *  this returns the next element after toEntity or the first if toEntity is last
330 * @param toEntity: the entity after which is an entity, that has to be returned, sorry, terrible phrase
331 * @returns the element after toEntity
[5229]332 */
[2822]333template<class T>
[5229]334    inline T* tList<T>::nextElement(T* toEntity)
[3585]335{
[3586]336  //if( this->last == this->first == NULL) return NULL;
337  if(this->size == 0) return NULL;
[3585]338  if( toEntity == NULL) return this->first->curr;
339  if( toEntity == this->last->curr ) return this->first->curr;
340  this->currentEl = this->first;
341  while(this->currentEl->curr != toEntity && this->currentEl->next != NULL)
[5229]342  {
343    this->currentEl = this->currentEl->next;
344  }
[3585]345  if(this->currentEl == NULL) return NULL;
346  return this->currentEl->next->curr;
347}
348
349
[4497]350/**
[4836]351 *  creates an array out of the list (ATTENTION: not implemented)
352 * @returns pointer to the array beginning
[4497]353
354   ATTENTION: function is not implemented and wont do anything
[5229]355 */
[3585]356template<class T>
[5229]357    T* tList<T>::toArray()
[4497]358{
359  return NULL;
360}
[2822]361
[5115]362
363
364
365/**
[5229]366    *  an iterator class
[5115]367
368   this enables the user to iterate through a list very easely
369 */
370template<class T> class tIterator
371{
372  public:
373    tIterator(const tList<T>* list);
374    ~tIterator();
375
376    T* firstElement();
[5118]377    T* lastElement();
[5115]378    T* nextElement();
[5118]379    T* prevElement();
[5229]380    T* seekElement(const T* element);
[5115]381    T* iteratorElement(const tIterator<T>* iterator);
[5248]382    bool compareListPointer(const tList<T>* list);
[5115]383
[5243]384    /** another way to iterate through the list
385     * !! THIS IS NOT MEANT FOR DELETION
386     */
387    T* prevStep();
388    T* nextStep();
389    T* getCurrent();
390
[5115]391  private:
392    listElement<T>*    currentEl;                      //!< pointer to the current list element in the iterator
393    listElement<T>*    tmpEl;                          //!< temp listElemnt pointer
394    const tList<T>*    list;                           //!< The List, that we want to iterate through
395};
396
397
398/**
399 *  iterator constructor
400 * @param startElement:  the first list element from the tList
401 *
402 * normaly you will use it like this:
403 **********************************************************
404 * tIterator<char>* nameIterator = nameList->getIterator();
405 * char name* = nameIterator->firstElement();
406 * while( name != NULL)
407 *  {
408 *   PRINTF(3)("found name: %s in list\n", name);
409 *   name = nameIterator->nextElement();
410 *  }
411 * delete nameIterator;
412 * ********************************************************
413 */
414template<class T>
415  inline tIterator<T>::tIterator (const tList<T>* list)
416{
[5209]417  this->currentEl = NULL;
[5115]418  this->tmpEl = NULL;
419  this->list = list;
420}
421
422
423/**
424 *  the destructor
425 */
426template<class T>
427    inline tIterator<T>::~tIterator ()
[5230]428{
429  this->currentEl = NULL;
430  this->tmpEl = NULL;
431  this->list = NULL;
432}
[5115]433
[5229]434/**
435 * this returns the first element of the iterator list
436 * @returns first element
437 */
[5115]438template<class T>
439    inline T* tIterator<T>::firstElement ()
440{
[5131]441  this->tmpEl = this->list->first;
[5229]442  if( likely(this->tmpEl != NULL))
[5131]443  {
444    this->currentEl = this->tmpEl->next;
445    return this->tmpEl->curr;
446  }
[5118]447  else
[5115]448    return NULL;
[5118]449}
450
[5229]451/**
452 * this returns the last element of the iterator list
453 * @returns last element
454 */
[5118]455template<class T>
456    inline T* tIterator<T>::lastElement ()
457{
[5131]458  this->tmpEl = this->list->last;
[5229]459  if( likely(this->tmpEl != NULL))
[5131]460  {
461    this->currentEl = tmpEl->prev;
462    return this->tmpEl->curr;
463  }
[5115]464  else
[5118]465    return NULL;
[5115]466}
467
468
469/**
470 *  use it to iterate through the list
471 * @returns next list element
472 */
473template<class T>
474    inline T* tIterator<T>::nextElement ()
475{
[5229]476  if( unlikely(this->currentEl == NULL))
[5115]477    return NULL;
478
[5131]479  this->tmpEl = this->currentEl;
[5115]480  this->currentEl = this->currentEl->next;
[5131]481
482  return this->tmpEl->curr;
[5115]483}
484
[5229]485
[5115]486/**
[5118]487 *  use it to iterate backwards through the list
488 * @returns next list element
489 */
490template<class T>
491    inline T* tIterator<T>::prevElement ()
492{
[5229]493  if( unlikely(this->currentEl == NULL))
[5118]494    return NULL;
495
[5131]496  this->tmpEl = this->currentEl;
[5118]497  this->currentEl = this->currentEl->prev;
[5131]498
499  return this->tmpEl->curr;
[5118]500}
501
502
503/**
[5115]504 *  gets the element after the selected one, sets the iterator to this point in the list
505 * @param element the element to seek
506 * @returns current list element
507 */
508template<class T>
[5229]509    inline T* tIterator<T>::seekElement (const T* element)
[5115]510{
[5229]511  if( unlikely(element == NULL))
[5115]512  {
513    this->currentEl = NULL;
514    return NULL;
515  }
516  this->tmpEl = this->list->first;
517  while( this->tmpEl != NULL)
518  {
519    if( unlikely(this->tmpEl->curr == element))
520    {
521      this->currentEl = this->tmpEl;
522      return this->currentEl->curr;
523    }
524    this->tmpEl = this->tmpEl->next;
525  }
526  this->currentEl = NULL;
527  return NULL;
528}
529
530/**
531 * grabs the iterator entity from another iterator
532 * @param iterator the iterator to grab the local currentEl from
[5120]533 * @returns the grabbed element (current). NULL if not found, or not defined
534 *
535 * Both iterators must be from the same List!
[5115]536 */
537template<class T>
538    T* tIterator<T>::iteratorElement(const tIterator<T>* iterator)
539{
[5229]540  if( unlikely(iterator != NULL && iterator->list == this->list))
[5115]541  {
542    this->currentEl = iterator->currentEl;
543    if (this->currentEl != NULL)
544      return this->currentEl->curr;
545    else
546      return NULL;
547  }
548  else
549  {
550    this->currentEl = NULL;
551    return NULL;
552  }
553}
554
[5248]555template<class T>
556    bool tIterator<T>::compareListPointer(const tList<T>* list)
557{
558  return (this->list == list)?true:false;
559}
560
561
[5243]562/**
563 *  use it to move through the list without interfering with the iteration
[5244]564 * @returns previous list element
565 *
566 * this stepping mode will !not! step beyond the boundraries of the List!
[5243]567 */
568template<class T>
569    inline T* tIterator<T>::nextStep ()
570{
571  if( unlikely(this->tmpEl == NULL || this->tmpEl->next == NULL))
572    return NULL;
573  else
574  {
575    this->tmpEl = this->tmpEl->next;
576    return tmpEl->curr;
577  }
578}
579
580/**
581 *  use it to move backwards through the list without interfering with the itereation
582 * @returns next list element
[5244]583 *
584 * this stepping mode will !not! step beyond the boundraries of the List!
[5243]585 */
586template<class T>
587    inline T* tIterator<T>::prevStep ()
588{
589  if( unlikely(this->tmpEl == NULL || this->tmpEl->prev == NULL))
590    return NULL;
591  else
592  {
593    this->tmpEl = this->tmpEl->prev;
594    return tmpEl->curr;
595  }
596}
597
[5244]598/**
599 * @returns the current Element
600 */
[5243]601template<class T>
602    inline T* tIterator<T>::getCurrent()
603{
[5247]604  if (likely(this->tmpEl != NULL))
[5243]605    return this->tmpEl->curr;
606  else
607    return NULL;
608}
609
[3224]610#endif /* _LIST_H */
Note: See TracBrowser for help on using the repository browser.