aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon/llskiplist.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/llskiplist.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/llskiplist.h')
-rw-r--r--linden/indra/llcommon/llskiplist.h521
1 files changed, 521 insertions, 0 deletions
diff --git a/linden/indra/llcommon/llskiplist.h b/linden/indra/llcommon/llskiplist.h
new file mode 100644
index 0000000..0d85749
--- /dev/null
+++ b/linden/indra/llcommon/llskiplist.h
@@ -0,0 +1,521 @@
1/**
2 * @file llskiplist.h
3 * @brief skip list implementation
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#ifndef LL_LLSKIPLIST_H
28#define LL_LLSKIPLIST_H
29
30#include "llerror.h"
31//#include "vmath.h"
32
33// NOTA BENE: Insert first needs to be < NOT <=
34
35template <class DATA_TYPE, S32 BINARY_DEPTH = 10>
36class LLSkipList
37{
38public:
39 typedef BOOL (*compare)(const DATA_TYPE& first, const DATA_TYPE& second);
40 typedef compare insert_func;
41 typedef compare equals_func;
42
43 void init();
44
45 // basic constructor
46 LLSkipList();
47
48 // basic constructor including sorter
49 LLSkipList(insert_func insert_first, equals_func equals);
50 ~LLSkipList();
51
52 inline void setInsertFirst(insert_func insert_first);
53 inline void setEquals(equals_func equals);
54
55 inline BOOL addData(const DATA_TYPE& data);
56 inline BOOL checkData(const DATA_TYPE& data);
57
58 // returns number of items in the list
59 inline S32 getLength() const; // NOT a constant time operation, traverses entire list!
60
61 inline BOOL moveData(const DATA_TYPE& data, LLSkipList *newlist);
62
63 inline BOOL removeData(const DATA_TYPE& data);
64
65 // remove all nodes from the list but do not delete data
66 inline void removeAllNodes();
67
68 // place mCurrentp on first node
69 inline void resetList();
70
71 // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
72 inline DATA_TYPE getCurrentData();
73
74 // same as getCurrentData() but a more intuitive name for the operation
75 inline DATA_TYPE getNextData();
76
77 // remove the Node at mCurentOperatingp
78 // leave mCurrentp and mCurentOperatingp on the next entry
79 inline void removeCurrentData();
80
81 // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
82 inline DATA_TYPE getFirstData();
83
84 class LLSkipNode
85 {
86 public:
87 LLSkipNode()
88 : mData(0)
89 {
90 S32 i;
91 for (i = 0; i < BINARY_DEPTH; i++)
92 {
93 mForward[i] = NULL;
94 }
95 }
96
97 LLSkipNode(DATA_TYPE data)
98 : mData(data)
99 {
100 S32 i;
101 for (i = 0; i < BINARY_DEPTH; i++)
102 {
103 mForward[i] = NULL;
104 }
105 }
106
107 ~LLSkipNode()
108 {
109 }
110
111 DATA_TYPE mData;
112 LLSkipNode *mForward[BINARY_DEPTH];
113
114 private:
115 // Disallow copying of LLSkipNodes by not implementing these methods.
116 LLSkipNode(const LLSkipNode &);
117 LLSkipNode &operator=(const LLSkipNode &);
118 };
119
120 static BOOL defaultEquals(const DATA_TYPE& first, const DATA_TYPE& second)
121 {
122 return first == second;
123 }
124
125private:
126 LLSkipNode mHead;
127 LLSkipNode *mUpdate[BINARY_DEPTH];
128 LLSkipNode *mCurrentp;
129 LLSkipNode *mCurrentOperatingp;
130 S32 mLevel;
131 insert_func mInsertFirst;
132 equals_func mEquals;
133
134private:
135 // Disallow copying of LLSkipNodes by not implementing these methods.
136 LLSkipList(const LLSkipList &);
137 LLSkipList &operator=(const LLSkipList &);
138};
139
140
141///////////////////////
142//
143// Implementation
144//
145
146template <class DATA_TYPE, S32 BINARY_DEPTH>
147inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::init()
148{
149 if (BINARY_DEPTH < 2)
150 {
151 llerrs << "Trying to create skip list with too little depth, "
152 "must be 2 or greater" << llendl;
153 }
154 S32 i;
155 for (i = 0; i < BINARY_DEPTH; i++)
156 {
157 mHead.mForward[i] = NULL;
158 mUpdate[i] = NULL;
159 }
160 mLevel = 1;
161 mCurrentp = *(mHead.mForward);
162 mCurrentOperatingp = *(mHead.mForward);
163}
164
165
166// basic constructor
167template <class DATA_TYPE, S32 BINARY_DEPTH>
168inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList()
169: mInsertFirst(NULL),
170 mEquals(defaultEquals)
171{
172 init();
173}
174
175// basic constructor including sorter
176template <class DATA_TYPE, S32 BINARY_DEPTH>
177inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList(insert_func insert,
178 equals_func equals)
179: mInsertFirst(insert),
180 mEquals(equals)
181{
182 init();
183}
184
185template <class DATA_TYPE, S32 BINARY_DEPTH>
186inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::~LLSkipList()
187{
188 removeAllNodes();
189}
190
191template <class DATA_TYPE, S32 BINARY_DEPTH>
192inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
193{
194 mInsertFirst = insert_first;
195}
196
197template <class DATA_TYPE, S32 BINARY_DEPTH>
198inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(equals_func equals)
199{
200 mEquals = equals;
201}
202
203template <class DATA_TYPE, S32 BINARY_DEPTH>
204inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::addData(const DATA_TYPE& data)
205{
206 S32 level;
207 LLSkipNode *current = &mHead;
208 LLSkipNode *temp;
209 // find the pointer one in front of the one we want
210 if (mInsertFirst)
211 {
212 for (level = mLevel - 1; level >= 0; level--)
213 {
214 temp = *(current->mForward + level);
215 while ( (temp)
216 &&(mInsertFirst(temp->mData, data)))
217 {
218 current = temp;
219 temp = *(current->mForward + level);
220 }
221 *(mUpdate + level) = current;
222 }
223 }
224 else
225 {
226 for (level = mLevel - 1; level >= 0; level--)
227 {
228 temp = *(current->mForward + level);
229 while ( (temp)
230 &&(temp->mData < data))
231 {
232 current = temp;
233 temp = *(current->mForward + level);
234 }
235 *(mUpdate + level) = current;
236 }
237 }
238 // we're now just in front of where we want to be . . . take one step forward
239 current = *current->mForward;
240
241 // now add the new node
242 S32 newlevel;
243 for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
244 {
245 if (frand(1.f) < 0.5f)
246 break;
247 }
248
249 LLSkipNode *snode = new LLSkipNode(data);
250
251 if (newlevel > mLevel)
252 {
253 mHead.mForward[mLevel] = NULL;
254 mUpdate[mLevel] = &mHead;
255 mLevel = newlevel;
256 }
257
258 for (level = 0; level < newlevel; level++)
259 {
260 snode->mForward[level] = mUpdate[level]->mForward[level];
261 mUpdate[level]->mForward[level] = snode;
262 }
263 return TRUE;
264}
265
266template <class DATA_TYPE, S32 BINARY_DEPTH>
267inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE& data)
268{
269 S32 level;
270 LLSkipNode *current = &mHead;
271 LLSkipNode *temp;
272 // find the pointer one in front of the one we want
273 if (mInsertFirst)
274 {
275 for (level = mLevel - 1; level >= 0; level--)
276 {
277 temp = *(current->mForward + level);
278 while ( (temp)
279 &&(mInsertFirst(temp->mData, data)))
280 {
281 current = temp;
282 temp = *(current->mForward + level);
283 }
284 *(mUpdate + level) = current;
285 }
286 }
287 else
288 {
289 for (level = mLevel - 1; level >= 0; level--)
290 {
291 temp = *(current->mForward + level);
292 while ( (temp)
293 &&(temp->mData < data))
294 {
295 current = temp;
296 temp = *(current->mForward + level);
297 }
298 *(mUpdate + level) = current;
299 }
300 }
301 // we're now just in front of where we want to be . . . take one step forward
302 current = *current->mForward;
303
304
305 if (current)
306 {
307 return mEquals(current->mData, data);
308 }
309
310 return FALSE;
311}
312
313// returns number of items in the list
314template <class DATA_TYPE, S32 BINARY_DEPTH>
315inline S32 LLSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() const
316{
317 U32 length = 0;
318 for (LLSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
319 {
320 length++;
321 }
322 return length;
323}
324
325
326template <class DATA_TYPE, S32 BINARY_DEPTH>
327inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE& data, LLSkipList *newlist)
328{
329 BOOL removed = removeData(data);
330 BOOL added = newlist->addData(data);
331 return removed && added;
332}
333
334
335template <class DATA_TYPE, S32 BINARY_DEPTH>
336inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE& data)
337{
338 S32 level;
339 LLSkipNode *current = &mHead;
340 LLSkipNode *temp;
341 // find the pointer one in front of the one we want
342 if (mInsertFirst)
343 {
344 for (level = mLevel - 1; level >= 0; level--)
345 {
346 temp = *(current->mForward + level);
347 while ( (temp)
348 &&(mInsertFirst(temp->mData, data)))
349 {
350 current = temp;
351 temp = *(current->mForward + level);
352 }
353 *(mUpdate + level) = current;
354 }
355 }
356 else
357 {
358 for (level = mLevel - 1; level >= 0; level--)
359 {
360 temp = *(current->mForward + level);
361 while ( (temp)
362 &&(temp->mData < data))
363 {
364 current = temp;
365 temp = *(current->mForward + level);
366 }
367 *(mUpdate + level) = current;
368 }
369 }
370 // we're now just in front of where we want to be . . . take one step forward
371 current = *current->mForward;
372
373
374 if (!current)
375 {
376 // empty list or beyond the end!
377 return FALSE;
378 }
379
380 // is this the one we want?
381 if (!mEquals(current->mData, data))
382 {
383 // nope!
384 return FALSE;
385 }
386 else
387 {
388 // do we need to fix current or currentop?
389 if (current == mCurrentp)
390 {
391 mCurrentp = current->mForward[0];
392 }
393
394 if (current == mCurrentOperatingp)
395 {
396 mCurrentOperatingp = current->mForward[0];
397 }
398 // yes it is! change pointers as required
399 for (level = 0; level < mLevel; level++)
400 {
401 if (mUpdate[level]->mForward[level] != current)
402 {
403 // cool, we've fixed all the pointers!
404 break;
405 }
406 mUpdate[level]->mForward[level] = current->mForward[level];
407 }
408
409 // clean up cuurent
410 delete current;
411
412 // clean up mHead
413 while ( (mLevel > 1)
414 &&(!mHead.mForward[mLevel - 1]))
415 {
416 mLevel--;
417 }
418 }
419 return TRUE;
420}
421
422// remove all nodes from the list but do not delete data
423template <class DATA_TYPE, S32 BINARY_DEPTH>
424inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
425{
426 LLSkipNode *temp;
427 // reset mCurrentp
428 mCurrentp = *(mHead.mForward);
429
430 while (mCurrentp)
431 {
432 temp = mCurrentp->mForward[0];
433 delete mCurrentp;
434 mCurrentp = temp;
435 }
436
437 S32 i;
438 for (i = 0; i < BINARY_DEPTH; i++)
439 {
440 mHead.mForward[i] = NULL;
441 mUpdate[i] = NULL;
442 }
443
444 mCurrentp = *(mHead.mForward);
445 mCurrentOperatingp = *(mHead.mForward);
446}
447
448// place mCurrentp on first node
449template <class DATA_TYPE, S32 BINARY_DEPTH>
450inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
451{
452 mCurrentp = *(mHead.mForward);
453 mCurrentOperatingp = *(mHead.mForward);
454}
455
456// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
457template <class DATA_TYPE, S32 BINARY_DEPTH>
458inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
459{
460 if (mCurrentp)
461 {
462 mCurrentOperatingp = mCurrentp;
463 mCurrentp = mCurrentp->mForward[0];
464 return mCurrentOperatingp->mData;
465 }
466 else
467 {
468 //return NULL; // causes compile warning
469 return (DATA_TYPE)0; // equivalent, but no warning
470 }
471}
472
473// same as getCurrentData() but a more intuitive name for the operation
474template <class DATA_TYPE, S32 BINARY_DEPTH>
475inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
476{
477 if (mCurrentp)
478 {
479 mCurrentOperatingp = mCurrentp;
480 mCurrentp = mCurrentp->mForward[0];
481 return mCurrentOperatingp->mData;
482 }
483 else
484 {
485 //return NULL; // causes compile warning
486 return (DATA_TYPE)0; // equivalent, but no warning
487 }
488}
489
490// remove the Node at mCurentOperatingp
491// leave mCurrentp and mCurentOperatingp on the next entry
492template <class DATA_TYPE, S32 BINARY_DEPTH>
493inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
494{
495 if (mCurrentOperatingp)
496 {
497 removeData(mCurrentOperatingp->mData);
498 }
499}
500
501// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
502template <class DATA_TYPE, S32 BINARY_DEPTH>
503inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
504{
505 mCurrentp = *(mHead.mForward);
506 mCurrentOperatingp = *(mHead.mForward);
507 if (mCurrentp)
508 {
509 mCurrentOperatingp = mCurrentp;
510 mCurrentp = mCurrentp->mForward[0];
511 return mCurrentOperatingp->mData;
512 }
513 else
514 {
515 //return NULL; // causes compile warning
516 return (DATA_TYPE)0; // equivalent, but no warning
517 }
518}
519
520
521#endif