linked_lists.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_LINKED_LISTS_H
00033 #define LL_LINKED_LISTS_H
00034 
00042 #include "llerror.h"
00043 
00044 
00045 template <class DATA_TYPE> class LLLinkedList
00046 {
00047 public:
00048         friend class LLLinkNode;
00049         // External interface
00050 
00051         // basic constructor
00052         LLLinkedList() : mHead(NULL), mCurrentp(NULL), mInsertBefore(NULL)
00053         {
00054                 mCurrentp = mHead.mNextp;
00055                 mCurrentOperatingp = mHead.mNextp;
00056                 mCount = 0;
00057         }
00058 
00059         // basic constructor
00060         LLLinkedList(BOOL       (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested)) : mHead(NULL), mCurrentp(NULL), mInsertBefore(insert_before)
00061         {
00062                 mCurrentp = mHead.mNextp;
00063                 mCurrentOperatingp = mHead.mNextp;
00064                 mCount = 0;
00065         }
00066 
00067         // destructor destroys list and nodes, but not data in nodes
00068         ~LLLinkedList()
00069         {
00070                 removeAllNodes();
00071         }
00072 
00073         // set mInsertBefore
00074         void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested))
00075         {
00076                 mInsertBefore = insert_before;
00077         }
00078 
00079         //
00080         // WARNING!!!!!!!
00081         // addData and addDataSorted are NOT O(1) operations, but O(n) because they check
00082         // for existence of the data in the linked list first.  Why, I don't know - djs
00083         // If you don't care about dupes, use addDataNoCheck
00084         //
00085 
00086         // put data into a node and stick it at the front of the list
00087         inline BOOL addData(DATA_TYPE *data);
00088 
00089         // put data into a node and sort into list by mInsertBefore()
00090         // calls normal add if mInsertBefore isn't set
00091         inline BOOL addDataSorted(DATA_TYPE *data);
00092 
00093         inline BOOL addDataNoCheck(DATA_TYPE *data);
00094 
00095         // bubbleSortList
00096         // does an improved bubble sort of the list . . . works best with almost sorted data
00097         // does nothing if mInsertBefore isn't set
00098         // Nota Bene: Swaps are accomplished by swapping data pointers
00099         inline void bubbleSortList();
00100 
00101         // put data into a node and stick it at the end of the list
00102         inline BOOL addDataAtEnd(DATA_TYPE *data);
00103 
00104         // returns number of items in the list
00105         inline S32 getLength() const;
00106 
00107         inline BOOL isEmpty();
00108 
00109         // search the list starting at mHead.mNextp and remove the link with mDatap == data
00110         // leave mCurrentp and mCurrentOperatingp on the next entry
00111         // return TRUE if found, FALSE if not found
00112         inline BOOL removeData(DATA_TYPE *data);
00113 
00114                 // search the list starting at mHead.mNextp and delete the link with mDatap == data
00115         // leave mCurrentp and mCurrentOperatingp on the next entry
00116         // return TRUE if found, FALSE if not found
00117         inline BOOL deleteData(DATA_TYPE *data);
00118 
00119         // remove all nodes from the list and delete the associated data
00120         inline void deleteAllData();
00121 
00122         // remove all nodes from the list but do not delete data
00123         inline void removeAllNodes();
00124 
00125         // check to see if data is in list
00126         // if TRUE then mCurrentp and mCurrentOperatingp point to data
00127         inline BOOL     checkData(DATA_TYPE *data);
00128 
00129         // place mCurrentp on first node
00130         inline void resetList();
00131 
00132         // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00133         inline DATA_TYPE        *getCurrentData();
00134 
00135         // same as getCurrentData() but a more intuitive name for the operation
00136         inline DATA_TYPE        *getNextData();
00137 
00138         // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00139         inline DATA_TYPE        *getFirstData();
00140 
00141         // reset the list and return the data at position n, set mCurentOperatingp to that node and bump mCurrentp
00142         // Note: n is zero-based
00143         inline DATA_TYPE        *getNthData( U32 n);
00144 
00145         // reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
00146         inline DATA_TYPE        *getLastData();
00147 
00148         // remove the Node at mCurentOperatingp
00149         // leave mCurrentp and mCurentOperatingp on the next entry
00150         inline void removeCurrentData();
00151 
00152         // remove the Node at mCurentOperatingp and add it to newlist
00153         // leave mCurrentp and mCurentOperatingp on the next entry
00154         void moveCurrentData(LLLinkedList *newlist, BOOL b_sort);
00155 
00156         BOOL moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort);
00157 
00158         // delete the Node at mCurentOperatingp
00159         // leave mCurrentp anf mCurentOperatingp on the next entry
00160         void deleteCurrentData();
00161 
00162 private:
00163         // node that actually contains the data
00164         class LLLinkNode
00165         {
00166         public:
00167                 // assign the mDatap pointer
00168                 LLLinkNode(DATA_TYPE *data) : mDatap(data), mNextp(NULL), mPrevpp(NULL)
00169                 {
00170                 }
00171 
00172                 // destructor does not, by default, destroy associated data
00173                 // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
00174                 ~LLLinkNode()
00175                 {
00176                         if (mDatap)
00177                         {
00178                                 llerror("Attempting to call LLLinkNode destructor with a non-null mDatap!", 1);
00179                         }
00180                 }
00181 
00182                 // delete associated data and NULL out pointer
00183                 void deleteData()
00184                 {
00185                         delete mDatap;
00186                         mDatap = NULL;
00187                 }
00188 
00189                 // NULL out pointer
00190                 void removeData()
00191                 {
00192                         mDatap = NULL;
00193                 }
00194 
00195                 DATA_TYPE       *mDatap;
00196                 LLLinkNode      *mNextp;
00197                 LLLinkNode      **mPrevpp;
00198         };
00199 
00200         // add a node at the front of the list
00201         void addData(LLLinkNode *node)
00202         {
00203                 // don't allow NULL to be passed to addData
00204                 if (!node)
00205                 {
00206                         llerror("NULL pointer passed to LLLinkedList::addData", 0);
00207                 }
00208 
00209                 // add the node to the front of the list
00210                 node->mPrevpp = &mHead.mNextp;
00211                 node->mNextp = mHead.mNextp;
00212 
00213                 // if there's something in the list, fix its back pointer
00214                 if (node->mNextp)
00215                 {
00216                         node->mNextp->mPrevpp = &node->mNextp;
00217                 }
00218 
00219                 mHead.mNextp = node;
00220         }
00221 
00222         LLLinkNode                      mHead;                                                                                                                  // fake head node. . . makes pointer operations faster and easier
00223         LLLinkNode                      *mCurrentp;                                                                                                             // mCurrentp is the Node that getCurrentData returns
00224         LLLinkNode                      *mCurrentOperatingp;                                                                                    // this is the node that the various mumbleCurrentData functions act on
00225         BOOL                            (*mInsertBefore)(DATA_TYPE *data_new, DATA_TYPE *data_tested);  // user function set to allow sorted lists
00226         U32                                     mCount;
00227 };
00228 
00229 template <class DATA_TYPE>
00230 BOOL LLLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
00231 {
00232         // don't allow NULL to be passed to addData
00233         if (!data)
00234         {
00235                 llerror("NULL pointer passed to LLLinkedList::addData", 0);
00236         }
00237 
00238         LLLinkNode *tcurr = mCurrentp;
00239         LLLinkNode *tcurrop = mCurrentOperatingp;
00240 
00241         if ( checkData(data))
00242         {
00243                 mCurrentp = tcurr;
00244                 mCurrentOperatingp = tcurrop;
00245                 return FALSE;
00246         }
00247 
00248         // make the new node
00249         LLLinkNode *temp = new LLLinkNode(data);
00250 
00251         // add the node to the front of the list
00252         temp->mPrevpp = &mHead.mNextp;
00253         temp->mNextp = mHead.mNextp;
00254 
00255         // if there's something in the list, fix its back pointer
00256         if (temp->mNextp)
00257         {
00258                 temp->mNextp->mPrevpp = &temp->mNextp;
00259         }
00260 
00261         mHead.mNextp = temp;
00262         mCurrentp = tcurr;
00263         mCurrentOperatingp = tcurrop;
00264         mCount++;
00265         return TRUE;
00266 }
00267 
00268 
00269 template <class DATA_TYPE>
00270 BOOL LLLinkedList<DATA_TYPE>::addDataNoCheck(DATA_TYPE *data)
00271 {
00272         // don't allow NULL to be passed to addData
00273         if (!data)
00274         {
00275                 llerror("NULL pointer passed to LLLinkedList::addData", 0);
00276         }
00277 
00278         LLLinkNode *tcurr = mCurrentp;
00279         LLLinkNode *tcurrop = mCurrentOperatingp;
00280 
00281         // make the new node
00282         LLLinkNode *temp = new LLLinkNode(data);
00283 
00284         // add the node to the front of the list
00285         temp->mPrevpp = &mHead.mNextp;
00286         temp->mNextp = mHead.mNextp;
00287 
00288         // if there's something in the list, fix its back pointer
00289         if (temp->mNextp)
00290         {
00291                 temp->mNextp->mPrevpp = &temp->mNextp;
00292         }
00293 
00294         mHead.mNextp = temp;
00295         mCurrentp = tcurr;
00296         mCurrentOperatingp = tcurrop;
00297         mCount++;
00298         return TRUE;
00299 }
00300 
00301 
00302 template <class DATA_TYPE>
00303 BOOL LLLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *data)
00304 {
00305         LLLinkNode *tcurr = mCurrentp;
00306         LLLinkNode *tcurrop = mCurrentOperatingp;
00307         // don't allow NULL to be passed to addData
00308         if (!data)
00309         {
00310                 llerror("NULL pointer passed to LLLinkedList::addDataSorted", 0);
00311         }
00312 
00313         if (checkData(data))
00314         {
00315                 // restore
00316                 mCurrentp = tcurr;
00317                 mCurrentOperatingp = tcurrop;
00318                 return FALSE;
00319         }
00320 
00321         // mInsertBefore not set?
00322         if (!mInsertBefore)
00323         {
00324                 addData(data);
00325                 // restore
00326                 mCurrentp = tcurr;
00327                 mCurrentOperatingp = tcurrop;
00328                 return FALSE;
00329         }
00330 
00331         // empty list?
00332         if (!mHead.mNextp)
00333         {
00334                 addData(data);
00335                 // restore
00336                 mCurrentp = tcurr;
00337                 mCurrentOperatingp = tcurrop;
00338                 return TRUE;
00339         }
00340 
00341         // make the new node
00342         LLLinkNode *temp = new LLLinkNode(data);
00343 
00344         // walk the list until mInsertBefore returns true 
00345         mCurrentp = mHead.mNextp;
00346         while (mCurrentp->mNextp)
00347         {
00348                 if (mInsertBefore(data, mCurrentp->mDatap))
00349                 {
00350                         // insert before the current one
00351                         temp->mPrevpp = mCurrentp->mPrevpp;
00352                         temp->mNextp = mCurrentp;
00353                         *(temp->mPrevpp) = temp;
00354                         mCurrentp->mPrevpp = &temp->mNextp;
00355                         // restore
00356                         mCurrentp = tcurr;
00357                         mCurrentOperatingp = tcurrop;
00358                         mCount++;
00359                         return TRUE;
00360                 }
00361                 else
00362                 {
00363                         mCurrentp = mCurrentp->mNextp;
00364                 }
00365         }
00366 
00367         // on the last element, add before?
00368         if (mInsertBefore(data, mCurrentp->mDatap))
00369         {
00370                 // insert before the current one
00371                 temp->mPrevpp = mCurrentp->mPrevpp;
00372                 temp->mNextp = mCurrentp;
00373                 *(temp->mPrevpp) = temp;
00374                 mCurrentp->mPrevpp = &temp->mNextp;
00375                 // restore
00376                 mCurrentp = tcurr;
00377                 mCurrentOperatingp = tcurrop;
00378         }
00379         else // insert after
00380         {
00381                 temp->mPrevpp = &mCurrentp->mNextp;
00382                 temp->mNextp = NULL;
00383                 mCurrentp->mNextp = temp;
00384 
00385                 // restore
00386                 mCurrentp = tcurr;
00387                 mCurrentOperatingp = tcurrop;
00388         }
00389         mCount++;
00390         return TRUE;
00391 }
00392 
00393 template <class DATA_TYPE>
00394 void LLLinkedList<DATA_TYPE>::bubbleSortList()
00395 {
00396         // mInsertBefore not set
00397         if (!mInsertBefore)
00398         {
00399                 return;
00400         }
00401 
00402         LLLinkNode *tcurr = mCurrentp;
00403         LLLinkNode *tcurrop = mCurrentOperatingp;
00404 
00405         BOOL            b_swapped = FALSE;
00406         DATA_TYPE       *temp;
00407 
00408         // Nota Bene: This will break if more than 0x7FFFFFFF members in list!
00409         S32                     length = 0x7FFFFFFF;
00410         S32                     count = 0;
00411         do
00412         {
00413                 b_swapped = FALSE;
00414                 mCurrentp = mHead.mNextp;
00415                 count = 0;
00416                 while (  (count + 1 < length)
00417                            &&(mCurrentp))
00418                 {
00419                         if (mCurrentp->mNextp)
00420                         {
00421                                 if (!mInsertBefore(mCurrentp->mDatap, mCurrentp->mNextp->mDatap))
00422                                 {
00423                                         // swap data pointers!
00424                                         temp = mCurrentp->mDatap;
00425                                         mCurrentp->mDatap = mCurrentp->mNextp->mDatap;
00426                                         mCurrentp->mNextp->mDatap = temp;
00427                                         b_swapped = TRUE;
00428                                 }
00429                         }
00430                         else
00431                         {
00432                                 break;
00433                         }
00434                         count++;
00435                         mCurrentp = mCurrentp->mNextp;
00436                 }
00437                 length = count;
00438         } while (b_swapped);
00439 
00440         // restore
00441         mCurrentp = tcurr;
00442         mCurrentOperatingp = tcurrop;
00443 }
00444 
00445 
00446 template <class DATA_TYPE>
00447 BOOL LLLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
00448 {
00449         LLLinkNode *tcurr = mCurrentp;
00450         LLLinkNode *tcurrop = mCurrentOperatingp;
00451 
00452         // don't allow NULL to be passed to addData
00453         if (!data)
00454         {
00455                 llerror("NULL pointer passed to LLLinkedList::addData", 0);
00456         }
00457 
00458         if (checkData(data))
00459         {
00460                 mCurrentp = tcurr;
00461                 mCurrentOperatingp = tcurrop;
00462                 return FALSE;
00463         }
00464 
00465         // make the new node
00466         LLLinkNode *temp = new LLLinkNode(data);
00467 
00468         // add the node to the end of the list
00469 
00470         // if empty, add to the front and be done with it
00471         if (!mHead.mNextp)
00472         {
00473                 temp->mPrevpp = &mHead.mNextp;
00474                 temp->mNextp = NULL;
00475                 mHead.mNextp = temp;
00476         }
00477         else
00478         {
00479                 // otherwise, walk to the end of the list
00480                 mCurrentp = mHead.mNextp;
00481                 while (mCurrentp->mNextp)
00482                 {
00483                         mCurrentp = mCurrentp->mNextp;
00484                 }
00485                 temp->mPrevpp = &mCurrentp->mNextp;
00486                 temp->mNextp = NULL;
00487                 mCurrentp->mNextp = temp;
00488         }
00489 
00490         // restore
00491         mCurrentp = tcurr;
00492         mCurrentOperatingp = tcurrop;
00493         mCount++;
00494         return TRUE;
00495 }
00496 
00497 
00498 // returns number of items in the list
00499 template <class DATA_TYPE>
00500 S32 LLLinkedList<DATA_TYPE>::getLength() const
00501 {
00502 //      S32     length = 0;
00503 //      for (LLLinkNode* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
00504 //      {
00505 //              length++;
00506 //      }
00507         return mCount;
00508 }
00509 
00510 
00511 template <class DATA_TYPE>
00512 BOOL LLLinkedList<DATA_TYPE>::isEmpty()
00513 {
00514         return (mCount == 0);
00515 }
00516 
00517 
00518 // search the list starting at mHead.mNextp and remove the link with mDatap == data
00519 // leave mCurrentp and mCurrentOperatingp on the next entry
00520 // return TRUE if found, FALSE if not found
00521 template <class DATA_TYPE>
00522 BOOL LLLinkedList<DATA_TYPE>::removeData(DATA_TYPE *data)
00523 {
00524         BOOL b_found = FALSE;
00525         // don't allow NULL to be passed to addData
00526         if (!data)
00527         {
00528                 llerror("NULL pointer passed to LLLinkedList::removeData", 0);
00529         }
00530 
00531         LLLinkNode *tcurr = mCurrentp;
00532         LLLinkNode *tcurrop = mCurrentOperatingp;
00533 
00534         mCurrentp = mHead.mNextp;
00535         mCurrentOperatingp = mHead.mNextp;
00536 
00537         while (mCurrentOperatingp)
00538         {
00539                 if (mCurrentOperatingp->mDatap == data)
00540                 {
00541                         b_found = TRUE;
00542 
00543                         // remove the node
00544 
00545                         // if there is a next one, fix it
00546                         if (mCurrentOperatingp->mNextp)
00547                         {
00548                                 mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00549                         }
00550                         *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00551 
00552                         // remove the LLLinkNode
00553 
00554                         // if we were on the one we want to delete, bump the cached copies
00555                         if (mCurrentOperatingp == tcurrop)
00556                         {
00557                                 tcurrop = tcurr = mCurrentOperatingp->mNextp;
00558                         }
00559                         else if (mCurrentOperatingp == tcurr)
00560                         {
00561                                 tcurrop = tcurr = mCurrentOperatingp->mNextp;
00562                         }
00563 
00564                         mCurrentp = mCurrentOperatingp->mNextp;
00565 
00566                         mCurrentOperatingp->removeData();
00567                         delete mCurrentOperatingp;
00568                         mCurrentOperatingp = mCurrentp;
00569                         mCount--;
00570                         break;
00571                 }
00572                 mCurrentOperatingp = mCurrentOperatingp->mNextp;
00573         }
00574         // restore
00575         mCurrentp = tcurr;
00576         mCurrentOperatingp = tcurrop;
00577         return b_found;
00578 }
00579 
00580 // search the list starting at mHead.mNextp and delete the link with mDatap == data
00581 // leave mCurrentp and mCurrentOperatingp on the next entry
00582 // return TRUE if found, FALSE if not found
00583 template <class DATA_TYPE>
00584 BOOL LLLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
00585 {
00586         BOOL b_found = FALSE;
00587         // don't allow NULL to be passed to addData
00588         if (!data)
00589         {
00590                 llerror("NULL pointer passed to LLLinkedList::removeData", 0);
00591         }
00592 
00593         LLLinkNode *tcurr = mCurrentp;
00594         LLLinkNode *tcurrop = mCurrentOperatingp;
00595 
00596         mCurrentp = mHead.mNextp;
00597         mCurrentOperatingp = mHead.mNextp;
00598 
00599         while (mCurrentOperatingp)
00600         {
00601                 if (mCurrentOperatingp->mDatap == data)
00602                 {
00603                         b_found = TRUE;
00604 
00605                         // remove the node
00606                         // if there is a next one, fix it
00607                         if (mCurrentOperatingp->mNextp)
00608                         {
00609                                 mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00610                         }
00611                         *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00612 
00613                         // delete the LLLinkNode
00614                         // if we were on the one we want to delete, bump the cached copies
00615                         if (mCurrentOperatingp == tcurrop)
00616                         {
00617                                 tcurrop = tcurr = mCurrentOperatingp->mNextp;
00618                         }
00619 
00620                         // and delete the associated data
00621                         llassert(mCurrentOperatingp);
00622                         mCurrentp = mCurrentOperatingp->mNextp;
00623                         mCurrentOperatingp->deleteData();
00624                         delete mCurrentOperatingp;
00625                         mCurrentOperatingp = mCurrentp;
00626                         mCount--;
00627                         break;
00628                 }
00629                 mCurrentOperatingp = mCurrentOperatingp->mNextp;
00630         }
00631         // restore
00632         mCurrentp = tcurr;
00633         mCurrentOperatingp = tcurrop;
00634         return b_found;
00635 }
00636 
00637         // remove all nodes from the list and delete the associated data
00638 template <class DATA_TYPE>
00639 void LLLinkedList<DATA_TYPE>::deleteAllData()
00640 {
00641         LLLinkNode *temp;
00642         // reset mCurrentp
00643         mCurrentp = mHead.mNextp;
00644 
00645         while (mCurrentp)
00646         {
00647                 temp = mCurrentp->mNextp;
00648                 mCurrentp->deleteData();
00649                 delete mCurrentp;
00650                 mCurrentp = temp;
00651         }
00652 
00653         // reset mHead and mCurrentp
00654         mHead.mNextp = NULL;
00655         mCurrentp = mHead.mNextp;
00656         mCurrentOperatingp = mHead.mNextp;
00657         mCount = 0;
00658 }
00659 
00660 // remove all nodes from the list but do not delete data
00661 template <class DATA_TYPE>
00662 void LLLinkedList<DATA_TYPE>::removeAllNodes()
00663 {
00664         LLLinkNode *temp;
00665         // reset mCurrentp
00666         mCurrentp = mHead.mNextp;
00667 
00668         while (mCurrentp)
00669         {
00670                 temp = mCurrentp->mNextp;
00671                 mCurrentp->removeData();
00672                 delete mCurrentp;
00673                 mCurrentp = temp;
00674         }
00675 
00676         // reset mHead and mCurrentp
00677         mHead.mNextp = NULL;
00678         mCurrentp = mHead.mNextp;
00679         mCurrentOperatingp = mHead.mNextp;
00680         mCount = 0;
00681 }
00682 
00683 // check to see if data is in list
00684 // if TRUE then mCurrentp and mCurrentOperatingp point to data
00685 template <class DATA_TYPE>
00686 BOOL LLLinkedList<DATA_TYPE>::checkData(DATA_TYPE *data)
00687 {
00688         // reset mCurrentp
00689         mCurrentp = mHead.mNextp;
00690 
00691         while (mCurrentp)
00692         {
00693                 if (mCurrentp->mDatap == data)
00694                 {
00695                         mCurrentOperatingp = mCurrentp;
00696                         return TRUE;
00697                 }
00698                 mCurrentp = mCurrentp->mNextp;
00699         }
00700         mCurrentOperatingp = mCurrentp;
00701         return FALSE;
00702 }
00703 
00704 // place mCurrentp on first node
00705 template <class DATA_TYPE>
00706 void LLLinkedList<DATA_TYPE>::resetList()
00707 {
00708         mCurrentp = mHead.mNextp;
00709         mCurrentOperatingp = mHead.mNextp;
00710 }
00711 
00712 // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00713 template <class DATA_TYPE>
00714 DATA_TYPE *LLLinkedList<DATA_TYPE>::getCurrentData()
00715 {
00716         if (mCurrentp)
00717         {
00718                 mCurrentOperatingp = mCurrentp;
00719                 mCurrentp = mCurrentp->mNextp;
00720                 return mCurrentOperatingp->mDatap;
00721         }
00722         else
00723         {
00724                 return NULL;
00725         }
00726 }
00727 
00728 // same as getCurrentData() but a more intuitive name for the operation
00729 template <class DATA_TYPE>
00730 DATA_TYPE *LLLinkedList<DATA_TYPE>::getNextData()
00731 {
00732         if (mCurrentp)
00733         {
00734                 mCurrentOperatingp = mCurrentp;
00735                 mCurrentp = mCurrentp->mNextp;
00736                 return mCurrentOperatingp->mDatap;
00737         }
00738         else
00739         {
00740                 return NULL;
00741         }
00742 }
00743 
00744 // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
00745 template <class DATA_TYPE>
00746 DATA_TYPE *LLLinkedList<DATA_TYPE>::getFirstData()
00747 {
00748         mCurrentp = mHead.mNextp;
00749         mCurrentOperatingp = mHead.mNextp;
00750         if (mCurrentp)
00751         {
00752                 mCurrentOperatingp = mCurrentp;
00753                 mCurrentp = mCurrentp->mNextp;
00754                 return mCurrentOperatingp->mDatap;
00755         }
00756         else
00757         {
00758                 return NULL;
00759         }
00760 }
00761 
00762 // Note: n is zero-based
00763 template <class DATA_TYPE>
00764 DATA_TYPE       *LLLinkedList<DATA_TYPE>::getNthData( U32 n )
00765 {
00766         mCurrentOperatingp = mHead.mNextp;
00767 
00768         // if empty, return NULL
00769         if (!mCurrentOperatingp)
00770         {
00771                 return NULL;
00772         }
00773 
00774         for( U32 i = 0; i < n; i++ )
00775         {
00776                 mCurrentOperatingp = mCurrentOperatingp->mNextp;
00777                 if( !mCurrentOperatingp )
00778                 {
00779                         return NULL;
00780                 }
00781         }
00782 
00783         mCurrentp = mCurrentOperatingp->mNextp;
00784         return mCurrentOperatingp->mDatap;
00785 }
00786 
00787 
00788 // reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
00789 template <class DATA_TYPE>
00790 DATA_TYPE *LLLinkedList<DATA_TYPE>::getLastData()
00791 {
00792         mCurrentOperatingp = mHead.mNextp;
00793 
00794         // if empty, return NULL
00795         if (!mCurrentOperatingp)
00796                 return NULL;
00797 
00798         // walk until we're pointing at the last entry
00799         while (mCurrentOperatingp->mNextp)
00800         {
00801                 mCurrentOperatingp = mCurrentOperatingp->mNextp;
00802         }
00803         mCurrentp = mCurrentOperatingp->mNextp;
00804         return mCurrentOperatingp->mDatap;
00805 }
00806 
00807 // remove the Node at mCurentOperatingp
00808 // leave mCurrentp and mCurentOperatingp on the next entry
00809 // return TRUE if found, FALSE if not found
00810 template <class DATA_TYPE>
00811 void LLLinkedList<DATA_TYPE>::removeCurrentData()
00812 {
00813         if (mCurrentOperatingp)
00814         {
00815                 // remove the node
00816                 // if there is a next one, fix it
00817                 if (mCurrentOperatingp->mNextp)
00818                 {
00819                         mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00820                 }
00821                 *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00822 
00823                 // remove the LLLinkNode
00824                 mCurrentp = mCurrentOperatingp->mNextp;
00825 
00826                 mCurrentOperatingp->removeData();
00827                 delete mCurrentOperatingp;
00828                 mCount--;
00829                 mCurrentOperatingp = mCurrentp;
00830         }
00831 }
00832 
00833 // remove the Node at mCurentOperatingp and add it to newlist
00834 // leave mCurrentp and mCurentOperatingp on the next entry
00835 // return TRUE if found, FALSE if not found
00836 template <class DATA_TYPE>
00837 void LLLinkedList<DATA_TYPE>::moveCurrentData(LLLinkedList *newlist, BOOL b_sort)
00838 {
00839         if (mCurrentOperatingp)
00840         {
00841                 // remove the node
00842                 // if there is a next one, fix it
00843                 if (mCurrentOperatingp->mNextp)
00844                 {
00845                         mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00846                 }
00847                 *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00848 
00849                 // remove the LLLinkNode
00850                 mCurrentp = mCurrentOperatingp->mNextp;
00851                 // move the node to the new list
00852                 newlist->addData(mCurrentOperatingp);
00853                 if (b_sort)
00854                         bubbleSortList();
00855                 mCurrentOperatingp = mCurrentp;
00856         }
00857 }
00858 
00859 template <class DATA_TYPE>
00860 BOOL LLLinkedList<DATA_TYPE>::moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort)
00861 {
00862         BOOL b_found = FALSE;
00863         // don't allow NULL to be passed to addData
00864         if (!data)
00865         {
00866                 llerror("NULL pointer passed to LLLinkedList::removeData", 0);
00867         }
00868 
00869         LLLinkNode *tcurr = mCurrentp;
00870         LLLinkNode *tcurrop = mCurrentOperatingp;
00871 
00872         mCurrentp = mHead.mNextp;
00873         mCurrentOperatingp = mHead.mNextp;
00874 
00875         while (mCurrentOperatingp)
00876         {
00877                 if (mCurrentOperatingp->mDatap == data)
00878                 {
00879                         b_found = TRUE;
00880 
00881                         // remove the node
00882 
00883                         // if there is a next one, fix it
00884                         if (mCurrentOperatingp->mNextp)
00885                         {
00886                                 mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00887                         }
00888                         *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00889 
00890                         // if we were on the one we want to delete, bump the cached copies
00891                         if (  (mCurrentOperatingp == tcurrop)
00892                                 ||(mCurrentOperatingp == tcurr))
00893                         {
00894                                 tcurrop = tcurr = mCurrentOperatingp->mNextp;
00895                         }
00896 
00897                         // remove the LLLinkNode
00898                         mCurrentp = mCurrentOperatingp->mNextp;
00899                         // move the node to the new list
00900                         newlist->addData(mCurrentOperatingp);
00901                         if (b_sort)
00902                                 newlist->bubbleSortList();
00903                         mCurrentOperatingp = mCurrentp;
00904                         break;
00905                 }
00906                 mCurrentOperatingp = mCurrentOperatingp->mNextp;
00907         }
00908         // restore
00909         mCurrentp = tcurr;
00910         mCurrentOperatingp = tcurrop;
00911         return b_found;
00912 }
00913 
00914 // delete the Node at mCurentOperatingp
00915 // leave mCurrentp anf mCurentOperatingp on the next entry
00916 // return TRUE if found, FALSE if not found
00917 template <class DATA_TYPE>
00918 void LLLinkedList<DATA_TYPE>::deleteCurrentData()
00919 {
00920         if (mCurrentOperatingp)
00921         {
00922                 // remove the node
00923                 // if there is a next one, fix it
00924                 if (mCurrentOperatingp->mNextp)
00925                 {
00926                         mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
00927                 }
00928                 *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
00929 
00930                 // remove the LLLinkNode
00931                 mCurrentp = mCurrentOperatingp->mNextp;
00932 
00933                 mCurrentOperatingp->deleteData();
00934                 if (mCurrentOperatingp->mDatap)
00935                         llerror("This is impossible!", 0);
00936                 delete mCurrentOperatingp;
00937                 mCurrentOperatingp = mCurrentp;
00938                 mCount--;
00939         }
00940 }
00941 
00942 #endif

Generated on Thu Jul 1 06:08:17 2010 for Second Life Viewer by  doxygen 1.4.7