hxslist.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:14k
源码类别:

Symbian

开发平台:

C/C++

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