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