📄 hxslist.cpp
字号:
/* ***** 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"#endifCHXSimpleList::CHXSimpleList() : m_nelems(0), m_pHead(0), m_pTail(0){}CHXSimpleList::~CHXSimpleList(){ RemoveAll();}// TRUE if list is internally consistentBOOL 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 elementvoid 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 elementvoid 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 listvoid 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 incrvoid*& 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 incrvoid* 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 decrvoid*& 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 decrvoid* 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 positionvoid* 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 positionvoid*& 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 positionvoid* 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 LISTPOSITIONvoid*& CHXSimpleList::GetAt(LISTPOSITION pos){ HX_ASSERT(pos != (LISTPOSITION)NULL); CNode* pNode = (CNode*)pos; return pNode->GetValue();}// get value at LISTPOSITIONvoid* CHXSimpleList::GetAt(LISTPOSITION pos) const{ HX_ASSERT(pos != (LISTPOSITION)NULL); CNode* pNode = (CNode*)pos; return pNode->GetValue();}// set value at LISTPOSITIONvoid CHXSimpleList::SetAt(LISTPOSITION pos, void* value){ HX_ASSERT(pos != (LISTPOSITION)NULL); CNode* pNode = (CNode*)pos; pNode->SetValue(value);}// remove nodeCHXSimpleList::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 LISTPOSITIONLISTPOSITION 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 LISTPOSITIONLISTPOSITION 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 listLISTPOSITION 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 indexLISTPOSITION 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;}LISTPOSITIONCHXSimpleList::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; }LISTPOSITIONCHXSimpleList::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 _DEBUGstatic 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 */voidCHXSimpleList::Dump(const char* label) const{#ifdef _DEBUG printf("%sthis=(CHXSimpleList*)%p; head=%p; tail=%p; nelems=%d\n", 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 listLISTPOSITION 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 orderLISTPOSITION 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 memvoid CHXStringList::RemoveHeadString(){ CHXString* pString = (CHXString*)RemoveHead(); delete pString;}// remove tail string and free memvoid CHXStringList::RemoveTailString(){ CHXString* pString = (CHXString*)RemoveTail(); delete pString;}#ifdef _DEBUGstatic 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 */voidCHXStringList::Dump(const char* label) const{#ifdef _DEBUG printf("%sthis=(CHXStringList*)%p; head=%p; tail=%p; nelems=%d\n", 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();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -