hxslist.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:15k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxslist.cpp,v 1.8.2.3 2004/07/09 01:45:59 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxslist.h"
  50. #include "debug.h"
  51. #include "hlxclib/ctype.h"
  52. #ifndef _MACINTOSH
  53. #include "hlxclib/string.h"
  54. #endif
  55. CHXSimpleList::CHXSimpleList()
  56.     : m_nelems(0),
  57.       m_pHead(0),
  58.       m_pTail(0)
  59. {
  60. }
  61. CHXSimpleList::~CHXSimpleList()
  62. {
  63.     RemoveAll();
  64. }
  65. // TRUE if list is internally consistent
  66. BOOL 
  67. CHXSimpleList::IsPtrListValid()
  68. {
  69.     if (!m_pHead)
  70.     {
  71. if (m_pTail)
  72.     return FALSE;
  73. if (m_nelems)
  74.     return FALSE;
  75.     }
  76.     else if (!m_pTail) return FALSE;
  77.     if (m_nelems == 1)
  78.     {
  79. if (m_pHead != m_pTail)
  80.     return FALSE;
  81.     }
  82.     if (m_nelems < 0) return FALSE;
  83.     return TRUE;
  84. }
  85. // insert list before first element
  86. void 
  87. CHXSimpleList::AddHead(CHXSimpleList* pList)
  88. {
  89.     HX_ASSERT(pList);
  90.     
  91.     for (CNode* pNode = pList->m_pTail; pNode; pNode = pNode->GetPrev())
  92. (void)InsertBefore((LISTPOSITION)m_pHead, pNode->GetValue());
  93. // insert list after last element
  94. void 
  95. CHXSimpleList::AddTail(CHXSimpleList* pList)
  96. {
  97.     HX_ASSERT(pList);
  98.     for (CNode* pNode = pList->m_pHead; pNode; pNode = pNode->GetNext())
  99. (void)InsertAfter((LISTPOSITION)m_pTail, pNode->GetValue());
  100. }
  101. // clear all elements from the list
  102. void 
  103. CHXSimpleList::RemoveAll()
  104. {
  105.     if (m_pHead)
  106.     {
  107. CNode* pNode = m_pHead;
  108.     
  109. while (pNode)
  110. {
  111.     CNode* pNext = pNode->GetNext();
  112.     delete pNode;
  113.     --m_nelems;
  114.     pNode = pNext;
  115. }
  116.     }
  117.     m_pHead = m_pTail = 0;
  118.     HX_ASSERT (m_nelems == 0);
  119. }
  120. // return value at current position and incr
  121. void*& 
  122. CHXSimpleList::GetNext(LISTPOSITION& pos)
  123. {
  124.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  125.     CNode* pNode = (CNode*)pos;
  126.     pos = (LISTPOSITION)pNode->GetNext();
  127.     return pNode->GetValue();
  128. }
  129. // return value at current position and incr
  130. void* 
  131. CHXSimpleList::GetNext(LISTPOSITION& pos) const
  132. {
  133.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  134.     CNode* pNode = (CNode*)pos;
  135.     pos = (LISTPOSITION)pNode->GetNext();
  136.     return pNode->GetValue();
  137. }
  138. // return value at current position and decr
  139. void*& 
  140. CHXSimpleList::GetPrev(LISTPOSITION& pos)
  141. {
  142.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  143.     CNode* pNode = (CNode*)pos;
  144.     pos = (LISTPOSITION)pNode->GetPrev();
  145.     return pNode->GetValue();
  146. }
  147. // return value at current position and decr
  148. void* 
  149. CHXSimpleList::GetPrev(LISTPOSITION& pos) const
  150. {
  151.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  152.     CNode* pNode = (CNode*)pos;
  153.     pos = (LISTPOSITION)pNode->GetPrev();
  154.     return pNode->GetValue();
  155. }
  156. // incr and return value at current position 
  157. void*& 
  158. CHXSimpleList::GetAtNext(LISTPOSITION& pos)
  159. {
  160.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  161.     CNode* pNode = (CNode*)pos;
  162.     pNode = pNode->GetNext();
  163.     pos = (LISTPOSITION)pNode;
  164.     return pNode ? pNode->GetValue() : (void*&)_nil();
  165. }
  166. // incr and return value at current position
  167. void* 
  168. CHXSimpleList::GetAtNext(LISTPOSITION& pos) const
  169. {
  170.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  171.     CNode* pNode = (CNode*)pos;
  172.     pNode = pNode->GetNext();
  173.     pos = (LISTPOSITION)pNode;
  174.     return pNode ? (void*)pNode->GetValue() : (void*)_nil();
  175. }
  176. // decr and return value at current position
  177. void*& 
  178. CHXSimpleList::GetAtPrev(LISTPOSITION& pos)
  179. {
  180.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  181.     CNode* pNode = (CNode*)pos;
  182.     pNode = pNode->GetPrev();
  183.     pos = (LISTPOSITION)pNode;
  184.     return pNode ? pNode->GetValue() : (void*&)_nil();
  185. }
  186. // decr and return value at current position
  187. void* 
  188. CHXSimpleList::GetAtPrev(LISTPOSITION& pos) const
  189. {
  190.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  191.     CNode* pNode = (CNode*)pos;
  192.     pNode = pNode->GetPrev();
  193.     pos = (LISTPOSITION)pNode;
  194.     return pNode ? (void*)pNode->GetValue() : (void*)_nil();
  195. }
  196. // get value at LISTPOSITION
  197. void*& 
  198. CHXSimpleList::GetAt(LISTPOSITION pos)
  199. {
  200.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  201.     CNode* pNode = (CNode*)pos;
  202.     return pNode->GetValue();
  203. }
  204. // get value at LISTPOSITION
  205. void* 
  206. CHXSimpleList::GetAt(LISTPOSITION pos) const
  207. {
  208.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  209.     CNode* pNode = (CNode*)pos;
  210.     return pNode->GetValue();
  211. }
  212. // set value at LISTPOSITION
  213. void 
  214. CHXSimpleList::SetAt(LISTPOSITION pos, void* value)
  215. {
  216.     HX_ASSERT(pos != (LISTPOSITION)NULL);
  217.     CNode* pNode = (CNode*)pos;
  218.     pNode->SetValue(value);
  219. }
  220. // remove node
  221. CHXSimpleList::CNode*
  222. CHXSimpleList::RemoveNode(CNode* pNode)
  223. {
  224.     HX_ASSERT(pNode != NULL);
  225.     CNode* pPrev = pNode->GetPrev();
  226.     CNode* pNext = pNode->GetNext();
  227.     if (pPrev)
  228. pPrev->SetNext(pNext);
  229.     else
  230. m_pHead = pNext;
  231.     if (pNext)
  232. pNext->SetPrev(pPrev);
  233.     else
  234. m_pTail = pPrev;
  235.     delete pNode;
  236.     --m_nelems;
  237.     // Yes, this is kinda goofy...
  238.     return (pNext ? pNext : pPrev);
  239. }
  240.     
  241. // insert before LISTPOSITION
  242. LISTPOSITION 
  243. CHXSimpleList::InsertBefore(LISTPOSITION pos, void* value)
  244. {
  245.     CNode* pNode = CreateNode(value);
  246.     if( !pNode )
  247.     {
  248.         return (LISTPOSITION)NULL;
  249.     }
  250.     CNode* pNext = (CNode*)(pos ? pos : m_pHead);
  251.     CNode* pPrev = NULL;
  252.     if (pNext)
  253.     {
  254. pPrev = pNext->GetPrev();
  255. pNext->SetPrev(pNode);
  256. pNode->SetNext(pNext);
  257.     }
  258.     else m_pTail = pNode;
  259.     if (pNext == m_pHead)
  260. m_pHead = pNode;
  261.     if (pPrev)
  262.     {
  263. pPrev->SetNext(pNode);
  264. pNode->SetPrev(pPrev);
  265.     }
  266.     ++m_nelems;
  267.     return (LISTPOSITION)pNode;
  268. }
  269. // insert after LISTPOSITION
  270. LISTPOSITION 
  271. CHXSimpleList::InsertAfter(LISTPOSITION pos, void* value)
  272. {
  273.     CNode* pNode = CreateNode(value);
  274.     if( !pNode )
  275.     {
  276.         return (LISTPOSITION)NULL;
  277.     }
  278.     CNode* pPrev = (CNode*)(pos ? pos : m_pTail);
  279.     CNode* pNext = NULL;
  280.     if (pPrev)
  281.     {
  282. pNext = pPrev->GetNext();
  283. pPrev->SetNext(pNode);
  284. pNode->SetPrev(pPrev);
  285.     }
  286.     else m_pHead = pNode;
  287.     if (pPrev == m_pTail)
  288.         m_pTail = pNode;
  289.     if (pNext)
  290.     {
  291. pNext->SetPrev(pNode);
  292. pNode->SetNext(pNext);
  293.     }
  294.     
  295.     ++m_nelems;
  296.     return (LISTPOSITION)pNode;
  297. }
  298.     
  299. // search for value in list
  300. LISTPOSITION 
  301. CHXSimpleList::Find(void* value, LISTPOSITION start)
  302. {
  303.     CNode* pNode;
  304.     if (!start)
  305. pNode = m_pHead;
  306.     else
  307. pNode = (CNode*)start;
  308.     while (pNode)
  309.     {
  310. if (pNode->GetValue() == value)
  311.     return (LISTPOSITION)pNode;
  312. pNode = pNode->GetNext();
  313.     }
  314.     return (LISTPOSITION)NULL;
  315. }
  316. // get the LISTPOSITION for element at index
  317. LISTPOSITION 
  318. CHXSimpleList::FindIndex(int index) const
  319. {
  320.     if (index >= m_nelems || index < 0) return NULL;
  321.     CNode* pNode = m_pHead;
  322.     while (pNode && index--)
  323. pNode = pNode->GetNext();
  324.     return (LISTPOSITION)pNode;
  325. }
  326. LISTPOSITION
  327. CHXSimpleList::ForEach(LISTPOSITION start, LISTPOSITION end, void* pUser,
  328.        ConditionFunc func)
  329. {
  330.     if (!m_pHead) return NULL;
  331.     CNode* pNode;
  332.     if (!start)
  333. pNode = m_pHead;
  334.     else
  335. pNode = (CNode*)start;
  336.     while (pNode != (CNode*)end)
  337.     {
  338. if (func(pUser, pNode->GetValue()))
  339.     return (LISTPOSITION)pNode;
  340. pNode = pNode->GetNext();
  341.     }
  342.     if (func(pUser, pNode->GetValue()))
  343. return (LISTPOSITION)pNode;
  344.     return (LISTPOSITION)NULL;  
  345. }
  346. LISTPOSITION
  347. CHXSimpleList::ForEach(LISTPOSITION start, LISTPOSITION end, void* pUser,
  348.        ConditionNodeFunc func) const
  349. {
  350.     if (!m_pHead) return NULL;
  351.     CNode* pNode;
  352.     if (!start)
  353. pNode = m_pHead;
  354.     else
  355. pNode = (CNode*)start;
  356.     while (pNode != (CNode*)end)
  357.     {
  358. if (func(pUser, pNode))
  359.     return (LISTPOSITION)pNode;
  360. pNode = pNode->GetNext();
  361.     }
  362.     if (func(pUser, pNode))
  363. return (LISTPOSITION)pNode;
  364.     return (LISTPOSITION)NULL;  
  365. }
  366. CHXSimpleList::CNode*
  367. CHXSimpleList::CreateNode(void* value)
  368. {
  369.     return new CNode(value);
  370. }
  371. #ifdef _DEBUG
  372. static BOOL DumpNode(void* /*pUser*/, const CHXSimpleList::CNode* pNode)
  373. {
  374.     printf("   %p: prev=%p; next=%p; val=%p;n",
  375.            pNode,
  376.            pNode->GetPrev(), pNode->GetNext(),
  377.            pNode->GetValue());
  378.     return FALSE;               // to continue iteration
  379. }
  380. #endif /* _DEBUG */
  381. void
  382. CHXSimpleList::Dump(const char* label) const
  383. {
  384. #ifdef _DEBUG
  385.     printf("%sthis=(CHXSimpleList*)%p; head=%p; tail=%p; nelems=%dn",
  386.            label ? label : "", this, m_pHead, m_pTail, m_nelems);
  387.     ForEach(GetHeadPosition(), GetTailPosition(), NULL, &DumpNode);
  388. #endif /* _DEBUG */
  389. }
  390. //
  391. // CHXStringList methods
  392. //
  393. static BOOL IsEqual(void* pUser, void* pData)
  394. {
  395.     const char* s = (const char*)pUser;
  396.     CHXString* pString = (CHXString*)pData;
  397.     return pString->Compare(s) == 0;
  398. }
  399. static BOOL IsEqualNoCase(void* pUser, void* pData)
  400. {
  401.     const char* s = (const char*)pUser;
  402.     CHXString* pString = (CHXString*)pData;
  403.     return pString->CompareNoCase(s) == 0;
  404. }
  405. static BOOL IsPrefix(void* pUser, void* pData)
  406. {
  407.     const char* prefix = (const char*)pUser;
  408.     const char* s = (const char*)*(CHXString*)pData;
  409.     return strncmp(s, prefix, strlen(prefix)) == 0;
  410. }
  411. static BOOL IsPrefixNoCase(void* pUser, void* pData)
  412. {
  413.     const char* prefix = (const char*)pUser;
  414.     const char* s = (const char*)*(CHXString*)pData;
  415.     return strnicmp(s, prefix, strlen(prefix)) == 0;
  416. }
  417. static BOOL IsGreaterAlpha(void* pUser, void* pData)
  418. {
  419.     const char* s = (const char*)pUser;
  420.     CHXString* pString = (CHXString*)pData;
  421.     return pString->Compare(s) > 0;
  422. }
  423. static BOOL IsGreaterAlphaNoCase(void* pUser, void* pData)
  424. {
  425.     const char* s = (const char*)pUser;
  426.     CHXString* pString = (CHXString*)pData;
  427.     return pString->CompareNoCase(s) > 0;
  428. }
  429. // find a string in the list
  430. LISTPOSITION 
  431. CHXStringList::FindString(const char* pString,
  432.   LISTPOSITION start,
  433.   BOOL caseSensitive)
  434. {
  435.     LISTPOSITION pos = NULL;
  436.     if (GetCount() > 0)
  437.     {
  438. if (start)
  439.     pos = start;
  440. else
  441.     pos = GetHeadPosition();
  442. if (caseSensitive)
  443.     pos = ForEach(pos, GetTailPosition(),
  444.   (void*)pString, &IsEqual);
  445. else
  446.     pos = ForEach(pos, GetTailPosition(),
  447.   (void*)pString, &IsEqualNoCase);
  448.     }
  449.     return pos;
  450. }
  451.  
  452. // find a string that starts with 'pPrefix'
  453. LISTPOSITION 
  454. CHXStringList::FindPrefixSubstring(const char* pPrefix,
  455.    LISTPOSITION start,
  456.    BOOL caseSensitive)
  457. {
  458.     LISTPOSITION pos = NULL;
  459.     if (GetCount() > 0)
  460.     {
  461. if (start)
  462.     pos = start;
  463. else
  464.     pos = GetHeadPosition();
  465. if (caseSensitive)
  466.     pos = ForEach(pos, GetTailPosition(),
  467.   (void*)pPrefix, &IsPrefix);
  468. else
  469.     pos = ForEach(pos, GetTailPosition(),
  470.   (void*)pPrefix, &IsPrefixNoCase);
  471.     }
  472.     return pos;
  473. }
  474. // add string in sorted alpha order
  475. LISTPOSITION 
  476. CHXStringList::AddStringAlphabetic(const char* pString, BOOL caseSensitive)
  477. {
  478.     LISTPOSITION pos = GetHeadPosition();
  479.     pos = ForEach(pos, GetTailPosition(), (void*)pString,
  480.                   caseSensitive ? &IsGreaterAlpha : &IsGreaterAlphaNoCase);
  481.     if (pos)
  482. return InsertBefore(pos, new CHXString(pString));
  483.     else
  484. return AddTail(new CHXString(pString));
  485. }
  486. LISTPOSITION 
  487. CHXStringList::RemoveAt(LISTPOSITION pos)
  488. {
  489.     if (pos)
  490.     {
  491.         CNode* pNode = (CNode*)pos;
  492.         delete (CHXString*)pNode->GetValue();
  493.         return CHXSimpleList::RemoveAt(pos);
  494.     }
  495.     return NULL;
  496. }
  497. // remove head string and free mem
  498. void 
  499. CHXStringList::RemoveHeadString()
  500. {
  501.     CHXString* pString = (CHXString*)RemoveHead();
  502.     delete pString;
  503. }
  504. // remove tail string and free mem
  505. void 
  506. CHXStringList::RemoveTailString()
  507. {
  508.     CHXString* pString = (CHXString*)RemoveTail();
  509.     delete pString;
  510. }
  511. #ifdef _DEBUG
  512. static BOOL DumpStringNode(void* /*pUser*/, const CHXSimpleList::CNode* pNode)
  513. {
  514.     const char* sz = (const char*)*(CHXString*)pNode->GetValue();
  515.     printf("   %p: prev=%p; next=%p; val="%s";n",
  516.            pNode,
  517.            pNode->GetPrev(), pNode->GetNext(),
  518.            sz);
  519.     return FALSE;               // to continue iteration
  520. }
  521. #endif /* _DEBUG */
  522. void
  523. CHXStringList::Dump(const char* label) const
  524. {
  525. #ifdef _DEBUG
  526.     printf("%sthis=(CHXStringList*)%p; head=%p; tail=%p; nelems=%dn",
  527.            label ? label : "",
  528.            this, GetHeadPosition(), GetTailPosition(), GetCount());
  529.     ForEach(GetHeadPosition(), GetTailPosition(), NULL, &DumpStringNode);
  530. #endif /* _DEBUG */
  531. }
  532. void 
  533. CHXStringList::RemoveAll()
  534. {
  535.     for (LISTPOSITION p = GetHeadPosition(); p != NULL;)
  536.     {
  537. CHXString* pStr = (CHXString*)GetNext(p);
  538. HX_ASSERT(pStr);
  539. delete pStr;
  540.     }
  541.     CHXSimpleList::RemoveAll();
  542. }