PageRenderTime 97ms CodeModel.GetById 18ms app.highlight 71ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llptrskipmap.h

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