home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / opendc12.zip / od124os2.exe / od12osr1.exe / src / LinkList.cpp < prev    next >
C/C++ Source or Header  |  1997-03-21  |  19KB  |  709 lines

  1. //====START_GENERATED_PROLOG======================================
  2. //
  3. //
  4. //   COMPONENT_NAME: odutils
  5. //
  6. //   CLASSES: none
  7. //
  8. //   ORIGINS: 82,27
  9. //
  10. //
  11. //   (C) COPYRIGHT International Business Machines Corp. 1995,1996
  12. //   All Rights Reserved
  13. //   Licensed Materials - Property of IBM
  14. //   US Government Users Restricted Rights - Use, duplication or
  15. //   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  16. //       
  17. //   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  18. //   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  19. //   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  20. //   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  21. //   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  22. //   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  23. //   OR PERFORMANCE OF THIS SOFTWARE.
  24. //
  25. //====END_GENERATED_PROLOG========================================
  26. //
  27. // @(#) 1.5 com/src/utils/LinkList.cpp, odutils, od96os2, odos29712d 7/15/96 17:58:27 [ 3/21/97 17:20:53 ]
  28. /*
  29.     File:        LinkList.cpp
  30.  
  31.     Contains:    Primitive linked list class
  32.  
  33.     Owned by:    Richard Rodseth, Jens Alfke
  34.  
  35.     Copyright:    ⌐ 1993 - 1995 by Apple Computer, Inc., all rights reserved.
  36.  
  37. */
  38.  
  39. #ifndef _LINKLIST_
  40. #include "LinkList.h"
  41. #endif
  42.  
  43. #ifndef _ODEXCEPT_
  44. #include "ODExcept.h"
  45. #endif
  46.  
  47. #ifndef __ERRORS__
  48. #include <Errors.h>
  49. #endif
  50.  
  51. #ifndef _ODDEBUG_
  52. #include "ODDebug.h"
  53. #endif
  54.  
  55. #ifndef _UTILERRS_
  56. #include "UtilErrs.h"
  57. #endif
  58.  
  59. #pragma segment ODLinkedList
  60.  
  61. //==============================================================================
  62. // Constants
  63. //==============================================================================
  64.  
  65. //==============================================================================
  66. // Scalar Types
  67. //==============================================================================
  68.  
  69. //==============================================================================
  70. // Local Classes
  71. //==============================================================================
  72.  
  73. //==============================================================================
  74. // Global Variables
  75. //==============================================================================
  76.  
  77. //==============================================================================
  78. // Function Prototype
  79. //==============================================================================
  80.  
  81.  
  82. //==============================================================================
  83. // Link
  84. //==============================================================================
  85.  
  86.  
  87.  
  88. // Many of the simple link methods are inlines; see List.h for implementations.
  89.  
  90.  
  91. //------------------------------------------------------------------------------
  92. // Link::Link
  93. //
  94. // Constructor for Link
  95. //------------------------------------------------------------------------------
  96.  
  97. Link::Link()                            
  98.     fNext = kODNULL; 
  99.     fPrevious = kODNULL;
  100. }
  101.  
  102. //------------------------------------------------------------------------------
  103. // Link::Link
  104. //
  105. // Constructor for Link
  106. //------------------------------------------------------------------------------
  107.  
  108. Link::Link(Link* next, Link* previous)                            
  109.     fNext = next; 
  110.     fPrevious = previous;
  111. }
  112.  
  113. //------------------------------------------------------------------------------
  114. // Link::Link
  115. //
  116. // Copy constructor for Link
  117. //------------------------------------------------------------------------------
  118.  
  119. Link::Link( const Link &link )                            
  120.     fNext = link.fNext; 
  121.     fPrevious = link.fPrevious;
  122. }
  123.  
  124. //------------------------------------------------------------------------------
  125. // Link::Link
  126. //
  127. // Destructor for Link
  128. //------------------------------------------------------------------------------
  129.  
  130. Link::~Link()                                            
  131. {
  132. }
  133.  
  134. //------------------------------------------------------------------------------
  135. // Link::Remove
  136. //
  137. // Remove a link from its list (if any). DO NOT call this directly if there are
  138. // any iterators active on the list; use LinkedList::Remove instead.
  139. //------------------------------------------------------------------------------
  140.  
  141. void    Link::Remove( )
  142. {
  143.     if( fPrevious )
  144.         fPrevious->SetNext(fNext);
  145.     if( fNext )
  146.         fNext->SetPrevious(fPrevious);
  147.     fNext = kODNULL;
  148.     fPrevious = kODNULL;
  149. }
  150.  
  151. //------------------------------------------------------------------------------
  152. // Link::AddBefore
  153. //
  154. // Add a link to a list before another link. It must not already be on any list.
  155. // DO NOT call this directly if there are any iterators active on the list;
  156. // use LinkedList::Remove instead.
  157. //------------------------------------------------------------------------------
  158.  
  159. void    Link::AddBefore( Link *link )
  160. {
  161.     ASSERT(link!=kODNULL,paramErr);
  162.     WASSERT(fNext==kODNULL);
  163.     WASSERT(fPrevious==kODNULL);
  164.     fNext = link;
  165.     fPrevious = link->GetPrevious();
  166.     fPrevious->SetNext(this);
  167.     fNext->SetPrevious(this);
  168. }
  169.  
  170. //------------------------------------------------------------------------------
  171. // Link::AddAfter
  172. //
  173. // Add a link to a list after another link. It must not already be on any list.
  174. // DO NOT call this directly if there are any iterators active on the list;
  175. // use LinkedList::Remove instead.
  176. //------------------------------------------------------------------------------
  177.  
  178. void    Link::AddAfter( Link *link )
  179. {
  180.     ASSERT(link!=kODNULL,paramErr);
  181.     WASSERT(fNext==kODNULL);
  182.     WASSERT(fPrevious==kODNULL);
  183.     fPrevious = link;
  184.     fNext = link->GetNext();
  185.     fPrevious->SetNext(this);
  186.     fNext->SetPrevious(this);
  187. }
  188.  
  189. //======================================================================================
  190. // Class LinkedList
  191. //======================================================================================
  192.  
  193. //------------------------------------------------------------------------------
  194. // LinkedList::LinkedList
  195. //
  196. // Constructor for LinkedList
  197. //------------------------------------------------------------------------------
  198.  
  199. LinkedList::LinkedList()
  200.     :fSentinel(&fSentinel,&fSentinel),
  201.      fSeed(0)
  202. {
  203. }
  204.  
  205. //------------------------------------------------------------------------------
  206. // LinkedList::~LinkedList
  207. //
  208. // Destructor for LinkedList
  209. //------------------------------------------------------------------------------
  210.  
  211. LinkedList::~LinkedList()
  212. {
  213.     // The list does NOT delete all its links!
  214. }
  215.  
  216. //------------------------------------------------------------------------------
  217. // LinkedList::IsEmpty
  218. //
  219. // Description
  220. //------------------------------------------------------------------------------
  221.  
  222. ODBoolean LinkedList::IsEmpty() const
  223. {
  224.     return this->IsSentinel( fSentinel.GetNext() );
  225. }
  226.  
  227. //------------------------------------------------------------------------------
  228. // LinkedList::Count
  229. //
  230. // Description
  231. //------------------------------------------------------------------------------
  232.  
  233. ODULong LinkedList::Count() const
  234. {
  235.     Link* l = fSentinel.GetNext();
  236.     ODULong count = 0;
  237.     while (this->NotSentinel(l))
  238.     {
  239.         count++;
  240.         l = l->GetNext();
  241.         ASSERT(l!=kODNULL,kODErrAssertionFailed);
  242.     }
  243.     return count;
  244. }
  245.  
  246. //------------------------------------------------------------------------------
  247. // LinkedList::Includes
  248. //
  249. // Does the list include a particular link?
  250. //------------------------------------------------------------------------------
  251.  
  252. ODBoolean LinkedList::Includes( const Link *link ) const
  253. {
  254.     Link* l = fSentinel.GetNext();
  255.     while (this->NotSentinel(l))
  256.     {
  257.         if( l == link )
  258.             return kODTrue;
  259.         else
  260.             l = l->GetNext();
  261.     }
  262.     return kODFalse;
  263. }
  264.  
  265. //------------------------------------------------------------------------------
  266. // LinkedList::DeleteAllLinks
  267. //
  268. // Description
  269. //------------------------------------------------------------------------------
  270.  
  271. void    LinkedList::DeleteAllLinks()
  272. {
  273.  
  274.     Link* l = fSentinel.GetNext();
  275.     Link* n = l;
  276.     while (this->NotSentinel(n))
  277.     {
  278.         n = l->GetNext();
  279.         delete l;    
  280.         l = n;
  281.     }
  282.     fSentinel.SetNext(&fSentinel);
  283.     fSentinel.SetPrevious(&fSentinel);
  284.     fSeed++;
  285. }
  286.  
  287. //------------------------------------------------------------------------------
  288. // LinkedList::RemoveAll
  289. //
  290. // Description
  291. //------------------------------------------------------------------------------
  292.  
  293. void    LinkedList::RemoveAll()
  294. {
  295.  
  296.     Link* l = fSentinel.GetNext();
  297.     Link* n = l;
  298.     while (this->NotSentinel(l))
  299.     {
  300.         n = l->GetNext();
  301.         l->SetNext(kODNULL);
  302.         l->SetPrevious(kODNULL);
  303.         l = n;
  304.     }
  305.     fSentinel.SetNext(&fSentinel);
  306.     fSentinel.SetPrevious(&fSentinel);
  307. }
  308.  
  309. //------------------------------------------------------------------------------
  310. // LinkedList::Remove
  311. //
  312. // Description
  313. //------------------------------------------------------------------------------
  314.  
  315. void    LinkedList::Remove(Link& aLink)
  316. {
  317.     fSeed++;
  318.     aLink.Remove();
  319. }
  320.  
  321. //------------------------------------------------------------------------------
  322. // LinkedList::RemoveFirst
  323. //
  324. // Description
  325. //------------------------------------------------------------------------------
  326.  
  327. Link* LinkedList::RemoveFirst()
  328. {
  329.     Link* old = fSentinel.GetNext();
  330.     if (this->NotSentinel(old))
  331.     {
  332.         fSeed++;
  333.         old->Remove();
  334.         return old;
  335.     }
  336.     else
  337.     {
  338.         return kODNULL;
  339.     }
  340. }
  341.  
  342. //------------------------------------------------------------------------------
  343. // LinkedList::RemoveLast
  344. //
  345. // Description
  346. //------------------------------------------------------------------------------
  347.  
  348. Link* LinkedList::RemoveLast()
  349. {
  350.     Link* old = fSentinel.GetPrevious();
  351.     if (this->NotSentinel(old))
  352.     {
  353.         fSeed++;
  354.         old->Remove();
  355.         return old;
  356.     }
  357.     else
  358.     {
  359.         return kODNULL;
  360.     }
  361. }
  362.  
  363. //------------------------------------------------------------------------------
  364. // LinkedList::AddFirst
  365. //
  366. // Description
  367. //------------------------------------------------------------------------------
  368.  
  369. void    LinkedList::AddFirst(Link* link)
  370. {
  371.     link->AddAfter(this->GetSentinel());
  372.     fSeed++;
  373. }
  374.  
  375. //------------------------------------------------------------------------------
  376. // LinkedList::AddLast( Link )
  377. //
  378. // Description
  379. //------------------------------------------------------------------------------
  380.  
  381. void    LinkedList::AddLast(Link* link)
  382. {
  383.     link->AddBefore(this->GetSentinel());
  384.     fSeed++;
  385. }
  386.  
  387. //------------------------------------------------------------------------------
  388. // LinkedList::AddLast( LinkedList )
  389. //
  390. // Append contents of another list to my end. (Other list becomes empty.)
  391. //------------------------------------------------------------------------------
  392.  
  393. void    LinkedList::AddLast( LinkedList &list )
  394. {
  395.     if( !list.IsEmpty() ) {
  396.         Link *myLast = fSentinel.GetPrevious();
  397.         Link *itsFirst = list.First();
  398.         myLast->SetNext(itsFirst);
  399.         itsFirst->SetPrevious(myLast);
  400.         
  401.         Link *itsLast = list.Last();
  402.         itsLast->SetNext(this->GetSentinel());
  403.         fSentinel.SetPrevious(itsLast);
  404.         
  405.         list.fSentinel.SetNext(this->GetSentinel());
  406.         list.fSentinel.SetPrevious(this->GetSentinel());
  407.  
  408.         fSeed++;
  409.         list.fSeed++;
  410.     }
  411. }
  412.  
  413. //------------------------------------------------------------------------------
  414. // LinkedList::AddLastUnique( LinkedList )
  415. //
  416. // Append contents of another list (w/o duplication) to my end.
  417. //------------------------------------------------------------------------------
  418.  
  419. void    LinkedList::AddLastUnique( LinkedList &list )
  420. {
  421.     for( Link *link = fSentinel.GetNext(); this->NotSentinel(link); link=link->GetNext() )
  422.         if( list.Includes(link) )
  423.             list.Remove(*link);
  424.     this->AddLast(list);
  425. }
  426.  
  427. //------------------------------------------------------------------------------
  428. // LinkedList::AddBefore
  429. //
  430. // Description
  431. //------------------------------------------------------------------------------
  432.  
  433. void LinkedList::AddBefore(Link& existing, Link* link)
  434. {
  435.     link->AddBefore(&existing);
  436.     fSeed++;
  437. }
  438.  
  439. //------------------------------------------------------------------------------
  440. // LinkedList::AddAfter
  441. //
  442. // Description
  443. //------------------------------------------------------------------------------
  444.  
  445. void LinkedList::AddAfter(Link& existing, Link* link)
  446. {
  447.     link->AddAfter(&existing);
  448.     fSeed++;
  449. }
  450.  
  451. //------------------------------------------------------------------------------
  452. // LinkedList::After
  453. //
  454. // Description
  455. //------------------------------------------------------------------------------
  456.  
  457. Link* LinkedList::After(const Link& link) const
  458. {
  459.     Link *next = link.GetNext();
  460.     if( this->IsSentinel(next) )
  461.         return kODNULL;
  462.     else
  463.         return next;
  464. }
  465.  
  466. //------------------------------------------------------------------------------
  467. // LinkedList::Before
  468. //
  469. // Description
  470. //------------------------------------------------------------------------------
  471.  
  472. Link* LinkedList::Before(const Link& link) const
  473. {
  474.     Link *prev = link.GetPrevious();
  475.     if( this->IsSentinel(prev) )
  476.         return kODNULL;
  477.     else
  478.         return prev;
  479. }
  480.  
  481. //------------------------------------------------------------------------------
  482. // LinkedList::First
  483. //
  484. // Description
  485. //------------------------------------------------------------------------------
  486.  
  487. Link*    LinkedList::First()  const
  488. {
  489.     return this->NotSentinel(fSentinel.GetNext()) ? fSentinel.GetNext() : (Link*) kODNULL;
  490. }
  491.  
  492. //------------------------------------------------------------------------------
  493. // LinkedList::Last
  494. //
  495. // Description
  496. //------------------------------------------------------------------------------
  497.  
  498. Link* LinkedList::Last() const
  499. {
  500.     return this->NotSentinel(fSentinel.GetPrevious()) ? fSentinel.GetPrevious() : (Link*) kODNULL;
  501. }
  502.  
  503.  
  504. //======================================================================================
  505. // Class LinkedListIterator
  506. //======================================================================================
  507.  
  508. //------------------------------------------------------------------------------
  509. // LinkedListIterator::LinkedListIterator
  510. //
  511. // Constructor for LinkedListIterator
  512. //------------------------------------------------------------------------------
  513.  
  514. LinkedListIterator::LinkedListIterator(LinkedList* list)
  515. {
  516.     fList = list;
  517.     fCurrent = kODNULL;
  518.     fNext = kODNULL;
  519.     fPrevious = kODNULL;
  520.     fSentinel = &list->fSentinel;
  521.     fSeed = fList->fSeed;    
  522. }
  523.  
  524. //------------------------------------------------------------------------------
  525. // LinkedListIterator::~LinkedListIterator
  526. //
  527. // Destructor for LinkedListIterator
  528. //------------------------------------------------------------------------------
  529.  
  530. LinkedListIterator::~LinkedListIterator()
  531. {
  532. }
  533.  
  534. //------------------------------------------------------------------------------
  535. // LinkedListIterator::First
  536. //
  537. // Description
  538. //------------------------------------------------------------------------------
  539.  
  540. Link* LinkedListIterator::First()
  541. {
  542.     if (fList == kODNULL)
  543.         return kODNULL;
  544.     
  545. #ifdef _PLATFORM_MACINTOSH_    
  546.     if (fSeed != fList->fSeed)
  547.         THROW(kODErrIteratorOutOfSync);
  548. #else
  549.     // re-initialize for a new run
  550.     fNext = kODNULL;
  551.     fPrevious = kODNULL;
  552.     fSentinel = &fList->fSentinel;
  553.     fSeed = fList->fSeed;
  554. #endif    
  555.         
  556.     fCurrent = fList->First();
  557.     if (fCurrent == fSentinel)
  558.         fCurrent = kODNULL;
  559.     return fCurrent;
  560. }
  561.  
  562. //------------------------------------------------------------------------------
  563. // LinkedListIterator::Next
  564. //
  565. // Description
  566. //------------------------------------------------------------------------------
  567.  
  568. Link* LinkedListIterator::Next()
  569. {
  570.     if (fList == kODNULL)
  571.         return kODNULL;
  572.  
  573.     if (fSeed != fList->fSeed)
  574.         THROW(kODErrIteratorOutOfSync);
  575.  
  576.     if (fCurrent == kODNULL)
  577.     {
  578.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  579.         {
  580.             return this->First();
  581.         }
  582.         else    // Just deleted
  583.         {
  584.             fCurrent = fNext;
  585.             fPrevious = kODNULL;
  586.             fNext = kODNULL;
  587.         }
  588.     }
  589.     else
  590.         fCurrent = fCurrent->GetNext();
  591.     
  592.     if (fCurrent == fSentinel)
  593.         fCurrent = kODNULL;
  594.     return fCurrent;
  595. }
  596.  
  597. //------------------------------------------------------------------------------
  598. // LinkedListIterator::Last
  599. //
  600. // Description
  601. //------------------------------------------------------------------------------
  602.  
  603. Link* LinkedListIterator::Last()
  604. {
  605.     if (fList == kODNULL)
  606.         return kODNULL;
  607.  
  608. #ifdef _PLATFORM_MACINTOSH_    
  609.     if (fSeed != fList->fSeed)
  610.         THROW(kODErrIteratorOutOfSync);
  611. #else
  612.     // re-initialize for a new run
  613.     fNext = kODNULL;
  614.     fPrevious = kODNULL;
  615.     fSentinel = &fList->fSentinel;
  616.     fSeed = fList->fSeed;
  617. #endif    
  618.  
  619.     fCurrent = fList->Last();
  620.     if (fCurrent == fSentinel)
  621.         fCurrent = kODNULL;
  622.     return fCurrent;
  623. }
  624.  
  625. //------------------------------------------------------------------------------
  626. // LinkedListIterator::Previous
  627. //
  628. // Description
  629. //------------------------------------------------------------------------------
  630.  
  631. Link* LinkedListIterator::Previous()
  632. {
  633.     if (fList == kODNULL)
  634.         return kODNULL;
  635.  
  636.     if (fSeed != fList->fSeed)
  637.         THROW(kODErrIteratorOutOfSync);
  638.  
  639.     if (fCurrent == kODNULL)
  640.     {
  641.         if ((fNext == kODNULL) && (fPrevious == kODNULL))    // Just starting out
  642.         {
  643.             return this->Last();
  644.         }
  645.         else    // Just deleted
  646.         {
  647.             fCurrent = fPrevious;
  648.             fPrevious = kODNULL;
  649.             fNext = kODNULL;
  650.         }
  651.     }
  652.     else
  653.         fCurrent = fCurrent->GetPrevious();
  654.  
  655.     if (fCurrent == fSentinel)
  656.         fCurrent = kODNULL;
  657.     return fCurrent;
  658. }
  659.  
  660. //------------------------------------------------------------------------------
  661. // LinkedListIterator::Current
  662. //
  663. // Description
  664. //------------------------------------------------------------------------------
  665.  
  666. Link* LinkedListIterator::Current()
  667. {
  668.     return fCurrent;
  669. }
  670.  
  671. //------------------------------------------------------------------------------
  672. // LinkedListIterator::IsNotComplete
  673. //
  674. // Description
  675. //------------------------------------------------------------------------------
  676.  
  677. ODBoolean LinkedListIterator::IsNotComplete()
  678. {
  679.     return (fCurrent != kODNULL);
  680. }
  681.  
  682. //------------------------------------------------------------------------------
  683. // LinkedListIterator::RemoveCurrent
  684. //
  685. // Description
  686. //------------------------------------------------------------------------------
  687.  
  688. void  LinkedListIterator::RemoveCurrent()
  689. {
  690.     if (fList == kODNULL)
  691.         return;
  692.         
  693.     if (fSeed != fList->fSeed)
  694.         THROW(kODErrIteratorOutOfSync);
  695.          
  696.     if (fCurrent != kODNULL)
  697.     {
  698.         fNext = fCurrent->GetNext();
  699.         fPrevious = fCurrent->GetPrevious();
  700.             
  701.         fList->Remove(*fCurrent);
  702.         fCurrent = kODNULL;
  703.         fSeed = fList->fSeed;
  704.     }
  705. }
  706.