hxslist.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:15k
- /* ***** BEGIN LICENSE BLOCK *****
- * Source last modified: $Id: hxslist.cpp,v 1.8.2.3 2004/07/09 01:45:59 hubbe Exp $
- *
- * Portions Copyright (c) 1995-2004 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 (the "RPSL") available at
- * http://www.helixcommunity.org/content/rpsl unless you have licensed
- * the file under the current version of the RealNetworks Community
- * Source License (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.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL") in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your version of
- * this file only under the terms of the GPL, and not to allow others
- * to use your version of this file under the terms of either the RPSL
- * or RCSL, indicate your decision by deleting the provisions above
- * and replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient may
- * use your version of this file under the terms of any one of the
- * RPSL, the RCSL or the GPL.
- *
- * 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();
- }