Files
mars-flaim/flaim/src/flist.cpp
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

386 lines
10 KiB
C++

//-------------------------------------------------------------------------
// Desc: List class.
// Tabs: 3
//
// Copyright (c) 1997-2000,2003,2005-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: flist.cpp 12263 2006-01-19 14:43:23 -0700 (Thu, 19 Jan 2006) dsanders $
//-------------------------------------------------------------------------
#include "flaimsys.h"
/***************************************************************************
* *
* F_ListMgr Class *
* *
****************************************************************************/
/****************************************************************************
Desc: Setup the pLNode array and set the count.
****************************************************************************/
RCODE F_ListMgr::Setup(
F_ListNode * pLNodes,
FLMUINT uiLNodeCnt)
{
flmAssert( pLNodes && uiLNodeCnt );
// Set the pLNodes array to null values.
m_uiLNodeCnt = uiLNodeCnt;
m_pLNodes = pLNodes;
f_memset( pLNodes, 0, sizeof( F_ListNode) * uiLNodeCnt );
return FERR_OK;
}
/****************************************************************************
Desc: Insert an item into the first of a list.
****************************************************************************/
void F_ListMgr::InsertAtFirst(
FLMUINT uiList, // List to insert this item.
F_ListItem * pNewFirstItem) // New item to be inserted at the first.
{
F_ListNode * pLNode;
// Check bounds with assert.
// This should be fine because uiList values are defined.
flmAssert( uiList < m_uiLNodeCnt );
pNewFirstItem->AddRef();
pLNode = &m_pLNodes[ uiList ];
if( pLNode->pNextItem == NULL)
{
// New last and first item.
pLNode->pPrevItem = pNewFirstItem;
pNewFirstItem->SetNextListItem( uiList, NULL);
}
else
{
// Add this new item to the first of the list.
pLNode->pNextItem->SetPrevListItem( uiList, pNewFirstItem );
pNewFirstItem->SetNextListItem( uiList, pLNode->pNextItem);
}
pLNode->pNextItem = pNewFirstItem;
pNewFirstItem->SetPrevListItem( uiList, NULL);
pNewFirstItem->m_bInList = TRUE;
// Increment the list's count element
pLNode->uiListCount++;
return;
}
/****************************************************************************
Desc: Insert an item into the end of a list.
****************************************************************************/
void F_ListMgr::InsertAtEnd(
FLMUINT uiList, // List to insert this item.
F_ListItem * pNewLastItem) // New item to be inserted at the end.
{
F_ListNode * pLNode;
// Check bounds with assert.
// This should be fine because uiList values are defined.
flmAssert( uiList < m_uiLNodeCnt );
pNewLastItem->AddRef();
pLNode = &m_pLNodes[ uiList ];
if( pLNode->pPrevItem == NULL)
{
// New last and first item.
pLNode->pNextItem = pNewLastItem;
pNewLastItem->SetPrevListItem( uiList, NULL);
}
else
{
// Add this new item to the end of the list.
pLNode->pPrevItem->SetNextListItem( uiList, pNewLastItem);
pNewLastItem->SetPrevListItem( uiList, pLNode->pPrevItem);
}
pLNode->pPrevItem = pNewLastItem;
pNewLastItem->SetNextListItem( uiList, NULL);
pNewLastItem->m_bInList = TRUE;
// Increment the list's count element
pLNode->uiListCount++;
return;
}
/****************************************************************************
Desc: Obtain an item from the list. Do not remove the item from the list.
****************************************************************************/
F_ListItem * F_ListMgr::GetItem(
FLMUINT uiList, // List to get the item from.
FLMUINT nth) // Which item to retrieve (0 == first)
{
F_ListNode * pLNode;
F_ListItem * pListItem;
// Check bounds with assert.
flmAssert( uiList < m_uiLNodeCnt );
pLNode = &m_pLNodes[ uiList ];
pListItem = pLNode ? pLNode->pNextItem : NULL;
while( nth-- )
{
pListItem = pListItem->GetNextListItem( uiList );
}
return pListItem;
}
/****************************************************************************
Desc: Remove the supplied ListItem object from the specified list.
****************************************************************************/
void F_ListMgr::RemoveItem(
FLMUINT uiList,
F_ListItem * pItem)
{
F_ListNode * pMgrLNode; /* Manager's list node (head/tail pointers)*/
F_ListItem * pPrevItem;
F_ListItem * pNextItem;
flmAssert( uiList < m_uiLNodeCnt);
pMgrLNode = &m_pLNodes[ uiList];
/* Get this item's Prev and Next items. */
pPrevItem = pItem->GetPrevListItem( uiList);
pNextItem = pItem->GetNextListItem( uiList);
if( pPrevItem == NULL && pNextItem == NULL
&& pMgrLNode->pPrevItem != pItem
&& pMgrLNode->pNextItem != pItem)
{
/* If the item is not within the list then skip to the end.
Note: Need to also make sure this item is not the head or tail. */
goto Exit;
}
/* Determine if this item is pointed to by the head or tail pointers
that the list manager maintains. */
if( pMgrLNode->pPrevItem == pItem)
{
pMgrLNode->pPrevItem = pItem->GetPrevListItem( uiList);
}
if( pMgrLNode->pNextItem == pItem)
{
pMgrLNode->pNextItem = pItem->GetNextListItem( uiList);
}
/* If there is a prev item - change it's next ptr to be items next ptr */
if( pPrevItem != NULL)
{
pPrevItem->SetNextListItem( uiList, pItem->GetNextListItem( uiList));
}
/* If there is a next item - change it's prev ptr to be items prev ptr */
if( pNextItem != NULL)
{
pNextItem->SetPrevListItem( uiList, pItem->GetPrevListItem( uiList));
}
/* Clear out this items prev and next links */
pItem->SetPrevListItem( uiList, NULL);
pItem->SetNextListItem( uiList, NULL);
pItem->m_bInList = FALSE;
/* This list no longer needs a reference to this object. */
pItem->Release();
/* Decrement this list's count element */
pMgrLNode->uiListCount--;
Exit:
return;
}
/****************************************************************************
Desc: Unlink all items from a single specified list or all lists.
****************************************************************************/
RCODE F_ListMgr::ClearList(
FLMUINT uiList) // List number or FLM_ALL_LISTS
{
FLMUINT uiListCnt;
F_ListNode * pLNode;
// Check bounds with assert.
flmAssert( (FLM_ALL_LISTS == uiList) || (uiList < m_uiLNodeCnt));
if( uiList == FLM_ALL_LISTS)
{
uiList = 0;
uiListCnt = m_uiLNodeCnt;
pLNode = m_pLNodes;
}
else
{
uiListCnt = 1;
pLNode = &m_pLNodes[ uiList ];
}
for( ; uiListCnt--; pLNode++, uiList++)
{
F_ListItem * pItem;
F_ListItem * pNextItem;
// Go through the list Releasing every list item.
for( pItem = pLNode->pNextItem; pItem; pItem = pNextItem)
{
pNextItem = pItem->GetNextListItem( uiList);
(void) RemoveItem( uiList, pItem);
}
// At this point the ListCount should be at 0.
flmAssert( pLNode->uiListCount == 0);
// Clear the managers head and tail list pointers.
pLNode->pNextItem = pLNode->pPrevItem = NULL;
}
return FERR_OK;
}
/****************************************************************************
Desc: Obtain an the number of items within a list.
****************************************************************************/
FLMUINT F_ListMgr::GetCount(
FLMUINT uiList) // List to get the item count from.
{
FLMUINT uiLNodeCnt;
FLMUINT uiCount = 0;
F_ListNode * pLNode;
// Check bounds with assert.
flmAssert( (FLM_ALL_LISTS == uiList) || (uiList < m_uiLNodeCnt));
if( uiList == FLM_ALL_LISTS)
{
uiLNodeCnt = m_uiLNodeCnt;
pLNode = m_pLNodes;
}
else
{
uiLNodeCnt = 1;
pLNode = &m_pLNodes[ uiList];
}
/* Calculate the count for the list[s] */
for( ; uiLNodeCnt--; pLNode++)
{
uiCount += pLNode->uiListCount;
}
return uiCount;
}
/****************************************************************************
Desc: Destructor
****************************************************************************/
F_ListItem::~F_ListItem()
{
#ifdef FLM_DEBUG
FLMUINT uiLoop;
F_ListNode * pTmpNd;
flmAssert( m_bInList == FALSE);
for( uiLoop = 0; uiLoop < m_uiLNodeCnt; uiLoop++)
{
pTmpNd = &m_pLNodes[ uiLoop];
flmAssert( pTmpNd->pPrevItem == NULL && pTmpNd->pNextItem == NULL);
}
#endif
}
/****************************************************************************
Desc: Setup the pLNode array and set the count.
Visit: We may want to add code in the future to check if Setup() has
been previous called. If so recode for uiLNodeCnt to be zero.
****************************************************************************/
RCODE F_ListItem::Setup(
F_ListMgr * pList, // List manager to use
F_ListNode * pLNodes, // Array of LNODEs to be used
FLMUINT uiLNodeCnt) // Number of LNODEs supplied.
{
flmAssert( pList != NULL);
flmAssert( pLNodes != NULL);
flmAssert( uiLNodeCnt != 0);
m_pListMgr = pList;
m_uiLNodeCnt = uiLNodeCnt;
m_pLNodes = pLNodes;
f_memset( pLNodes, 0, sizeof( F_ListNode) * uiLNodeCnt );
return FERR_OK;
}
/****************************************************************************
Desc: Remove this list item from all of the lists it is in.
****************************************************************************/
RCODE F_ListItem::RemoveFromList( // Remove this list item from all lists.
FLMUINT uiList) // Which list to remove item from
// To remove item from all lists pass in
// FLM_ALL_LISTS define.
{
flmAssert( (uiList < m_uiLNodeCnt) || (uiList == FLM_ALL_LISTS));
if( uiList == FLM_ALL_LISTS)
{
FLMUINT uiListCnt = m_uiLNodeCnt;
F_ListNode * pLNode = m_pLNodes;
uiList = 0;
/* Remove this item from all lists. */
for( ; uiListCnt--; uiList++, pLNode++)
{
m_pListMgr->RemoveItem( uiList, this);
}
}
else
{
/* Remove item from a specific list. */
m_pListMgr->RemoveItem( uiList, this);
}
return FERR_OK;
}