Main Page   Class Hierarchy   Compound List   File List   Compound Members  

TPtrListT.hh

00001 #ifndef _T_PTR_LIST_T_HH
00002 #define _T_PTR_LIST_T_HH
00003 
00004 #include <stdlib.h>
00005 #include "TBoundsException.hh"
00006 #include "TMemoryException.hh"
00007 
00008 #define T_ABS(x) (x < 0 ? -x: x)
00009 
00010 typedef struct TListEntry TListEntry_t;
00011 
00012 
00013 // Holder for an entry in the list.
00014 struct TListEntry
00015 {
00016   // Previous entry.
00017   TListEntry_t *prev;
00018   
00019   // Next entry.
00020   TListEntry_t *next;
00021   
00022   // Pointer to object in this entry.
00023   void *data;
00024 };
00025 
00026 
00033 template <class T>
00034 class TPtrListT
00035 {
00036 public:
00037   
00041   TPtrListT () { Reset (); }
00042   
00046   TPtrListT (TPtrListT<T> &list) { Copy (list); }
00047   
00051   ~TPtrListT () { Clear (); }
00052   
00056   void Append (T *a);
00057   
00064   void Apply (void (*fn)(T *, void *), void *d);
00065   
00069   void Clear ();
00070   
00075   void ClearAndDestroy ();
00076   
00080   inline int Entries () const { return myNumElements; }
00081   
00086   inline T* First () { return (T*)myFirst->data; }
00087   
00091   void Insert (T *a, int i = 0);
00092   
00097   inline T* Last () { return (T*)myLast->data; }
00098   
00102   T* Remove (int i = 0);
00103   
00107   T* RemoveLast ();
00108   
00114   void Sort (bool reverse = false);
00115   
00120   T*& operator[](int i);
00121   
00125   TPtrListT<T>& operator=(const TPtrListT<T> &list);
00126   
00127   
00128 private:
00129   
00133   inline void Reset ()
00134   {
00135     myFirst = NULL;
00136     myLast  = NULL;
00137     myCurrentPtr  = NULL;
00138     myCurrentNum  = 0;
00139     myNumElements = 0;
00140   }
00141 
00145   void UpdateCurrent (int i);
00146   
00151   void Copy (TPtrListT<T> &list);
00152   
00153   
00154   /* First entry. */
00155   TListEntry_t *myFirst;
00156   
00157   /* Last entry. */
00158   TListEntry_t *myLast;
00159   
00160   /* Pointer of last entry used.
00161      Used to speed up index operator etc. */
00162   TListEntry_t *myCurrentPtr;
00163   
00164   /* Number of last entry used.
00165      Used to speed up index operator etc. */
00166   int myCurrentNum;
00167   
00168   /* Number of elements in list. */
00169   int myNumElements;
00170 };
00171 
00172 
00173 template <class T>
00174 void TPtrListT<T>::Append (T *a)
00175 {
00176   TListEntry_t *entry;
00177   
00178   if (! (entry = (TListEntry_t *) malloc (sizeof (TListEntry_t))))
00179     throw TMemoryException ();
00180   
00181   entry->data = a;
00182   
00183   if (myNumElements)
00184     {
00185       myLast->next = entry;
00186       entry->prev = myLast;
00187       myLast = entry;
00188     }
00189   else
00190     {
00191       myFirst = entry;
00192       myLast = entry;
00193       myCurrentPtr = myFirst;
00194       myCurrentNum = 0;
00195     }
00196   
00197   myNumElements++;
00198 }
00199 
00200 
00201 template <class T>
00202 void TPtrListT<T>::Apply (void (*fn)(T *, void *), void *d)
00203 {
00204   TListEntry_t *entry = myFirst;
00205   
00206   for (int i = 0; i < myNumElements; i++)
00207     {
00208       fn ((T *)entry->data, d);
00209       entry = entry->next;
00210     }
00211 }
00212 
00213 
00214 template <class T>
00215 void TPtrListT<T>::Clear ()
00216 {
00217   TListEntry_t *entry = myFirst, *tmp_entry;
00218   
00219   for (int i = 0; i < myNumElements; i++)
00220     {
00221       tmp_entry = entry;
00222       entry = entry->next;
00223       free (tmp_entry);
00224     }
00225   
00226   Reset ();
00227 }
00228 
00229 
00230 template <class T>
00231 void TPtrListT<T>::ClearAndDestroy ()
00232 {
00233   TListEntry_t *entry = myFirst, *tmp_entry;
00234   
00235   for (int i = 0; i < myNumElements; i++)
00236     {
00237       delete (T*)entry->data;
00238       tmp_entry = entry;
00239       entry = entry->next;
00240       free (tmp_entry);
00241     }
00242   
00243   Reset ();
00244 }
00245 
00246 
00247 template <class T>
00248 void TPtrListT<T>::Insert (T *a, int i)
00249 {
00250   TListEntry_t *entry, *prev;
00251   
00252   /* Takes care of inserting to empty list or after last entry. */
00253   if (i == myNumElements)
00254     {
00255       Append (a);
00256       return;
00257     }
00258   
00259 #ifdef TOOLS_BOUND_CHECK
00260   if (i >= myNumElements || i < 0)
00261     throw TBoundsException ();
00262 #endif
00263   
00264   if (! (entry = (TListEntry_t *) malloc (sizeof (TListEntry_t))))
00265     throw TMemoryException ();
00266   
00267   entry->data = a;
00268   
00269   /* Insert to first entry? */
00270   if (! i)
00271     {
00272       myFirst->prev = entry;
00273       entry->next = myFirst;
00274       myFirst = entry;
00275       myCurrentPtr = myFirst;
00276       myCurrentNum = 0;
00277     }
00278   else
00279     {
00280       UpdateCurrent (i);
00281       entry->prev = myCurrentPtr->prev;
00282       entry->next = myCurrentPtr;
00283       myCurrentPtr->prev->next = entry;
00284       myCurrentPtr->prev = entry;
00285       myCurrentPtr = entry;
00286       /* myCurrentNum stays the same! */
00287     }
00288   
00289   myNumElements++;
00290 }
00291 
00292 
00293 template <class T>
00294 T* TPtrListT<T>::Remove (int i)
00295 {
00296 #ifdef TOOLS_BOUND_CHECK  
00297   if (i >= myNumElements || i < 0)
00298     throw TBoundsException ();
00299 #endif  
00300   
00301   /* Removing last entry? */
00302   if (i == (myNumElements - 1))
00303     return RemoveLast ();
00304   
00305   TListEntry_t *entry;
00306   T *data;
00307   
00308   /* Remove first entry? */
00309   if (! i)
00310     {
00311       entry = myFirst;
00312       data = (T *)myFirst->data;
00313       myFirst = myFirst->next;
00314       myCurrentPtr = myFirst;
00315       myCurrentNum = 0;
00316     }
00317   else
00318     {
00319       UpdateCurrent (i);
00320       entry = myCurrentPtr;
00321       data = (T *)myCurrentPtr->data;
00322       myCurrentPtr->prev->next = myCurrentPtr->next;
00323       myCurrentPtr->next->prev = myCurrentPtr->prev;
00324       myCurrentPtr = myCurrentPtr->next;
00325       /* myCurrentNum stays the same! */
00326     }
00327   
00328   free (entry);
00329   myNumElements--;
00330   
00331   return data;
00332 }
00333 
00334 
00335 template <class T>
00336 T* TPtrListT<T>::RemoveLast ()
00337 {
00338 #ifdef TOOLS_BOUND_CHECK
00339   if (! myNumElements)
00340     throw TBoundsException ();
00341 #endif
00342   
00343   TListEntry_t *entry = myLast;
00344   T *data = (T *)myLast->data;
00345   
00346   if (myNumElements == 1)
00347     Reset ();
00348   else
00349     {
00350       myLast = myLast->prev;
00351       myNumElements--;
00352       if (myCurrentNum >= myNumElements)
00353         {
00354           myCurrentPtr = myFirst;
00355           myCurrentNum = 0;
00356         }
00357     }
00358   
00359   free (entry);
00360   return data;
00361 }
00362 
00363 
00364 /* FIXME */
00365 template <class T>
00366 void TPtrListT<T>::Sort (bool reverse)
00367 {
00368 }
00369 
00370 
00371 template <class T>
00372 T*& TPtrListT<T>::operator[](int i)
00373 {
00374 #ifdef TOOLS_BOUND_CHECK
00375   if (i >= myNumElements || i < 0)
00376     throw TBoundsException ();
00377 #endif
00378   
00379   UpdateCurrent (i);
00380   
00381   return (T*)myCurrentPtr->data;
00382 }
00383 
00384 
00385 template <class T>
00386 TPtrListT<T>& TPtrListT<T>::operator=(const TPtrListT<T> &list)
00387 {
00388   /* Only copy if different objects. */
00389   if (&list != this)
00390     {
00391       Clear ();
00392       Copy (list);
00393     }
00394   
00395   return *this;
00396 }
00397 
00398 
00399 template <class T>
00400 void TPtrListT<T>::Copy (TPtrListT<T> &list)
00401 {
00402   TListEntry_t *entry = NULL, *prev = NULL;
00403   TListEntry_t *entry_orig = list.myFirst;
00404   
00405   myFirst       = NULL;
00406   myNumElements = list.myNumElements;
00407   
00408   for (int i = 0; i < myNumElements; i++)
00409     {
00410       if (! (entry = (TListEntry_t *) malloc (sizeof (TListEntry_t))))
00411         throw TMemoryException ();
00412       
00413       /* Hook previous entry to this one. */
00414       if (prev)
00415         prev->next = entry;
00416       
00417       entry->prev = prev;
00418       entry->data = entry_orig->data;
00419       prev = entry;
00420       
00421       entry_orig = entry_orig->next;
00422       
00423       /* Store pointer to first entry. */
00424       if (! i)
00425         myFirst = entry;
00426     }
00427   
00428   myCurrentPtr  = myFirst;
00429   myCurrentNum  = 0;
00430   myLast = entry;
00431 }
00432 
00433 
00434 template <class T>
00435 void TPtrListT<T>::UpdateCurrent (int i)
00436 {
00437   int l_dist = (myNumElements - 1) - i;
00438   int c_dist = T_ABS (myCurrentNum - i);
00439   
00440   /* First better then last? */
00441   if (i <= l_dist)
00442     {
00443       /* First better than current? */
00444       if (i < c_dist)
00445         {
00446           myCurrentPtr = myFirst;
00447           myCurrentNum = 0;
00448         }
00449     }
00450   else
00451     {
00452       /* Last better than current? */
00453       if (l_dist < c_dist)
00454         {
00455           myCurrentPtr = myLast;
00456           myCurrentNum = (myNumElements - 1);
00457         }
00458     }
00459   
00460   /* Scan forward? */
00461   if (myCurrentNum < i)
00462     {
00463       for (; myCurrentNum < i; myCurrentNum++)
00464         myCurrentPtr = myCurrentPtr->next;
00465     }
00466   
00467   /* Scan backwards */
00468   if (myCurrentNum > i)
00469     {
00470       for (; myCurrentNum > i; myCurrentNum--)
00471         myCurrentPtr = myCurrentPtr->prev;
00472     }
00473 }
00474 
00475 #endif // _T_PTR_LIST_T_HH

Generated on Sat Feb 15 18:37:16 2003 for Tools by doxygen1.3-rc2