PageRenderTime 39ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/doublelinkedlist.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 1397 lines | 875 code | 204 blank | 318 comment | 117 complexity | 38523a93cddf21a20d0ebaa8ba4f183a MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file doublelinkedlist.h
  3. * @brief Provides a standard doubly linked list for fun and profit.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_DOUBLELINKEDLIST_H
  27. #define LL_DOUBLELINKEDLIST_H
  28. #include "llerror.h"
  29. #include "llrand.h"
  30. // node that actually contains the data
  31. template <class DATA_TYPE> class LLDoubleLinkedNode
  32. {
  33. public:
  34. DATA_TYPE *mDatap;
  35. LLDoubleLinkedNode *mNextp;
  36. LLDoubleLinkedNode *mPrevp;
  37. public:
  38. // assign the mDatap pointer
  39. LLDoubleLinkedNode(DATA_TYPE *data);
  40. // destructor does not, by default, destroy associated data
  41. // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  42. ~LLDoubleLinkedNode();
  43. // delete associated data and NULL out pointer
  44. void deleteData();
  45. // remove associated data and NULL out pointer
  46. void removeData();
  47. };
  48. const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
  49. template <class DATA_TYPE> class LLDoubleLinkedList
  50. {
  51. private:
  52. LLDoubleLinkedNode<DATA_TYPE> mHead; // head node
  53. LLDoubleLinkedNode<DATA_TYPE> mTail; // tail node
  54. LLDoubleLinkedNode<DATA_TYPE> *mQueuep; // The node in the batter's box
  55. LLDoubleLinkedNode<DATA_TYPE> *mCurrentp; // The node we're talking about
  56. // The state stack allows nested exploration of the LLDoubleLinkedList
  57. // but should be used with great care
  58. LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  59. LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  60. U32 mStateStackDepth;
  61. U32 mCount;
  62. // mInsertBefore is a pointer to a user-set function that returns
  63. // TRUE if "first" should be located before "second"
  64. // NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
  65. // or never-ending loops can occur
  66. BOOL (*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);
  67. public:
  68. LLDoubleLinkedList();
  69. // destructor destroys list and nodes, but not data in nodes
  70. ~LLDoubleLinkedList();
  71. // put data into a node and stick it at the front of the list
  72. // set mCurrentp to mQueuep
  73. void addData(DATA_TYPE *data);
  74. // put data into a node and stick it at the end of the list
  75. // set mCurrentp to mQueuep
  76. void addDataAtEnd(DATA_TYPE *data);
  77. S32 getLength() const;
  78. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  79. // set mCurrentp to mQueuep
  80. // return TRUE if found, FALSE if not found
  81. BOOL removeData(const DATA_TYPE *data);
  82. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  83. // set mCurrentp to mQueuep
  84. // return TRUE if found, FALSE if not found
  85. BOOL deleteData(DATA_TYPE *data);
  86. // remove all nodes from the list and delete the associated data
  87. void deleteAllData();
  88. // remove all nodes from the list but do not delete data
  89. void removeAllNodes();
  90. BOOL isEmpty();
  91. // check to see if data is in list
  92. // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
  93. // return TRUE if found, FALSE if not found
  94. BOOL checkData(const DATA_TYPE *data);
  95. // NOTE: This next two funtions are only included here
  96. // for those too familiar with the LLLinkedList template class.
  97. // They are depreciated. resetList() is unecessary while
  98. // getCurrentData() is identical to getNextData() and has
  99. // a misleading name.
  100. //
  101. // The recommended way to loop through a list is as follows:
  102. //
  103. // datap = list.getFirstData();
  104. // while (datap)
  105. // {
  106. // /* do stuff */
  107. // datap = list.getNextData();
  108. // }
  109. // place mQueuep on mHead node
  110. void resetList();
  111. // return the data currently pointed to,
  112. // set mCurrentp to that node and bump mQueuep down the list
  113. // NOTE: this function is identical to getNextData()
  114. DATA_TYPE *getCurrentData();
  115. // reset the list and return the data currently pointed to,
  116. // set mCurrentp to that node and bump mQueuep down the list
  117. DATA_TYPE *getFirstData();
  118. // reset the list and return the data at position n, set mCurentp
  119. // to that node and bump mQueuep down the list
  120. // Note: n=0 will behave like getFirstData()
  121. DATA_TYPE *getNthData(U32 n);
  122. // reset the list and return the last data in it,
  123. // set mCurrentp to that node and bump mQueuep up the list
  124. DATA_TYPE *getLastData();
  125. // return data in mQueuep,
  126. // set mCurrentp mQueuep and bump mQueuep down the list
  127. DATA_TYPE *getNextData();
  128. // return the data in mQueuep,
  129. // set mCurrentp to mQueuep and bump mQueuep up the list
  130. DATA_TYPE *getPreviousData();
  131. // remove the Node at mCurrentp
  132. // set mCurrentp to mQueuep
  133. void removeCurrentData();
  134. // delete the Node at mCurrentp
  135. // set mCurrentp to mQueuep
  136. void deleteCurrentData();
  137. // remove the Node at mCurrentp and insert it into newlist
  138. // set mCurrentp to mQueuep
  139. void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
  140. // insert the node in front of mCurrentp
  141. // set mCurrentp to mQueuep
  142. void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
  143. // insert the data in front of mCurrentp
  144. // set mCurrentp to mQueuep
  145. void insertData(DATA_TYPE *data);
  146. // if mCurrentp has a previous node then :
  147. // * swaps mCurrentp with its previous
  148. // * set mCurrentp to mQueuep
  149. // (convenient for forward bubble-sort)
  150. // otherwise does nothing
  151. void swapCurrentWithPrevious();
  152. // if mCurrentp has a next node then :
  153. // * swaps mCurrentp with its next
  154. // * set mCurrentp to mQueuep
  155. // (convenient for backwards bubble-sort)
  156. // otherwise does nothing
  157. void swapCurrentWithNext();
  158. // move mCurrentp to the front of the list
  159. // set mCurrentp to mQueuep
  160. void moveCurrentToFront();
  161. // move mCurrentp to the end of the list
  162. // set mCurrentp to mQueuep
  163. void moveCurrentToEnd();
  164. // set mInsertBefore
  165. void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
  166. // add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
  167. // set mCurrentp to mQueuep
  168. BOOL addDataSorted(DATA_TYPE *datap);
  169. // sort the list using bubble-sort
  170. // Yes, this is a different name than the same function in LLLinkedList.
  171. // When it comes time for a name consolidation hopefully this one will win.
  172. BOOL bubbleSort();
  173. // does a single bubble sort pass on the list
  174. BOOL lazyBubbleSort();
  175. // returns TRUE if state successfully pushed (state stack not full)
  176. BOOL pushState();
  177. // returns TRUE if state successfully popped (state stack not empty)
  178. BOOL popState();
  179. // empties the state stack
  180. void clearStateStack();
  181. // randomly move the the links in the list for debug or (Discordian) purposes
  182. // sets mCurrentp and mQueuep to top of list
  183. void scramble();
  184. private:
  185. // add node to beginning of list
  186. // set mCurrentp to mQueuep
  187. void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
  188. // add node to end of list
  189. // set mCurrentp to mQueuep
  190. void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
  191. };
  192. //#endif
  193. ////////////////////////////////////////////////////////////////////////////////////////////
  194. // doublelinkedlist.cpp
  195. // LLDoubleLinkedList template class implementation file.
  196. // Provides a standard doubly linked list for fun and profit.
  197. //
  198. // Copyright 2001, Linden Research, Inc.
  199. //#include "llerror.h"
  200. //#include "doublelinkedlist.h"
  201. //////////////////////////////////////////////////////////////////////////////////////////
  202. // LLDoubleLinkedNode
  203. //////////////////////////////////////////////////////////////////////////////////////////
  204. // assign the mDatap pointer
  205. template <class DATA_TYPE>
  206. LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) :
  207. mDatap(data), mNextp(NULL), mPrevp(NULL)
  208. {
  209. }
  210. // destructor does not, by default, destroy associated data
  211. // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  212. template <class DATA_TYPE>
  213. LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
  214. {
  215. if (mDatap)
  216. {
  217. llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
  218. }
  219. }
  220. // delete associated data and NULL out pointer
  221. template <class DATA_TYPE>
  222. void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
  223. {
  224. delete mDatap;
  225. mDatap = NULL;
  226. }
  227. template <class DATA_TYPE>
  228. void LLDoubleLinkedNode<DATA_TYPE>::removeData()
  229. {
  230. mDatap = NULL;
  231. }
  232. //////////////////////////////////////////////////////////////////////////////////////
  233. // LLDoubleLinkedList
  234. //////////////////////////////////////////////////////////////////////////////////////
  235. // <------- up -------
  236. //
  237. // mCurrentp
  238. // mQueuep |
  239. // | |
  240. // | |
  241. // .------. .------. .------. .------.
  242. // | |---->| |---->| |----->| |-----> NULL
  243. // NULL <-----| |<----| |<----| |<-----| |
  244. // _'------' '------' '------' '------:_
  245. // .------. /| | | |\ .------.
  246. // NULL <-----|mHead |/ | mQueuep \|mTail |-----> NULL
  247. // | | mCurrentp | |
  248. // '------' '------'
  249. // -------- down --------->
  250. template <class DATA_TYPE>
  251. LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
  252. : mHead(NULL), mTail(NULL), mQueuep(NULL)
  253. {
  254. mCurrentp = mHead.mNextp;
  255. mQueuep = mHead.mNextp;
  256. mStateStackDepth = 0;
  257. mCount = 0;
  258. mInsertBefore = NULL;
  259. }
  260. // destructor destroys list and nodes, but not data in nodes
  261. template <class DATA_TYPE>
  262. LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
  263. {
  264. removeAllNodes();
  265. }
  266. // put data into a node and stick it at the front of the list
  267. // doesn't change mCurrentp nor mQueuep
  268. template <class DATA_TYPE>
  269. void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
  270. {
  271. // don't allow NULL to be passed to addData
  272. if (!data)
  273. {
  274. llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
  275. }
  276. // make the new node
  277. LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
  278. // add the node to the front of the list
  279. temp->mPrevp = NULL;
  280. temp->mNextp = mHead.mNextp;
  281. mHead.mNextp = temp;
  282. // if there's something in the list, fix its back pointer
  283. if (temp->mNextp)
  284. {
  285. temp->mNextp->mPrevp = temp;
  286. }
  287. // otherwise, fix the tail of the list
  288. else
  289. {
  290. mTail.mPrevp = temp;
  291. }
  292. mCount++;
  293. }
  294. // put data into a node and stick it at the end of the list
  295. template <class DATA_TYPE>
  296. void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
  297. {
  298. // don't allow NULL to be passed to addData
  299. if (!data)
  300. {
  301. llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
  302. }
  303. // make the new node
  304. LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
  305. addNodeAtEnd(nodep);
  306. mCount++;
  307. }
  308. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  309. // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
  310. // return TRUE if found, FALSE if not found
  311. template <class DATA_TYPE>
  312. BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
  313. {
  314. BOOL b_found = FALSE;
  315. // don't allow NULL to be passed to addData
  316. if (!data)
  317. {
  318. llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
  319. }
  320. mCurrentp = mHead.mNextp;
  321. while (mCurrentp)
  322. {
  323. if (mCurrentp->mDatap == data)
  324. {
  325. b_found = TRUE;
  326. // if there is a next one, fix it
  327. if (mCurrentp->mNextp)
  328. {
  329. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  330. }
  331. else // we are at end of list
  332. {
  333. mTail.mPrevp = mCurrentp->mPrevp;
  334. }
  335. // if there is a previous one, fix it
  336. if (mCurrentp->mPrevp)
  337. {
  338. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  339. }
  340. else // we are at beginning of list
  341. {
  342. mHead.mNextp = mCurrentp->mNextp;
  343. }
  344. // remove the node
  345. mCurrentp->removeData();
  346. delete mCurrentp;
  347. mCount--;
  348. break;
  349. }
  350. mCurrentp = mCurrentp->mNextp;
  351. }
  352. // reset the list back to where it was
  353. if (mCurrentp == mQueuep)
  354. {
  355. mCurrentp = mQueuep = NULL;
  356. }
  357. else
  358. {
  359. mCurrentp = mQueuep;
  360. }
  361. return b_found;
  362. }
  363. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  364. // set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
  365. // return TRUE if found, FALSE if not found
  366. template <class DATA_TYPE>
  367. BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
  368. {
  369. BOOL b_found = FALSE;
  370. // don't allow NULL to be passed to addData
  371. if (!data)
  372. {
  373. llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
  374. }
  375. mCurrentp = mHead.mNextp;
  376. while (mCurrentp)
  377. {
  378. if (mCurrentp->mDatap == data)
  379. {
  380. b_found = TRUE;
  381. // if there is a next one, fix it
  382. if (mCurrentp->mNextp)
  383. {
  384. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  385. }
  386. else // we are at end of list
  387. {
  388. mTail.mPrevp = mCurrentp->mPrevp;
  389. }
  390. // if there is a previous one, fix it
  391. if (mCurrentp->mPrevp)
  392. {
  393. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  394. }
  395. else // we are at beginning of list
  396. {
  397. mHead.mNextp = mCurrentp->mNextp;
  398. }
  399. // remove the node
  400. mCurrentp->deleteData();
  401. delete mCurrentp;
  402. mCount--;
  403. break;
  404. }
  405. mCurrentp = mCurrentp->mNextp;
  406. }
  407. // reset the list back to where it was
  408. if (mCurrentp == mQueuep)
  409. {
  410. mCurrentp = mQueuep = NULL;
  411. }
  412. else
  413. {
  414. mCurrentp = mQueuep;
  415. }
  416. return b_found;
  417. }
  418. // remove all nodes from the list and delete the associated data
  419. template <class DATA_TYPE>
  420. void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
  421. {
  422. mCurrentp = mHead.mNextp;
  423. while (mCurrentp)
  424. {
  425. mQueuep = mCurrentp->mNextp;
  426. mCurrentp->deleteData();
  427. delete mCurrentp;
  428. mCurrentp = mQueuep;
  429. }
  430. // reset mHead and mQueuep
  431. mHead.mNextp = NULL;
  432. mTail.mPrevp = NULL;
  433. mCurrentp = mHead.mNextp;
  434. mQueuep = mHead.mNextp;
  435. mStateStackDepth = 0;
  436. mCount = 0;
  437. }
  438. // remove all nodes from the list but do not delete associated data
  439. template <class DATA_TYPE>
  440. void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
  441. {
  442. mCurrentp = mHead.mNextp;
  443. while (mCurrentp)
  444. {
  445. mQueuep = mCurrentp->mNextp;
  446. mCurrentp->removeData();
  447. delete mCurrentp;
  448. mCurrentp = mQueuep;
  449. }
  450. // reset mHead and mCurrentp
  451. mHead.mNextp = NULL;
  452. mTail.mPrevp = NULL;
  453. mCurrentp = mHead.mNextp;
  454. mQueuep = mHead.mNextp;
  455. mStateStackDepth = 0;
  456. mCount = 0;
  457. }
  458. template <class DATA_TYPE>
  459. S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
  460. {
  461. // U32 length = 0;
  462. // for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
  463. // {
  464. // length++;
  465. // }
  466. return mCount;
  467. }
  468. // check to see if data is in list
  469. // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
  470. // return TRUE if found, FALSE if not found
  471. template <class DATA_TYPE>
  472. BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
  473. {
  474. mCurrentp = mHead.mNextp;
  475. while (mCurrentp)
  476. {
  477. if (mCurrentp->mDatap == data)
  478. {
  479. mQueuep = mCurrentp;
  480. return TRUE;
  481. }
  482. mCurrentp = mCurrentp->mNextp;
  483. }
  484. mCurrentp = mQueuep;
  485. return FALSE;
  486. }
  487. // NOTE: This next two funtions are only included here
  488. // for those too familiar with the LLLinkedList template class.
  489. // They are depreciated. resetList() is unecessary while
  490. // getCurrentData() is identical to getNextData() and has
  491. // a misleading name.
  492. //
  493. // The recommended way to loop through a list is as follows:
  494. //
  495. // datap = list.getFirstData();
  496. // while (datap)
  497. // {
  498. // /* do stuff */
  499. // datap = list.getNextData();
  500. // }
  501. // place mCurrentp and mQueuep on first node
  502. template <class DATA_TYPE>
  503. void LLDoubleLinkedList<DATA_TYPE>::resetList()
  504. {
  505. mCurrentp = mHead.mNextp;
  506. mQueuep = mHead.mNextp;
  507. mStateStackDepth = 0;
  508. }
  509. // return the data currently pointed to,
  510. // set mCurrentp to that node and bump mQueuep down the list
  511. template <class DATA_TYPE>
  512. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
  513. {
  514. if (mQueuep)
  515. {
  516. mCurrentp = mQueuep;
  517. mQueuep = mQueuep->mNextp;
  518. return mCurrentp->mDatap;
  519. }
  520. else
  521. {
  522. return NULL;
  523. }
  524. }
  525. // reset the list and return the data currently pointed to,
  526. // set mCurrentp to that node and bump mQueuep down the list
  527. template <class DATA_TYPE>
  528. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
  529. {
  530. mQueuep = mHead.mNextp;
  531. mCurrentp = mQueuep;
  532. if (mQueuep)
  533. {
  534. mQueuep = mQueuep->mNextp;
  535. return mCurrentp->mDatap;
  536. }
  537. else
  538. {
  539. return NULL;
  540. }
  541. }
  542. // reset the list and return the data at position n, set mCurentp
  543. // to that node and bump mQueuep down the list
  544. // Note: n=0 will behave like getFirstData()
  545. template <class DATA_TYPE>
  546. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
  547. {
  548. mCurrentp = mHead.mNextp;
  549. if (mCurrentp)
  550. {
  551. for (U32 i=0; i<n; i++)
  552. {
  553. mCurrentp = mCurrentp->mNextp;
  554. if (!mCurrentp)
  555. {
  556. break;
  557. }
  558. }
  559. }
  560. if (mCurrentp)
  561. {
  562. // bump mQueuep down the list
  563. mQueuep = mCurrentp->mNextp;
  564. return mCurrentp->mDatap;
  565. }
  566. else
  567. {
  568. mQueuep = NULL;
  569. return NULL;
  570. }
  571. }
  572. // reset the list and return the last data in it,
  573. // set mCurrentp to that node and bump mQueuep up the list
  574. template <class DATA_TYPE>
  575. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
  576. {
  577. mQueuep = mTail.mPrevp;
  578. mCurrentp = mQueuep;
  579. if (mQueuep)
  580. {
  581. mQueuep = mQueuep->mPrevp;
  582. return mCurrentp->mDatap;
  583. }
  584. else
  585. {
  586. return NULL;
  587. }
  588. }
  589. // return the data in mQueuep,
  590. // set mCurrentp to mQueuep and bump mQueuep down the list
  591. template <class DATA_TYPE>
  592. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
  593. {
  594. if (mQueuep)
  595. {
  596. mCurrentp = mQueuep;
  597. mQueuep = mQueuep->mNextp;
  598. return mCurrentp->mDatap;
  599. }
  600. else
  601. {
  602. return NULL;
  603. }
  604. }
  605. // return the data in mQueuep,
  606. // set mCurrentp to mQueuep and bump mQueuep up the list
  607. template <class DATA_TYPE>
  608. DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
  609. {
  610. if (mQueuep)
  611. {
  612. mCurrentp = mQueuep;
  613. mQueuep = mQueuep->mPrevp;
  614. return mCurrentp->mDatap;
  615. }
  616. else
  617. {
  618. return NULL;
  619. }
  620. }
  621. // remove the Node at mCurrentp
  622. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
  623. template <class DATA_TYPE>
  624. void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
  625. {
  626. if (mCurrentp)
  627. {
  628. // if there is a next one, fix it
  629. if (mCurrentp->mNextp)
  630. {
  631. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  632. }
  633. else // otherwise we are at end of list
  634. {
  635. mTail.mPrevp = mCurrentp->mPrevp;
  636. }
  637. // if there is a previous one, fix it
  638. if (mCurrentp->mPrevp)
  639. {
  640. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  641. }
  642. else // otherwise we are at beginning of list
  643. {
  644. mHead.mNextp = mCurrentp->mNextp;
  645. }
  646. // remove the node
  647. mCurrentp->removeData();
  648. delete mCurrentp;
  649. mCount--;
  650. // check for redundant pointing
  651. if (mCurrentp == mQueuep)
  652. {
  653. mCurrentp = mQueuep = NULL;
  654. }
  655. else
  656. {
  657. mCurrentp = mQueuep;
  658. }
  659. }
  660. }
  661. // delete the Node at mCurrentp
  662. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
  663. template <class DATA_TYPE>
  664. void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
  665. {
  666. if (mCurrentp)
  667. {
  668. // remove the node
  669. // if there is a next one, fix it
  670. if (mCurrentp->mNextp)
  671. {
  672. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  673. }
  674. else // otherwise we are at end of list
  675. {
  676. mTail.mPrevp = mCurrentp->mPrevp;
  677. }
  678. // if there is a previous one, fix it
  679. if (mCurrentp->mPrevp)
  680. {
  681. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  682. }
  683. else // otherwise we are at beginning of list
  684. {
  685. mHead.mNextp = mCurrentp->mNextp;
  686. }
  687. // remove the LLDoubleLinkedNode
  688. mCurrentp->deleteData();
  689. delete mCurrentp;
  690. mCount--;
  691. // check for redundant pointing
  692. if (mCurrentp == mQueuep)
  693. {
  694. mCurrentp = mQueuep = NULL;
  695. }
  696. else
  697. {
  698. mCurrentp = mQueuep;
  699. }
  700. }
  701. }
  702. // remove the Node at mCurrentp and insert it into newlist
  703. // set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
  704. template <class DATA_TYPE>
  705. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
  706. {
  707. if (mCurrentp)
  708. {
  709. // remove the node
  710. // if there is a next one, fix it
  711. if (mCurrentp->mNextp)
  712. {
  713. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  714. }
  715. else // otherwise we are at end of list
  716. {
  717. mTail.mPrevp = mCurrentp->mPrevp;
  718. }
  719. // if there is a previous one, fix it
  720. if (mCurrentp->mPrevp)
  721. {
  722. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  723. }
  724. else // otherwise we are at beginning of list
  725. {
  726. mHead.mNextp = mCurrentp->mNextp;
  727. }
  728. // move the node to the new list
  729. newlist->addNode(mCurrentp);
  730. // check for redundant pointing
  731. if (mCurrentp == mQueuep)
  732. {
  733. mCurrentp = mQueuep = NULL;
  734. }
  735. else
  736. {
  737. mCurrentp = mQueuep;
  738. }
  739. }
  740. }
  741. // Inserts the node previous to mCurrentp
  742. // set mCurrentp to mQueuep
  743. template <class DATA_TYPE>
  744. void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
  745. {
  746. // don't allow pointer to NULL to be passed
  747. if (!nodep)
  748. {
  749. llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
  750. }
  751. if (!nodep->mDatap)
  752. {
  753. llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
  754. }
  755. if (mCurrentp)
  756. {
  757. if (mCurrentp->mPrevp)
  758. {
  759. nodep->mPrevp = mCurrentp->mPrevp;
  760. nodep->mNextp = mCurrentp;
  761. mCurrentp->mPrevp->mNextp = nodep;
  762. mCurrentp->mPrevp = nodep;
  763. }
  764. else // at beginning of list
  765. {
  766. nodep->mPrevp = NULL;
  767. nodep->mNextp = mCurrentp;
  768. mHead.mNextp = nodep;
  769. mCurrentp->mPrevp = nodep;
  770. }
  771. mCurrentp = mQueuep;
  772. }
  773. else // add to front of list
  774. {
  775. addNode(nodep);
  776. }
  777. }
  778. // insert the data in front of mCurrentp
  779. // set mCurrentp to mQueuep
  780. template <class DATA_TYPE>
  781. void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
  782. {
  783. if (!data)
  784. {
  785. llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
  786. }
  787. LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
  788. insertNode(node);
  789. mCount++;
  790. }
  791. // if mCurrentp has a previous node then :
  792. // * swaps mCurrentp with its previous
  793. // * set mCurrentp to mQueuep
  794. // otherwise does nothing
  795. template <class DATA_TYPE>
  796. void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
  797. {
  798. if (mCurrentp)
  799. {
  800. if (mCurrentp->mPrevp)
  801. {
  802. // Pull mCurrentp out of list
  803. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  804. if (mCurrentp->mNextp)
  805. {
  806. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  807. }
  808. else // mCurrentp was at end of list
  809. {
  810. mTail.mPrevp = mCurrentp->mPrevp;
  811. }
  812. // Fix mCurrentp's pointers
  813. mCurrentp->mNextp = mCurrentp->mPrevp;
  814. mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
  815. mCurrentp->mNextp->mPrevp = mCurrentp;
  816. if (mCurrentp->mPrevp)
  817. {
  818. // Fix the backward pointer of mCurrentp's new previous
  819. mCurrentp->mPrevp->mNextp = mCurrentp;
  820. }
  821. else // mCurrentp is now at beginning of list
  822. {
  823. mHead.mNextp = mCurrentp;
  824. }
  825. // Set the list back to the way it was
  826. mCurrentp = mQueuep;
  827. }
  828. }
  829. }
  830. // if mCurrentp has a next node then :
  831. // * swaps mCurrentp with its next
  832. // * set mCurrentp to mQueuep
  833. // otherwise does nothing
  834. template <class DATA_TYPE>
  835. void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
  836. {
  837. if (mCurrentp)
  838. {
  839. if (mCurrentp->mNextp)
  840. {
  841. // Pull mCurrentp out of list
  842. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  843. if (mCurrentp->mPrevp)
  844. {
  845. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  846. }
  847. else // mCurrentp was at beginning of list
  848. {
  849. mHead.mNextp = mCurrentp->mNextp;
  850. }
  851. // Fix mCurrentp's pointers
  852. mCurrentp->mPrevp = mCurrentp->mNextp;
  853. mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
  854. mCurrentp->mPrevp->mNextp = mCurrentp;
  855. if (mCurrentp->mNextp)
  856. {
  857. // Fix the back pointer of mCurrentp's new next
  858. mCurrentp->mNextp->mPrevp = mCurrentp;
  859. }
  860. else // mCurrentp is now at end of list
  861. {
  862. mTail.mPrevp = mCurrentp;
  863. }
  864. // Set the list back to the way it was
  865. mCurrentp = mQueuep;
  866. }
  867. }
  868. }
  869. // move mCurrentp to the front of the list
  870. // set mCurrentp to mQueuep
  871. template <class DATA_TYPE>
  872. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
  873. {
  874. if (mCurrentp)
  875. {
  876. // if there is a previous one, fix it
  877. if (mCurrentp->mPrevp)
  878. {
  879. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  880. }
  881. else // otherwise we are at beginning of list
  882. {
  883. // check for redundant pointing
  884. if (mCurrentp == mQueuep)
  885. {
  886. mCurrentp = mQueuep = NULL;
  887. }
  888. else
  889. {
  890. mCurrentp = mQueuep;
  891. }
  892. return;
  893. }
  894. // if there is a next one, fix it
  895. if (mCurrentp->mNextp)
  896. {
  897. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  898. }
  899. else // otherwise we are at end of list
  900. {
  901. mTail.mPrevp = mCurrentp->mPrevp;
  902. }
  903. // add mCurrentp to beginning of list
  904. mCurrentp->mNextp = mHead.mNextp;
  905. mHead.mNextp->mPrevp = mCurrentp; // mHead.mNextp MUST be valid,
  906. // or the list had only one node
  907. // and we would have returned already
  908. mCurrentp->mPrevp = NULL;
  909. mHead.mNextp = mCurrentp;
  910. // check for redundant pointing
  911. if (mCurrentp == mQueuep)
  912. {
  913. mCurrentp = mQueuep = NULL;
  914. }
  915. else
  916. {
  917. mCurrentp = mQueuep;
  918. }
  919. }
  920. }
  921. // move mCurrentp to the end of the list
  922. // set mCurrentp to mQueuep
  923. template <class DATA_TYPE>
  924. void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
  925. {
  926. if (mCurrentp)
  927. {
  928. // if there is a next one, fix it
  929. if (mCurrentp->mNextp)
  930. {
  931. mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
  932. }
  933. else // otherwise we are at end of list and we're done
  934. {
  935. // check for redundant pointing
  936. if (mCurrentp == mQueuep)
  937. {
  938. mCurrentp = mQueuep = NULL;
  939. }
  940. else
  941. {
  942. mCurrentp = mQueuep;
  943. }
  944. return;
  945. }
  946. // if there is a previous one, fix it
  947. if (mCurrentp->mPrevp)
  948. {
  949. mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
  950. }
  951. else // otherwise we are at beginning of list
  952. {
  953. mHead.mNextp = mCurrentp->mNextp;
  954. }
  955. // add mCurrentp to end of list
  956. mCurrentp->mPrevp = mTail.mPrevp;
  957. mTail.mPrevp->mNextp = mCurrentp; // mTail.mPrevp MUST be valid,
  958. // or the list had only one node
  959. // and we would have returned already
  960. mCurrentp->mNextp = NULL;
  961. mTail.mPrevp = mCurrentp;
  962. // check for redundant pointing
  963. if (mCurrentp == mQueuep)
  964. {
  965. mCurrentp = mQueuep = NULL;
  966. }
  967. else
  968. {
  969. mCurrentp = mQueuep;
  970. }
  971. }
  972. }
  973. template <class DATA_TYPE>
  974. void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
  975. {
  976. mInsertBefore = insert_before;
  977. }
  978. // add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
  979. // set mCurrentp to mQueuep
  980. template <class DATA_TYPE>
  981. BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
  982. {
  983. // don't allow NULL to be passed to addData()
  984. if (!datap)
  985. {
  986. llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
  987. }
  988. // has mInsertBefore not been set?
  989. if (!mInsertBefore)
  990. {
  991. addData(datap);
  992. return FALSE;
  993. }
  994. // is the list empty?
  995. if (!mHead.mNextp)
  996. {
  997. addData(datap);
  998. return TRUE;
  999. }
  1000. // Note: this step has been added so that the behavior of LLDoubleLinkedList
  1001. // is as rigorous as the LLLinkedList class about adding duplicate nodes.
  1002. // Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo)
  1003. // returns TRUE. However, if mInsertBefore(foo, foo) returns FALSE, then there
  1004. // shouldn't be any reason to exclude duplicate nodes (as we do here).
  1005. if (checkData(datap))
  1006. {
  1007. return FALSE;
  1008. }
  1009. mCurrentp = mHead.mNextp;
  1010. while (mCurrentp)
  1011. {
  1012. // check to see if datap is already in the list
  1013. if (datap == mCurrentp->mDatap)
  1014. {
  1015. return FALSE;
  1016. }
  1017. else if (mInsertBefore(datap, mCurrentp->mDatap))
  1018. {
  1019. insertData(datap);
  1020. return TRUE;
  1021. }
  1022. mCurrentp = mCurrentp->mNextp;
  1023. }
  1024. addDataAtEnd(datap);
  1025. return TRUE;
  1026. }
  1027. // bubble-sort until sorted and return TRUE if anything was sorted
  1028. // leaves mQueuep pointing at last node that was swapped with its mNextp
  1029. //
  1030. // NOTE: if you find this function looping for really long times, then you
  1031. // probably need to check your implementation of mInsertBefore(a,b) and make
  1032. // sure it does not return TRUE when (a == b)!
  1033. template <class DATA_TYPE>
  1034. BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
  1035. {
  1036. BOOL b_swapped = FALSE;
  1037. U32 count = 0;
  1038. while (lazyBubbleSort())
  1039. {
  1040. b_swapped = TRUE;
  1041. if (count++ > 0x7FFFFFFF)
  1042. {
  1043. llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
  1044. llwarning(" make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
  1045. break;
  1046. }
  1047. }
  1048. return b_swapped;
  1049. }
  1050. // do a single bubble-sort pass and return TRUE if anything was sorted
  1051. // leaves mQueuep pointing at last node that was swapped with its mNextp
  1052. template <class DATA_TYPE>
  1053. BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
  1054. {
  1055. // has mInsertBefore been set?
  1056. if (!mInsertBefore)
  1057. {
  1058. return FALSE;
  1059. }
  1060. // is list empty?
  1061. mCurrentp = mHead.mNextp;
  1062. if (!mCurrentp)
  1063. {
  1064. return FALSE;
  1065. }
  1066. BOOL b_swapped = FALSE;
  1067. // the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
  1068. S32 length = 0x7FFFFFFF;
  1069. S32 count = 0;
  1070. while (mCurrentp && mCurrentp->mNextp && count<length)
  1071. {
  1072. if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
  1073. {
  1074. b_swapped = TRUE;
  1075. mQueuep = mCurrentp;
  1076. swapCurrentWithNext(); // sets mCurrentp to mQueuep
  1077. }
  1078. count++;
  1079. mCurrentp = mCurrentp->mNextp;
  1080. }
  1081. return b_swapped;
  1082. }
  1083. template <class DATA_TYPE>
  1084. BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
  1085. {
  1086. if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
  1087. {
  1088. *(mQueuepStack + mStateStackDepth) = mQueuep;
  1089. *(mCurrentpStack + mStateStackDepth) = mCurrentp;
  1090. mStateStackDepth++;
  1091. return TRUE;
  1092. }
  1093. return FALSE;
  1094. }
  1095. template <class DATA_TYPE>
  1096. BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
  1097. {
  1098. if (mStateStackDepth > 0)
  1099. {
  1100. mStateStackDepth--;
  1101. mQueuep = *(mQueuepStack + mStateStackDepth);
  1102. mCurrentp = *(mCurrentpStack + mStateStackDepth);
  1103. return TRUE;
  1104. }
  1105. return FALSE;
  1106. }
  1107. template <class DATA_TYPE>
  1108. void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
  1109. {
  1110. mStateStackDepth = 0;
  1111. }
  1112. //////////////////////////////////////////////////////////////////////////////////////////
  1113. // private members
  1114. //////////////////////////////////////////////////////////////////////////////////////////
  1115. // add node to beginning of list
  1116. // set mCurrentp to mQueuep
  1117. template <class DATA_TYPE>
  1118. void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
  1119. {
  1120. // add the node to the front of the list
  1121. nodep->mPrevp = NULL;
  1122. nodep->mNextp = mHead.mNextp;
  1123. mHead.mNextp = nodep;
  1124. // if there's something in the list, fix its back pointer
  1125. if (nodep->mNextp)
  1126. {
  1127. nodep->mNextp->mPrevp = nodep;
  1128. }
  1129. else // otherwise fix the tail node
  1130. {
  1131. mTail.mPrevp = nodep;
  1132. }
  1133. mCurrentp = mQueuep;
  1134. }
  1135. // add node to end of list
  1136. // set mCurrentp to mQueuep
  1137. template <class DATA_TYPE>
  1138. void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
  1139. {
  1140. // add the node to the end of the list
  1141. node->mNextp = NULL;
  1142. node->mPrevp = mTail.mPrevp;
  1143. mTail.mPrevp = node;
  1144. // if there's something in the list, fix its back pointer
  1145. if (node->mPrevp)
  1146. {
  1147. node->mPrevp->mNextp = node;
  1148. }
  1149. else // otherwise fix the head node
  1150. {
  1151. mHead.mNextp = node;
  1152. }
  1153. mCurrentp = mQueuep;
  1154. }
  1155. // randomly move nodes in the list for DEBUG (or Discordian) purposes
  1156. // sets mCurrentp and mQueuep to top of list
  1157. template <class DATA_TYPE>
  1158. void LLDoubleLinkedList<DATA_TYPE>::scramble()
  1159. {
  1160. S32 random_number;
  1161. DATA_TYPE *datap = getFirstData();
  1162. while(datap)
  1163. {
  1164. random_number = ll_rand(5);
  1165. if (0 == random_number)
  1166. {
  1167. removeCurrentData();
  1168. addData(datap);
  1169. }
  1170. else if (1 == random_number)
  1171. {
  1172. removeCurrentData();
  1173. addDataAtEnd(datap);
  1174. }
  1175. else if (2 == random_number)
  1176. {
  1177. swapCurrentWithPrevious();
  1178. }
  1179. else if (3 == random_number)
  1180. {
  1181. swapCurrentWithNext();
  1182. }
  1183. datap = getNextData();
  1184. }
  1185. mQueuep = mHead.mNextp;
  1186. mCurrentp = mQueuep;
  1187. }
  1188. template <class DATA_TYPE>
  1189. BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
  1190. {
  1191. return (mCount == 0);
  1192. }
  1193. #endif