PageRenderTime 87ms CodeModel.GetById 15ms app.highlight 65ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/doublelinkedlist.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 1397 lines | 875 code | 204 blank | 318 comment | 117 complexity | 38523a93cddf21a20d0ebaa8ba4f183a MD5 | raw file
   1/** 
   2 * @file doublelinkedlist.h
   3 * @brief Provides a standard doubly linked list for fun and profit.
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#ifndef LL_DOUBLELINKEDLIST_H
  28#define LL_DOUBLELINKEDLIST_H
  29
  30#include "llerror.h"
  31#include "llrand.h"
  32
  33// node that actually contains the data
  34template <class DATA_TYPE> class LLDoubleLinkedNode
  35{
  36public:
  37	DATA_TYPE			*mDatap;
  38	LLDoubleLinkedNode	*mNextp;
  39	LLDoubleLinkedNode	*mPrevp;
  40
  41
  42public:
  43	// assign the mDatap pointer
  44	LLDoubleLinkedNode(DATA_TYPE *data);
  45
  46	// destructor does not, by default, destroy associated data
  47	// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
  48	~LLDoubleLinkedNode();
  49
  50	// delete associated data and NULL out pointer
  51	void deleteData();
  52
  53	// remove associated data and NULL out pointer
  54	void removeData();
  55};
  56
  57
  58const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
  59
  60template <class DATA_TYPE> class LLDoubleLinkedList
  61{
  62private:
  63	LLDoubleLinkedNode<DATA_TYPE> mHead;		// head node
  64	LLDoubleLinkedNode<DATA_TYPE> mTail;		// tail node
  65	LLDoubleLinkedNode<DATA_TYPE> *mQueuep;		// The node in the batter's box
  66	LLDoubleLinkedNode<DATA_TYPE> *mCurrentp;	// The node we're talking about
  67
  68	// The state stack allows nested exploration of the LLDoubleLinkedList
  69	// but should be used with great care
  70	LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  71	LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
  72	U32 mStateStackDepth;
  73	U32	mCount;
  74
  75	// mInsertBefore is a pointer to a user-set function that returns 
  76	// TRUE if "first" should be located before "second"
  77	// NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
  78	// or never-ending loops can occur
  79	BOOL				(*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);	
  80																				
  81public:
  82	LLDoubleLinkedList();
  83
  84	// destructor destroys list and nodes, but not data in nodes
  85	~LLDoubleLinkedList();
  86
  87	// put data into a node and stick it at the front of the list
  88	// set mCurrentp to mQueuep
  89	void addData(DATA_TYPE *data);
  90
  91	// put data into a node and stick it at the end of the list
  92	// set mCurrentp to mQueuep
  93	void addDataAtEnd(DATA_TYPE *data);
  94
  95	S32 getLength() const;
  96	// search the list starting at mHead.mNextp and remove the link with mDatap == data
  97	// set mCurrentp to mQueuep
  98	// return TRUE if found, FALSE if not found
  99	BOOL removeData(const DATA_TYPE *data);
 100
 101	// search the list starting at mHead.mNextp and delete the link with mDatap == data
 102	// set mCurrentp to mQueuep
 103	// return TRUE if found, FALSE if not found
 104	BOOL deleteData(DATA_TYPE *data);
 105
 106	// remove all nodes from the list and delete the associated data
 107	void deleteAllData();
 108
 109	// remove all nodes from the list but do not delete data
 110	void removeAllNodes();
 111
 112	BOOL isEmpty();
 113
 114	// check to see if data is in list
 115	// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
 116	// return TRUE if found, FALSE if not found
 117	BOOL	checkData(const DATA_TYPE *data);
 118
 119	// NOTE: This next two funtions are only included here 
 120	// for those too familiar with the LLLinkedList template class.
 121	// They are depreciated.  resetList() is unecessary while 
 122	// getCurrentData() is identical to getNextData() and has
 123	// a misleading name.
 124	//
 125	// The recommended way to loop through a list is as follows:
 126	//
 127	// datap = list.getFirstData();
 128	// while (datap)
 129	// {
 130	//     /* do stuff */
 131	//     datap = list.getNextData();
 132	// }
 133
 134		// place mQueuep on mHead node
 135		void resetList();
 136	
 137		// return the data currently pointed to, 
 138		// set mCurrentp to that node and bump mQueuep down the list
 139		// NOTE: this function is identical to getNextData()
 140		DATA_TYPE *getCurrentData();
 141
 142
 143	// reset the list and return the data currently pointed to, 
 144	// set mCurrentp to that node and bump mQueuep down the list
 145	DATA_TYPE *getFirstData();
 146
 147
 148	// reset the list and return the data at position n, set mCurentp 
 149	// to that node and bump mQueuep down the list
 150	// Note: n=0 will behave like getFirstData()
 151	DATA_TYPE *getNthData(U32 n);
 152
 153	// reset the list and return the last data in it, 
 154	// set mCurrentp to that node and bump mQueuep up the list
 155	DATA_TYPE *getLastData();
 156
 157	// return data in mQueuep,
 158	// set mCurrentp mQueuep and bump mQueuep down the list
 159	DATA_TYPE *getNextData();
 160
 161	// return the data in mQueuep, 
 162	// set mCurrentp to mQueuep and bump mQueuep up the list
 163	DATA_TYPE *getPreviousData();
 164
 165	// remove the Node at mCurrentp
 166	// set mCurrentp to mQueuep
 167	void removeCurrentData();
 168
 169	// delete the Node at mCurrentp
 170	// set mCurrentp to mQueuep
 171	void deleteCurrentData();
 172
 173	// remove the Node at mCurrentp and insert it into newlist
 174	// set mCurrentp to mQueuep
 175	void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
 176
 177	// insert the node in front of mCurrentp
 178	// set mCurrentp to mQueuep
 179	void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
 180
 181	// insert the data in front of mCurrentp
 182	// set mCurrentp to mQueuep
 183	void insertData(DATA_TYPE *data);
 184
 185	// if mCurrentp has a previous node then :
 186	//   * swaps mCurrentp with its previous
 187	//   * set mCurrentp to mQueuep
 188	//     (convenient for forward bubble-sort)
 189	// otherwise does nothing
 190	void swapCurrentWithPrevious();
 191
 192	// if mCurrentp has a next node then :
 193	//   * swaps mCurrentp with its next
 194	//   * set mCurrentp to mQueuep
 195	//     (convenient for backwards bubble-sort)
 196	// otherwise does nothing
 197	void swapCurrentWithNext();
 198
 199	// move mCurrentp to the front of the list
 200	// set mCurrentp to mQueuep
 201	void moveCurrentToFront();
 202	
 203	// move mCurrentp to the end of the list
 204	// set mCurrentp to mQueuep
 205	void moveCurrentToEnd();
 206
 207	// set mInsertBefore
 208	void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
 209
 210	// add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
 211	// set mCurrentp to mQueuep
 212	BOOL addDataSorted(DATA_TYPE *datap);
 213
 214	// sort the list using bubble-sort
 215	// Yes, this is a different name than the same function in LLLinkedList.
 216	// When it comes time for a name consolidation hopefully this one will win.
 217	BOOL bubbleSort();
 218
 219	// does a single bubble sort pass on the list
 220	BOOL lazyBubbleSort();
 221
 222	// returns TRUE if state successfully pushed (state stack not full)
 223	BOOL pushState();
 224
 225	// returns TRUE if state successfully popped (state stack not empty)
 226	BOOL popState();
 227
 228	// empties the state stack
 229	void clearStateStack();
 230
 231	// randomly move the the links in the list for debug or (Discordian) purposes
 232	// sets mCurrentp and mQueuep to top of list
 233	void scramble();
 234
 235private:
 236	// add node to beginning of list
 237	// set mCurrentp to mQueuep
 238	void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
 239
 240	// add node to end of list
 241	// set mCurrentp to mQueuep
 242	void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
 243};
 244
 245//#endif
 246
 247////////////////////////////////////////////////////////////////////////////////////////////
 248
 249// doublelinkedlist.cpp
 250// LLDoubleLinkedList template class implementation file.
 251// Provides a standard doubly linked list for fun and profit.
 252// 
 253// Copyright 2001, Linden Research, Inc.
 254
 255//#include "llerror.h"
 256//#include "doublelinkedlist.h"
 257
 258//////////////////////////////////////////////////////////////////////////////////////////
 259// LLDoubleLinkedNode
 260//////////////////////////////////////////////////////////////////////////////////////////
 261
 262
 263// assign the mDatap pointer
 264template <class DATA_TYPE>
 265LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) : 
 266	mDatap(data), mNextp(NULL), mPrevp(NULL)
 267{
 268}
 269
 270
 271// destructor does not, by default, destroy associated data
 272// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
 273template <class DATA_TYPE>
 274LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
 275{
 276	if (mDatap)
 277	{
 278		llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
 279	}
 280}
 281
 282
 283// delete associated data and NULL out pointer
 284template <class DATA_TYPE>
 285void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
 286{
 287	delete mDatap;
 288	mDatap = NULL;
 289}
 290
 291
 292template <class DATA_TYPE>
 293void LLDoubleLinkedNode<DATA_TYPE>::removeData()
 294{
 295	mDatap = NULL;
 296}
 297
 298
 299//////////////////////////////////////////////////////////////////////////////////////
 300// LLDoubleLinkedList
 301//////////////////////////////////////////////////////////////////////////////////////
 302
 303//                                   <------- up -------
 304//
 305//                                               mCurrentp
 306//                                   mQueuep         |
 307//                                      |            |
 308//                                      |            | 
 309//                      .------.     .------.     .------.      .------.
 310//                      |      |---->|      |---->|      |----->|      |-----> NULL
 311//           NULL <-----|      |<----|      |<----|      |<-----|      |
 312//                     _'------'     '------'     '------'      '------:_
 313//             .------. /|               |             |               |\ .------.
 314//  NULL <-----|mHead |/                 |         mQueuep               \|mTail |-----> NULL
 315//             |      |               mCurrentp                           |      |
 316//             '------'                                                   '------'
 317//                               -------- down --------->
 318
 319template <class DATA_TYPE>
 320LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
 321: mHead(NULL), mTail(NULL), mQueuep(NULL)
 322{
 323	mCurrentp = mHead.mNextp;
 324	mQueuep = mHead.mNextp;
 325	mStateStackDepth = 0;
 326	mCount = 0;
 327	mInsertBefore = NULL;
 328}
 329
 330
 331// destructor destroys list and nodes, but not data in nodes
 332template <class DATA_TYPE>
 333LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
 334{
 335	removeAllNodes();
 336}
 337
 338
 339// put data into a node and stick it at the front of the list
 340// doesn't change mCurrentp nor mQueuep
 341template <class DATA_TYPE>
 342void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
 343{
 344	// don't allow NULL to be passed to addData
 345	if (!data)
 346	{
 347		llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
 348	}
 349
 350	// make the new node
 351	LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
 352
 353	// add the node to the front of the list
 354	temp->mPrevp = NULL; 
 355	temp->mNextp = mHead.mNextp;
 356	mHead.mNextp = temp;
 357
 358	// if there's something in the list, fix its back pointer
 359	if (temp->mNextp)
 360	{
 361		temp->mNextp->mPrevp = temp;
 362	}
 363	// otherwise, fix the tail of the list
 364	else 
 365	{
 366		mTail.mPrevp = temp;
 367	}
 368
 369	mCount++;
 370}
 371
 372
 373// put data into a node and stick it at the end of the list
 374template <class DATA_TYPE>
 375void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
 376{
 377	// don't allow NULL to be passed to addData
 378	if (!data)
 379	{
 380		llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
 381	}
 382
 383	// make the new node
 384	LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
 385
 386	addNodeAtEnd(nodep);
 387	mCount++;
 388}
 389
 390
 391// search the list starting at mHead.mNextp and remove the link with mDatap == data
 392// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
 393// return TRUE if found, FALSE if not found
 394template <class DATA_TYPE>
 395BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
 396{
 397	BOOL b_found = FALSE;
 398	// don't allow NULL to be passed to addData
 399	if (!data)
 400	{
 401		llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
 402	}
 403
 404	mCurrentp = mHead.mNextp;
 405
 406	while (mCurrentp)
 407	{
 408		if (mCurrentp->mDatap == data)
 409		{
 410			b_found = TRUE;
 411
 412			// if there is a next one, fix it
 413			if (mCurrentp->mNextp)
 414			{
 415				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 416			}
 417			else // we are at end of list
 418			{
 419				mTail.mPrevp = mCurrentp->mPrevp;
 420			}
 421
 422			// if there is a previous one, fix it
 423			if (mCurrentp->mPrevp)
 424			{
 425				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 426			}
 427			else // we are at beginning of list
 428			{
 429				mHead.mNextp = mCurrentp->mNextp;
 430			}
 431
 432			// remove the node
 433			mCurrentp->removeData();
 434			delete mCurrentp;
 435			mCount--;
 436			break;
 437		}
 438		mCurrentp = mCurrentp->mNextp; 
 439	}
 440
 441	// reset the list back to where it was
 442	if (mCurrentp == mQueuep)
 443	{
 444		mCurrentp = mQueuep = NULL;
 445	}
 446	else
 447	{
 448		mCurrentp = mQueuep;
 449	}
 450
 451	return b_found;
 452}
 453
 454
 455// search the list starting at mHead.mNextp and delete the link with mDatap == data
 456// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
 457// return TRUE if found, FALSE if not found
 458template <class DATA_TYPE>
 459BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
 460{
 461	BOOL b_found = FALSE;
 462	// don't allow NULL to be passed to addData
 463	if (!data)
 464	{
 465		llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
 466	}
 467
 468	mCurrentp = mHead.mNextp;
 469
 470	while (mCurrentp)
 471	{
 472		if (mCurrentp->mDatap == data)
 473		{
 474			b_found = TRUE;
 475
 476			// if there is a next one, fix it
 477			if (mCurrentp->mNextp)
 478			{
 479				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 480			}
 481			else // we are at end of list
 482			{
 483				mTail.mPrevp = mCurrentp->mPrevp;
 484			}
 485
 486			// if there is a previous one, fix it
 487			if (mCurrentp->mPrevp)
 488			{
 489				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 490			}
 491			else // we are at beginning of list
 492			{
 493				mHead.mNextp = mCurrentp->mNextp;
 494			}
 495
 496			// remove the node
 497			mCurrentp->deleteData();
 498			delete mCurrentp;
 499			mCount--;
 500			break;
 501		}
 502		mCurrentp = mCurrentp->mNextp;
 503	}
 504
 505	// reset the list back to where it was
 506	if (mCurrentp == mQueuep)
 507	{
 508		mCurrentp = mQueuep = NULL;
 509	}
 510	else
 511	{
 512		mCurrentp = mQueuep;
 513	}
 514
 515	return b_found;
 516}
 517
 518
 519// remove all nodes from the list and delete the associated data
 520template <class DATA_TYPE>
 521void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
 522{
 523	mCurrentp = mHead.mNextp;
 524
 525	while (mCurrentp)
 526	{
 527		mQueuep = mCurrentp->mNextp;
 528		mCurrentp->deleteData();
 529		delete mCurrentp;
 530		mCurrentp = mQueuep;
 531	}
 532
 533	// reset mHead and mQueuep
 534	mHead.mNextp = NULL;
 535	mTail.mPrevp = NULL;
 536	mCurrentp = mHead.mNextp;
 537	mQueuep = mHead.mNextp;
 538	mStateStackDepth = 0;
 539	mCount = 0;
 540}
 541
 542
 543// remove all nodes from the list but do not delete associated data
 544template <class DATA_TYPE>
 545void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
 546{
 547	mCurrentp = mHead.mNextp;
 548
 549	while (mCurrentp)
 550	{
 551		mQueuep = mCurrentp->mNextp;
 552		mCurrentp->removeData();
 553		delete mCurrentp;
 554		mCurrentp = mQueuep;
 555	}
 556
 557	// reset mHead and mCurrentp
 558	mHead.mNextp = NULL;
 559	mTail.mPrevp = NULL;
 560	mCurrentp = mHead.mNextp;
 561	mQueuep = mHead.mNextp;
 562	mStateStackDepth = 0;
 563	mCount = 0;
 564}
 565
 566template <class DATA_TYPE>
 567S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
 568{
 569//	U32	length = 0;
 570//	for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
 571//	{
 572//		length++;
 573//	}
 574	return mCount;
 575}
 576
 577// check to see if data is in list
 578// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
 579// return TRUE if found, FALSE if not found
 580template <class DATA_TYPE>
 581BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
 582{
 583	mCurrentp = mHead.mNextp;
 584
 585	while (mCurrentp)
 586	{
 587		if (mCurrentp->mDatap == data)
 588		{
 589			mQueuep = mCurrentp;
 590			return TRUE;
 591		}
 592		mCurrentp = mCurrentp->mNextp;
 593	}
 594
 595	mCurrentp = mQueuep;
 596	return FALSE;
 597}
 598
 599// NOTE: This next two funtions are only included here 
 600// for those too familiar with the LLLinkedList template class.
 601// They are depreciated.  resetList() is unecessary while 
 602// getCurrentData() is identical to getNextData() and has
 603// a misleading name.
 604//
 605// The recommended way to loop through a list is as follows:
 606//
 607// datap = list.getFirstData();
 608// while (datap)
 609// {
 610//     /* do stuff */
 611//     datap = list.getNextData();
 612// }
 613
 614	// place mCurrentp and mQueuep on first node
 615	template <class DATA_TYPE>
 616	void LLDoubleLinkedList<DATA_TYPE>::resetList()
 617	{
 618		mCurrentp = mHead.mNextp;
 619		mQueuep = mHead.mNextp;
 620		mStateStackDepth = 0;
 621	}
 622	
 623	
 624	// return the data currently pointed to, 
 625	// set mCurrentp to that node and bump mQueuep down the list
 626	template <class DATA_TYPE>
 627	DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
 628	{
 629		if (mQueuep)
 630		{
 631			mCurrentp = mQueuep;
 632			mQueuep = mQueuep->mNextp;
 633			return mCurrentp->mDatap;
 634		}
 635		else
 636		{
 637			return NULL;
 638		}
 639	}
 640
 641
 642// reset the list and return the data currently pointed to, 
 643// set mCurrentp to that node and bump mQueuep down the list
 644template <class DATA_TYPE>
 645DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
 646{
 647	mQueuep = mHead.mNextp;
 648	mCurrentp = mQueuep;
 649	if (mQueuep)
 650	{
 651		mQueuep = mQueuep->mNextp;
 652		return mCurrentp->mDatap;
 653	}
 654	else
 655	{
 656		return NULL;
 657	}
 658}
 659
 660
 661// reset the list and return the data at position n, set mCurentp 
 662// to that node and bump mQueuep down the list
 663// Note: n=0 will behave like getFirstData()
 664template <class DATA_TYPE>
 665DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
 666{
 667	mCurrentp = mHead.mNextp;
 668
 669	if (mCurrentp)
 670	{
 671		for (U32 i=0; i<n; i++)
 672		{
 673			mCurrentp = mCurrentp->mNextp;
 674			if (!mCurrentp)
 675			{
 676				break;
 677			}		
 678		}
 679	}
 680
 681	if (mCurrentp)
 682	{
 683		// bump mQueuep down the list
 684		mQueuep = mCurrentp->mNextp;
 685		return mCurrentp->mDatap;
 686	}
 687	else
 688	{
 689		mQueuep = NULL;
 690		return NULL;
 691	}
 692}
 693
 694
 695// reset the list and return the last data in it, 
 696// set mCurrentp to that node and bump mQueuep up the list
 697template <class DATA_TYPE>
 698DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
 699{
 700	mQueuep = mTail.mPrevp;
 701	mCurrentp = mQueuep;
 702	if (mQueuep)
 703	{
 704		mQueuep = mQueuep->mPrevp;
 705		return mCurrentp->mDatap;
 706	}
 707	else
 708	{
 709		return NULL;
 710	}
 711}
 712
 713
 714// return the data in mQueuep, 
 715// set mCurrentp to mQueuep and bump mQueuep down the list
 716template <class DATA_TYPE>
 717DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
 718{
 719	if (mQueuep)
 720	{
 721		mCurrentp = mQueuep;
 722		mQueuep = mQueuep->mNextp;
 723		return mCurrentp->mDatap;
 724	}
 725	else
 726	{
 727		return NULL;
 728	}
 729}
 730
 731
 732// return the data in mQueuep, 
 733// set mCurrentp to mQueuep and bump mQueuep up the list
 734template <class DATA_TYPE>
 735DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
 736{
 737	if (mQueuep)
 738	{
 739		mCurrentp = mQueuep;
 740		mQueuep = mQueuep->mPrevp;
 741		return mCurrentp->mDatap;
 742	}
 743	else
 744	{
 745		return NULL;
 746	}
 747}
 748
 749
 750// remove the Node at mCurrentp
 751// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
 752template <class DATA_TYPE>
 753void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
 754{
 755	if (mCurrentp)
 756	{
 757		// if there is a next one, fix it
 758		if (mCurrentp->mNextp)
 759		{
 760			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 761		}
 762		else	// otherwise we are at end of list
 763		{
 764			mTail.mPrevp = mCurrentp->mPrevp;
 765		}
 766
 767		// if there is a previous one, fix it
 768		if (mCurrentp->mPrevp)
 769		{
 770			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 771		}
 772		else	// otherwise we are at beginning of list
 773		{
 774			mHead.mNextp = mCurrentp->mNextp;
 775		}
 776
 777		// remove the node
 778		mCurrentp->removeData();
 779		delete mCurrentp;
 780		mCount--;
 781
 782		// check for redundant pointing
 783		if (mCurrentp == mQueuep)
 784		{
 785			mCurrentp = mQueuep = NULL;
 786		}
 787		else
 788		{
 789			mCurrentp = mQueuep;
 790		}
 791	}
 792}
 793
 794
 795// delete the Node at mCurrentp
 796// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) 
 797template <class DATA_TYPE>
 798void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
 799{
 800	if (mCurrentp)
 801	{
 802		// remove the node
 803		// if there is a next one, fix it
 804		if (mCurrentp->mNextp)
 805		{
 806			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 807		}
 808		else	// otherwise we are at end of list
 809		{
 810			mTail.mPrevp = mCurrentp->mPrevp;
 811		}
 812
 813		// if there is a previous one, fix it
 814		if (mCurrentp->mPrevp)
 815		{
 816			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 817		}
 818		else	// otherwise we are at beginning of list
 819		{
 820			mHead.mNextp = mCurrentp->mNextp;
 821		}
 822
 823		// remove the LLDoubleLinkedNode
 824		mCurrentp->deleteData();
 825		delete mCurrentp;
 826		mCount--;
 827
 828		// check for redundant pointing
 829		if (mCurrentp == mQueuep)
 830		{
 831			mCurrentp = mQueuep = NULL;
 832		}
 833		else
 834		{
 835			mCurrentp = mQueuep;
 836		}
 837	}
 838}
 839
 840
 841// remove the Node at mCurrentp and insert it into newlist
 842// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
 843template <class DATA_TYPE>
 844void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
 845{
 846	if (mCurrentp)
 847	{
 848		// remove the node
 849		// if there is a next one, fix it
 850		if (mCurrentp->mNextp)
 851		{
 852			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 853		}
 854		else	// otherwise we are at end of list
 855		{
 856			mTail.mPrevp = mCurrentp->mPrevp;
 857		}
 858
 859		// if there is a previous one, fix it
 860		if (mCurrentp->mPrevp)
 861		{
 862			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 863		}
 864		else	// otherwise we are at beginning of list
 865		{
 866			mHead.mNextp = mCurrentp->mNextp;
 867		}
 868
 869		// move the node to the new list
 870		newlist->addNode(mCurrentp);
 871
 872		// check for redundant pointing
 873		if (mCurrentp == mQueuep)
 874		{
 875			mCurrentp = mQueuep = NULL;
 876		}
 877		else
 878		{
 879			mCurrentp = mQueuep;
 880		}
 881	}
 882}
 883
 884
 885// Inserts the node previous to mCurrentp
 886// set mCurrentp to mQueuep
 887template <class DATA_TYPE>
 888void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
 889{
 890	// don't allow pointer to NULL to be passed
 891	if (!nodep)
 892	{
 893		llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
 894	}
 895	if (!nodep->mDatap)
 896	{
 897		llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
 898	}
 899
 900	if (mCurrentp)
 901	{
 902		if (mCurrentp->mPrevp)
 903		{
 904			nodep->mPrevp = mCurrentp->mPrevp;
 905			nodep->mNextp = mCurrentp;
 906			mCurrentp->mPrevp->mNextp = nodep;
 907			mCurrentp->mPrevp = nodep;
 908		}
 909		else	// at beginning of list
 910		{
 911			nodep->mPrevp = NULL;
 912			nodep->mNextp = mCurrentp;
 913			mHead.mNextp = nodep;
 914			mCurrentp->mPrevp = nodep;
 915		}
 916		mCurrentp = mQueuep;
 917	}
 918	else	// add to front of list
 919	{
 920		addNode(nodep);
 921	}
 922}
 923
 924
 925// insert the data in front of mCurrentp
 926// set mCurrentp to mQueuep
 927template <class DATA_TYPE>
 928void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
 929{
 930	if (!data)
 931	{
 932		llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
 933	}
 934	LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
 935	insertNode(node);
 936	mCount++;
 937}
 938
 939
 940// if mCurrentp has a previous node then :
 941//   * swaps mCurrentp with its previous
 942//   * set mCurrentp to mQueuep
 943// otherwise does nothing
 944template <class DATA_TYPE>
 945void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
 946{
 947	if (mCurrentp)
 948	{
 949		if (mCurrentp->mPrevp)
 950		{
 951			// Pull mCurrentp out of list
 952			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
 953			if (mCurrentp->mNextp)
 954			{
 955				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 956			}
 957			else 	// mCurrentp was at end of list
 958			{
 959				mTail.mPrevp = mCurrentp->mPrevp;
 960			}
 961
 962			// Fix mCurrentp's pointers
 963			mCurrentp->mNextp = mCurrentp->mPrevp;
 964			mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
 965			mCurrentp->mNextp->mPrevp = mCurrentp;
 966
 967			if (mCurrentp->mPrevp)
 968			{
 969				// Fix the backward pointer of mCurrentp's new previous
 970				mCurrentp->mPrevp->mNextp = mCurrentp;
 971			}
 972			else	// mCurrentp is now at beginning of list
 973			{
 974				mHead.mNextp = mCurrentp;
 975			}
 976
 977			// Set the list back to the way it was
 978			mCurrentp = mQueuep;
 979		}
 980	}
 981}
 982
 983
 984// if mCurrentp has a next node then :
 985//   * swaps mCurrentp with its next
 986//   * set mCurrentp to mQueuep
 987// otherwise does nothing
 988template <class DATA_TYPE>
 989void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
 990{
 991	if (mCurrentp)
 992	{
 993		if (mCurrentp->mNextp)
 994		{
 995			// Pull mCurrentp out of list
 996			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
 997			if (mCurrentp->mPrevp)
 998			{
 999				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
1000			}
1001			else 	// mCurrentp was at beginning of list
1002			{
1003				mHead.mNextp = mCurrentp->mNextp;
1004			}
1005
1006			// Fix mCurrentp's pointers
1007			mCurrentp->mPrevp = mCurrentp->mNextp;
1008			mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
1009			mCurrentp->mPrevp->mNextp = mCurrentp;
1010
1011			if (mCurrentp->mNextp)
1012			{
1013				// Fix the back pointer of mCurrentp's new next
1014				mCurrentp->mNextp->mPrevp = mCurrentp;
1015			}
1016			else 	// mCurrentp is now at end of list
1017			{
1018				mTail.mPrevp = mCurrentp;
1019			}
1020			
1021			// Set the list back to the way it was
1022			mCurrentp = mQueuep;
1023		}
1024	}
1025}
1026
1027// move mCurrentp to the front of the list
1028// set mCurrentp to mQueuep
1029template <class DATA_TYPE>
1030void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
1031{
1032	if (mCurrentp)
1033	{
1034		// if there is a previous one, fix it
1035		if (mCurrentp->mPrevp)
1036		{
1037			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
1038		}
1039		else	// otherwise we are at beginning of list
1040		{
1041			// check for redundant pointing
1042			if (mCurrentp == mQueuep)
1043			{
1044				mCurrentp = mQueuep = NULL;
1045			}
1046			else
1047			{
1048				mCurrentp = mQueuep;
1049			}
1050			return;
1051		}
1052
1053		// if there is a next one, fix it
1054		if (mCurrentp->mNextp)
1055		{
1056			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
1057		}
1058		else	// otherwise we are at end of list
1059		{
1060			mTail.mPrevp = mCurrentp->mPrevp;
1061		}
1062
1063		// add mCurrentp to beginning of list
1064		mCurrentp->mNextp = mHead.mNextp;
1065		mHead.mNextp->mPrevp = mCurrentp;	// mHead.mNextp MUST be valid, 
1066											// or the list had only one node
1067											// and we would have returned already
1068		mCurrentp->mPrevp = NULL;
1069		mHead.mNextp = mCurrentp;
1070
1071		// check for redundant pointing
1072		if (mCurrentp == mQueuep)
1073		{
1074			mCurrentp = mQueuep = NULL;
1075		}
1076		else
1077		{
1078			mCurrentp = mQueuep;
1079		}
1080	}
1081
1082}
1083
1084// move mCurrentp to the end of the list
1085// set mCurrentp to mQueuep
1086template <class DATA_TYPE>
1087void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
1088{
1089	if (mCurrentp)
1090	{
1091		// if there is a next one, fix it
1092		if (mCurrentp->mNextp)
1093		{
1094			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
1095		}
1096		else	// otherwise we are at end of list and we're done
1097		{
1098			// check for redundant pointing
1099			if (mCurrentp == mQueuep)
1100			{
1101				mCurrentp = mQueuep = NULL;
1102			}
1103			else
1104			{
1105				mCurrentp = mQueuep;
1106			}
1107			return;
1108		}
1109
1110		// if there is a previous one, fix it
1111		if (mCurrentp->mPrevp)
1112		{
1113			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
1114		}
1115		else	// otherwise we are at beginning of list
1116		{
1117			mHead.mNextp = mCurrentp->mNextp;
1118		}
1119
1120		// add mCurrentp to end of list
1121		mCurrentp->mPrevp = mTail.mPrevp;
1122		mTail.mPrevp->mNextp = mCurrentp;	// mTail.mPrevp MUST be valid, 
1123											// or the list had only one node
1124											// and we would have returned already
1125		mCurrentp->mNextp = NULL;
1126		mTail.mPrevp = mCurrentp;
1127
1128		// check for redundant pointing
1129		if (mCurrentp == mQueuep)
1130		{
1131			mCurrentp = mQueuep = NULL;
1132		}
1133		else
1134		{
1135			mCurrentp = mQueuep;
1136		}
1137	}
1138}
1139
1140
1141template <class DATA_TYPE>
1142void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
1143{
1144	mInsertBefore = insert_before;
1145}
1146
1147
1148// add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
1149// set mCurrentp to mQueuep
1150template <class DATA_TYPE>
1151BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
1152{
1153	// don't allow NULL to be passed to addData()
1154	if (!datap)
1155	{
1156		llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
1157	}
1158
1159	// has mInsertBefore not been set?
1160	if (!mInsertBefore)
1161	{
1162		addData(datap);
1163		return FALSE;
1164	}
1165
1166	// is the list empty?
1167	if (!mHead.mNextp)
1168	{
1169		addData(datap);
1170		return TRUE;
1171	}
1172
1173	// Note: this step has been added so that the behavior of LLDoubleLinkedList
1174	// is as rigorous as the LLLinkedList class about adding duplicate nodes.
1175	// Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo) 
1176	// returns TRUE.  However, if mInsertBefore(foo, foo) returns FALSE, then there 
1177	// shouldn't be any reason to exclude duplicate nodes (as we do here).
1178	if (checkData(datap))
1179	{
1180		return FALSE;
1181	}
1182	
1183	mCurrentp = mHead.mNextp;
1184	while (mCurrentp)
1185	{
1186		// check to see if datap is already in the list
1187		if (datap == mCurrentp->mDatap)
1188		{
1189			return FALSE;
1190		}
1191		else if (mInsertBefore(datap, mCurrentp->mDatap))
1192		{
1193			insertData(datap);
1194			return TRUE;
1195		}
1196		mCurrentp = mCurrentp->mNextp;
1197	}
1198	
1199	addDataAtEnd(datap);
1200	return TRUE;
1201}
1202
1203
1204// bubble-sort until sorted and return TRUE if anything was sorted
1205// leaves mQueuep pointing at last node that was swapped with its mNextp
1206//
1207// NOTE: if you find this function looping for really long times, then you
1208// probably need to check your implementation of mInsertBefore(a,b) and make 
1209// sure it does not return TRUE when (a == b)!
1210template <class DATA_TYPE>
1211BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
1212{
1213	BOOL b_swapped = FALSE;
1214	U32 count = 0;
1215	while (lazyBubbleSort()) 
1216	{
1217		b_swapped = TRUE;
1218		if (count++ > 0x7FFFFFFF)
1219		{
1220			llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
1221			llwarning("    make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
1222			break;
1223		}
1224	}
1225	return b_swapped;
1226}
1227
1228
1229// do a single bubble-sort pass and return TRUE if anything was sorted
1230// leaves mQueuep pointing at last node that was swapped with its mNextp
1231template <class DATA_TYPE>
1232BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
1233{
1234	// has mInsertBefore been set?
1235	if (!mInsertBefore)
1236	{
1237		return FALSE;
1238	}
1239
1240	// is list empty?
1241	mCurrentp = mHead.mNextp;
1242	if (!mCurrentp)
1243	{
1244		return FALSE;
1245	}
1246
1247	BOOL b_swapped = FALSE;
1248
1249	// the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
1250	S32  length = 0x7FFFFFFF;
1251	S32  count = 0;
1252
1253	while (mCurrentp  &&  mCurrentp->mNextp  &&  count<length)
1254	{
1255		if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
1256		{
1257			b_swapped = TRUE;
1258			mQueuep = mCurrentp;
1259			swapCurrentWithNext();	// sets mCurrentp to mQueuep
1260		}
1261		count++;
1262		mCurrentp = mCurrentp->mNextp;
1263	}
1264	
1265	return b_swapped;
1266}
1267
1268
1269template <class DATA_TYPE>
1270BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
1271{
1272	if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
1273	{
1274		*(mQueuepStack + mStateStackDepth) = mQueuep;
1275		*(mCurrentpStack + mStateStackDepth) = mCurrentp;
1276		mStateStackDepth++;
1277		return TRUE;
1278	}
1279	return FALSE;
1280}
1281
1282
1283template <class DATA_TYPE>
1284BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
1285{
1286	if (mStateStackDepth > 0)
1287	{
1288		mStateStackDepth--;
1289		mQueuep = *(mQueuepStack + mStateStackDepth);
1290		mCurrentp = *(mCurrentpStack + mStateStackDepth);
1291		return TRUE;
1292	}
1293	return FALSE;
1294}
1295
1296
1297template <class DATA_TYPE>
1298void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
1299{
1300	mStateStackDepth = 0;
1301}
1302
1303//////////////////////////////////////////////////////////////////////////////////////////
1304// private members
1305//////////////////////////////////////////////////////////////////////////////////////////
1306
1307// add node to beginning of list
1308// set mCurrentp to mQueuep
1309template <class DATA_TYPE>
1310void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
1311{
1312	// add the node to the front of the list
1313	nodep->mPrevp = NULL;
1314	nodep->mNextp = mHead.mNextp;
1315	mHead.mNextp = nodep;
1316
1317	// if there's something in the list, fix its back pointer
1318	if (nodep->mNextp)
1319	{
1320		nodep->mNextp->mPrevp = nodep;
1321	}
1322	else	// otherwise fix the tail node
1323	{
1324		mTail.mPrevp = nodep;
1325	}
1326
1327	mCurrentp = mQueuep;
1328}
1329
1330
1331// add node to end of list
1332// set mCurrentp to mQueuep
1333template <class DATA_TYPE>
1334void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
1335{
1336	// add the node to the end of the list
1337	node->mNextp = NULL;
1338	node->mPrevp = mTail.mPrevp;
1339	mTail.mPrevp = node;
1340
1341	// if there's something in the list, fix its back pointer
1342	if (node->mPrevp)
1343	{
1344		node->mPrevp->mNextp = node;
1345	}
1346	else	// otherwise fix the head node
1347	{
1348		mHead.mNextp = node;
1349	}
1350
1351	mCurrentp = mQueuep;
1352}
1353
1354
1355// randomly move nodes in the list for DEBUG (or Discordian) purposes
1356// sets mCurrentp and mQueuep to top of list
1357template <class DATA_TYPE>
1358void LLDoubleLinkedList<DATA_TYPE>::scramble()
1359{
1360	S32 random_number;
1361	DATA_TYPE *datap = getFirstData();
1362	while(datap)
1363	{
1364		random_number = ll_rand(5);
1365
1366		if (0 == random_number)
1367		{
1368			removeCurrentData();
1369			addData(datap);
1370		}
1371		else if (1 == random_number)
1372		{
1373			removeCurrentData();
1374			addDataAtEnd(datap);
1375		}
1376		else if (2 == random_number)
1377		{
1378			swapCurrentWithPrevious();
1379		}
1380		else if (3 == random_number)
1381		{
1382			swapCurrentWithNext();
1383		}
1384		datap = getNextData();
1385	}
1386	mQueuep = mHead.mNextp;
1387	mCurrentp = mQueuep;
1388}
1389
1390template <class DATA_TYPE>
1391BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
1392{
1393	return (mCount == 0);
1394}
1395
1396
1397#endif