home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / MiscKit / Source / MiscLinkedList.m < prev    next >
Encoding:
Text File  |  1994-01-31  |  13.6 KB  |  640 lines

  1. //
  2. //    MiscLinkedList.m -- an implementation of a doubly linked list
  3. //        Written by Sean Luke (c) 1993, 1994 by Sean Luke.
  4. //        Additional methods and editing by Don Yacktman.
  5. //                Version 0.9.  All rights reserved.
  6. //
  7. //        This notice may not be removed from this source code.
  8. //
  9. //    This object is included in the MiscKit by permission from the author
  10. //    and its use is governed by the MiscKit license, found in the file
  11. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  12. //    for a list of all applicable permissions and restrictions.
  13. //    
  14.  
  15. // ***** make sure that the list insertion methods don't reverse the order
  16. // of the inserted list!
  17.  
  18. // ***** finish writing the extra methods
  19.  
  20.  
  21. #import <misckit/misckit.h>
  22.  
  23. @implementation MiscLinkedList
  24.  
  25. - init
  26.     {
  27.     return [self initForClass:[MiscLinkedListNode class]];
  28.     }
  29.     
  30. - initForClass: this_class
  31.     {
  32.     id returnval=[super init];
  33.     node_length=0;
  34.     node_class=this_class;
  35.     return returnval;
  36.     }
  37.  
  38. - free
  39. {
  40.     [self freeNodes];
  41.     return [super free];
  42. }
  43.     
  44. - freeObjects
  45.     {
  46.     id temp;
  47.     [self goFirst];
  48.     while (node_length)
  49.         {
  50.         temp=[self deleteObject];
  51.         if (temp!=nil) [[temp freeObject] free]; // deletes node AND object
  52.         }
  53.     return self;
  54.     }
  55.  
  56. - freeNodes
  57.     {
  58.     id temp;
  59.     [self goFirst];
  60.     while (node_length)
  61.         {
  62.         temp=[self deleteObject];
  63.         if (temp!=nil) [temp free]; // deletes node ONLY
  64.         }
  65.     return self;
  66.     }
  67.  
  68. - goFirst
  69.     {
  70.     current_node=first_node;
  71.     if (current_node==nil) return nil;
  72.     return [current_node getObject];
  73.     }
  74.     
  75. - goNext
  76.      {
  77.     id new_node;
  78.     if (current_node==nil) return nil;
  79.     new_node=[current_node getNext];
  80.     if (new_node==nil) return nil;
  81.     current_node=new_node;
  82.     return [current_node getObject];
  83.     }
  84.     
  85. - goLast
  86.     {
  87.     current_node=last_node;
  88.     if (current_node==nil) return nil;
  89.     return [current_node getObject];
  90.     }
  91.  
  92. - goPrevious
  93.      {
  94.     id new_node;
  95.     if (current_node==nil) return nil;
  96.     new_node=[current_node getPrevious];
  97.     if (new_node==nil) return nil;
  98.     current_node=new_node;
  99.     return [current_node getObject];
  100.     }
  101.  
  102. - getNode
  103.     {
  104.     if (current_node==nil) return nil;
  105.     return current_node;
  106.     }
  107.  
  108.     
  109. - getObject
  110.     {
  111.     if (current_node==nil) return nil;
  112.     return [current_node getObject];
  113.     }
  114.  
  115. - setObject:this_object
  116.     {
  117.     if (current_node==nil) return nil;
  118.     return [current_node setObject:this_object];
  119.     }
  120.     
  121. - insertObjectAfter: this_object
  122.     {
  123.     id new_node;
  124.     if (this_object==nil) return nil;
  125.     new_node=[[node_class alloc] initObject:this_object];
  126.     if (node_length==0)                    // node is both ends
  127.         {
  128.         first_node=new_node;
  129.         last_node=new_node;
  130.         current_node=new_node;
  131.         }
  132.     else if (current_node==last_node)     // node is last end
  133.         {
  134.         [new_node setNext:nil];
  135.         [new_node setPrevious:current_node];
  136.         [current_node setNext:new_node];
  137.         last_node=new_node;
  138.         current_node=new_node;
  139.         }
  140.     else                                 // node is in the middle
  141.         {
  142.         [new_node setNext:[current_node getNext]];
  143.         [new_node setPrevious:current_node];
  144.         [current_node setNext:new_node];
  145.         [[new_node getNext] setPrevious:new_node];
  146.         current_node=new_node;
  147.         }
  148.     node_length++;
  149. //    printf ("Last Node: %d\n",(int)last_node);
  150.     return this_object;
  151.     }
  152.     
  153. - insertObjectBefore: this_object
  154.     {
  155.     id new_node;
  156.     if (this_object==nil) return nil;
  157.     new_node=[[node_class alloc] initObject:this_object];
  158.     
  159.     if (node_length==0)                    // node is both ends
  160.         {
  161.         first_node=new_node;
  162.         last_node=new_node;
  163.         current_node=new_node;
  164.         }
  165.     else if (current_node==first_node)     // node is first end
  166.         {
  167.         [new_node setPrevious:nil];
  168.         [new_node setNext:current_node];
  169.         [current_node setPrevious:new_node];
  170.         first_node=new_node;
  171.         current_node=new_node;
  172.         }
  173.     else                                 // node is in the middle
  174.         {
  175.         [new_node setPrevious:[current_node getPrevious]];
  176.         [new_node setNext:current_node];
  177.         [current_node setPrevious:new_node];
  178.         [[new_node getPrevious] setNext:new_node];
  179.         current_node=new_node;
  180.         }
  181.     node_length++;
  182. //    printf ("Last Node: %d\n",(int)last_node);
  183.     return this_object;
  184.     }
  185.     
  186. - deleteObject
  187.     {
  188.     id next_node, previous_node, the_object;
  189.     if (current_node==nil) return nil;
  190.     
  191.     next_node=[current_node getNext];
  192.     previous_node=[current_node getPrevious];
  193.     the_object=[current_node getObject];
  194.     [current_node free];
  195.     node_length--;
  196.     
  197.     if (node_length==0)                    // that was the last node!
  198.         {
  199.         first_node=nil;
  200.         last_node=nil;
  201.         current_node=nil;
  202.         }
  203.     else if (next_node==nil)             // current node was last
  204.         {
  205.         last_node=previous_node;
  206.         [previous_node setNext:nil];
  207.         current_node=previous_node;
  208.         }
  209.     else if (previous_node==nil)        // current node was first
  210.         {
  211.         first_node=next_node;
  212.         [next_node setPrevious:nil];
  213.         current_node=next_node;
  214.         }
  215.     else                                // node is in the center
  216.         {
  217.         [next_node setPrevious:previous_node];
  218.         [previous_node setNext:next_node];
  219.         current_node=previous_node;            // (default)
  220.         }
  221. //    printf ("Deleting Last Node: %d\n",(int)last_node);
  222.     
  223.     return the_object;
  224.     }
  225.  
  226. - (int) getLength
  227.     {
  228.     return node_length;
  229.     }
  230.     
  231. - read: (NXTypedStream*) stream
  232.     {
  233.     int x;
  234.     id temp=nil;
  235.     id previous=nil;
  236.     
  237.     [super read:stream];
  238.     NXReadTypes(stream, "i", &node_length);
  239.     // others don't matter, since they'll be different anyhow.
  240.     
  241.     first_node=temp;
  242.     current_node=temp;
  243.     for (x=1;x<=node_length;x++)
  244.         {
  245.         temp=NXReadObject(stream);
  246.         if (previous==nil) 
  247.             {
  248.             first_node=temp;                // only read one!
  249.             current_node=temp;
  250.             [temp setPrevious: nil];        // just in case
  251.             }
  252.         else
  253.             {
  254.             [temp setPrevious:previous];
  255.             [previous setNext:temp];
  256.             }
  257.         previous=temp;
  258.         }
  259.     last_node=temp;
  260.     [temp setNext:nil];                    // just in case
  261.     node_class=[temp class]; // assume that all nodes are same class.
  262.     return self;
  263.     }
  264.     
  265. - insertList: this_list
  266.     { // ***** need a version that will insert objects from a NeXT List too
  267.     // inserts this_list into the beginning of the list
  268.     
  269.     if ([this_list getLength])            // not empty
  270.         {
  271.         [this_list goFirst];
  272.         do
  273.             {
  274.             [self insertObjectBefore: [this_list getObject]];
  275.             }
  276.         while ([this_list goNext]!=nil);
  277.         }
  278.     return self;
  279.     }
  280.  
  281.  
  282.  
  283. - insertListAtFront: this_list
  284.     { // ***** need a version that will insert objects from a NeXT List too
  285.     // inserts this_list into the beginning of the list
  286.     
  287.     if ([this_list getLength])            // not empty
  288.         {
  289.         [this_list goFirst];
  290.         [self goFirst];
  291.         do
  292.             {
  293.             [self insertObjectBefore: [this_list getObject]];
  294.             }
  295.         while ([this_list goNext]!=nil);
  296.         }
  297.     return self;
  298.     }
  299.  
  300.  
  301.  
  302. - appendList: this_list
  303.     { // ***** need a version that will insert objects from a NeXT List too
  304.     // appends this_list onto the end of the list
  305.     
  306.     if ([this_list getLength])            // not empty
  307.         {
  308.         [this_list goFirst];
  309.         [self goLast];
  310.         do
  311.             {
  312.             [self insertObjectAfter: [this_list getObject]];
  313.             }
  314.         while ([this_list goNext]!=nil);
  315.         }
  316.     return self;
  317.     }
  318.  
  319.  
  320.  
  321. - write: (NXTypedStream*) stream    
  322.     {
  323.     int x;
  324.     id temp;
  325.     
  326.     [super write:stream];
  327.     NXWriteTypes(stream, "i", (const int*) &node_length);
  328.     temp=first_node;
  329.     for (x=1;x<=node_length;x++)
  330.         {
  331.         NXWriteObject(stream,temp);
  332.         temp=[temp getNext];
  333.         }
  334.     return self;
  335.     }
  336.  
  337. - swapWithNext
  338.     {
  339.     id farnext;
  340.     id farprevious;
  341.     id swapnode;
  342.     
  343.     if (current_node==nil) return nil;                    // node doesn't exist
  344.     if ([current_node getNext]==nil) return nil;        // no node with which to swap
  345.     
  346.     farnext=[[current_node getNext] getNext];
  347.     farprevious=[current_node getPrevious];
  348.     swapnode=[current_node getNext];
  349.     
  350.     [swapnode setPrevious: farprevious];
  351.     [swapnode setNext: current_node];
  352.     [current_node setPrevious: swapnode];
  353.     [current_node setNext: farnext];
  354.     
  355.     if (farnext!=nil)                                        // swapping doesn't move node to back
  356.         {
  357.         [farnext setPrevious: current_node];
  358.         }
  359.     if (farprevious!=nil)                                    // swapping doesn't move node from front
  360.         {
  361.         [farprevious setNext: swapnode];
  362.         }
  363.     return self;
  364.     }
  365.     
  366. - swapWithPrevious
  367.     {
  368.     id farnext;
  369.     id farprevious;
  370.     id swapnode;
  371.     
  372.     if (current_node==nil) return nil;                    // node doesn't exist
  373.     if ([current_node getPrevious]==nil) return nil;    // no node with which to swap
  374.     
  375.     farnext=[current_node getNext];
  376.     farprevious=[[current_node getPrevious] getPrevious];
  377.     swapnode=[current_node getPrevious];
  378.     
  379.     [swapnode setNext: farnext];
  380.     [swapnode setPrevious: current_node];
  381.     [current_node setNext: swapnode];
  382.     [current_node setPrevious: farprevious];
  383.     
  384.     if (farnext!=nil)                                        // swapping doesn't move node from back
  385.         {
  386.         [farnext setPrevious: swapnode];
  387.         }
  388.     if (farprevious!=nil)                                    // swapping doesn't move node to front
  389.         {
  390.         [farprevious setNext: current_node];
  391.         }
  392.     return self;
  393.     }
  394.     
  395.  
  396. - moveToFirst
  397.     {
  398.     id next_node;
  399.     id previous_node;
  400.     
  401.     if (current_node==nil) return nil;
  402.     
  403.     next_node=[current_node getNext];
  404.     previous_node=[current_node getPrevious];
  405.     
  406.     if (next_node!=nil) [next_node setPrevious: previous_node];
  407.     if (previous_node!=nil) [previous_node setNext: next_node];
  408.     [first_node setPrevious:current_node];
  409.     [current_node setNext:first_node];
  410.     [current_node setPrevious:nil];
  411.     first_node=current_node;
  412.     return self;
  413.     }
  414.     
  415.  
  416. - moveToLast
  417.     {
  418.     id next_node;
  419.     id previous_node;
  420.     
  421.     if (current_node==nil) return nil;
  422.     
  423.     next_node=[current_node getNext];
  424.     previous_node=[current_node getPrevious];
  425.     
  426.     if (next_node!=nil) [next_node setPrevious: previous_node];
  427.     if (previous_node!=nil) [previous_node setNext: next_node];
  428.     [last_node setNext:current_node];
  429.     [current_node setPrevious:last_node];
  430.     [current_node setNext:nil];
  431.     last_node=current_node;
  432.     return self;
  433.     }
  434.  
  435. // We guess in the -read method and choose for the node class the
  436. // node at the end of the list...likely to be more correct than
  437. // simply setting the default class, and means that whomever un-archives
  438. // the list doesn't have to worry as much about making sure the class
  439. // is the right one.  Of course, the archiver has to make sure that
  440. // the last node is representative of what we want, but that is
  441. // not likely to be a problem, since typically all nodes will be of
  442. // the same class.
  443. /*- awake
  444.     {
  445.     [super awake];
  446.     node_class=[MiscLinkedListNode class];
  447.     return self;
  448.     }*/
  449.  
  450. - empty
  451. {
  452.     return [self freeNodes];
  453. }
  454.  
  455. - (BOOL)isEqual:anObject;
  456. {
  457.     id temp2, temp = first_node;
  458.     
  459.     // first, a few shortcuts to speed up common cases
  460.     if (anObject == self) return YES;    // same object
  461.     if ([anObject class] != [self class]) return NO; // different classes
  462.     if ([anObject count] != [self count]) return NO; // different lengths
  463.     
  464.     [anObject goFirst];
  465.     temp2 = [anObject getNode];
  466.     while (temp && temp2) { // check each object against counterpart in other
  467.         if (![[temp getObject] isEqual:[temp2 getObject]]) return NO; // diff!
  468.         temp = [temp getNext];
  469.         temp2 = [temp2 getNext];
  470.     }
  471.     if (temp || temp2) return NO; // different lengths (shouldn't happen)
  472.     return YES;
  473. }
  474.  
  475.  
  476. - makeObjectsPerform:(SEL)aSelector;
  477. {
  478.     id temp = first_node;
  479.     while (temp) {
  480.         id tobj = [temp getObject];
  481.         if ([tobj respondsTo:aSelector]) {
  482.             [tobj perform:aSelector];
  483.         }
  484.         temp = [temp getNext];
  485.     }
  486.     return self;
  487. }
  488.  
  489. - makeObjectsPerform:(SEL)aSelector with:anObject
  490. {
  491.     id temp = first_node;
  492.     while (temp) {
  493.         id tobj = [temp getObject];
  494.         if ([tobj respondsTo:aSelector]) {
  495.             [tobj perform:aSelector with:anObject];
  496.         }
  497.         temp = [temp getNext];
  498.     }
  499.     return self;
  500. }
  501.  
  502. - replaceObject:anObject with:newObject; // return anObject
  503. {
  504.     id temp = first_node;
  505.     while (temp) {
  506.         if ([temp getObject] == anObject) {
  507.             return [temp setObject:newObject];
  508.         }
  509.         temp = [temp getNext];
  510.     }
  511.     return nil;
  512. }
  513.  
  514. - removeObject:anObject; // return anObject
  515. {
  516.     current_node = first_node;
  517.     while (current_node) {
  518.         if ([current_node getObject] == anObject) {
  519.             return [self deleteObject];
  520.         }
  521.         current_node = [current_node getNext];
  522.     }
  523.     return nil;
  524. }
  525.  
  526. - addObjectIfAbsent:anObject; // appends it
  527. {
  528.     id temp = first_node;
  529.     while (temp) {
  530.         if ([temp getObject] == anObject) return nil; // found it!
  531.         temp = [temp getNext];
  532.     }
  533.     return [self addObject:anObject];
  534. }
  535.  
  536. // these four are obvious:
  537. - removeLastObject
  538. {
  539.     id the_object = [last_node getObject];
  540.     id new_last = [last_node getPrevious];
  541.     if (!last_node) return nil;
  542.     node_length--;
  543.     [last_node free];
  544.     last_node = new_last;
  545.     [last_node setNext:nil];
  546.     return the_object;
  547. }
  548. - lastObject
  549. {
  550.     return [last_node getObject];
  551. }
  552.  
  553. - removeFirstObject
  554. {
  555.     id the_object = [first_node getObject];
  556.     id new_first = [first_node getNext];
  557.     if (!first_node) return nil;
  558.     node_length--;
  559.     [first_node free];
  560.     first_node = new_first;
  561.     [first_node setPrevious:nil];
  562.     return the_object;
  563. }
  564.  
  565. - firstObject
  566. {
  567.     return [first_node getObject];
  568. }
  569.  
  570. - (unsigned int)count // same as -getLength
  571. {
  572.     return (unsigned int)node_length;
  573. }
  574.  
  575. - addObject:anObject // appends object to list
  576. {
  577.     id new_node = [[node_class alloc] initObject:anObject];
  578.     
  579.     [last_node setNext:new_node];
  580.     [new_node setPrevious:last_node];
  581.     [new_node setNext:nil];
  582.     last_node = new_node;
  583.     if (!first_node) first_node = new_node;
  584.     node_length++;
  585.     return self;
  586. }
  587.  
  588. // NXTransport protocol implementation:
  589. - encodeUsing:(id <NXEncoding>)portal
  590. {
  591.     int i; id temp;
  592.     [portal encodeData:&node_length ofType:"i"];
  593.     [portal encodeObjectBycopy:node_class];
  594.     temp = first_node;
  595.     for (i=1; i<=node_length; i++) {
  596.         [portal encodeObjectBycopy:temp];
  597.         temp=[temp getNext];
  598.     }
  599.     return self;
  600. }
  601.  
  602. - decodeUsing:(id <NXDecoding>)portal
  603. {
  604.     int x; id temp = nil; id previous = nil;
  605.     [portal decodeData:&node_length ofType:"i"];
  606.     first_node = temp;
  607.     current_node = temp;
  608.     node_class = [portal decodeObject];
  609.     for (x=1; x<=node_length; x++) {
  610.         temp = [portal decodeObject];
  611.         if (previous == nil) {
  612.             first_node = temp;                // only read one!
  613.             current_node = temp;
  614.             [temp setPrevious: nil];        // just in case
  615.         } else {
  616.             [temp setPrevious:previous];
  617.             [previous setNext:temp];
  618.         }
  619.         previous = temp;
  620.     }
  621.     last_node = temp;
  622.     [temp setNext:nil];                    // just in case
  623.     return self;
  624. }
  625.  
  626. - encodeRemotelyFor:(NXConnection *)connection
  627.     freeAfterEncoding:(BOOL *)flagp isBycopy:(BOOL)isByCopy
  628. {
  629.     if (isByCopy) {
  630.         *flagp = NO; // object will copy.
  631.         return self; //encode object (copy it)
  632.     }
  633.     *flagp = NO; // object will copy.
  634.     // super will encode the proxy otherwise
  635.     return [super encodeRemotelyFor:connection
  636.                 freeAfterEncoding:flagp isBycopy:isByCopy];
  637. }
  638.  
  639. @end
  640.