Main Page   Class Hierarchy   Compound List   File List   Compound Members  

TValListT.hh

00001 #ifndef _T_VAL_LIST_T_HH
00002 #define _T_VAL_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 
00011 // Holder for an entry in the list.
00012 
00013 template <class T>
00014 class TValListEntryT
00015 {
00016 public:
00017   
00019   TValListEntryT<T> *prev;
00020   
00022   TValListEntryT<T> *next;
00023   
00025   T data;
00026 };
00027 
00028 
00035 template <class T>
00036 class TValListT
00037 {
00038 public:
00039   
00043   TValListT () { Reset (); }
00044   
00048   TValListT (TValListT<T> &list) { Copy (list); }
00049   
00053   ~TValListT () { Clear (); }
00054   
00058   void Append (T a);
00059   
00066   void Apply (void (*fn)(T *, void *), void *d);
00067   
00071   void Clear ();
00072   
00076   inline int Entries () const { return myNumElements; }
00077   
00082   inline T First () { return myFirst->data; }
00083   
00087   void Insert (T a, int i = 0);
00088   
00093   inline T Last () { return myLast->data; }
00094   
00098   T Remove (int i = 0);
00099   
00103   T RemoveLast ();
00104   
00110   void Sort (bool reverse = false);
00111   
00116   T& operator[](int i);
00117   
00121   TValListT<T>& operator=(const TValListT<T> &list);
00122   
00123   
00124 private:
00125   
00129   inline void Reset ()
00130   {
00131     myFirst = NULL;
00132     myLast  = NULL;
00133     myCurrentPtr  = NULL;
00134     myCurrentNum  = 0;
00135     myNumElements = 0;
00136   }
00137 
00141   void UpdateCurrent (int i);
00142   
00147   void Copy (const TValListT<T> &list);
00148   
00149   
00150   /* First entry. */
00151   TValListEntryT<T> *myFirst;
00152   
00153   /* Last entry. */
00154   TValListEntryT<T> *myLast;
00155   
00156   /* Pointer of last entry used.
00157      Used to speed up index operator etc. */
00158   TValListEntryT<T> *myCurrentPtr;
00159   
00160   /* Number of last entry used.
00161      Used to speed up index operator etc. */
00162   int myCurrentNum;
00163   
00164   /* Number of elements in list. */
00165   int myNumElements;
00166 };
00167 
00168 
00169 template <class T>
00170 void TValListT<T>::Append (T a)
00171 {
00172   TValListEntryT<T> *entry;
00173   
00174   entry = new TValListEntryT<T>;
00175   entry->data = a;
00176   
00177   if (myNumElements)
00178     {
00179       myLast->next = entry;
00180       entry->prev = myLast;
00181       myLast = entry;
00182     }
00183   else
00184     {
00185       myFirst = entry;
00186       myLast = entry;
00187       myCurrentPtr = myFirst;
00188       myCurrentNum = 0;
00189     }
00190   
00191   myNumElements++;
00192 }
00193 
00194 
00195 template <class T>
00196 void TValListT<T>::Apply (void (*fn)(T *, void *), void *d)
00197 {
00198   TValListEntryT<T> *entry = myFirst;
00199   
00200   for (int i = 0; i < myNumElements; i++)
00201     {
00202       fn (&entry->data, d);
00203       entry = entry->next;
00204     }
00205 }
00206 
00207 
00208 template <class T>
00209 void TValListT<T>::Clear ()
00210 {
00211   TValListEntryT<T> *entry = myFirst, *tmp_entry;
00212   
00213   for (int i = 0; i < myNumElements; i++)
00214     {
00215       tmp_entry = entry;
00216       entry = entry->next;
00217       delete tmp_entry;
00218     }
00219   
00220   Reset ();
00221 }
00222 
00223 
00224 template <class T>
00225 void TValListT<T>::Insert (T a, int i)
00226 {
00227   TValListEntryT<T> *entry;
00228   
00229   /* Takes care of inserting to empty list or after last entry. */
00230   if (i == myNumElements)
00231     {
00232       Append (a);
00233       return;
00234     }
00235   
00236 #ifdef TOOLS_BOUND_CHECK
00237   if (i >= myNumElements || i < 0)
00238     throw TBoundsException ();
00239 #endif
00240   
00241   entry = new TValListEntryT<T>;
00242   entry->data = a;
00243   
00244   /* Insert to first entry? */
00245   if (! i)
00246     {
00247       myFirst->prev = entry;
00248       entry->next = myFirst;
00249       myFirst = entry;
00250       myCurrentPtr = myFirst;
00251       myCurrentNum = 0;
00252     }
00253   else
00254     {
00255       UpdateCurrent (i);
00256       entry->prev = myCurrentPtr->prev;
00257       entry->next = myCurrentPtr;
00258       myCurrentPtr->prev->next = entry;
00259       myCurrentPtr->prev = entry;
00260       myCurrentPtr = entry;
00261       /* myCurrentNum stays the same! */
00262     }
00263   
00264   myNumElements++;
00265 }
00266 
00267 
00268 template <class T>
00269 T TValListT<T>::Remove (int i)
00270 {
00271 #ifdef TOOLS_BOUND_CHECK
00272   if (i >= myNumElements || i < 0)
00273     throw TBoundsException ();
00274 #endif
00275   
00276   /* Removing last entry? */
00277   if (i == (myNumElements - 1))
00278     return RemoveLast ();
00279   
00280   TValListEntryT<T> *entry;
00281   T data;
00282   
00283   /* Remove first entry? */
00284   if (! i)
00285     {
00286       entry = myFirst;
00287       data = myFirst->data;
00288       myFirst = myFirst->next;
00289       myCurrentPtr = myFirst;
00290       myCurrentNum = 0;
00291     }
00292   else
00293     {
00294       UpdateCurrent (i);
00295       entry = myCurrentPtr;
00296       data = myCurrentPtr->data;
00297       myCurrentPtr->prev->next = myCurrentPtr->next;
00298       myCurrentPtr->next->prev = myCurrentPtr->prev;
00299       myCurrentPtr = myCurrentPtr->next;
00300       /* myCurrentNum stays the same! */
00301     }
00302   
00303   delete entry;
00304   myNumElements--;
00305   
00306   return data;
00307 }
00308 
00309 
00310 template <class T>
00311 T TValListT<T>::RemoveLast ()
00312 {
00313 #ifdef TOOLS_BOUND_CHECK
00314   if (! myNumElements)
00315     throw TBoundsException ();
00316 #endif
00317   
00318   TValListEntryT<T> *entry = myLast;
00319   T data = myLast->data;
00320   
00321   if (myNumElements == 1)
00322     Reset ();
00323   else
00324     {
00325       myLast = myLast->prev;
00326       myNumElements--;
00327       if (myCurrentNum >= myNumElements)
00328         {
00329           myCurrentPtr = myFirst;
00330           myCurrentNum = 0;
00331         }
00332     }
00333   
00334   delete entry;
00335   return data;
00336 }
00337 
00338 
00339 /* FIXME */
00340 template <class T>
00341 void TValListT<T>::Sort (bool reverse)
00342 {
00343 }
00344 
00345 
00346 template <class T>
00347 T& TValListT<T>::operator[](int i)
00348 {
00349 #ifdef TOOLS_BOUND_CHECK
00350   if (i >= myNumElements || i < 0)
00351     throw TBoundsException ();
00352 #endif
00353   
00354   UpdateCurrent (i);
00355   
00356   return myCurrentPtr->data;
00357 }
00358 
00359 
00360 template <class T>
00361 TValListT<T>& TValListT<T>::operator=(const TValListT<T> &list)
00362 {
00363   /* Only copy if different objects. */
00364   if (&list != this)
00365     {
00366       Clear ();
00367       Copy (list);
00368     }
00369   
00370   return *this;
00371 }
00372 
00373 
00374 template <class T>
00375 void TValListT<T>::Copy (const TValListT<T> &list)
00376 {
00377   TValListEntryT<T> *entry = NULL, *prev = NULL;
00378   TValListEntryT<T> *entry_orig = list.myFirst;
00379   
00380   myFirst = NULL;
00381   myNumElements = list.myNumElements;
00382   
00383   for (int i = 0; i < myNumElements; i++)
00384     {
00385       entry = new TValListEntryT<T>;
00386       
00387       /* Hook previous entry to this one. */
00388       if (prev)
00389         prev->next = entry;
00390       
00391       entry->prev = prev;
00392       entry->data = entry_orig->data;
00393       prev = entry;
00394       
00395       entry_orig = entry_orig->next;
00396       
00397       /* Store pointer to first entry. */
00398       if (! i)
00399         myFirst = entry;
00400     }
00401   
00402   myCurrentPtr  = myFirst;
00403   myCurrentNum  = 0;
00404   myLast = entry;
00405 }
00406 
00407 
00408 template <class T>
00409 void TValListT<T>::UpdateCurrent (int i)
00410 {
00411   int l_dist = (myNumElements - 1) - i;
00412   int c_dist = T_ABS (myCurrentNum - i);
00413   
00414   /* First better then last? */
00415   if (i <= l_dist)
00416     {
00417       /* First better than current? */
00418       if (i < c_dist)
00419         {
00420           myCurrentPtr = myFirst;
00421           myCurrentNum = 0;
00422         }
00423     }
00424   else
00425     {
00426       /* Last better than current? */
00427       if (l_dist < c_dist)
00428         {
00429           myCurrentPtr = myLast;
00430           myCurrentNum = (myNumElements - 1);
00431         }
00432     }
00433   
00434   /* Scan forward? */
00435   if (myCurrentNum < i)
00436     {
00437       for (; myCurrentNum < i; myCurrentNum++)
00438         myCurrentPtr = myCurrentPtr->next;
00439     }
00440   
00441   /* Scan backwards */
00442   if (myCurrentNum > i)
00443     {
00444       for (; myCurrentNum > i; myCurrentNum--)
00445         myCurrentPtr = myCurrentPtr->prev;
00446     }
00447 }
00448 
00449 #endif // _T_VAL_LIST_T_HH

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