aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llptrskipmap.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/llptrskipmap.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/llptrskipmap.h')
-rw-r--r--linden/indra/llcommon/llptrskipmap.h1238
1 files changed, 1238 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llptrskipmap.h b/linden/indra/llcommon/llptrskipmap.h
new file mode 100644
index 0000000..d4e4de3
--- /dev/null
+++ b/linden/indra/llcommon/llptrskipmap.h
@@ -0,0 +1,1238 @@
1/**
2 * @file llptrskipmap.h
3 * @brief Just like a LLSkipMap, but since it's pointers, you can call
4 * deleteAllData
5 *
6 * Copyright (c) 2003-2007, Linden Research, Inc.
7 *
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28#ifndef LL_LLPTRSKIPMAP_H
29#define LL_LLPTRSKIPMAP_H
30
31#include "llerror.h"
32#include "llrand.h"
33
34template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8>
35class LLPtrSkipMapNode
36{
37public:
38 LLPtrSkipMapNode()
39 {
40 S32 i;
41 for (i = 0; i < BINARY_DEPTH; i++)
42 {
43 mForward[i] = NULL;
44 }
45
46 U8 *zero = (U8 *)&mIndex;
47
48 for (i = 0; i < (S32)sizeof(INDEX_T); i++)
49 {
50 *(zero + i) = 0;
51 }
52
53 zero = (U8 *)&mData;
54
55 for (i = 0; i < (S32)sizeof(DATA_T); i++)
56 {
57 *(zero + i) = 0;
58 }
59 }
60
61 LLPtrSkipMapNode(const INDEX_T &index)
62 : mIndex(index)
63 {
64
65 S32 i;
66 for (i = 0; i < BINARY_DEPTH; i++)
67 {
68 mForward[i] = NULL;
69 }
70
71 U8 *zero = (U8 *)&mData;
72
73 for (i = 0; i < (S32)sizeof(DATA_T); i++)
74 {
75 *(zero + i) = 0;
76 }
77 }
78
79 LLPtrSkipMapNode(const INDEX_T &index, DATA_T datap)
80 : mIndex(index)
81 {
82
83 S32 i;
84 for (i = 0; i < BINARY_DEPTH; i++)
85 {
86 mForward[i] = NULL;
87 }
88
89 mData = datap;
90 }
91
92 ~LLPtrSkipMapNode()
93 {
94 }
95
96 // delete associated data and NULLs out pointer
97 void deleteData()
98 {
99 delete mData;
100 mData = 0;
101 }
102
103 // NULLs out pointer
104 void removeData()
105 {
106 mData = 0;
107 }
108
109 INDEX_T mIndex;
110 DATA_T mData;
111 LLPtrSkipMapNode *mForward[BINARY_DEPTH];
112
113private:
114 // Disallow copying of LLPtrSkipMapNodes by not implementing these methods.
115 LLPtrSkipMapNode(const LLPtrSkipMapNode &);
116 LLPtrSkipMapNode &operator=(const LLPtrSkipMapNode &rhs);
117};
118
119//---------------------------------------------------------------------------
120
121template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8>
122class LLPtrSkipMap
123{
124public:
125 typedef BOOL (*compare)(const DATA_T& first, const DATA_T& second);
126 typedef compare insert_func;
127 typedef compare equals_func;
128
129 void init();
130
131 // basic constructor
132 LLPtrSkipMap();
133
134 // basic constructor including sorter
135 LLPtrSkipMap(insert_func insert_first, equals_func equals);
136
137 ~LLPtrSkipMap();
138
139 void setInsertFirst(insert_func insert_first);
140 void setEquals(equals_func equals);
141
142 DATA_T &addData(const INDEX_T &index, DATA_T datap);
143 DATA_T &addData(const INDEX_T &index);
144 DATA_T &getData(const INDEX_T &index);
145 DATA_T &operator[](const INDEX_T &index);
146
147 // If index present, returns data.
148 // If index not present, adds <index,NULL> and returns NULL.
149 DATA_T &getData(const INDEX_T &index, BOOL &b_new_entry);
150
151 // returns data entry before and after index
152 BOOL getInterval(const INDEX_T &index, INDEX_T &index_before, INDEX_T &index_after,
153 DATA_T &data_before, DATA_T &data_after );
154
155 // Returns TRUE if data present in map.
156 BOOL checkData(const INDEX_T &index);
157
158 // Returns TRUE if key is present in map. This is useful if you
159 // are potentially storing NULL pointers in the map
160 BOOL checkKey(const INDEX_T &index);
161
162 // If there, returns the data.
163 // If not, returns NULL.
164 // Never adds entries to the map.
165 DATA_T getIfThere(const INDEX_T &index);
166
167 INDEX_T reverseLookup(const DATA_T datap);
168
169 // returns number of items in the list
170 S32 getLength(); // WARNING! getLength is O(n), not O(1)!
171
172 BOOL removeData(const INDEX_T &index);
173 BOOL deleteData(const INDEX_T &index);
174
175 // remove all nodes from the list but do not delete data
176 void removeAllData();
177 void deleteAllData();
178
179 // place mCurrentp on first node
180 void resetList();
181
182 // return the data currently pointed to
183 DATA_T getCurrentDataWithoutIncrement();
184
185 // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
186 DATA_T getCurrentData();
187
188 // same as getCurrentData() but a more intuitive name for the operation
189 DATA_T getNextData();
190
191 INDEX_T getNextKey();
192
193 // return the key currently pointed to
194 INDEX_T getCurrentKeyWithoutIncrement();
195
196 // remove the Node at mCurentOperatingp
197 // leave mCurrentp and mCurentOperatingp on the next entry
198 void removeCurrentData();
199
200 void deleteCurrentData();
201
202 // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
203 DATA_T getFirstData();
204
205 INDEX_T getFirstKey();
206
207 static BOOL defaultEquals(const INDEX_T &first, const INDEX_T &second)
208 {
209 return first == second;
210 }
211
212private:
213 // don't generate implicit copy constructor or copy assignment
214 LLPtrSkipMap(const LLPtrSkipMap &);
215 LLPtrSkipMap &operator=(const LLPtrSkipMap &);
216
217private:
218 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> mHead;
219 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mUpdate[BINARY_DEPTH];
220 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentp;
221 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentOperatingp;
222 S32 mLevel;
223 BOOL (*mInsertFirst)(const INDEX_T &first, const INDEX_T &second);
224 BOOL (*mEquals)(const INDEX_T &first, const INDEX_T &second);
225 S32 mNumberOfSteps;
226};
227
228//////////////////////////////////////////////////
229//
230// LLPtrSkipMap implementation
231//
232//
233
234template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
235inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap()
236 : mInsertFirst(NULL),
237 mEquals(defaultEquals)
238{
239 if (BINARY_DEPTH < 2)
240 {
241 llerrs << "Trying to create skip list with too little depth, "
242 "must be 2 or greater" << llendl;
243 }
244 S32 i;
245 for (i = 0; i < BINARY_DEPTH; i++)
246 {
247 mUpdate[i] = NULL;
248 }
249 mLevel = 1;
250 mCurrentp = *(mHead.mForward);
251 mCurrentOperatingp = *(mHead.mForward);
252}
253
254template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
255inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first,
256 equals_func equals)
257: mInsertFirst(insert_first),
258 mEquals(equals)
259{
260 if (BINARY_DEPTH < 2)
261 {
262 llerrs << "Trying to create skip list with too little depth, "
263 "must be 2 or greater" << llendl;
264 }
265 mLevel = 1;
266 S32 i;
267 for (i = 0; i < BINARY_DEPTH; i++)
268 {
269 mHead.mForward[i] = NULL;
270 mUpdate[i] = NULL;
271 }
272 mCurrentp = *(mHead.mForward);
273 mCurrentOperatingp = *(mHead.mForward);
274}
275
276template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
277inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::~LLPtrSkipMap()
278{
279 removeAllData();
280}
281
282template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
283inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
284{
285 mInsertFirst = insert_first;
286}
287
288template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
289inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setEquals(equals_func equals)
290{
291 mEquals = equals;
292}
293
294template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
295inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index, DATA_T datap)
296{
297 S32 level;
298 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
299 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
300
301 // find the pointer one in front of the one we want
302 if (mInsertFirst)
303 {
304 for (level = mLevel - 1; level >= 0; level--)
305 {
306 temp = *(current->mForward + level);
307 while ( (temp)
308 &&(mInsertFirst(temp->mIndex, index)))
309 {
310 current = temp;
311 temp = *(current->mForward + level);
312 }
313 *(mUpdate + level) = current;
314 }
315 }
316 else
317 {
318 for (level = mLevel - 1; level >= 0; level--)
319 {
320 temp = *(current->mForward + level);
321 while ( (temp)
322 &&(temp->mIndex < index))
323 {
324 current = temp;
325 temp = *(current->mForward + level);
326 }
327 *(mUpdate + level) = current;
328 }
329 }
330
331 // we're now just in front of where we want to be . . . take one step forward
332 current = *current->mForward;
333
334 // replace the existing data if a node is already there
335 if ( (current)
336 &&(mEquals(current->mIndex, index)))
337 {
338 current->mData = datap;
339 return current->mData;
340 }
341
342 // now add the new node
343 S32 newlevel;
344 for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
345 {
346 if (frand(1.f) < 0.5f)
347 {
348 break;
349 }
350 }
351
352 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
353 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index, datap);
354
355 if (newlevel > mLevel)
356 {
357 mHead.mForward[mLevel] = NULL;
358 mUpdate[mLevel] = &mHead;
359 mLevel = newlevel;
360 }
361
362 for (level = 0; level < newlevel; level++)
363 {
364 snode->mForward[level] = mUpdate[level]->mForward[level];
365 mUpdate[level]->mForward[level] = snode;
366 }
367 return snode->mData;
368}
369
370template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
371inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index)
372{
373 S32 level;
374 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
375 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
376
377 // find the pointer one in front of the one we want
378 if (mInsertFirst)
379 {
380 for (level = mLevel - 1; level >= 0; level--)
381 {
382 temp = *(current->mForward + level);
383 while ( (temp)
384 &&(mInsertFirst(temp->mIndex, index)))
385 {
386 current = temp;
387 temp = *(current->mForward + level);
388 }
389 *(mUpdate + level) = current;
390 }
391 }
392 else
393 {
394 for (level = mLevel - 1; level >= 0; level--)
395 {
396 temp = *(current->mForward + level);
397 while ( (temp)
398 &&(temp->mIndex < index))
399 {
400 current = temp;
401 temp = *(current->mForward + level);
402 }
403 *(mUpdate + level) = current;
404 }
405 }
406
407 // we're now just in front of where we want to be . . . take one step forward
408 current = *current->mForward;
409
410 // now add the new node
411 S32 newlevel;
412 for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
413 {
414 if (frand(1.f) < 0.5f)
415 break;
416 }
417
418 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
419 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
420
421 if (newlevel > mLevel)
422 {
423 mHead.mForward[mLevel] = NULL;
424 mUpdate[mLevel] = &mHead;
425 mLevel = newlevel;
426 }
427
428 for (level = 0; level < newlevel; level++)
429 {
430 snode->mForward[level] = mUpdate[level]->mForward[level];
431 mUpdate[level]->mForward[level] = snode;
432 }
433 return snode->mData;
434}
435
436template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
437inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index)
438{
439 S32 level;
440 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
441 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
442
443 mNumberOfSteps = 0;
444
445 // find the pointer one in front of the one we want
446 if (mInsertFirst)
447 {
448 for (level = mLevel - 1; level >= 0; level--)
449 {
450 temp = *(current->mForward + level);
451 while ( (temp)
452 &&(mInsertFirst(temp->mIndex, index)))
453 {
454 current = temp;
455 temp = *(current->mForward + level);
456 mNumberOfSteps++;
457 }
458 *(mUpdate + level) = current;
459 }
460 }
461 else
462 {
463 for (level = mLevel - 1; level >= 0; level--)
464 {
465 temp = *(current->mForward + level);
466 while ( (temp)
467 &&(temp->mIndex < index))
468 {
469 current = temp;
470 temp = *(current->mForward + level);
471 mNumberOfSteps++;
472 }
473 *(mUpdate + level) = current;
474 }
475 }
476
477 // we're now just in front of where we want to be . . . take one step forward
478 current = *current->mForward;
479 mNumberOfSteps++;
480
481 if ( (current)
482 &&(mEquals(current->mIndex, index)))
483 {
484
485 return current->mData;
486 }
487
488 // now add the new node
489 S32 newlevel;
490 for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
491 {
492 if (frand(1.f) < 0.5f)
493 break;
494 }
495
496 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
497 = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
498
499 if (newlevel > mLevel)
500 {
501 mHead.mForward[mLevel] = NULL;
502 mUpdate[mLevel] = &mHead;
503 mLevel = newlevel;
504 }
505
506 for (level = 0; level < newlevel; level++)
507 {
508 snode->mForward[level] = mUpdate[level]->mForward[level];
509 mUpdate[level]->mForward[level] = snode;
510 }
511
512 return snode->mData;
513}
514
515template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
516inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getInterval(const INDEX_T &index,
517 INDEX_T &index_before,
518 INDEX_T &index_after,
519 DATA_T &data_before,
520 DATA_T &data_after)
521{
522 S32 level;
523 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
524 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
525
526 mNumberOfSteps = 0;
527
528 // find the pointer one in front of the one we want
529 if (mInsertFirst)
530 {
531 for (level = mLevel - 1; level >= 0; level--)
532 {
533 temp = *(current->mForward + level);
534 while ( (temp)
535 &&(mInsertFirst(temp->mIndex, index)))
536 {
537 current = temp;
538 temp = *(current->mForward + level);
539 mNumberOfSteps++;
540 }
541 *(mUpdate + level) = current;
542 }
543 }
544 else
545 {
546 for (level = mLevel - 1; level >= 0; level--)
547 {
548 temp = *(current->mForward + level);
549 while ( (temp)
550 &&(temp->mIndex < index))
551 {
552 current = temp;
553 temp = *(current->mForward + level);
554 mNumberOfSteps++;
555 }
556 *(mUpdate + level) = current;
557 }
558 }
559
560 BOOL both_found = TRUE;
561
562 if (current != &mHead)
563 {
564 index_before = current->mIndex;
565 data_before = current->mData;
566 }
567 else
568 {
569 data_before = 0;
570 index_before = 0;
571 both_found = FALSE;
572 }
573
574 // we're now just in front of where we want to be . . . take one step forward
575 mNumberOfSteps++;
576 current = *current->mForward;
577
578 if (current)
579 {
580 data_after = current->mData;
581 index_after = current->mIndex;
582 }
583 else
584 {
585 data_after = 0;
586 index_after = 0;
587 both_found = FALSE;
588 }
589
590 return both_found;
591}
592
593
594template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
595inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::operator[](const INDEX_T &index)
596{
597
598 return getData(index);
599}
600
601// If index present, returns data.
602// If index not present, adds <index,NULL> and returns NULL.
603template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
604inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index, BOOL &b_new_entry)
605{
606 S32 level;
607 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
608 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
609
610 mNumberOfSteps = 0;
611
612 // find the pointer one in front of the one we want
613 if (mInsertFirst)
614 {
615 for (level = mLevel - 1; level >= 0; level--)
616 {
617 temp = *(current->mForward + level);
618 while ( (temp)
619 &&(mInsertFirst(temp->mIndex, index)))
620 {
621 current = temp;
622 temp = *(current->mForward + level);
623 mNumberOfSteps++;
624 }
625 *(mUpdate + level) = current;
626 }
627 }
628 else
629 {
630 for (level = mLevel - 1; level >= 0; level--)
631 {
632 temp = *(current->mForward + level);
633 while ( (temp)
634 &&(temp->mIndex < index))
635 {
636 current = temp;
637 temp = *(current->mForward + level);
638 mNumberOfSteps++;
639 }
640 *(mUpdate + level) = current;
641 }
642 }
643
644 // we're now just in front of where we want to be . . . take one step forward
645 mNumberOfSteps++;
646 current = *current->mForward;
647
648 if ( (current)
649 &&(mEquals(current->mIndex, index)))
650 {
651
652 return current->mData;
653 }
654 b_new_entry = TRUE;
655 addData(index);
656
657 return current->mData;
658}
659
660// Returns TRUE if data present in map.
661template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
662inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkData(const INDEX_T &index)
663{
664 S32 level;
665 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
666 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
667
668 // find the pointer one in front of the one we want
669 if (mInsertFirst)
670 {
671 for (level = mLevel - 1; level >= 0; level--)
672 {
673 temp = *(current->mForward + level);
674 while ( (temp)
675 &&(mInsertFirst(temp->mIndex, index)))
676 {
677 current = temp;
678 temp = *(current->mForward + level);
679 }
680 *(mUpdate + level) = current;
681 }
682 }
683 else
684 {
685 for (level = mLevel - 1; level >= 0; level--)
686 {
687 temp = *(current->mForward + level);
688 while ( (temp)
689 &&(temp->mIndex < index))
690 {
691 current = temp;
692 temp = *(current->mForward + level);
693 }
694 *(mUpdate + level) = current;
695 }
696 }
697
698 // we're now just in front of where we want to be . . . take one step forward
699 current = *current->mForward;
700
701 if (current)
702 {
703 // Gets rid of some compiler ambiguity for the LLPointer<> templated class.
704 if (current->mData)
705 {
706 return mEquals(current->mIndex, index);
707 }
708 }
709
710 return FALSE;
711}
712
713// Returns TRUE if key is present in map. This is useful if you
714// are potentially storing NULL pointers in the map
715template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
716inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkKey(const INDEX_T &index)
717{
718 S32 level;
719 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
720 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
721
722 // find the pointer one in front of the one we want
723 if (mInsertFirst)
724 {
725 for (level = mLevel - 1; level >= 0; level--)
726 {
727 temp = *(current->mForward + level);
728 while ( (temp)
729 &&(mInsertFirst(temp->mIndex, index)))
730 {
731 current = temp;
732 temp = *(current->mForward + level);
733 }
734 *(mUpdate + level) = current;
735 }
736 }
737 else
738 {
739 for (level = mLevel - 1; level >= 0; level--)
740 {
741 temp = *(current->mForward + level);
742 while ( (temp)
743 &&(temp->mIndex < index))
744 {
745 current = temp;
746 temp = *(current->mForward + level);
747 }
748 *(mUpdate + level) = current;
749 }
750 }
751
752 // we're now just in front of where we want to be . . . take one step forward
753 current = *current->mForward;
754
755 if (current)
756 {
757 return mEquals(current->mIndex, index);
758 }
759
760 return FALSE;
761}
762
763// If there, returns the data.
764// If not, returns NULL.
765// Never adds entries to the map.
766template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
767inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getIfThere(const INDEX_T &index)
768{
769 S32 level;
770 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
771 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
772
773 mNumberOfSteps = 0;
774
775 // find the pointer one in front of the one we want
776 if (mInsertFirst)
777 {
778 for (level = mLevel - 1; level >= 0; level--)
779 {
780 temp = *(current->mForward + level);
781 while ( (temp)
782 &&(mInsertFirst(temp->mIndex, index)))
783 {
784 current = temp;
785 temp = *(current->mForward + level);
786 mNumberOfSteps++;
787 }
788 *(mUpdate + level) = current;
789 }
790 }
791 else
792 {
793 for (level = mLevel - 1; level >= 0; level--)
794 {
795 temp = *(current->mForward + level);
796 while ( (temp)
797 &&(temp->mIndex < index))
798 {
799 current = temp;
800 temp = *(current->mForward + level);
801 mNumberOfSteps++;
802 }
803 *(mUpdate + level) = current;
804 }
805 }
806
807 // we're now just in front of where we want to be . . . take one step forward
808 mNumberOfSteps++;
809 current = *current->mForward;
810
811 if (current)
812 {
813 if (mEquals(current->mIndex, index))
814 {
815 return current->mData;
816 }
817 }
818
819 // Avoid Linux compiler warning on returning NULL.
820 return (DATA_T)0;
821}
822
823template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
824inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::reverseLookup(const DATA_T datap)
825{
826 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
827
828 while (current)
829 {
830 if (datap == current->mData)
831 {
832
833 return current->mIndex;
834 }
835 current = *current->mForward;
836 }
837
838 // not found! return NULL
839 return INDEX_T();
840}
841
842// returns number of items in the list
843template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
844inline S32 LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getLength()
845{
846 U32 length = 0;
847 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>* temp;
848 for (temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
849 {
850 length++;
851 }
852
853 return length;
854}
855
856template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
857inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeData(const INDEX_T &index)
858{
859 S32 level;
860 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
861 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
862
863 // find the pointer one in front of the one we want
864 if (mInsertFirst)
865 {
866 for (level = mLevel - 1; level >= 0; level--)
867 {
868 temp = *(current->mForward + level);
869 while ( (temp)
870 &&(mInsertFirst(temp->mIndex, index)))
871 {
872 current = temp;
873 temp = *(current->mForward + level);
874 }
875 *(mUpdate + level) = current;
876 }
877 }
878 else
879 {
880 for (level = mLevel - 1; level >= 0; level--)
881 {
882 temp = *(current->mForward + level);
883 while ( (temp)
884 &&(temp->mIndex < index))
885 {
886 current = temp;
887 temp = *(current->mForward + level);
888 }
889 *(mUpdate + level) = current;
890 }
891 }
892
893 // we're now just in front of where we want to be . . . take one step forward
894 current = *current->mForward;
895
896 if (!current)
897 {
898 // empty list or beyond the end!
899
900 return FALSE;
901 }
902
903 // is this the one we want?
904 if (!mEquals(current->mIndex, index))
905 {
906 // nope!
907
908 return FALSE;
909 }
910 else
911 {
912 // do we need to fix current or currentop?
913 if (current == mCurrentp)
914 {
915 mCurrentp = *current->mForward;
916 }
917
918 if (current == mCurrentOperatingp)
919 {
920 mCurrentOperatingp = *current->mForward;
921 }
922 // yes it is! change pointers as required
923 for (level = 0; level < mLevel; level++)
924 {
925 if (*((*(mUpdate + level))->mForward + level) != current)
926 {
927 // cool, we've fixed all the pointers!
928 break;
929 }
930 *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
931 }
932
933 // clean up cuurent
934 current->removeData();
935 delete current;
936
937 // clean up mHead
938 while ( (mLevel > 1)
939 &&(!*(mHead.mForward + mLevel - 1)))
940 {
941 mLevel--;
942 }
943 }
944
945 return TRUE;
946}
947
948template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
949inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteData(const INDEX_T &index)
950{
951 S32 level;
952 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
953 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
954
955 // find the pointer one in front of the one we want
956 if (mInsertFirst)
957 {
958 for (level = mLevel - 1; level >= 0; level--)
959 {
960 temp = *(current->mForward + level);
961 while ( (temp)
962 &&(mInsertFirst(temp->mIndex, index)))
963 {
964 current = temp;
965 temp = *(current->mForward + level);
966 }
967 *(mUpdate + level) = current;
968 }
969 }
970 else
971 {
972 for (level = mLevel - 1; level >= 0; level--)
973 {
974 temp = *(current->mForward + level);
975 while ( (temp)
976 &&(temp->mIndex < index))
977 {
978 current = temp;
979 temp = *(current->mForward + level);
980 }
981 *(mUpdate + level) = current;
982 }
983 }
984
985 // we're now just in front of where we want to be . . . take one step forward
986 current = *current->mForward;
987
988 if (!current)
989 {
990 // empty list or beyond the end!
991
992 return FALSE;
993 }
994
995 // is this the one we want?
996 if (!mEquals(current->mIndex, index))
997 {
998 // nope!
999
1000 return FALSE;
1001 }
1002 else
1003 {
1004 // do we need to fix current or currentop?
1005 if (current == mCurrentp)
1006 {
1007 mCurrentp = *current->mForward;
1008 }
1009
1010 if (current == mCurrentOperatingp)
1011 {
1012 mCurrentOperatingp = *current->mForward;
1013 }
1014 // yes it is! change pointers as required
1015 for (level = 0; level < mLevel; level++)
1016 {
1017 if (*((*(mUpdate + level))->mForward + level) != current)
1018 {
1019 // cool, we've fixed all the pointers!
1020 break;
1021 }
1022 *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
1023 }
1024
1025 // clean up cuurent
1026 current->deleteData();
1027 delete current;
1028
1029 // clean up mHead
1030 while ( (mLevel > 1)
1031 &&(!*(mHead.mForward + mLevel - 1)))
1032 {
1033 mLevel--;
1034 }
1035 }
1036
1037 return TRUE;
1038}
1039
1040// remove all nodes from the list but do not delete data
1041template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1042void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeAllData()
1043{
1044 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
1045 // reset mCurrentp
1046 mCurrentp = *(mHead.mForward);
1047
1048 while (mCurrentp)
1049 {
1050 temp = mCurrentp->mForward[0];
1051 mCurrentp->removeData();
1052 delete mCurrentp;
1053 mCurrentp = temp;
1054 }
1055
1056 S32 i;
1057 for (i = 0; i < BINARY_DEPTH; i++)
1058 {
1059 mHead.mForward[i] = NULL;
1060 mUpdate[i] = NULL;
1061 }
1062
1063 mCurrentp = *(mHead.mForward);
1064 mCurrentOperatingp = *(mHead.mForward);
1065}
1066
1067template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1068inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteAllData()
1069{
1070 LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
1071 // reset mCurrentp
1072 mCurrentp = *(mHead.mForward);
1073
1074 while (mCurrentp)
1075 {
1076 temp = mCurrentp->mForward[0];
1077 mCurrentp->deleteData();
1078 delete mCurrentp;
1079 mCurrentp = temp;
1080 }
1081
1082 S32 i;
1083 for (i = 0; i < BINARY_DEPTH; i++)
1084 {
1085 mHead.mForward[i] = NULL;
1086 mUpdate[i] = NULL;
1087 }
1088
1089 mCurrentp = *(mHead.mForward);
1090 mCurrentOperatingp = *(mHead.mForward);
1091}
1092
1093// place mCurrentp on first node
1094template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1095inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::resetList()
1096{
1097 mCurrentp = *(mHead.mForward);
1098 mCurrentOperatingp = *(mHead.mForward);
1099}
1100
1101
1102// return the data currently pointed to
1103template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1104inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
1105{
1106 if (mCurrentOperatingp)
1107 {
1108 return mCurrentOperatingp->mData;
1109 }
1110 else
1111 {
1112 //return NULL; // causes warning
1113 return (DATA_T)0; // equivalent, but no warning
1114 }
1115}
1116
1117// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
1118template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1119inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentData()
1120{
1121 if (mCurrentp)
1122 {
1123 mCurrentOperatingp = mCurrentp;
1124 mCurrentp = mCurrentp->mForward[0];
1125 return mCurrentOperatingp->mData;
1126 }
1127 else
1128 {
1129 //return NULL; // causes warning
1130 return (DATA_T)0; // equivalent, but no warning
1131 }
1132}
1133
1134// same as getCurrentData() but a more intuitive name for the operation
1135template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1136inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextData()
1137{
1138 if (mCurrentp)
1139 {
1140 mCurrentOperatingp = mCurrentp;
1141 mCurrentp = mCurrentp->mForward[0];
1142 return mCurrentOperatingp->mData;
1143 }
1144 else
1145 {
1146 //return NULL; // causes compile warning
1147 return (DATA_T)0; // equivalent, but removes warning
1148 }
1149}
1150
1151template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1152inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextKey()
1153{
1154 if (mCurrentp)
1155 {
1156 mCurrentOperatingp = mCurrentp;
1157 mCurrentp = mCurrentp->mForward[0];
1158 return mCurrentOperatingp->mIndex;
1159 }
1160 else
1161 {
1162 return mHead.mIndex;
1163 }
1164}
1165
1166// return the key currently pointed to
1167template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1168inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
1169{
1170 if (mCurrentOperatingp)
1171 {
1172 return mCurrentOperatingp->mIndex;
1173 }
1174 else
1175 {
1176 //return NULL; // causes compile warning
1177 return (INDEX_T)0; // equivalent, but removes warning
1178 }
1179}
1180
1181
1182// remove the Node at mCurentOperatingp
1183// leave mCurrentp and mCurentOperatingp on the next entry
1184template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1185inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeCurrentData()
1186{
1187 if (mCurrentOperatingp)
1188 {
1189 removeData(mCurrentOperatingp->mIndex);
1190 }
1191}
1192
1193template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1194inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteCurrentData()
1195{
1196 if (mCurrentOperatingp)
1197 {
1198 deleteData(mCurrentOperatingp->mIndex);
1199 }
1200}
1201
1202// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
1203template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1204inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstData()
1205{
1206 mCurrentp = *(mHead.mForward);
1207 mCurrentOperatingp = *(mHead.mForward);
1208 if (mCurrentp)
1209 {
1210 mCurrentOperatingp = mCurrentp;
1211 mCurrentp = mCurrentp->mForward[0];
1212 return mCurrentOperatingp->mData;
1213 }
1214 else
1215 {
1216 //return NULL; // causes compile warning
1217 return (DATA_T)0; // equivalent, but removes warning
1218 }
1219}
1220
1221template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
1222inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstKey()
1223{
1224 mCurrentp = *(mHead.mForward);
1225 mCurrentOperatingp = *(mHead.mForward);
1226 if (mCurrentp)
1227 {
1228 mCurrentOperatingp = mCurrentp;
1229 mCurrentp = mCurrentp->mForward[0];
1230 return mCurrentOperatingp->mIndex;
1231 }
1232 else
1233 {
1234 return mHead.mIndex;
1235 }
1236}
1237
1238#endif