diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llcommon/linked_lists.h | |
parent | README.txt (diff) | |
download | meta-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.h | 938 |
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 | |||
41 | template <class DATA_TYPE> class LLLinkedList | ||
42 | { | ||
43 | public: | ||
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 | |||
158 | private: | ||
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 | |||
225 | template <class DATA_TYPE> | ||
226 | BOOL 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 | |||
265 | template <class DATA_TYPE> | ||
266 | BOOL 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 | |||
298 | template <class DATA_TYPE> | ||
299 | BOOL 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 | |||
389 | template <class DATA_TYPE> | ||
390 | void 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 | |||
442 | template <class DATA_TYPE> | ||
443 | BOOL 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 | ||
495 | template <class DATA_TYPE> | ||
496 | S32 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 | |||
507 | template <class DATA_TYPE> | ||
508 | BOOL 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 | ||
517 | template <class DATA_TYPE> | ||
518 | BOOL 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 | ||
579 | template <class DATA_TYPE> | ||
580 | BOOL 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 | ||
634 | template <class DATA_TYPE> | ||
635 | void 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 | ||
657 | template <class DATA_TYPE> | ||
658 | void 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 | ||
681 | template <class DATA_TYPE> | ||
682 | BOOL 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 | ||
701 | template <class DATA_TYPE> | ||
702 | void 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 | ||
709 | template <class DATA_TYPE> | ||
710 | DATA_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 | ||
725 | template <class DATA_TYPE> | ||
726 | DATA_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 | ||
741 | template <class DATA_TYPE> | ||
742 | DATA_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 | ||
759 | template <class DATA_TYPE> | ||
760 | DATA_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 | ||
785 | template <class DATA_TYPE> | ||
786 | DATA_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 | ||
806 | template <class DATA_TYPE> | ||
807 | void 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 | ||
832 | template <class DATA_TYPE> | ||
833 | void 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 | |||
855 | template <class DATA_TYPE> | ||
856 | BOOL 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 | ||
913 | template <class DATA_TYPE> | ||
914 | void 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 | ||