home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / SRC / DLBASE.CPP < prev    next >
C/C++ Source or Header  |  1996-07-08  |  11KB  |  363 lines

  1. /****************************************************************************
  2.     $Id: dlbase.cpp 501.0 1995/03/07 12:26:12 RON Exp $
  3.  
  4.     Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
  5.  
  6.     Project:    Tarma Library for C++ V5.0
  7.     Author:    Ron van der Wal
  8.  
  9.     Implementation of class TLDLBase.
  10.  
  11.     $Log: dlbase.cpp $
  12.     Revision 501.0  1995/03/07 12:26:12  RON
  13.     Updated for TLX 5.01
  14.     Revision 1.7  1995/01/31 16:30:10  RON
  15.     Update for release 012
  16.     Added partial support for SunPro C++ compiler
  17.     Revision 1.6  1995/01/06  15:57:36  ron
  18.     Corrected Revision keyword
  19.  
  20.     Revision 1.5  1994/11/16  15:38:25  ron
  21.     Added module info; rearranged #include directives
  22.  
  23.     Revision 1.4  1994/09/28  14:16:55  ron
  24.     Removed Macintosh-style #include references
  25.  
  26.     Revision 1.3  1994/09/27  20:22:12  ron
  27.     Changed path separator from / to \
  28.  
  29.     Revision 1.2  1994/09/26  15:41:33  ron
  30.     Changed include file references
  31.  
  32.     Revision 1.1  1994/08/16  18:12:58  ron
  33.     Initial revision
  34.  
  35. ****************************************************************************/
  36.  
  37. #include <tlx\501\_build.h>
  38.  
  39. TLX_MODULE_INFO("$Revision: 501.0 $");
  40.  
  41. #include <tlx\501\dlists.h>        // Class declaration
  42. #include <tlx\501\except.h>        // Exception handling
  43.  
  44. /*-------------------------------------------------------------------------*/
  45.     TLDLBase::TLDLBase(bool aOwner)
  46.  
  47. /*  Constructor, also doubles as default constructor. Creates an empty list.
  48. ---------------------------------------------------------------------------*/
  49. : mHead(0), mTail(0), mCount(0), mOwner(aOwner)
  50. {
  51. }
  52.  
  53. /*-------------------------------------------------------------------------*/
  54.     TLDLBase::TLDLBase(const TLDLBase &)
  55.  
  56. /*  Copy constructor, does not copy the other list.
  57. ---------------------------------------------------------------------------*/
  58. : mHead(0), mTail(0), mCount(0), mOwner(false)
  59. {
  60. }
  61.  
  62. /*-------------------------------------------------------------------------*/
  63.     TLDLBase::~TLDLBase()
  64.  
  65. /*  Destructor. If the list is woner of its elements at the time of
  66.     destruction, it deletes all its elements.
  67. ---------------------------------------------------------------------------*/
  68. {
  69.     if (mOwner) CleanUp();
  70. }
  71.  
  72. /*-------------------------------------------------------------------------*/
  73.     void TLDLBase::Append(TLDLink *aLink)
  74.  
  75. /*  Adds an element at the end of the list. The element pointer must be
  76.     nonzero, and the element must not currently be part of a list.
  77. ---------------------------------------------------------------------------*/
  78. {
  79.     TLX_ASSERT_PTR(aLink);
  80.     TLX_ASSERT_NULL(aLink->mNext);
  81.     TLX_ASSERT_NULL(aLink->mPrev);
  82.  
  83.     if (mTail)
  84.     mTail->Append(aLink);
  85.     else
  86.     mHead = aLink;
  87.  
  88.     mTail = aLink;
  89.     mCount++;
  90. }
  91.  
  92. /*-------------------------------------------------------------------------*/
  93.     void TLDLBase::Append(TLDLink *aLink, TLDLink *aPos)
  94.  
  95. /*  Inserts a link after another link in the list. The link to insert
  96.     must not currently be part of a list.
  97. ---------------------------------------------------------------------------*/
  98. {
  99.     TLX_ASSERT_PTR(aLink);
  100.     TLX_ASSERT_PTR(aPos);
  101.     TLX_ASSERT_NULL(aLink->mNext);
  102.     TLX_ASSERT_NULL(aLink->mPrev);
  103.     TLX_ASSERT(Contains(aPos));
  104.  
  105.     aPos->Append(aLink);
  106.     if (aPos == mTail)
  107.         mTail = aLink;
  108.     mCount++;
  109. }
  110.  
  111. /*-------------------------------------------------------------------------*/
  112.     bool TLDLBase::BecomeOwner(bool aOwner)
  113.  
  114. /*  Changes the owner status, returning the previous status.
  115. ---------------------------------------------------------------------------*/
  116. {
  117.     bool oldstat = mOwner;
  118.     mOwner = aOwner;
  119.     return oldstat;
  120. }
  121.  
  122. /*-------------------------------------------------------------------------*/
  123.     void TLDLBase::CleanUp()
  124.  
  125. /*  Deletes all elements in the list. The list should be owner for this
  126.     function to be called.
  127. ---------------------------------------------------------------------------*/
  128. {
  129.     TLX_ASSERT(mOwner);
  130.  
  131.     TLDLink *rover = mHead;
  132.     while (rover)
  133.     {
  134.     TLDLink *tmp = rover;
  135.     rover = rover->Next();
  136.     tmp->Unlink();
  137.     delete tmp;
  138.     }
  139. }
  140.  
  141. /*-------------------------------------------------------------------------*/
  142.     void TLDLBase::Concat(TLDLink *aList)
  143.  
  144. /*  Appends another list to the current one. This function differs from
  145.     Append() in that Append() assumes the addition of a single element.
  146. ---------------------------------------------------------------------------*/
  147. {
  148.     TLX_ASSERT_PTR(aList);
  149.     TLX_ASSERT_NULL(aList->mPrev);
  150.  
  151.     if (mTail)
  152.     mTail->Append(aList);
  153.     else
  154.     mHead = aList;
  155.  
  156.     // Find end of new list, counting additional elements as we go
  157.     mTail = aList;
  158.     while (mTail)
  159.     {
  160.     ++mCount;
  161.     mTail = mTail->mNext;
  162.     }
  163. }
  164.  
  165. /*-------------------------------------------------------------------------*/
  166.     void TLDLBase::Concat(TLDLBase &aList)
  167.  
  168. /*  Takes over another list in its entirety. The new list is added at the
  169.     end of the current list; the original list is then made empty.
  170. ---------------------------------------------------------------------------*/
  171. {
  172.     TLX_ASSERT(this != &aList);
  173.     TLX_ASSERT(aList.mCount > 0 || (aList.mHead == 0 && aList.mTail == 0));
  174.  
  175.     if (aList.mHead)
  176.     {
  177.     Concat(aList.mHead);
  178.     aList.mHead  =
  179.     aList.mTail  = 0;
  180.     aList.mCount = 0;
  181.     }
  182. }
  183.  
  184. /*-------------------------------------------------------------------------*/
  185.     bool TLDLBase::Contains(TLDLink *aLink) const
  186.  
  187. /*  Tests whether a given element appears in the list. The function performs
  188.     a linear search.
  189. ---------------------------------------------------------------------------*/
  190. {
  191.     if (!aLink) return false;
  192.  
  193.     for (TLDLink *rover = mHead; rover; rover = rover->Next())
  194.     if (rover == aLink)
  195.         return true;
  196.  
  197.     return false;
  198. }
  199.  
  200. /*-------------------------------------------------------------------------*/
  201.     TLDLink *TLDLBase::Extract(TLDLink *aLink)
  202.  
  203. /*  Removes and returns a specific link from the list.
  204. ---------------------------------------------------------------------------*/
  205. {
  206.     TLX_ASSERT_PTR(aLink);
  207.     TLX_ASSERT(Contains(aLink));
  208.  
  209.     if (aLink == mHead) mHead = aLink->Next();
  210.     if (aLink == mTail) mTail = aLink->Prev();
  211.  
  212.     aLink->Unlink();
  213.     TLX_ASSERT(mCount > 0);
  214.     mCount--;
  215.  
  216.     return aLink;
  217. }
  218.  
  219. /*-------------------------------------------------------------------------*/
  220.     TLDLink *TLDLBase::ExtractHead()
  221.  
  222. /*  Removes and returns the first element of the list.
  223. ---------------------------------------------------------------------------*/
  224. {
  225.     if (IsEmpty())
  226.     THROW(TLXEmpty(LOCUS));
  227.  
  228.     TLX_ASSERT_PTR(mHead);
  229.     return Extract(mHead);
  230. }
  231.  
  232. /*-------------------------------------------------------------------------*/
  233.     TLDLink *TLDLBase::ExtractTail()
  234.  
  235. /*  Removes and returns the last element of the list.
  236. ---------------------------------------------------------------------------*/
  237. {
  238.     if (IsEmpty())
  239.     THROW(TLXEmpty(LOCUS));
  240.  
  241.     TLX_ASSERT_PTR(mTail);
  242.     return Extract(mTail);
  243. }
  244.  
  245. /*-------------------------------------------------------------------------*/
  246.     bool TLDLBase::IsEmpty() const
  247.  
  248. /*  Checks if the list is currently empty, returning nonzero if it is.
  249. ---------------------------------------------------------------------------*/
  250. {
  251.     TLX_ASSERT(mCount > 0 || (mHead == 0 && mTail == 0));
  252.     return mCount == 0;
  253. }
  254.  
  255. /*-------------------------------------------------------------------------*/
  256.     TLDLBase &TLDLBase::operator =(const TLDLBase &)
  257.  
  258. /*  Assignment operator, does not copy anything.
  259. ---------------------------------------------------------------------------*/
  260. {
  261.     return *this;
  262. }
  263.  
  264. /*-------------------------------------------------------------------------*/
  265.     void TLDLBase::Prepend(TLDLink *aLink)
  266.  
  267. /*  Adds a new link at the start of the current list. The new link should
  268.     not be 0 and not be part of a list yet.
  269. ---------------------------------------------------------------------------*/
  270. {
  271.     TLX_ASSERT_PTR(aLink);
  272.     TLX_ASSERT_NULL(aLink->mNext);
  273.     TLX_ASSERT_NULL(aLink->mPrev);
  274.  
  275.     if (mHead)
  276.     mHead->Prepend(aLink);
  277.     else
  278.     mTail = aLink;
  279.  
  280.     mHead = aLink;
  281.     mCount++;
  282. }
  283.  
  284. /*-------------------------------------------------------------------------*/
  285.     void TLDLBase::Prepend(TLDLink *aLink, TLDLink *aPos)
  286.  
  287. /*  Inserts a link before another one. The link to insert should not
  288.     be 0 and not be part of a list yet.
  289. ---------------------------------------------------------------------------*/
  290. {
  291.     TLX_ASSERT_PTR(aLink);
  292.     TLX_ASSERT_PTR(aPos);
  293.     TLX_ASSERT_NULL(aLink->mNext);
  294.     TLX_ASSERT_NULL(aLink->mPrev);
  295.     TLX_ASSERT(Contains(aPos));
  296.  
  297.     aPos->Prepend(aLink);
  298.     if (aPos == mHead)
  299.         mHead = aLink;
  300.     mCount++;
  301. }
  302.  
  303. /*-------------------------------------------------------------------------*/
  304.     void TLDLBase::RemoveAll()
  305.  
  306. /*  Removes all elements from the list. If the list owns its items, they
  307.     are deleted; else they are simply forgotten.
  308. ---------------------------------------------------------------------------*/
  309. {
  310.     if (mOwner) CleanUp();
  311.     mHead = mTail = 0;
  312.     mCount = 0;
  313. }
  314.  
  315. /*-------------------------------------------------------------------------*/
  316.     TLDLink *TLDLBase::Replace(TLDLink *aPos, TLDLink *aLink)
  317.  
  318. /*  Replaces one link by another, returning the original link.
  319. ---------------------------------------------------------------------------*/
  320. {
  321.     TLX_ASSERT_PTR(aPos);
  322.     TLX_ASSERT_PTR(aLink);
  323.     TLX_ASSERT(Contains(aPos));
  324.  
  325.     // Insert the new link (before or after the original one), then remove
  326.     // and return the original link.
  327.  
  328.     Append(aLink, aPos);
  329.     return Extract(aPos);
  330. }
  331.  
  332. /*-------------------------------------------------------------------------*/
  333.     TLDLink *TLDLBase::Split(TLDLink *aLink)
  334.  
  335. /*  Splits the list in two at the indicated position. The indicated link
  336.     will become the head of the new list.
  337. ---------------------------------------------------------------------------*/
  338. {
  339.     TLX_ASSERT_PTR(aLink);
  340.     TLX_ASSERT(Contains(aLink));
  341.  
  342.     if (mHead == aLink)
  343.     {
  344.     TLX_ASSERT_NULL(aLink->mPrev);
  345.     mHead = 0;
  346.     }
  347.  
  348.     mTail = aLink->mPrev;
  349.     aLink->mPrev->mNext = 0;
  350.     aLink->mPrev = 0;
  351.  
  352.     // Recount remaining elements
  353.     mCount = 0;
  354.     mTail  = mHead;
  355.     while (mTail)
  356.     {
  357.     ++mCount;
  358.     mTail = mTail->mNext;
  359.     }
  360.     return aLink;
  361. }
  362.  
  363.