hxslist.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:14k
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: RCSL 1.0/RPSL 1.0
- *
- * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
- *
- * The contents of this file, and the files included with this file, are
- * subject to the current version of the RealNetworks Public Source License
- * Version 1.0 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the RealNetworks Community Source License Version 1.0
- * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
- * in which case the RCSL will apply. You may also obtain the license terms
- * directly from RealNetworks. You may not use this file except in
- * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
- * applicable to this file, the RCSL. Please see the applicable RPSL or
- * RCSL for the rights, obligations and limitations governing use of the
- * contents of the file.
- *
- * This file is part of the Helix DNA Technology. RealNetworks is the
- * developer of the Original Code and owns the copyrights in the portions
- * it created.
- *
- * This file, and the files included with this file, is distributed and made
- * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- *
- * Technology Compatibility Kit Test Suite(s) Location:
- * http://www.helixcommunity.org/content/tck
- *
- * Contributor(s):
- *
- * ***** END LICENSE BLOCK ***** */
- #include "hxslist.h"
- #include "debug.h"
- #include "hlxclib/ctype.h"
- #ifndef _MACINTOSH
- #include "hlxclib/string.h"
- #endif
- CHXSimpleList::CHXSimpleList()
- : m_nelems(0),
- m_pHead(0),
- m_pTail(0)
- {
- }
- CHXSimpleList::~CHXSimpleList()
- {
- RemoveAll();
- }
- // TRUE if list is internally consistent
- BOOL
- CHXSimpleList::IsPtrListValid()
- {
- if (!m_pHead)
- {
- if (m_pTail)
- return FALSE;
- if (m_nelems)
- return FALSE;
- }
- else if (!m_pTail) return FALSE;
- if (m_nelems == 1)
- {
- if (m_pHead != m_pTail)
- return FALSE;
- }
- if (m_nelems < 0) return FALSE;
-
- return TRUE;
- }
- // insert list before first element
- void
- CHXSimpleList::AddHead(CHXSimpleList* pList)
- {
- HX_ASSERT(pList);
-
- for (CNode* pNode = pList->m_pTail; pNode; pNode = pNode->GetPrev())
- (void)InsertBefore((LISTPOSITION)m_pHead, pNode->GetValue());
- }
- // insert list after last element
- void
- CHXSimpleList::AddTail(CHXSimpleList* pList)
- {
- HX_ASSERT(pList);
- for (CNode* pNode = pList->m_pHead; pNode; pNode = pNode->GetNext())
- (void)InsertAfter((LISTPOSITION)m_pTail, pNode->GetValue());
- }
- // clear all elements from the list
- void
- CHXSimpleList::RemoveAll()
- {
- if (m_pHead)
- {
- CNode* pNode = m_pHead;
-
- while (pNode)
- {
- CNode* pNext = pNode->GetNext();
- delete pNode;
- --m_nelems;
- pNode = pNext;
- }
- }
- m_pHead = m_pTail = 0;
- HX_ASSERT (m_nelems == 0);
- }
- // return value at current position and incr
- void*&
- CHXSimpleList::GetNext(LISTPOSITION& pos)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pos = (LISTPOSITION)pNode->GetNext();
- return pNode->GetValue();
- }
- // return value at current position and incr
- void*
- CHXSimpleList::GetNext(LISTPOSITION& pos) const
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pos = (LISTPOSITION)pNode->GetNext();
- return pNode->GetValue();
- }
- // return value at current position and decr
- void*&
- CHXSimpleList::GetPrev(LISTPOSITION& pos)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pos = (LISTPOSITION)pNode->GetPrev();
- return pNode->GetValue();
- }
- // return value at current position and decr
- void*
- CHXSimpleList::GetPrev(LISTPOSITION& pos) const
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pos = (LISTPOSITION)pNode->GetPrev();
- return pNode->GetValue();
- }
- // incr and return value at current position
- void*&
- CHXSimpleList::GetAtNext(LISTPOSITION& pos)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pNode = pNode->GetNext();
- pos = (LISTPOSITION)pNode;
- return pNode ? pNode->GetValue() : (void*&)_nil();
- }
- // incr and return value at current position
- void*
- CHXSimpleList::GetAtNext(LISTPOSITION& pos) const
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pNode = pNode->GetNext();
- pos = (LISTPOSITION)pNode;
- return pNode ? (void*)pNode->GetValue() : (void*)_nil();
- }
- // decr and return value at current position
- void*&
- CHXSimpleList::GetAtPrev(LISTPOSITION& pos)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pNode = pNode->GetPrev();
- pos = (LISTPOSITION)pNode;
- return pNode ? pNode->GetValue() : (void*&)_nil();
- }
- // decr and return value at current position
- void*
- CHXSimpleList::GetAtPrev(LISTPOSITION& pos) const
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pNode = pNode->GetPrev();
- pos = (LISTPOSITION)pNode;
- return pNode ? (void*)pNode->GetValue() : (void*)_nil();
- }
- // get value at LISTPOSITION
- void*&
- CHXSimpleList::GetAt(LISTPOSITION pos)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- return pNode->GetValue();
- }
- // get value at LISTPOSITION
- void*
- CHXSimpleList::GetAt(LISTPOSITION pos) const
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- return pNode->GetValue();
- }
- // set value at LISTPOSITION
- void
- CHXSimpleList::SetAt(LISTPOSITION pos, void* value)
- {
- HX_ASSERT(pos != (LISTPOSITION)NULL);
- CNode* pNode = (CNode*)pos;
- pNode->SetValue(value);
- }
- // remove node
- CHXSimpleList::CNode*
- CHXSimpleList::RemoveNode(CNode* pNode)
- {
- HX_ASSERT(pNode != NULL);
- CNode* pPrev = pNode->GetPrev();
- CNode* pNext = pNode->GetNext();
- if (pPrev)
- pPrev->SetNext(pNext);
- else
- m_pHead = pNext;
- if (pNext)
- pNext->SetPrev(pPrev);
- else
- m_pTail = pPrev;
- delete pNode;
- --m_nelems;
- // Yes, this is kinda goofy...
- return (pNext ? pNext : pPrev);
- }
-
- // insert before LISTPOSITION
- LISTPOSITION
- CHXSimpleList::InsertBefore(LISTPOSITION pos, void* value)
- {
- CNode* pNode = CreateNode(value);
- if( !pNode )
- {
- return (LISTPOSITION)NULL;
- }
- CNode* pNext = (CNode*)(pos ? pos : m_pHead);
- CNode* pPrev = NULL;
- if (pNext)
- {
- pPrev = pNext->GetPrev();
- pNext->SetPrev(pNode);
- pNode->SetNext(pNext);
- }
- else m_pTail = pNode;
- if (pNext == m_pHead)
- m_pHead = pNode;
- if (pPrev)
- {
- pPrev->SetNext(pNode);
- pNode->SetPrev(pPrev);
- }
- ++m_nelems;
- return (LISTPOSITION)pNode;
- }
- // insert after LISTPOSITION
- LISTPOSITION
- CHXSimpleList::InsertAfter(LISTPOSITION pos, void* value)
- {
- CNode* pNode = CreateNode(value);
- if( !pNode )
- {
- return (LISTPOSITION)NULL;
- }
- CNode* pPrev = (CNode*)(pos ? pos : m_pTail);
- CNode* pNext = NULL;
- if (pPrev)
- {
- pNext = pPrev->GetNext();
- pPrev->SetNext(pNode);
- pNode->SetPrev(pPrev);
- }
- else m_pHead = pNode;
- if (pPrev == m_pTail)
- m_pTail = pNode;
- if (pNext)
- {
- pNext->SetPrev(pNode);
- pNode->SetNext(pNext);
- }
-
- ++m_nelems;
- return (LISTPOSITION)pNode;
- }
-
- // search for value in list
- LISTPOSITION
- CHXSimpleList::Find(void* value, LISTPOSITION start)
- {
- CNode* pNode;
- if (!start)
- pNode = m_pHead;
- else
- pNode = (CNode*)start;
- while (pNode)
- {
- if (pNode->GetValue() == value)
- return (LISTPOSITION)pNode;
- pNode = pNode->GetNext();
- }
- return (LISTPOSITION)NULL;
- }
- // get the LISTPOSITION for element at index
- LISTPOSITION
- CHXSimpleList::FindIndex(int index) const
- {
- if (index >= m_nelems || index < 0) return NULL;
- CNode* pNode = m_pHead;
- while (pNode && index--)
- pNode = pNode->GetNext();
- return (LISTPOSITION)pNode;
- }
- LISTPOSITION
- CHXSimpleList::ForEach(LISTPOSITION start, LISTPOSITION end, void* pUser,
- ConditionFunc func)
- {
- if (!m_pHead) return NULL;
- CNode* pNode;
- if (!start)
- pNode = m_pHead;
- else
- pNode = (CNode*)start;
- while (pNode != (CNode*)end)
- {
- if (func(pUser, pNode->GetValue()))
- return (LISTPOSITION)pNode;
- pNode = pNode->GetNext();
- }
- if (func(pUser, pNode->GetValue()))
- return (LISTPOSITION)pNode;
- return (LISTPOSITION)NULL;
- }
- LISTPOSITION
- CHXSimpleList::ForEach(LISTPOSITION start, LISTPOSITION end, void* pUser,
- ConditionNodeFunc func) const
- {
- if (!m_pHead) return NULL;
- CNode* pNode;
- if (!start)
- pNode = m_pHead;
- else
- pNode = (CNode*)start;
- while (pNode != (CNode*)end)
- {
- if (func(pUser, pNode))
- return (LISTPOSITION)pNode;
- pNode = pNode->GetNext();
- }
- if (func(pUser, pNode))
- return (LISTPOSITION)pNode;
- return (LISTPOSITION)NULL;
- }
- CHXSimpleList::CNode*
- CHXSimpleList::CreateNode(void* value)
- {
- return new CNode(value);
- }
- #ifdef _DEBUG
- static BOOL DumpNode(void* /*pUser*/, const CHXSimpleList::CNode* pNode)
- {
- printf(" %p: prev=%p; next=%p; val=%p;n",
- pNode,
- pNode->GetPrev(), pNode->GetNext(),
- pNode->GetValue());
- return FALSE; // to continue iteration
- }
- #endif /* _DEBUG */
- void
- CHXSimpleList::Dump(const char* label) const
- {
- #ifdef _DEBUG
- printf("%sthis=(CHXSimpleList*)%p; head=%p; tail=%p; nelems=%dn",
- label ? label : "", this, m_pHead, m_pTail, m_nelems);
- ForEach(GetHeadPosition(), GetTailPosition(), NULL, &DumpNode);
- #endif /* _DEBUG */
- }
- //
- // CHXStringList methods
- //
- static BOOL IsEqual(void* pUser, void* pData)
- {
- const char* s = (const char*)pUser;
- CHXString* pString = (CHXString*)pData;
- return pString->Compare(s) == 0;
- }
- static BOOL IsEqualNoCase(void* pUser, void* pData)
- {
- const char* s = (const char*)pUser;
- CHXString* pString = (CHXString*)pData;
- return pString->CompareNoCase(s) == 0;
- }
- static BOOL IsPrefix(void* pUser, void* pData)
- {
- const char* prefix = (const char*)pUser;
- const char* s = (const char*)*(CHXString*)pData;
- return strncmp(s, prefix, strlen(prefix)) == 0;
- }
- static BOOL IsPrefixNoCase(void* pUser, void* pData)
- {
- const char* prefix = (const char*)pUser;
- const char* s = (const char*)*(CHXString*)pData;
- return strnicmp(s, prefix, strlen(prefix)) == 0;
- }
- static BOOL IsGreaterAlpha(void* pUser, void* pData)
- {
- const char* s = (const char*)pUser;
- CHXString* pString = (CHXString*)pData;
- return pString->Compare(s) > 0;
- }
- static BOOL IsGreaterAlphaNoCase(void* pUser, void* pData)
- {
- const char* s = (const char*)pUser;
- CHXString* pString = (CHXString*)pData;
- return pString->CompareNoCase(s) > 0;
- }
- // find a string in the list
- LISTPOSITION
- CHXStringList::FindString(const char* pString,
- LISTPOSITION start,
- BOOL caseSensitive)
- {
- LISTPOSITION pos = NULL;
- if (GetCount() > 0)
- {
- if (start)
- pos = start;
- else
- pos = GetHeadPosition();
- if (caseSensitive)
- pos = ForEach(pos, GetTailPosition(),
- (void*)pString, &IsEqual);
- else
- pos = ForEach(pos, GetTailPosition(),
- (void*)pString, &IsEqualNoCase);
- }
- return pos;
- }
-
- // find a string that starts with 'pPrefix'
- LISTPOSITION
- CHXStringList::FindPrefixSubstring(const char* pPrefix,
- LISTPOSITION start,
- BOOL caseSensitive)
- {
- LISTPOSITION pos = NULL;
- if (GetCount() > 0)
- {
- if (start)
- pos = start;
- else
- pos = GetHeadPosition();
- if (caseSensitive)
- pos = ForEach(pos, GetTailPosition(),
- (void*)pPrefix, &IsPrefix);
- else
- pos = ForEach(pos, GetTailPosition(),
- (void*)pPrefix, &IsPrefixNoCase);
- }
- return pos;
- }
- // add string in sorted alpha order
- LISTPOSITION
- CHXStringList::AddStringAlphabetic(const char* pString, BOOL caseSensitive)
- {
- LISTPOSITION pos = GetHeadPosition();
- pos = ForEach(pos, GetTailPosition(), (void*)pString,
- caseSensitive ? &IsGreaterAlpha : &IsGreaterAlphaNoCase);
- if (pos)
- return InsertBefore(pos, new CHXString(pString));
- else
- return AddTail(new CHXString(pString));
- }
- LISTPOSITION
- CHXStringList::RemoveAt(LISTPOSITION pos)
- {
- if (pos)
- {
- CNode* pNode = (CNode*)pos;
- delete (CHXString*)pNode->GetValue();
- return CHXSimpleList::RemoveAt(pos);
- }
- return NULL;
- }
- // remove head string and free mem
- void
- CHXStringList::RemoveHeadString()
- {
- CHXString* pString = (CHXString*)RemoveHead();
- delete pString;
- }
- // remove tail string and free mem
- void
- CHXStringList::RemoveTailString()
- {
- CHXString* pString = (CHXString*)RemoveTail();
- delete pString;
- }
- #ifdef _DEBUG
- static BOOL DumpStringNode(void* /*pUser*/, const CHXSimpleList::CNode* pNode)
- {
- const char* sz = (const char*)*(CHXString*)pNode->GetValue();
- printf(" %p: prev=%p; next=%p; val="%s";n",
- pNode,
- pNode->GetPrev(), pNode->GetNext(),
- sz);
- return FALSE; // to continue iteration
- }
- #endif /* _DEBUG */
- void
- CHXStringList::Dump(const char* label) const
- {
- #ifdef _DEBUG
- printf("%sthis=(CHXStringList*)%p; head=%p; tail=%p; nelems=%dn",
- label ? label : "",
- this, GetHeadPosition(), GetTailPosition(), GetCount());
- ForEach(GetHeadPosition(), GetTailPosition(), NULL, &DumpStringNode);
- #endif /* _DEBUG */
- }
- void
- CHXStringList::RemoveAll()
- {
- for (LISTPOSITION p = GetHeadPosition(); p != NULL;)
- {
- CHXString* pStr = (CHXString*)GetNext(p);
- HX_ASSERT(pStr);
- delete pStr;
- }
- CHXSimpleList::RemoveAll();
- }