Files
SingularityViewer/indra/llcommon/lllinkedqueue.h
2010-04-02 02:48:44 -03:00

316 lines
6.8 KiB
C++

/**
* @file lllinkedqueue.h
* @brief Declaration of linked queue classes.
*
* $LicenseInfo:firstyear=2003&license=viewergpl$
*
* Copyright (c) 2003-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#ifndef LL_LLLINKEDQUEUE_H
#define LL_LLLINKEDQUEUE_H
#include "llerror.h"
// node that actually contains the data
template <class DATA_TYPE> class LLLinkedQueueNode
{
public:
DATA_TYPE mData;
LLLinkedQueueNode *mNextp;
LLLinkedQueueNode *mPrevp;
public:
LLLinkedQueueNode();
LLLinkedQueueNode(const DATA_TYPE data);
// destructor does not, by default, destroy associated data
// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
~LLLinkedQueueNode();
};
template <class DATA_TYPE> class LLLinkedQueue
{
public:
LLLinkedQueue();
// destructor destroys list and nodes, but not data in nodes
~LLLinkedQueue();
// Puts at end of FIFO
void push(const DATA_TYPE data);
// Takes off front of FIFO
BOOL pop(DATA_TYPE &data);
BOOL peek(DATA_TYPE &data);
void reset();
S32 getLength() const;
BOOL isEmpty() const;
BOOL remove(const DATA_TYPE data);
BOOL checkData(const DATA_TYPE data) const;
private:
// add node to end of list
// set mCurrentp to mQueuep
void addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep);
private:
LLLinkedQueueNode<DATA_TYPE> mHead; // head node
LLLinkedQueueNode<DATA_TYPE> mTail; // tail node
S32 mLength;
};
//
// Nodes
//
template <class DATA_TYPE>
LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode() :
mData(), mNextp(NULL), mPrevp(NULL)
{ }
template <class DATA_TYPE>
LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode(const DATA_TYPE data) :
mData(data), mNextp(NULL), mPrevp(NULL)
{ }
template <class DATA_TYPE>
LLLinkedQueueNode<DATA_TYPE>::~LLLinkedQueueNode()
{ }
//
// Queue itself
//
template <class DATA_TYPE>
LLLinkedQueue<DATA_TYPE>::LLLinkedQueue()
: mHead(),
mTail(),
mLength(0)
{ }
// destructor destroys list and nodes, but not data in nodes
template <class DATA_TYPE>
LLLinkedQueue<DATA_TYPE>::~LLLinkedQueue()
{
reset();
}
// put data into a node and stick it at the end of the list
template <class DATA_TYPE>
void LLLinkedQueue<DATA_TYPE>::push(const DATA_TYPE data)
{
// make the new node
LLLinkedQueueNode<DATA_TYPE> *nodep = new LLLinkedQueueNode<DATA_TYPE>(data);
addNodeAtEnd(nodep);
}
// search the list starting at mHead.mNextp and remove the link with mDatap == data
// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
// return TRUE if found, FALSE if not found
template <class DATA_TYPE>
BOOL LLLinkedQueue<DATA_TYPE>::remove(const DATA_TYPE data)
{
BOOL b_found = FALSE;
LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
while (currentp)
{
if (currentp->mData == data)
{
b_found = TRUE;
// if there is a next one, fix it
if (currentp->mNextp)
{
currentp->mNextp->mPrevp = currentp->mPrevp;
}
else // we are at end of list
{
mTail.mPrevp = currentp->mPrevp;
}
// if there is a previous one, fix it
if (currentp->mPrevp)
{
currentp->mPrevp->mNextp = currentp->mNextp;
}
else // we are at beginning of list
{
mHead.mNextp = currentp->mNextp;
}
// remove the node
delete currentp;
mLength--;
break;
}
currentp = currentp->mNextp;
}
return b_found;
}
// remove all nodes from the list but do not delete associated data
template <class DATA_TYPE>
void LLLinkedQueue<DATA_TYPE>::reset()
{
LLLinkedQueueNode<DATA_TYPE> *currentp;
LLLinkedQueueNode<DATA_TYPE> *nextp;
currentp = mHead.mNextp;
while (currentp)
{
nextp = currentp->mNextp;
delete currentp;
currentp = nextp;
}
// reset mHead and mCurrentp
mHead.mNextp = NULL;
mTail.mPrevp = NULL;
mLength = 0;
}
template <class DATA_TYPE>
S32 LLLinkedQueue<DATA_TYPE>::getLength() const
{
return mLength;
}
template <class DATA_TYPE>
BOOL LLLinkedQueue<DATA_TYPE>::isEmpty() const
{
return mLength <= 0;
}
// check to see if data is in list
// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
// return TRUE if found, FALSE if not found
template <class DATA_TYPE>
BOOL LLLinkedQueue<DATA_TYPE>::checkData(const DATA_TYPE data) const
{
LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
while (currentp)
{
if (currentp->mData == data)
{
return TRUE;
}
currentp = currentp->mNextp;
}
return FALSE;
}
template <class DATA_TYPE>
BOOL LLLinkedQueue<DATA_TYPE>::pop(DATA_TYPE &data)
{
LLLinkedQueueNode<DATA_TYPE> *currentp;
currentp = mHead.mNextp;
if (!currentp)
{
return FALSE;
}
mHead.mNextp = currentp->mNextp;
if (currentp->mNextp)
{
currentp->mNextp->mPrevp = currentp->mPrevp;
}
else
{
mTail.mPrevp = currentp->mPrevp;
}
data = currentp->mData;
delete currentp;
mLength--;
return TRUE;
}
template <class DATA_TYPE>
BOOL LLLinkedQueue<DATA_TYPE>::peek(DATA_TYPE &data)
{
LLLinkedQueueNode<DATA_TYPE> *currentp;
currentp = mHead.mNextp;
if (!currentp)
{
return FALSE;
}
data = currentp->mData;
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////////////////
// private members
//////////////////////////////////////////////////////////////////////////////////////////
// add node to end of list
// set mCurrentp to mQueuep
template <class DATA_TYPE>
void LLLinkedQueue<DATA_TYPE>::addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep)
{
// add the node to the end of the list
nodep->mNextp = NULL;
nodep->mPrevp = mTail.mPrevp;
mTail.mPrevp = nodep;
// if there's something in the list, fix its back pointer
if (nodep->mPrevp)
{
nodep->mPrevp->mNextp = nodep;
}
else // otherwise fix the head node
{
mHead.mNextp = nodep;
}
mLength++;
}
#endif