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
00014 struct TListEntry
00015 {
00016
00017 TListEntry_t *prev;
00018
00019
00020 TListEntry_t *next;
00021
00022
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
00155 TListEntry_t *myFirst;
00156
00157
00158 TListEntry_t *myLast;
00159
00160
00161
00162 TListEntry_t *myCurrentPtr;
00163
00164
00165
00166 int myCurrentNum;
00167
00168
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
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
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
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
00302 if (i == (myNumElements - 1))
00303 return RemoveLast ();
00304
00305 TListEntry_t *entry;
00306 T *data;
00307
00308
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
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
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
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
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
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
00441 if (i <= l_dist)
00442 {
00443
00444 if (i < c_dist)
00445 {
00446 myCurrentPtr = myFirst;
00447 myCurrentNum = 0;
00448 }
00449 }
00450 else
00451 {
00452
00453 if (l_dist < c_dist)
00454 {
00455 myCurrentPtr = myLast;
00456 myCurrentNum = (myNumElements - 1);
00457 }
00458 }
00459
00460
00461 if (myCurrentNum < i)
00462 {
00463 for (; myCurrentNum < i; myCurrentNum++)
00464 myCurrentPtr = myCurrentPtr->next;
00465 }
00466
00467
00468 if (myCurrentNum > i)
00469 {
00470 for (; myCurrentNum > i; myCurrentNum--)
00471 myCurrentPtr = myCurrentPtr->prev;
00472 }
00473 }
00474
00475 #endif // _T_PTR_LIST_T_HH