linked_lists.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:22k
源码类别:

游戏引擎

开发平台:

C++ Builder

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