doublelinkedlist.h

Go to the documentation of this file.
00001 
00032 #ifndef LL_DOUBLELINKEDLIST_H
00033 #define LL_DOUBLELINKEDLIST_H
00034 
00035 #include "llerror.h"
00036 #include "llrand.h"
00037 
00038 // node that actually contains the data
00039 template <class DATA_TYPE> class LLDoubleLinkedNode
00040 {
00041 public:
00042         DATA_TYPE                       *mDatap;
00043         LLDoubleLinkedNode      *mNextp;
00044         LLDoubleLinkedNode      *mPrevp;
00045 
00046 
00047 public:
00048         // assign the mDatap pointer
00049         LLDoubleLinkedNode(DATA_TYPE *data);
00050 
00051         // destructor does not, by default, destroy associated data
00052         // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
00053         ~LLDoubleLinkedNode();
00054 
00055         // delete associated data and NULL out pointer
00056         void deleteData();
00057 
00058         // remove associated data and NULL out pointer
00059         void removeData();
00060 };
00061 
00062 
00063 const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
00064 
00065 template <class DATA_TYPE> class LLDoubleLinkedList
00066 {
00067 private:
00068         LLDoubleLinkedNode<DATA_TYPE> mHead;            // head node
00069         LLDoubleLinkedNode<DATA_TYPE> mTail;            // tail node
00070         LLDoubleLinkedNode<DATA_TYPE> *mQueuep;         // The node in the batter's box
00071         LLDoubleLinkedNode<DATA_TYPE> *mCurrentp;       // The node we're talking about
00072 
00073         // The state stack allows nested exploration of the LLDoubleLinkedList
00074         // but should be used with great care
00075         LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
00076         LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
00077         U32 mStateStackDepth;
00078         U32     mCount;
00079 
00080         // mInsertBefore is a pointer to a user-set function that returns 
00081         // TRUE if "first" should be located before "second"
00082         // NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
00083         // or never-ending loops can occur
00084         BOOL                            (*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);  
00085                                                                                                                                                                 
00086 public:
00087         LLDoubleLinkedList();
00088 
00089         // destructor destroys list and nodes, but not data in nodes
00090         ~LLDoubleLinkedList();
00091 
00092         // put data into a node and stick it at the front of the list
00093         // set mCurrentp to mQueuep
00094         void addData(DATA_TYPE *data);
00095 
00096         // put data into a node and stick it at the end of the list
00097         // set mCurrentp to mQueuep
00098         void addDataAtEnd(DATA_TYPE *data);
00099 
00100         S32 getLength() const;
00101         // search the list starting at mHead.mNextp and remove the link with mDatap == data
00102         // set mCurrentp to mQueuep
00103         // return TRUE if found, FALSE if not found
00104         BOOL removeData(const DATA_TYPE *data);
00105 
00106         // search the list starting at mHead.mNextp and delete the link with mDatap == data
00107         // set mCurrentp to mQueuep
00108         // return TRUE if found, FALSE if not found
00109         BOOL deleteData(DATA_TYPE *data);
00110 
00111         // remove all nodes from the list and delete the associated data
00112         void deleteAllData();
00113 
00114         // remove all nodes from the list but do not delete data
00115         void removeAllNodes();
00116 
00117         BOOL isEmpty();
00118 
00119         // check to see if data is in list
00120         // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
00121         // return TRUE if found, FALSE if not found
00122         BOOL    checkData(const DATA_TYPE *data);
00123 
00124         // NOTE: This next two funtions are only included here 
00125         // for those too familiar with the LLLinkedList template class.
00126         // They are depreciated.  resetList() is unecessary while 
00127         // getCurrentData() is identical to getNextData() and has
00128         // a misleading name.
00129         //
00130         // The recommended way to loop through a list is as follows:
00131         //
00132         // datap = list.getFirstData();
00133         // while (datap)
00134         // {
00135         //     /* do stuff */
00136         //     datap = list.getNextData();
00137         // }
00138 
00139                 // place mQueuep on mHead node
00140                 void resetList();
00141         
00142                 // return the data currently pointed to, 
00143                 // set mCurrentp to that node and bump mQueuep down the list
00144                 // NOTE: this function is identical to getNextData()
00145                 DATA_TYPE *getCurrentData();
00146 
00147 
00148         // reset the list and return the data currently pointed to, 
00149         // set mCurrentp to that node and bump mQueuep down the list
00150         DATA_TYPE *getFirstData();
00151 
00152 
00153         // reset the list and return the data at position n, set mCurentp 
00154         // to that node and bump mQueuep down the list
00155         // Note: n=0 will behave like getFirstData()
00156         DATA_TYPE *getNthData(U32 n);
00157 
00158         // reset the list and return the last data in it, 
00159         // set mCurrentp to that node and bump mQueuep up the list
00160         DATA_TYPE *getLastData();
00161 
00162         // return data in mQueuep,
00163         // set mCurrentp mQueuep and bump mQueuep down the list
00164         DATA_TYPE *getNextData();
00165 
00166         // return the data in mQueuep, 
00167         // set mCurrentp to mQueuep and bump mQueuep up the list
00168         DATA_TYPE *getPreviousData();
00169 
00170         // remove the Node at mCurrentp
00171         // set mCurrentp to mQueuep
00172         void removeCurrentData();
00173 
00174         // delete the Node at mCurrentp
00175         // set mCurrentp to mQueuep
00176         void deleteCurrentData();
00177 
00178         // remove the Node at mCurrentp and insert it into newlist
00179         // set mCurrentp to mQueuep
00180         void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
00181 
00182         // insert the node in front of mCurrentp
00183         // set mCurrentp to mQueuep
00184         void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
00185 
00186         // insert the data in front of mCurrentp
00187         // set mCurrentp to mQueuep
00188         void insertData(DATA_TYPE *data);
00189 
00190         // if mCurrentp has a previous node then :
00191         //   * swaps mCurrentp with its previous
00192         //   * set mCurrentp to mQueuep
00193         //     (convenient for forward bubble-sort)
00194         // otherwise does nothing
00195         void swapCurrentWithPrevious();
00196 
00197         // if mCurrentp has a next node then :
00198         //   * swaps mCurrentp with its next
00199         //   * set mCurrentp to mQueuep
00200         //     (convenient for backwards bubble-sort)
00201         // otherwise does nothing
00202         void swapCurrentWithNext();
00203 
00204         // move mCurrentp to the front of the list
00205         // set mCurrentp to mQueuep
00206         void moveCurrentToFront();
00207         
00208         // move mCurrentp to the end of the list
00209         // set mCurrentp to mQueuep
00210         void moveCurrentToEnd();
00211 
00212         // set mInsertBefore
00213         void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
00214 
00215         // add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
00216         // set mCurrentp to mQueuep
00217         BOOL addDataSorted(DATA_TYPE *datap);
00218 
00219         // sort the list using bubble-sort
00220         // Yes, this is a different name than the same function in LLLinkedList.
00221         // When it comes time for a name consolidation hopefully this one will win.
00222         BOOL bubbleSort();
00223 
00224         // does a single bubble sort pass on the list
00225         BOOL lazyBubbleSort();
00226 
00227         // returns TRUE if state successfully pushed (state stack not full)
00228         BOOL pushState();
00229 
00230         // returns TRUE if state successfully popped (state stack not empty)
00231         BOOL popState();
00232 
00233         // empties the state stack
00234         void clearStateStack();
00235 
00236         // randomly move the the links in the list for debug or (Discordian) purposes
00237         // sets mCurrentp and mQueuep to top of list
00238         void scramble();
00239 
00240 private:
00241         // add node to beginning of list
00242         // set mCurrentp to mQueuep
00243         void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
00244 
00245         // add node to end of list
00246         // set mCurrentp to mQueuep
00247         void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
00248 };
00249 
00250 //#endif
00251 
00253 
00254 // doublelinkedlist.cpp
00255 // LLDoubleLinkedList template class implementation file.
00256 // Provides a standard doubly linked list for fun and profit.
00257 // 
00258 // Copyright 2001, Linden Research, Inc.
00259 
00260 //#include "llerror.h"
00261 //#include "doublelinkedlist.h"
00262 
00264 // LLDoubleLinkedNode
00266 
00267 
00268 // assign the mDatap pointer
00269 template <class DATA_TYPE>
00270 LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) : 
00271         mDatap(data), mNextp(NULL), mPrevp(NULL)
00272 {
00273 }
00274 
00275 
00276 // destructor does not, by default, destroy associated data
00277 // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
00278 template <class DATA_TYPE>
00279 LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
00280 {
00281         if (mDatap)
00282         {
00283                 llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
00284         }
00285 }
00286 
00287 
00288 // delete associated data and NULL out pointer
00289 template <class DATA_TYPE>
00290 void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
00291 {
00292         delete mDatap;
00293         mDatap = NULL;
00294 }
00295 
00296 
00297 template <class DATA_TYPE>
00298 void LLDoubleLinkedNode<DATA_TYPE>::removeData()
00299 {
00300         mDatap = NULL;
00301 }
00302 
00303 
00305 // LLDoubleLinkedList
00307 
00308 //                                   <------- up -------
00309 //
00310 //                                               mCurrentp
00311 //                                   mQueuep         |
00312 //                                      |            |
00313 //                                      |            | 
00314 //                      .------.     .------.     .------.      .------.
00315 //                      |      |---->|      |---->|      |----->|      |-----> NULL
00316 //           NULL <-----|      |<----|      |<----|      |<-----|      |
00317 //                     _'------'     '------'     '------'      '------:_
00318 //             .------. /|               |             |               |\ .------.
00319 //  NULL <-----|mHead |/                 |         mQueuep               \|mTail |-----> NULL
00320 //             |      |               mCurrentp                           |      |
00321 //             '------'                                                   '------'
00322 //                               -------- down --------->
00323 
00324 template <class DATA_TYPE>
00325 LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
00326 : mHead(NULL), mTail(NULL), mQueuep(NULL)
00327 {
00328         mCurrentp = mHead.mNextp;
00329         mQueuep = mHead.mNextp;
00330         mStateStackDepth = 0;
00331         mCount = 0;
00332         mInsertBefore = NULL;
00333 }
00334 
00335 
00336 // destructor destroys list and nodes, but not data in nodes
00337 template <class DATA_TYPE>
00338 LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
00339 {
00340         removeAllNodes();
00341 }
00342 
00343 
00344 // put data into a node and stick it at the front of the list
00345 // doesn't change mCurrentp nor mQueuep
00346 template <class DATA_TYPE>
00347 void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
00348 {
00349         // don't allow NULL to be passed to addData
00350         if (!data)
00351         {
00352                 llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
00353         }
00354 
00355         // make the new node
00356         LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
00357 
00358         // add the node to the front of the list
00359         temp->mPrevp = NULL; 
00360         temp->mNextp = mHead.mNextp;
00361         mHead.mNextp = temp;
00362 
00363         // if there's something in the list, fix its back pointer
00364         if (temp->mNextp)
00365         {
00366                 temp->mNextp->mPrevp = temp;
00367         }
00368         // otherwise, fix the tail of the list
00369         else 
00370         {
00371                 mTail.mPrevp = temp;
00372         }
00373 
00374         mCount++;
00375 }
00376 
00377 
00378 // put data into a node and stick it at the end of the list
00379 template <class DATA_TYPE>
00380 void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
00381 {
00382         // don't allow NULL to be passed to addData
00383         if (!data)
00384         {
00385                 llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
00386         }
00387 
00388         // make the new node
00389         LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
00390 
00391         addNodeAtEnd(nodep);
00392         mCount++;
00393 }
00394 
00395 
00396 // search the list starting at mHead.mNextp and remove the link with mDatap == data
00397 // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
00398 // return TRUE if found, FALSE if not found
00399 template <class DATA_TYPE>
00400 BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
00401 {
00402         BOOL b_found = FALSE;
00403         // don't allow NULL to be passed to addData
00404         if (!data)
00405         {
00406                 llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
00407         }
00408 
00409         mCurrentp = mHead.mNextp;
00410 
00411         while (mCurrentp)
00412         {
00413                 if (mCurrentp->mDatap == data)
00414                 {
00415                         b_found = TRUE;
00416 
00417                         // if there is a next one, fix it
00418                         if (mCurrentp->mNextp)
00419                         {
00420                                 mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00421                         }
00422                         else // we are at end of list
00423                         {
00424                                 mTail.mPrevp = mCurrentp->mPrevp;
00425                         }
00426 
00427                         // if there is a previous one, fix it
00428                         if (mCurrentp->mPrevp)
00429                         {
00430                                 mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00431                         }
00432                         else // we are at beginning of list
00433                         {
00434                                 mHead.mNextp = mCurrentp->mNextp;
00435                         }
00436 
00437                         // remove the node
00438                         mCurrentp->removeData();
00439                         delete mCurrentp;
00440                         mCount--;
00441                         break;
00442                 }
00443                 mCurrentp = mCurrentp->mNextp; 
00444         }
00445 
00446         // reset the list back to where it was
00447         if (mCurrentp == mQueuep)
00448         {
00449                 mCurrentp = mQueuep = NULL;
00450         }
00451         else
00452         {
00453                 mCurrentp = mQueuep;
00454         }
00455 
00456         return b_found;
00457 }
00458 
00459 
00460 // search the list starting at mHead.mNextp and delete the link with mDatap == data
00461 // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
00462 // return TRUE if found, FALSE if not found
00463 template <class DATA_TYPE>
00464 BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
00465 {
00466         BOOL b_found = FALSE;
00467         // don't allow NULL to be passed to addData
00468         if (!data)
00469         {
00470                 llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
00471         }
00472 
00473         mCurrentp = mHead.mNextp;
00474 
00475         while (mCurrentp)
00476         {
00477                 if (mCurrentp->mDatap == data)
00478                 {
00479                         b_found = TRUE;
00480 
00481                         // if there is a next one, fix it
00482                         if (mCurrentp->mNextp)
00483                         {
00484                                 mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00485                         }
00486                         else // we are at end of list
00487                         {
00488                                 mTail.mPrevp = mCurrentp->mPrevp;
00489                         }
00490 
00491                         // if there is a previous one, fix it
00492                         if (mCurrentp->mPrevp)
00493                         {
00494                                 mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00495                         }
00496                         else // we are at beginning of list
00497                         {
00498                                 mHead.mNextp = mCurrentp->mNextp;
00499                         }
00500 
00501                         // remove the node
00502                         mCurrentp->deleteData();
00503                         delete mCurrentp;
00504                         mCount--;
00505                         break;
00506                 }
00507                 mCurrentp = mCurrentp->mNextp;
00508         }
00509 
00510         // reset the list back to where it was
00511         if (mCurrentp == mQueuep)
00512         {
00513                 mCurrentp = mQueuep = NULL;
00514         }
00515         else
00516         {
00517                 mCurrentp = mQueuep;
00518         }
00519 
00520         return b_found;
00521 }
00522 
00523 
00524 // remove all nodes from the list and delete the associated data
00525 template <class DATA_TYPE>
00526 void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
00527 {
00528         mCurrentp = mHead.mNextp;
00529 
00530         while (mCurrentp)
00531         {
00532                 mQueuep = mCurrentp->mNextp;
00533                 mCurrentp->deleteData();
00534                 delete mCurrentp;
00535                 mCurrentp = mQueuep;
00536         }
00537 
00538         // reset mHead and mQueuep
00539         mHead.mNextp = NULL;
00540         mTail.mPrevp = NULL;
00541         mCurrentp = mHead.mNextp;
00542         mQueuep = mHead.mNextp;
00543         mStateStackDepth = 0;
00544         mCount = 0;
00545 }
00546 
00547 
00548 // remove all nodes from the list but do not delete associated data
00549 template <class DATA_TYPE>
00550 void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
00551 {
00552         mCurrentp = mHead.mNextp;
00553 
00554         while (mCurrentp)
00555         {
00556                 mQueuep = mCurrentp->mNextp;
00557                 mCurrentp->removeData();
00558                 delete mCurrentp;
00559                 mCurrentp = mQueuep;
00560         }
00561 
00562         // reset mHead and mCurrentp
00563         mHead.mNextp = NULL;
00564         mTail.mPrevp = NULL;
00565         mCurrentp = mHead.mNextp;
00566         mQueuep = mHead.mNextp;
00567         mStateStackDepth = 0;
00568         mCount = 0;
00569 }
00570 
00571 template <class DATA_TYPE>
00572 S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
00573 {
00574 //      U32     length = 0;
00575 //      for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
00576 //      {
00577 //              length++;
00578 //      }
00579         return mCount;
00580 }
00581 
00582 // check to see if data is in list
00583 // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
00584 // return TRUE if found, FALSE if not found
00585 template <class DATA_TYPE>
00586 BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
00587 {
00588         mCurrentp = mHead.mNextp;
00589 
00590         while (mCurrentp)
00591         {
00592                 if (mCurrentp->mDatap == data)
00593                 {
00594                         mQueuep = mCurrentp;
00595                         return TRUE;
00596                 }
00597                 mCurrentp = mCurrentp->mNextp;
00598         }
00599 
00600         mCurrentp = mQueuep;
00601         return FALSE;
00602 }
00603 
00604 // NOTE: This next two funtions are only included here 
00605 // for those too familiar with the LLLinkedList template class.
00606 // They are depreciated.  resetList() is unecessary while 
00607 // getCurrentData() is identical to getNextData() and has
00608 // a misleading name.
00609 //
00610 // The recommended way to loop through a list is as follows:
00611 //
00612 // datap = list.getFirstData();
00613 // while (datap)
00614 // {
00615 //     /* do stuff */
00616 //     datap = list.getNextData();
00617 // }
00618 
00619         // place mCurrentp and mQueuep on first node
00620         template <class DATA_TYPE>
00621         void LLDoubleLinkedList<DATA_TYPE>::resetList()
00622         {
00623                 mCurrentp = mHead.mNextp;
00624                 mQueuep = mHead.mNextp;
00625                 mStateStackDepth = 0;
00626         }
00627         
00628         
00629         // return the data currently pointed to, 
00630         // set mCurrentp to that node and bump mQueuep down the list
00631         template <class DATA_TYPE>
00632         DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
00633         {
00634                 if (mQueuep)
00635                 {
00636                         mCurrentp = mQueuep;
00637                         mQueuep = mQueuep->mNextp;
00638                         return mCurrentp->mDatap;
00639                 }
00640                 else
00641                 {
00642                         return NULL;
00643                 }
00644         }
00645 
00646 
00647 // reset the list and return the data currently pointed to, 
00648 // set mCurrentp to that node and bump mQueuep down the list
00649 template <class DATA_TYPE>
00650 DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
00651 {
00652         mQueuep = mHead.mNextp;
00653         mCurrentp = mQueuep;
00654         if (mQueuep)
00655         {
00656                 mQueuep = mQueuep->mNextp;
00657                 return mCurrentp->mDatap;
00658         }
00659         else
00660         {
00661                 return NULL;
00662         }
00663 }
00664 
00665 
00666 // reset the list and return the data at position n, set mCurentp 
00667 // to that node and bump mQueuep down the list
00668 // Note: n=0 will behave like getFirstData()
00669 template <class DATA_TYPE>
00670 DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
00671 {
00672         mCurrentp = mHead.mNextp;
00673 
00674         if (mCurrentp)
00675         {
00676                 for (U32 i=0; i<n; i++)
00677                 {
00678                         mCurrentp = mCurrentp->mNextp;
00679                         if (!mCurrentp)
00680                         {
00681                                 break;
00682                         }               
00683                 }
00684         }
00685 
00686         if (mCurrentp)
00687         {
00688                 // bump mQueuep down the list
00689                 mQueuep = mCurrentp->mNextp;
00690                 return mCurrentp->mDatap;
00691         }
00692         else
00693         {
00694                 mQueuep = NULL;
00695                 return NULL;
00696         }
00697 }
00698 
00699 
00700 // reset the list and return the last data in it, 
00701 // set mCurrentp to that node and bump mQueuep up the list
00702 template <class DATA_TYPE>
00703 DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
00704 {
00705         mQueuep = mTail.mPrevp;
00706         mCurrentp = mQueuep;
00707         if (mQueuep)
00708         {
00709                 mQueuep = mQueuep->mPrevp;
00710                 return mCurrentp->mDatap;
00711         }
00712         else
00713         {
00714                 return NULL;
00715         }
00716 }
00717 
00718 
00719 // return the data in mQueuep, 
00720 // set mCurrentp to mQueuep and bump mQueuep down the list
00721 template <class DATA_TYPE>
00722 DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
00723 {
00724         if (mQueuep)
00725         {
00726                 mCurrentp = mQueuep;
00727                 mQueuep = mQueuep->mNextp;
00728                 return mCurrentp->mDatap;
00729         }
00730         else
00731         {
00732                 return NULL;
00733         }
00734 }
00735 
00736 
00737 // return the data in mQueuep, 
00738 // set mCurrentp to mQueuep and bump mQueuep up the list
00739 template <class DATA_TYPE>
00740 DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
00741 {
00742         if (mQueuep)
00743         {
00744                 mCurrentp = mQueuep;
00745                 mQueuep = mQueuep->mPrevp;
00746                 return mCurrentp->mDatap;
00747         }
00748         else
00749         {
00750                 return NULL;
00751         }
00752 }
00753 
00754 
00755 // remove the Node at mCurrentp
00756 // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
00757 template <class DATA_TYPE>
00758 void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
00759 {
00760         if (mCurrentp)
00761         {
00762                 // if there is a next one, fix it
00763                 if (mCurrentp->mNextp)
00764                 {
00765                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00766                 }
00767                 else    // otherwise we are at end of list
00768                 {
00769                         mTail.mPrevp = mCurrentp->mPrevp;
00770                 }
00771 
00772                 // if there is a previous one, fix it
00773                 if (mCurrentp->mPrevp)
00774                 {
00775                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00776                 }
00777                 else    // otherwise we are at beginning of list
00778                 {
00779                         mHead.mNextp = mCurrentp->mNextp;
00780                 }
00781 
00782                 // remove the node
00783                 mCurrentp->removeData();
00784                 delete mCurrentp;
00785                 mCount--;
00786 
00787                 // check for redundant pointing
00788                 if (mCurrentp == mQueuep)
00789                 {
00790                         mCurrentp = mQueuep = NULL;
00791                 }
00792                 else
00793                 {
00794                         mCurrentp = mQueuep;
00795                 }
00796         }
00797 }
00798 
00799 
00800 // delete the Node at mCurrentp
00801 // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) 
00802 template <class DATA_TYPE>
00803 void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
00804 {
00805         if (mCurrentp)
00806         {
00807                 // remove the node
00808                 // if there is a next one, fix it
00809                 if (mCurrentp->mNextp)
00810                 {
00811                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00812                 }
00813                 else    // otherwise we are at end of list
00814                 {
00815                         mTail.mPrevp = mCurrentp->mPrevp;
00816                 }
00817 
00818                 // if there is a previous one, fix it
00819                 if (mCurrentp->mPrevp)
00820                 {
00821                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00822                 }
00823                 else    // otherwise we are at beginning of list
00824                 {
00825                         mHead.mNextp = mCurrentp->mNextp;
00826                 }
00827 
00828                 // remove the LLDoubleLinkedNode
00829                 mCurrentp->deleteData();
00830                 delete mCurrentp;
00831                 mCount--;
00832 
00833                 // check for redundant pointing
00834                 if (mCurrentp == mQueuep)
00835                 {
00836                         mCurrentp = mQueuep = NULL;
00837                 }
00838                 else
00839                 {
00840                         mCurrentp = mQueuep;
00841                 }
00842         }
00843 }
00844 
00845 
00846 // remove the Node at mCurrentp and insert it into newlist
00847 // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
00848 template <class DATA_TYPE>
00849 void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
00850 {
00851         if (mCurrentp)
00852         {
00853                 // remove the node
00854                 // if there is a next one, fix it
00855                 if (mCurrentp->mNextp)
00856                 {
00857                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00858                 }
00859                 else    // otherwise we are at end of list
00860                 {
00861                         mTail.mPrevp = mCurrentp->mPrevp;
00862                 }
00863 
00864                 // if there is a previous one, fix it
00865                 if (mCurrentp->mPrevp)
00866                 {
00867                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00868                 }
00869                 else    // otherwise we are at beginning of list
00870                 {
00871                         mHead.mNextp = mCurrentp->mNextp;
00872                 }
00873 
00874                 // move the node to the new list
00875                 newlist->addNode(mCurrentp);
00876 
00877                 // check for redundant pointing
00878                 if (mCurrentp == mQueuep)
00879                 {
00880                         mCurrentp = mQueuep = NULL;
00881                 }
00882                 else
00883                 {
00884                         mCurrentp = mQueuep;
00885                 }
00886         }
00887 }
00888 
00889 
00890 // Inserts the node previous to mCurrentp
00891 // set mCurrentp to mQueuep
00892 template <class DATA_TYPE>
00893 void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
00894 {
00895         // don't allow pointer to NULL to be passed
00896         if (!nodep)
00897         {
00898                 llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
00899         }
00900         if (!nodep->mDatap)
00901         {
00902                 llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
00903         }
00904 
00905         if (mCurrentp)
00906         {
00907                 if (mCurrentp->mPrevp)
00908                 {
00909                         nodep->mPrevp = mCurrentp->mPrevp;
00910                         nodep->mNextp = mCurrentp;
00911                         mCurrentp->mPrevp->mNextp = nodep;
00912                         mCurrentp->mPrevp = nodep;
00913                 }
00914                 else    // at beginning of list
00915                 {
00916                         nodep->mPrevp = NULL;
00917                         nodep->mNextp = mCurrentp;
00918                         mHead.mNextp = nodep;
00919                         mCurrentp->mPrevp = nodep;
00920                 }
00921                 mCurrentp = mQueuep;
00922         }
00923         else    // add to front of list
00924         {
00925                 addNode(nodep);
00926         }
00927 }
00928 
00929 
00930 // insert the data in front of mCurrentp
00931 // set mCurrentp to mQueuep
00932 template <class DATA_TYPE>
00933 void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
00934 {
00935         if (!data)
00936         {
00937                 llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
00938         }
00939         LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
00940         insertNode(node);
00941         mCount++;
00942 }
00943 
00944 
00945 // if mCurrentp has a previous node then :
00946 //   * swaps mCurrentp with its previous
00947 //   * set mCurrentp to mQueuep
00948 // otherwise does nothing
00949 template <class DATA_TYPE>
00950 void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
00951 {
00952         if (mCurrentp)
00953         {
00954                 if (mCurrentp->mPrevp)
00955                 {
00956                         // Pull mCurrentp out of list
00957                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
00958                         if (mCurrentp->mNextp)
00959                         {
00960                                 mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
00961                         }
00962                         else    // mCurrentp was at end of list
00963                         {
00964                                 mTail.mPrevp = mCurrentp->mPrevp;
00965                         }
00966 
00967                         // Fix mCurrentp's pointers
00968                         mCurrentp->mNextp = mCurrentp->mPrevp;
00969                         mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
00970                         mCurrentp->mNextp->mPrevp = mCurrentp;
00971 
00972                         if (mCurrentp->mPrevp)
00973                         {
00974                                 // Fix the backward pointer of mCurrentp's new previous
00975                                 mCurrentp->mPrevp->mNextp = mCurrentp;
00976                         }
00977                         else    // mCurrentp is now at beginning of list
00978                         {
00979                                 mHead.mNextp = mCurrentp;
00980                         }
00981 
00982                         // Set the list back to the way it was
00983                         mCurrentp = mQueuep;
00984                 }
00985         }
00986 }
00987 
00988 
00989 // if mCurrentp has a next node then :
00990 //   * swaps mCurrentp with its next
00991 //   * set mCurrentp to mQueuep
00992 // otherwise does nothing
00993 template <class DATA_TYPE>
00994 void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
00995 {
00996         if (mCurrentp)
00997         {
00998                 if (mCurrentp->mNextp)
00999                 {
01000                         // Pull mCurrentp out of list
01001                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
01002                         if (mCurrentp->mPrevp)
01003                         {
01004                                 mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
01005                         }
01006                         else    // mCurrentp was at beginning of list
01007                         {
01008                                 mHead.mNextp = mCurrentp->mNextp;
01009                         }
01010 
01011                         // Fix mCurrentp's pointers
01012                         mCurrentp->mPrevp = mCurrentp->mNextp;
01013                         mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
01014                         mCurrentp->mPrevp->mNextp = mCurrentp;
01015 
01016                         if (mCurrentp->mNextp)
01017                         {
01018                                 // Fix the back pointer of mCurrentp's new next
01019                                 mCurrentp->mNextp->mPrevp = mCurrentp;
01020                         }
01021                         else    // mCurrentp is now at end of list
01022                         {
01023                                 mTail.mPrevp = mCurrentp;
01024                         }
01025                         
01026                         // Set the list back to the way it was
01027                         mCurrentp = mQueuep;
01028                 }
01029         }
01030 }
01031 
01032 // move mCurrentp to the front of the list
01033 // set mCurrentp to mQueuep
01034 template <class DATA_TYPE>
01035 void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
01036 {
01037         if (mCurrentp)
01038         {
01039                 // if there is a previous one, fix it
01040                 if (mCurrentp->mPrevp)
01041                 {
01042                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
01043                 }
01044                 else    // otherwise we are at beginning of list
01045                 {
01046                         // check for redundant pointing
01047                         if (mCurrentp == mQueuep)
01048                         {
01049                                 mCurrentp = mQueuep = NULL;
01050                         }
01051                         else
01052                         {
01053                                 mCurrentp = mQueuep;
01054                         }
01055                         return;
01056                 }
01057 
01058                 // if there is a next one, fix it
01059                 if (mCurrentp->mNextp)
01060                 {
01061                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
01062                 }
01063                 else    // otherwise we are at end of list
01064                 {
01065                         mTail.mPrevp = mCurrentp->mPrevp;
01066                 }
01067 
01068                 // add mCurrentp to beginning of list
01069                 mCurrentp->mNextp = mHead.mNextp;
01070                 mHead.mNextp->mPrevp = mCurrentp;       // mHead.mNextp MUST be valid, 
01071                                                                                         // or the list had only one node
01072                                                                                         // and we would have returned already
01073                 mCurrentp->mPrevp = NULL;
01074                 mHead.mNextp = mCurrentp;
01075 
01076                 // check for redundant pointing
01077                 if (mCurrentp == mQueuep)
01078                 {
01079                         mCurrentp = mQueuep = NULL;
01080                 }
01081                 else
01082                 {
01083                         mCurrentp = mQueuep;
01084                 }
01085         }
01086 
01087 }
01088 
01089 // move mCurrentp to the end of the list
01090 // set mCurrentp to mQueuep
01091 template <class DATA_TYPE>
01092 void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
01093 {
01094         if (mCurrentp)
01095         {
01096                 // if there is a next one, fix it
01097                 if (mCurrentp->mNextp)
01098                 {
01099                         mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
01100                 }
01101                 else    // otherwise we are at end of list and we're done
01102                 {
01103                         // check for redundant pointing
01104                         if (mCurrentp == mQueuep)
01105                         {
01106                                 mCurrentp = mQueuep = NULL;
01107                         }
01108                         else
01109                         {
01110                                 mCurrentp = mQueuep;
01111                         }
01112                         return;
01113                 }
01114 
01115                 // if there is a previous one, fix it
01116                 if (mCurrentp->mPrevp)
01117                 {
01118                         mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
01119                 }
01120                 else    // otherwise we are at beginning of list
01121                 {
01122                         mHead.mNextp = mCurrentp->mNextp;
01123                 }
01124 
01125                 // add mCurrentp to end of list
01126                 mCurrentp->mPrevp = mTail.mPrevp;
01127                 mTail.mPrevp->mNextp = mCurrentp;       // mTail.mPrevp MUST be valid, 
01128                                                                                         // or the list had only one node
01129                                                                                         // and we would have returned already
01130                 mCurrentp->mNextp = NULL;
01131                 mTail.mPrevp = mCurrentp;
01132 
01133                 // check for redundant pointing
01134                 if (mCurrentp == mQueuep)
01135                 {
01136                         mCurrentp = mQueuep = NULL;
01137                 }
01138                 else
01139                 {
01140                         mCurrentp = mQueuep;
01141                 }
01142         }
01143 }
01144 
01145 
01146 template <class DATA_TYPE>
01147 void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
01148 {
01149         mInsertBefore = insert_before;
01150 }
01151 
01152 
01153 // add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
01154 // set mCurrentp to mQueuep
01155 template <class DATA_TYPE>
01156 BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
01157 {
01158         // don't allow NULL to be passed to addData()
01159         if (!datap)
01160         {
01161                 llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
01162         }
01163 
01164         // has mInsertBefore not been set?
01165         if (!mInsertBefore)
01166         {
01167                 addData(datap);
01168                 return FALSE;
01169         }
01170 
01171         // is the list empty?
01172         if (!mHead.mNextp)
01173         {
01174                 addData(datap);
01175                 return TRUE;
01176         }
01177 
01178         // Note: this step has been added so that the behavior of LLDoubleLinkedList
01179         // is as rigorous as the LLLinkedList class about adding duplicate nodes.
01180         // Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo) 
01181         // returns TRUE.  However, if mInsertBefore(foo, foo) returns FALSE, then there 
01182         // shouldn't be any reason to exclude duplicate nodes (as we do here).
01183         if (checkData(datap))
01184         {
01185                 return FALSE;
01186         }
01187         
01188         mCurrentp = mHead.mNextp;
01189         while (mCurrentp)
01190         {
01191                 // check to see if datap is already in the list
01192                 if (datap == mCurrentp->mDatap)
01193                 {
01194                         return FALSE;
01195                 }
01196                 else if (mInsertBefore(datap, mCurrentp->mDatap))
01197                 {
01198                         insertData(datap);
01199                         return TRUE;
01200                 }
01201                 mCurrentp = mCurrentp->mNextp;
01202         }
01203         
01204         addDataAtEnd(datap);
01205         return TRUE;
01206 }
01207 
01208 
01209 // bubble-sort until sorted and return TRUE if anything was sorted
01210 // leaves mQueuep pointing at last node that was swapped with its mNextp
01211 //
01212 // NOTE: if you find this function looping for really long times, then you
01213 // probably need to check your implementation of mInsertBefore(a,b) and make 
01214 // sure it does not return TRUE when (a == b)!
01215 template <class DATA_TYPE>
01216 BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
01217 {
01218         BOOL b_swapped = FALSE;
01219         U32 count = 0;
01220         while (lazyBubbleSort()) 
01221         {
01222                 b_swapped = TRUE;
01223                 if (count++ > 0x7FFFFFFF)
01224                 {
01225                         llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
01226                         llwarning("    make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
01227                         break;
01228                 }
01229         }
01230         return b_swapped;
01231 }
01232 
01233 
01234 // do a single bubble-sort pass and return TRUE if anything was sorted
01235 // leaves mQueuep pointing at last node that was swapped with its mNextp
01236 template <class DATA_TYPE>
01237 BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
01238 {
01239         // has mInsertBefore been set?
01240         if (!mInsertBefore)
01241         {
01242                 return FALSE;
01243         }
01244 
01245         // is list empty?
01246         mCurrentp = mHead.mNextp;
01247         if (!mCurrentp)
01248         {
01249                 return FALSE;
01250         }
01251 
01252         BOOL b_swapped = FALSE;
01253 
01254         // the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
01255         S32  length = 0x7FFFFFFF;
01256         S32  count = 0;
01257 
01258         while (mCurrentp  &&  mCurrentp->mNextp  &&  count<length)
01259         {
01260                 if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
01261                 {
01262                         b_swapped = TRUE;
01263                         mQueuep = mCurrentp;
01264                         swapCurrentWithNext();  // sets mCurrentp to mQueuep
01265                 }
01266                 count++;
01267                 mCurrentp = mCurrentp->mNextp;
01268         }
01269         
01270         return b_swapped;
01271 }
01272 
01273 
01274 template <class DATA_TYPE>
01275 BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
01276 {
01277         if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
01278         {
01279                 *(mQueuepStack + mStateStackDepth) = mQueuep;
01280                 *(mCurrentpStack + mStateStackDepth) = mCurrentp;
01281                 mStateStackDepth++;
01282                 return TRUE;
01283         }
01284         return FALSE;
01285 }
01286 
01287 
01288 template <class DATA_TYPE>
01289 BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
01290 {
01291         if (mStateStackDepth > 0)
01292         {
01293                 mStateStackDepth--;
01294                 mQueuep = *(mQueuepStack + mStateStackDepth);
01295                 mCurrentp = *(mCurrentpStack + mStateStackDepth);
01296                 return TRUE;
01297         }
01298         return FALSE;
01299 }
01300 
01301 
01302 template <class DATA_TYPE>
01303 void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
01304 {
01305         mStateStackDepth = 0;
01306 }
01307 
01309 // private members
01311 
01312 // add node to beginning of list
01313 // set mCurrentp to mQueuep
01314 template <class DATA_TYPE>
01315 void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
01316 {
01317         // add the node to the front of the list
01318         nodep->mPrevp = NULL;
01319         nodep->mNextp = mHead.mNextp;
01320         mHead.mNextp = nodep;
01321 
01322         // if there's something in the list, fix its back pointer
01323         if (nodep->mNextp)
01324         {
01325                 nodep->mNextp->mPrevp = nodep;
01326         }
01327         else    // otherwise fix the tail node
01328         {
01329                 mTail.mPrevp = nodep;
01330         }
01331 
01332         mCurrentp = mQueuep;
01333 }
01334 
01335 
01336 // add node to end of list
01337 // set mCurrentp to mQueuep
01338 template <class DATA_TYPE>
01339 void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
01340 {
01341         // add the node to the end of the list
01342         node->mNextp = NULL;
01343         node->mPrevp = mTail.mPrevp;
01344         mTail.mPrevp = node;
01345 
01346         // if there's something in the list, fix its back pointer
01347         if (node->mPrevp)
01348         {
01349                 node->mPrevp->mNextp = node;
01350         }
01351         else    // otherwise fix the head node
01352         {
01353                 mHead.mNextp = node;
01354         }
01355 
01356         mCurrentp = mQueuep;
01357 }
01358 
01359 
01360 // randomly move nodes in the list for DEBUG (or Discordian) purposes
01361 // sets mCurrentp and mQueuep to top of list
01362 template <class DATA_TYPE>
01363 void LLDoubleLinkedList<DATA_TYPE>::scramble()
01364 {
01365         S32 random_number;
01366         DATA_TYPE *datap = getFirstData();
01367         while(datap)
01368         {
01369                 random_number = ll_rand(5);
01370 
01371                 if (0 == random_number)
01372                 {
01373                         removeCurrentData();
01374                         addData(datap);
01375                 }
01376                 else if (1 == random_number)
01377                 {
01378                         removeCurrentData();
01379                         addDataAtEnd(datap);
01380                 }
01381                 else if (2 == random_number)
01382                 {
01383                         swapCurrentWithPrevious();
01384                 }
01385                 else if (3 == random_number)
01386                 {
01387                         swapCurrentWithNext();
01388                 }
01389                 datap = getNextData();
01390         }
01391         mQueuep = mHead.mNextp;
01392         mCurrentp = mQueuep;
01393 }
01394 
01395 template <class DATA_TYPE>
01396 BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
01397 {
01398         return (mCount == 0);
01399 }
01400 
01401 
01402 #endif

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