include/df/list.hpp

00001 //List (DoubleLinkedList class)
00002 
00003 // new/delete are used to create data
00004 
00005 template <class DATA>
00006 class List : virtual public SystemCode {
00007   _PROTECTED_:
00008     //private data
00009     struct DataStruct {
00010       DATA Data;
00011       DataStruct *prev;
00012       DataStruct *next;
00013     };
00014     DataStruct *tail;       //begining of List (prev = NULL)
00015     DataStruct *head;       //end of list (next = NULL)
00016     DataStruct *Iterator;   //current ptr for Insert(), Delete(), etc.
00017   public:
00018     //constructor
00019     List();
00020     //dtor
00021     ~List() {
00022       Seek(0, SEEK_SET);
00023       while (Delete());
00024     }
00025     //public data
00026     uint32 Count;          //# of objects (read only)
00027     uint32 Offset;         //offset in list (read only)
00028     BOOL Eol;              //Iterator past end of list
00029     //public members
00030     //Insert()/Delete() work with pointers you provide
00031     DATA &Insert(DATA x, BOOL _inc = TRUE);
00032     DATA &Insert(DATA *x, BOOL _inc = TRUE) { return Insert(*x, _inc);}
00033     DATA &Insert();
00034     BOOL Delete();             //may fail if no more Data to delete
00035     BOOL Set(DATA x, BOOL _inc = TRUE);    //increments Iterator after set complete
00036     BOOL Set(DATA *x, BOOL _inc = TRUE) { return Set(*x, _inc);}
00037     BOOL Get(DATA &x, BOOL _inc = TRUE);    //increments Iterator after get complete
00038     BOOL Get(DATA *&x, BOOL _inc = TRUE);    //increments Iterator after get complete
00039     //stack members (DF/1.4.1)
00040     void Push(DATA x);
00041     BOOL Pop(DATA &x);
00042     //fifo buffer members (DF/1.4.1)
00043     void fifoPush(DATA x);
00044     BOOL fifoPop(DATA &x);
00045     //searching members
00046     int Find(DATA x);    //find offset of object (-1 = not found)
00047     int Find(DATA *x) { return Find(*x);}
00048     //seeking members
00049     BOOL Seek(int32 offset, int fromwhere); //SEEK_SET, SEEK_END, or SEEK_CUR
00050     //operators
00051     DATA &operator [](int);
00052     DATA &operator =(DATA);
00053 };
00054 
00055 template <class DATA>
00056 DATA &List<DATA>::operator [](int idx) {
00057   DataStruct *walk = tail;  //DF/1.3 - was starting at head!
00058   while (idx--) {  //DF/1.3 - dec was missing
00059     if (!walk) SystemCode::RaiseException(ERR_ASSERT);
00060     walk = walk->next;
00061   }
00062   if (!walk) SystemCode::RaiseException(ERR_ASSERT);
00063   return walk->Data;
00064 }
00065 
00066 template <class DATA>
00067 DATA &List<DATA>::operator =(DATA x) {
00068   if (Eol) SystemCode::RaiseException(ERR_ASSERT);
00069   Set(x, FALSE);
00070   return Iterator->Data;
00071 }
00072 
00073 //ctor
00074 template <class DATA>
00075 List<DATA>::List() {
00076   Iterator = head = tail = (DataStruct*)NULL;
00077   Eol = TRUE;
00078   Count = 0;
00079   Offset = 0;
00080 }
00081 
00082 //Insert DATA at Iterator
00083 template <class DATA>
00084 DATA &List<DATA>::Insert(DATA x, BOOL _inc) {
00085   DataStruct *New;
00086   New = new DataStruct;  //DF/1.3 - use new instead of - (DataStruct*)SystemCode::MemAlloc(sizeof(DataStruct));
00087   New->Data = x;
00088   if (!Count) {
00089     //create 1st block
00090     New->next = (DataStruct*)NULL;
00091     New->prev = (DataStruct*)NULL;
00092     Iterator = tail = head = New;
00093     Count = 1;
00094     if (_inc) {
00095       Offset++;
00096       Iterator = (DataStruct*)NULL;
00097       Eol = TRUE;
00098     }
00099     return New->Data;
00100   }
00101   if (Eol) {
00102     //insert object after head
00103     head->next = New;
00104     New ->prev = head;
00105     New ->next = (DataStruct*)NULL;
00106     head = Iterator = New;
00107     Eol = FALSE;  //Iterator no longer beyond head
00108     Count++;
00109     if (_inc) {
00110       Offset++;
00111       Iterator = (DataStruct*)NULL;
00112       Eol = TRUE;
00113     }
00114     return New->Data;
00115   }
00116   New->next = Iterator;
00117   if (Iterator->prev) {
00118     //patch prev DataStruct
00119     (Iterator->prev)->next = New;
00120     New->prev = Iterator->prev;
00121   } else {
00122     tail = New;  //creating block at tail
00123     New->prev = (DataStruct*)NULL;
00124   }
00125   Iterator->prev = New;  //patch Iterator.prev
00126   Iterator = New;
00127   Count++;
00128   if (_inc) {
00129     Offset++;
00130     Iterator = Iterator->next;
00131     if (!Iterator) Eol = TRUE;
00132   }
00133   return New->Data;
00134 }
00135 
00136 //Insert DATA at Iterator
00137 template <class DATA>
00138 DATA &List<DATA>::Insert() {
00139   DataStruct *New;
00140   New = new DataStruct;  //DF/1.3 - use new
00141   //  New->Data = *x;  //No init data
00142   if (!Count) {
00143     //create 1st block
00144     New->next = (DataStruct*)NULL;
00145     New->prev = (DataStruct*)NULL;
00146     tail = head = New;
00147     Count = 1;
00148     return New->Data;
00149   }
00150   if (Eol) {
00151     //insert object after head
00152     head->next = New;
00153     New ->prev = head;
00154     New ->next = (DataStruct*)NULL;
00155     head = New;
00156     Count++;
00157     return New->Data;
00158   }
00159   New->next = Iterator;
00160   if (Iterator->prev) {
00161     //patch prev DataStruct
00162     (Iterator->prev)->next = New;
00163     New->prev = Iterator->prev;
00164   } else {
00165     tail = New;  //creating block at tail
00166     New->prev = (DataStruct*)NULL;
00167   }
00168   Iterator->prev = New;  //patch Iterator.prev
00169   Iterator = New->next;
00170   Count++;
00171   return New->Data;
00172 }
00173 
00174 //Deletes DATA at Iterator
00175 template <class DATA>
00176 BOOL List<DATA>::Delete() {
00177 
00178   if (Eol) return FALSE;  //eol or no list
00179   //delete object at Iterator
00180   DataStruct *newIterator;
00181 
00182   if (Iterator->prev) {
00183     (Iterator->prev)->next = Iterator->next;
00184   } else {
00185     tail = Iterator->next;
00186   }
00187   if (Iterator->next) {
00188     newIterator = Iterator->next;
00189     (Iterator->next)->prev = Iterator->prev;
00190   } else {
00191     head = (Iterator->prev);  //update head
00192     newIterator = (DataStruct*)NULL;
00193     Eol = TRUE;
00194   }
00195 
00196   delete Iterator;  //DF/1.3 - use delete instead of - SystemCode::MemFree(Interator);
00197 
00198   Count--;
00199 #ifdef DEBUG
00200   if (!Count) Iterator = head = tail = (DataStruct*)NULL;
00201 #endif
00202   Iterator = newIterator;
00203 
00204   return TRUE;
00205 }
00206 
00207 //Sets object at Iterator and then increments Iterator
00208 template <class DATA>
00209 BOOL List<DATA>::Set(DATA x, BOOL _inc) {
00210   if (Eol) return FALSE;
00211   Iterator->Data = x;
00212   if (_inc) {
00213     Offset++;
00214     Iterator = Iterator->next;
00215     if (!Iterator) Eol = TRUE;
00216   }
00217   return TRUE;
00218 }
00219 
00220 //Gets object at Iterator and then increments Iterator
00221 template <class DATA>
00222 BOOL List<DATA>::Get(DATA &x, BOOL _inc) {
00223   if (Eol) return FALSE;
00224   x = Iterator->Data;
00225   if (_inc) {
00226     Offset++;
00227     Iterator = Iterator->next;
00228     if (!Iterator) Eol = TRUE;
00229   }
00230   return TRUE;
00231 }
00232 
00233 //Gets object at Iterator and then increments Iterator
00234 template <class DATA>
00235 BOOL List<DATA>::Get(DATA *&x, BOOL _inc) {
00236   if (Eol) return FALSE;
00237   x = &(Iterator->Data);
00238   if (_inc) {
00239     Offset++;
00240     Iterator = Iterator->next;
00241     if (!Iterator) Eol = TRUE;
00242   }
00243   return TRUE;
00244 }
00245 
00246 //Seek thru list (fast!)
00247 template <class DATA>
00248 BOOL List<DATA>::Seek(int32 offset, int fromwhere) {
00249   // fromwhere = SEEK_SET, SEEK_END, or SEEK_CUR
00250   // check 1st if list is empty
00251   if (!Count) {
00252     Eol = TRUE;
00253     Iterator = (DataStruct *)NULL;
00254     return FALSE;
00255   }
00256   uint32 newOffset;
00257   switch (fromwhere) {
00258     case SEEK_SET:
00259       if (offset < 0) offset = 0;
00260       if (offset > Count) offset = Count;
00261       newOffset = offset;
00262       if (Offset == newOffset) return !Eol;
00263       if ((Offset + 1) == newOffset) {
00264         Offset++;
00265         Iterator = Iterator->next;
00266         if (!Iterator) Eol = TRUE;
00267         return !Eol;
00268       }
00269       break;
00270     case SEEK_END:
00271       if (offset > 0) offset = 0;
00272       offset *= -1;
00273       if (offset > Count) offset = Count;
00274       newOffset = Count - offset;
00275       if (Offset == newOffset) return !Eol;
00276       break;
00277     case SEEK_CUR:
00278       newOffset = Offset + offset;
00279       if (newOffset < 0) newOffset = 0;
00280       if (newOffset > Count) newOffset = Count;
00281       break;
00282     default:
00283       SystemCode::RaiseException(ERR_BADARGS);
00284   }
00285 
00286   //check if it's faster to seek from either end of list
00287 /*
00288   if ((newOffset < Offset) && ((Offset / 2) > newOffset)) {
00289     //start from tail(start)
00290     Iterator = tail;
00291     Eol = FALSE;
00292     Offset = 0;
00293   } else if ((newOffset > Offset) && ((Count - newOffset) < (newOffset - Offset))) {
00294     //start from head(end)
00295     Iterator = (DataStruct *)NULL;
00296     Eol = TRUE;
00297     Offset = Count;
00298   }
00299 */
00300   if (newOffset < Offset) {
00301     //seeking in reverse direction
00302     if (!Iterator) {
00303       Iterator = head;
00304       Offset--;
00305       Eol = FALSE;
00306     }
00307     while (newOffset != Offset) {
00308       Offset--;
00309       Iterator = Iterator->prev;
00310     }
00311   } else {
00312     //seeking in forward direction
00313     while (newOffset != Offset) {
00314       Offset++;
00315       Iterator = Iterator->next;
00316     }
00317     if (!Iterator) Eol = TRUE;
00318   }
00319   return !Eol;   //stopped seeking on an object?
00320 }
00321 
00322 template <class DATA>
00323 int List<DATA>::Find(DATA x) {
00324   //find offset of object (-1 = not found)
00325   int offset = 0;
00326   DataStruct *walk = tail;
00327   while (walk) {
00328     if ((walk->Data) == x) return offset;
00329     offset++;
00330     walk = walk->next;
00331   }
00332   return (-1);  //not found
00333 }
00334 
00335 template <class DATA>
00336 void List<DATA>::Push(DATA x) {
00337   Seek(0, SEEK_END);
00338   Insert(x);
00339 }
00340 
00341 template <class DATA>
00342 BOOL List<DATA>::Pop(DATA &x) {
00343   if (!Count) return FALSE;  //nothing to pop
00344   Seek(-1, SEEK_END);
00345   x = Iterator->Data;
00346   Delete();
00347   return TRUE;
00348 }
00349 
00350 template <class DATA>
00351 void List<DATA>::fifoPush(DATA x) {
00352   Seek(0, SEEK_END);
00353   Insert(x);
00354 }
00355 
00356 template <class DATA>
00357 BOOL List<DATA>::fifoPop(DATA &x) {
00358   if (!Count) return FALSE;  //nothing to pop
00359   Seek(0, SEEK_SET);
00360   x = Iterator->Data;
00361   Delete();
00362   return TRUE;
00363 }
00364 

Generated on Mon Mar 5 09:49:14 2007 for DigiForce by  doxygen 1.4.7