/indra/llcommon/linked_lists.h

https://bitbucket.org/lindenlab/viewer-beta/ · C++ Header · 937 lines · 615 code · 137 blank · 185 comment · 73 complexity · 98c6bcbfc27b0fa50bd6f4cd59c937d0 MD5 · raw file

  1. /**
  2. * @file linked_lists.h
  3. * @brief LLLinkedList class header amd implementation file.
  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_LINKED_LISTS_H
  27. #define LL_LINKED_LISTS_H
  28. /**
  29. * Provides a standard doubly linked list for fun and profit
  30. * Utilizes a neat trick off of Flipcode where the back pointer is a
  31. * pointer to a pointer, allowing easier transfer of nodes between lists, &c
  32. * And a template class, of course
  33. */
  34. #include "llerror.h"
  35. template <class DATA_TYPE> class LLLinkedList
  36. {
  37. public:
  38. friend class LLLinkNode;
  39. // External interface
  40. // basic constructor
  41. LLLinkedList() : mHead(NULL), mCurrentp(NULL), mInsertBefore(NULL)
  42. {
  43. mCurrentp = mHead.mNextp;
  44. mCurrentOperatingp = mHead.mNextp;
  45. mCount = 0;
  46. }
  47. // basic constructor
  48. LLLinkedList(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested)) : mHead(NULL), mCurrentp(NULL), mInsertBefore(insert_before)
  49. {
  50. mCurrentp = mHead.mNextp;
  51. mCurrentOperatingp = mHead.mNextp;
  52. mCount = 0;
  53. }
  54. // destructor destroys list and nodes, but not data in nodes
  55. ~LLLinkedList()
  56. {
  57. removeAllNodes();
  58. }
  59. // set mInsertBefore
  60. void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested))
  61. {
  62. mInsertBefore = insert_before;
  63. }
  64. //
  65. // WARNING!!!!!!!
  66. // addData and addDataSorted are NOT O(1) operations, but O(n) because they check
  67. // for existence of the data in the linked list first. Why, I don't know - djs
  68. // If you don't care about dupes, use addDataNoCheck
  69. //
  70. // put data into a node and stick it at the front of the list
  71. inline BOOL addData(DATA_TYPE *data);
  72. // put data into a node and sort into list by mInsertBefore()
  73. // calls normal add if mInsertBefore isn't set
  74. inline BOOL addDataSorted(DATA_TYPE *data);
  75. inline BOOL addDataNoCheck(DATA_TYPE *data);
  76. // bubbleSortList
  77. // does an improved bubble sort of the list . . . works best with almost sorted data
  78. // does nothing if mInsertBefore isn't set
  79. // Nota Bene: Swaps are accomplished by swapping data pointers
  80. inline void bubbleSortList();
  81. // put data into a node and stick it at the end of the list
  82. inline BOOL addDataAtEnd(DATA_TYPE *data);
  83. // returns number of items in the list
  84. inline S32 getLength() const;
  85. inline BOOL isEmpty();
  86. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  87. // leave mCurrentp and mCurrentOperatingp on the next entry
  88. // return TRUE if found, FALSE if not found
  89. inline BOOL removeData(DATA_TYPE *data);
  90. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  91. // leave mCurrentp and mCurrentOperatingp on the next entry
  92. // return TRUE if found, FALSE if not found
  93. inline BOOL deleteData(DATA_TYPE *data);
  94. // remove all nodes from the list and delete the associated data
  95. inline void deleteAllData();
  96. // remove all nodes from the list but do not delete data
  97. inline void removeAllNodes();
  98. // check to see if data is in list
  99. // if TRUE then mCurrentp and mCurrentOperatingp point to data
  100. inline BOOL checkData(DATA_TYPE *data);
  101. // place mCurrentp on first node
  102. inline void resetList();
  103. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  104. inline DATA_TYPE *getCurrentData();
  105. // same as getCurrentData() but a more intuitive name for the operation
  106. inline DATA_TYPE *getNextData();
  107. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  108. inline DATA_TYPE *getFirstData();
  109. // reset the list and return the data at position n, set mCurentOperatingp to that node and bump mCurrentp
  110. // Note: n is zero-based
  111. inline DATA_TYPE *getNthData( U32 n);
  112. // reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
  113. inline DATA_TYPE *getLastData();
  114. // remove the Node at mCurentOperatingp
  115. // leave mCurrentp and mCurentOperatingp on the next entry
  116. inline void removeCurrentData();
  117. // remove the Node at mCurentOperatingp and add it to newlist
  118. // leave mCurrentp and mCurentOperatingp on the next entry
  119. void moveCurrentData(LLLinkedList *newlist, BOOL b_sort);
  120. BOOL moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort);
  121. // delete the Node at mCurentOperatingp
  122. // leave mCurrentp anf mCurentOperatingp on the next entry
  123. void deleteCurrentData();
  124. private:
  125. // node that actually contains the data
  126. class LLLinkNode
  127. {
  128. public:
  129. // assign the mDatap pointer
  130. LLLinkNode(DATA_TYPE *data) : mDatap(data), mNextp(NULL), mPrevpp(NULL)
  131. {
  132. }
  133. // destructor does not, by default, destroy associated data
  134. // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  135. ~LLLinkNode()
  136. {
  137. if (mDatap)
  138. {
  139. llerror("Attempting to call LLLinkNode destructor with a non-null mDatap!", 1);
  140. }
  141. }
  142. // delete associated data and NULL out pointer
  143. void deleteData()
  144. {
  145. delete mDatap;
  146. mDatap = NULL;
  147. }
  148. // NULL out pointer
  149. void removeData()
  150. {
  151. mDatap = NULL;
  152. }
  153. DATA_TYPE *mDatap;
  154. LLLinkNode *mNextp;
  155. LLLinkNode **mPrevpp;
  156. };
  157. // add a node at the front of the list
  158. void addData(LLLinkNode *node)
  159. {
  160. // don't allow NULL to be passed to addData
  161. if (!node)
  162. {
  163. llerror("NULL pointer passed to LLLinkedList::addData", 0);
  164. }
  165. // add the node to the front of the list
  166. node->mPrevpp = &mHead.mNextp;
  167. node->mNextp = mHead.mNextp;
  168. // if there's something in the list, fix its back pointer
  169. if (node->mNextp)
  170. {
  171. node->mNextp->mPrevpp = &node->mNextp;
  172. }
  173. mHead.mNextp = node;
  174. }
  175. LLLinkNode mHead; // fake head node. . . makes pointer operations faster and easier
  176. LLLinkNode *mCurrentp; // mCurrentp is the Node that getCurrentData returns
  177. LLLinkNode *mCurrentOperatingp; // this is the node that the various mumbleCurrentData functions act on
  178. BOOL (*mInsertBefore)(DATA_TYPE *data_new, DATA_TYPE *data_tested); // user function set to allow sorted lists
  179. U32 mCount;
  180. };
  181. template <class DATA_TYPE>
  182. BOOL LLLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
  183. {
  184. // don't allow NULL to be passed to addData
  185. if (!data)
  186. {
  187. llerror("NULL pointer passed to LLLinkedList::addData", 0);
  188. }
  189. LLLinkNode *tcurr = mCurrentp;
  190. LLLinkNode *tcurrop = mCurrentOperatingp;
  191. if ( checkData(data))
  192. {
  193. mCurrentp = tcurr;
  194. mCurrentOperatingp = tcurrop;
  195. return FALSE;
  196. }
  197. // make the new node
  198. LLLinkNode *temp = new LLLinkNode(data);
  199. // add the node to the front of the list
  200. temp->mPrevpp = &mHead.mNextp;
  201. temp->mNextp = mHead.mNextp;
  202. // if there's something in the list, fix its back pointer
  203. if (temp->mNextp)
  204. {
  205. temp->mNextp->mPrevpp = &temp->mNextp;
  206. }
  207. mHead.mNextp = temp;
  208. mCurrentp = tcurr;
  209. mCurrentOperatingp = tcurrop;
  210. mCount++;
  211. return TRUE;
  212. }
  213. template <class DATA_TYPE>
  214. BOOL LLLinkedList<DATA_TYPE>::addDataNoCheck(DATA_TYPE *data)
  215. {
  216. // don't allow NULL to be passed to addData
  217. if (!data)
  218. {
  219. llerror("NULL pointer passed to LLLinkedList::addData", 0);
  220. }
  221. LLLinkNode *tcurr = mCurrentp;
  222. LLLinkNode *tcurrop = mCurrentOperatingp;
  223. // make the new node
  224. LLLinkNode *temp = new LLLinkNode(data);
  225. // add the node to the front of the list
  226. temp->mPrevpp = &mHead.mNextp;
  227. temp->mNextp = mHead.mNextp;
  228. // if there's something in the list, fix its back pointer
  229. if (temp->mNextp)
  230. {
  231. temp->mNextp->mPrevpp = &temp->mNextp;
  232. }
  233. mHead.mNextp = temp;
  234. mCurrentp = tcurr;
  235. mCurrentOperatingp = tcurrop;
  236. mCount++;
  237. return TRUE;
  238. }
  239. template <class DATA_TYPE>
  240. BOOL LLLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *data)
  241. {
  242. LLLinkNode *tcurr = mCurrentp;
  243. LLLinkNode *tcurrop = mCurrentOperatingp;
  244. // don't allow NULL to be passed to addData
  245. if (!data)
  246. {
  247. llerror("NULL pointer passed to LLLinkedList::addDataSorted", 0);
  248. }
  249. if (checkData(data))
  250. {
  251. // restore
  252. mCurrentp = tcurr;
  253. mCurrentOperatingp = tcurrop;
  254. return FALSE;
  255. }
  256. // mInsertBefore not set?
  257. if (!mInsertBefore)
  258. {
  259. addData(data);
  260. // restore
  261. mCurrentp = tcurr;
  262. mCurrentOperatingp = tcurrop;
  263. return FALSE;
  264. }
  265. // empty list?
  266. if (!mHead.mNextp)
  267. {
  268. addData(data);
  269. // restore
  270. mCurrentp = tcurr;
  271. mCurrentOperatingp = tcurrop;
  272. return TRUE;
  273. }
  274. // make the new node
  275. LLLinkNode *temp = new LLLinkNode(data);
  276. // walk the list until mInsertBefore returns true
  277. mCurrentp = mHead.mNextp;
  278. while (mCurrentp->mNextp)
  279. {
  280. if (mInsertBefore(data, mCurrentp->mDatap))
  281. {
  282. // insert before the current one
  283. temp->mPrevpp = mCurrentp->mPrevpp;
  284. temp->mNextp = mCurrentp;
  285. *(temp->mPrevpp) = temp;
  286. mCurrentp->mPrevpp = &temp->mNextp;
  287. // restore
  288. mCurrentp = tcurr;
  289. mCurrentOperatingp = tcurrop;
  290. mCount++;
  291. return TRUE;
  292. }
  293. else
  294. {
  295. mCurrentp = mCurrentp->mNextp;
  296. }
  297. }
  298. // on the last element, add before?
  299. if (mInsertBefore(data, mCurrentp->mDatap))
  300. {
  301. // insert before the current one
  302. temp->mPrevpp = mCurrentp->mPrevpp;
  303. temp->mNextp = mCurrentp;
  304. *(temp->mPrevpp) = temp;
  305. mCurrentp->mPrevpp = &temp->mNextp;
  306. // restore
  307. mCurrentp = tcurr;
  308. mCurrentOperatingp = tcurrop;
  309. }
  310. else // insert after
  311. {
  312. temp->mPrevpp = &mCurrentp->mNextp;
  313. temp->mNextp = NULL;
  314. mCurrentp->mNextp = temp;
  315. // restore
  316. mCurrentp = tcurr;
  317. mCurrentOperatingp = tcurrop;
  318. }
  319. mCount++;
  320. return TRUE;
  321. }
  322. template <class DATA_TYPE>
  323. void LLLinkedList<DATA_TYPE>::bubbleSortList()
  324. {
  325. // mInsertBefore not set
  326. if (!mInsertBefore)
  327. {
  328. return;
  329. }
  330. LLLinkNode *tcurr = mCurrentp;
  331. LLLinkNode *tcurrop = mCurrentOperatingp;
  332. BOOL b_swapped = FALSE;
  333. DATA_TYPE *temp;
  334. // Nota Bene: This will break if more than 0x7FFFFFFF members in list!
  335. S32 length = 0x7FFFFFFF;
  336. S32 count = 0;
  337. do
  338. {
  339. b_swapped = FALSE;
  340. mCurrentp = mHead.mNextp;
  341. count = 0;
  342. while ( (count + 1 < length)
  343. &&(mCurrentp))
  344. {
  345. if (mCurrentp->mNextp)
  346. {
  347. if (!mInsertBefore(mCurrentp->mDatap, mCurrentp->mNextp->mDatap))
  348. {
  349. // swap data pointers!
  350. temp = mCurrentp->mDatap;
  351. mCurrentp->mDatap = mCurrentp->mNextp->mDatap;
  352. mCurrentp->mNextp->mDatap = temp;
  353. b_swapped = TRUE;
  354. }
  355. }
  356. else
  357. {
  358. break;
  359. }
  360. count++;
  361. mCurrentp = mCurrentp->mNextp;
  362. }
  363. length = count;
  364. } while (b_swapped);
  365. // restore
  366. mCurrentp = tcurr;
  367. mCurrentOperatingp = tcurrop;
  368. }
  369. template <class DATA_TYPE>
  370. BOOL LLLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
  371. {
  372. LLLinkNode *tcurr = mCurrentp;
  373. LLLinkNode *tcurrop = mCurrentOperatingp;
  374. // don't allow NULL to be passed to addData
  375. if (!data)
  376. {
  377. llerror("NULL pointer passed to LLLinkedList::addData", 0);
  378. }
  379. if (checkData(data))
  380. {
  381. mCurrentp = tcurr;
  382. mCurrentOperatingp = tcurrop;
  383. return FALSE;
  384. }
  385. // make the new node
  386. LLLinkNode *temp = new LLLinkNode(data);
  387. // add the node to the end of the list
  388. // if empty, add to the front and be done with it
  389. if (!mHead.mNextp)
  390. {
  391. temp->mPrevpp = &mHead.mNextp;
  392. temp->mNextp = NULL;
  393. mHead.mNextp = temp;
  394. }
  395. else
  396. {
  397. // otherwise, walk to the end of the list
  398. mCurrentp = mHead.mNextp;
  399. while (mCurrentp->mNextp)
  400. {
  401. mCurrentp = mCurrentp->mNextp;
  402. }
  403. temp->mPrevpp = &mCurrentp->mNextp;
  404. temp->mNextp = NULL;
  405. mCurrentp->mNextp = temp;
  406. }
  407. // restore
  408. mCurrentp = tcurr;
  409. mCurrentOperatingp = tcurrop;
  410. mCount++;
  411. return TRUE;
  412. }
  413. // returns number of items in the list
  414. template <class DATA_TYPE>
  415. S32 LLLinkedList<DATA_TYPE>::getLength() const
  416. {
  417. // S32 length = 0;
  418. // for (LLLinkNode* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
  419. // {
  420. // length++;
  421. // }
  422. return mCount;
  423. }
  424. template <class DATA_TYPE>
  425. BOOL LLLinkedList<DATA_TYPE>::isEmpty()
  426. {
  427. return (mCount == 0);
  428. }
  429. // search the list starting at mHead.mNextp and remove the link with mDatap == data
  430. // leave mCurrentp and mCurrentOperatingp on the next entry
  431. // return TRUE if found, FALSE if not found
  432. template <class DATA_TYPE>
  433. BOOL LLLinkedList<DATA_TYPE>::removeData(DATA_TYPE *data)
  434. {
  435. BOOL b_found = FALSE;
  436. // don't allow NULL to be passed to addData
  437. if (!data)
  438. {
  439. llerror("NULL pointer passed to LLLinkedList::removeData", 0);
  440. }
  441. LLLinkNode *tcurr = mCurrentp;
  442. LLLinkNode *tcurrop = mCurrentOperatingp;
  443. mCurrentp = mHead.mNextp;
  444. mCurrentOperatingp = mHead.mNextp;
  445. while (mCurrentOperatingp)
  446. {
  447. if (mCurrentOperatingp->mDatap == data)
  448. {
  449. b_found = TRUE;
  450. // remove the node
  451. // if there is a next one, fix it
  452. if (mCurrentOperatingp->mNextp)
  453. {
  454. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  455. }
  456. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  457. // remove the LLLinkNode
  458. // if we were on the one we want to delete, bump the cached copies
  459. if (mCurrentOperatingp == tcurrop)
  460. {
  461. tcurrop = tcurr = mCurrentOperatingp->mNextp;
  462. }
  463. else if (mCurrentOperatingp == tcurr)
  464. {
  465. tcurrop = tcurr = mCurrentOperatingp->mNextp;
  466. }
  467. mCurrentp = mCurrentOperatingp->mNextp;
  468. mCurrentOperatingp->removeData();
  469. delete mCurrentOperatingp;
  470. mCurrentOperatingp = mCurrentp;
  471. mCount--;
  472. break;
  473. }
  474. mCurrentOperatingp = mCurrentOperatingp->mNextp;
  475. }
  476. // restore
  477. mCurrentp = tcurr;
  478. mCurrentOperatingp = tcurrop;
  479. return b_found;
  480. }
  481. // search the list starting at mHead.mNextp and delete the link with mDatap == data
  482. // leave mCurrentp and mCurrentOperatingp on the next entry
  483. // return TRUE if found, FALSE if not found
  484. template <class DATA_TYPE>
  485. BOOL LLLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
  486. {
  487. BOOL b_found = FALSE;
  488. // don't allow NULL to be passed to addData
  489. if (!data)
  490. {
  491. llerror("NULL pointer passed to LLLinkedList::removeData", 0);
  492. }
  493. LLLinkNode *tcurr = mCurrentp;
  494. LLLinkNode *tcurrop = mCurrentOperatingp;
  495. mCurrentp = mHead.mNextp;
  496. mCurrentOperatingp = mHead.mNextp;
  497. while (mCurrentOperatingp)
  498. {
  499. if (mCurrentOperatingp->mDatap == data)
  500. {
  501. b_found = TRUE;
  502. // remove the node
  503. // if there is a next one, fix it
  504. if (mCurrentOperatingp->mNextp)
  505. {
  506. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  507. }
  508. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  509. // delete the LLLinkNode
  510. // if we were on the one we want to delete, bump the cached copies
  511. if (mCurrentOperatingp == tcurrop)
  512. {
  513. tcurrop = tcurr = mCurrentOperatingp->mNextp;
  514. }
  515. // and delete the associated data
  516. llassert(mCurrentOperatingp);
  517. mCurrentp = mCurrentOperatingp->mNextp;
  518. mCurrentOperatingp->deleteData();
  519. delete mCurrentOperatingp;
  520. mCurrentOperatingp = mCurrentp;
  521. mCount--;
  522. break;
  523. }
  524. mCurrentOperatingp = mCurrentOperatingp->mNextp;
  525. }
  526. // restore
  527. mCurrentp = tcurr;
  528. mCurrentOperatingp = tcurrop;
  529. return b_found;
  530. }
  531. // remove all nodes from the list and delete the associated data
  532. template <class DATA_TYPE>
  533. void LLLinkedList<DATA_TYPE>::deleteAllData()
  534. {
  535. LLLinkNode *temp;
  536. // reset mCurrentp
  537. mCurrentp = mHead.mNextp;
  538. while (mCurrentp)
  539. {
  540. temp = mCurrentp->mNextp;
  541. mCurrentp->deleteData();
  542. delete mCurrentp;
  543. mCurrentp = temp;
  544. }
  545. // reset mHead and mCurrentp
  546. mHead.mNextp = NULL;
  547. mCurrentp = mHead.mNextp;
  548. mCurrentOperatingp = mHead.mNextp;
  549. mCount = 0;
  550. }
  551. // remove all nodes from the list but do not delete data
  552. template <class DATA_TYPE>
  553. void LLLinkedList<DATA_TYPE>::removeAllNodes()
  554. {
  555. LLLinkNode *temp;
  556. // reset mCurrentp
  557. mCurrentp = mHead.mNextp;
  558. while (mCurrentp)
  559. {
  560. temp = mCurrentp->mNextp;
  561. mCurrentp->removeData();
  562. delete mCurrentp;
  563. mCurrentp = temp;
  564. }
  565. // reset mHead and mCurrentp
  566. mHead.mNextp = NULL;
  567. mCurrentp = mHead.mNextp;
  568. mCurrentOperatingp = mHead.mNextp;
  569. mCount = 0;
  570. }
  571. // check to see if data is in list
  572. // if TRUE then mCurrentp and mCurrentOperatingp point to data
  573. template <class DATA_TYPE>
  574. BOOL LLLinkedList<DATA_TYPE>::checkData(DATA_TYPE *data)
  575. {
  576. // reset mCurrentp
  577. mCurrentp = mHead.mNextp;
  578. while (mCurrentp)
  579. {
  580. if (mCurrentp->mDatap == data)
  581. {
  582. mCurrentOperatingp = mCurrentp;
  583. return TRUE;
  584. }
  585. mCurrentp = mCurrentp->mNextp;
  586. }
  587. mCurrentOperatingp = mCurrentp;
  588. return FALSE;
  589. }
  590. // place mCurrentp on first node
  591. template <class DATA_TYPE>
  592. void LLLinkedList<DATA_TYPE>::resetList()
  593. {
  594. mCurrentp = mHead.mNextp;
  595. mCurrentOperatingp = mHead.mNextp;
  596. }
  597. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  598. template <class DATA_TYPE>
  599. DATA_TYPE *LLLinkedList<DATA_TYPE>::getCurrentData()
  600. {
  601. if (mCurrentp)
  602. {
  603. mCurrentOperatingp = mCurrentp;
  604. mCurrentp = mCurrentp->mNextp;
  605. return mCurrentOperatingp->mDatap;
  606. }
  607. else
  608. {
  609. return NULL;
  610. }
  611. }
  612. // same as getCurrentData() but a more intuitive name for the operation
  613. template <class DATA_TYPE>
  614. DATA_TYPE *LLLinkedList<DATA_TYPE>::getNextData()
  615. {
  616. if (mCurrentp)
  617. {
  618. mCurrentOperatingp = mCurrentp;
  619. mCurrentp = mCurrentp->mNextp;
  620. return mCurrentOperatingp->mDatap;
  621. }
  622. else
  623. {
  624. return NULL;
  625. }
  626. }
  627. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  628. template <class DATA_TYPE>
  629. DATA_TYPE *LLLinkedList<DATA_TYPE>::getFirstData()
  630. {
  631. mCurrentp = mHead.mNextp;
  632. mCurrentOperatingp = mHead.mNextp;
  633. if (mCurrentp)
  634. {
  635. mCurrentOperatingp = mCurrentp;
  636. mCurrentp = mCurrentp->mNextp;
  637. return mCurrentOperatingp->mDatap;
  638. }
  639. else
  640. {
  641. return NULL;
  642. }
  643. }
  644. // Note: n is zero-based
  645. template <class DATA_TYPE>
  646. DATA_TYPE *LLLinkedList<DATA_TYPE>::getNthData( U32 n )
  647. {
  648. mCurrentOperatingp = mHead.mNextp;
  649. // if empty, return NULL
  650. if (!mCurrentOperatingp)
  651. {
  652. return NULL;
  653. }
  654. for( U32 i = 0; i < n; i++ )
  655. {
  656. mCurrentOperatingp = mCurrentOperatingp->mNextp;
  657. if( !mCurrentOperatingp )
  658. {
  659. return NULL;
  660. }
  661. }
  662. mCurrentp = mCurrentOperatingp->mNextp;
  663. return mCurrentOperatingp->mDatap;
  664. }
  665. // reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
  666. template <class DATA_TYPE>
  667. DATA_TYPE *LLLinkedList<DATA_TYPE>::getLastData()
  668. {
  669. mCurrentOperatingp = mHead.mNextp;
  670. // if empty, return NULL
  671. if (!mCurrentOperatingp)
  672. return NULL;
  673. // walk until we're pointing at the last entry
  674. while (mCurrentOperatingp->mNextp)
  675. {
  676. mCurrentOperatingp = mCurrentOperatingp->mNextp;
  677. }
  678. mCurrentp = mCurrentOperatingp->mNextp;
  679. return mCurrentOperatingp->mDatap;
  680. }
  681. // remove the Node at mCurentOperatingp
  682. // leave mCurrentp and mCurentOperatingp on the next entry
  683. // return TRUE if found, FALSE if not found
  684. template <class DATA_TYPE>
  685. void LLLinkedList<DATA_TYPE>::removeCurrentData()
  686. {
  687. if (mCurrentOperatingp)
  688. {
  689. // remove the node
  690. // if there is a next one, fix it
  691. if (mCurrentOperatingp->mNextp)
  692. {
  693. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  694. }
  695. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  696. // remove the LLLinkNode
  697. mCurrentp = mCurrentOperatingp->mNextp;
  698. mCurrentOperatingp->removeData();
  699. delete mCurrentOperatingp;
  700. mCount--;
  701. mCurrentOperatingp = mCurrentp;
  702. }
  703. }
  704. // remove the Node at mCurentOperatingp and add it to newlist
  705. // leave mCurrentp and mCurentOperatingp on the next entry
  706. // return TRUE if found, FALSE if not found
  707. template <class DATA_TYPE>
  708. void LLLinkedList<DATA_TYPE>::moveCurrentData(LLLinkedList *newlist, BOOL b_sort)
  709. {
  710. if (mCurrentOperatingp)
  711. {
  712. // remove the node
  713. // if there is a next one, fix it
  714. if (mCurrentOperatingp->mNextp)
  715. {
  716. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  717. }
  718. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  719. // remove the LLLinkNode
  720. mCurrentp = mCurrentOperatingp->mNextp;
  721. // move the node to the new list
  722. newlist->addData(mCurrentOperatingp);
  723. if (b_sort)
  724. bubbleSortList();
  725. mCurrentOperatingp = mCurrentp;
  726. }
  727. }
  728. template <class DATA_TYPE>
  729. BOOL LLLinkedList<DATA_TYPE>::moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort)
  730. {
  731. BOOL b_found = FALSE;
  732. // don't allow NULL to be passed to addData
  733. if (!data)
  734. {
  735. llerror("NULL pointer passed to LLLinkedList::removeData", 0);
  736. }
  737. LLLinkNode *tcurr = mCurrentp;
  738. LLLinkNode *tcurrop = mCurrentOperatingp;
  739. mCurrentp = mHead.mNextp;
  740. mCurrentOperatingp = mHead.mNextp;
  741. while (mCurrentOperatingp)
  742. {
  743. if (mCurrentOperatingp->mDatap == data)
  744. {
  745. b_found = TRUE;
  746. // remove the node
  747. // if there is a next one, fix it
  748. if (mCurrentOperatingp->mNextp)
  749. {
  750. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  751. }
  752. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  753. // if we were on the one we want to delete, bump the cached copies
  754. if ( (mCurrentOperatingp == tcurrop)
  755. ||(mCurrentOperatingp == tcurr))
  756. {
  757. tcurrop = tcurr = mCurrentOperatingp->mNextp;
  758. }
  759. // remove the LLLinkNode
  760. mCurrentp = mCurrentOperatingp->mNextp;
  761. // move the node to the new list
  762. newlist->addData(mCurrentOperatingp);
  763. if (b_sort)
  764. newlist->bubbleSortList();
  765. mCurrentOperatingp = mCurrentp;
  766. break;
  767. }
  768. mCurrentOperatingp = mCurrentOperatingp->mNextp;
  769. }
  770. // restore
  771. mCurrentp = tcurr;
  772. mCurrentOperatingp = tcurrop;
  773. return b_found;
  774. }
  775. // delete the Node at mCurentOperatingp
  776. // leave mCurrentp anf mCurentOperatingp on the next entry
  777. // return TRUE if found, FALSE if not found
  778. template <class DATA_TYPE>
  779. void LLLinkedList<DATA_TYPE>::deleteCurrentData()
  780. {
  781. if (mCurrentOperatingp)
  782. {
  783. // remove the node
  784. // if there is a next one, fix it
  785. if (mCurrentOperatingp->mNextp)
  786. {
  787. mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
  788. }
  789. *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
  790. // remove the LLLinkNode
  791. mCurrentp = mCurrentOperatingp->mNextp;
  792. mCurrentOperatingp->deleteData();
  793. if (mCurrentOperatingp->mDatap)
  794. llerror("This is impossible!", 0);
  795. delete mCurrentOperatingp;
  796. mCurrentOperatingp = mCurrentp;
  797. mCount--;
  798. }
  799. }
  800. #endif