home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_std / link2_list.e < prev    next >
Text File  |  1999-06-05  |  12KB  |  489 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. class LINK2_LIST[E]
  13.    -- 
  14.    -- Two way linked list with internal automatic memorization of 
  15.    -- the last access.
  16.    --
  17. obsolete "This class will be soon removed.%N%
  18.          %Since release -0.78, the new name for this class is %
  19.          %TWO_WAY_LINKED_LIST.%N%
  20.          %Please, update your code.%N%
  21.          %Hint to find client(s)/caller(s) : remove the LINK2_LIST file."
  22.  
  23.  
  24. inherit LINKED_COLLECTION[E];
  25.  
  26. creation make, from_collection
  27.  
  28. feature {LINK2_LIST}
  29.    
  30.    first_link: LINK2[E];
  31.          -- Void when empty or gives access to the first element.
  32.  
  33.    last_link: like first_link; 
  34.          -- Void when empty or gives access to the last element.
  35.  
  36.    mem_idx: INTEGER; mem_lnk: like first_link; 
  37.          -- To speed up accessing, `mem_idx' and `mem_lnk' is the 
  38.          -- memory of the last access done. For example, after 
  39.          -- item(1), `mem_idx' is 1 and `mem_lnk' is `first_link'.
  40.          -- When list is empty, `first_link' is Void as well as 
  41.          -- `mem_lnk' and `mem_idx' is 0;
  42.  
  43. feature
  44.    
  45.    make is
  46.          -- Make an empty list;
  47.       do
  48.          first_link := Void;
  49.          last_link := Void;
  50.          upper := 0;
  51.          mem_idx := 0;
  52.          mem_lnk := Void;
  53.       ensure
  54.          count = 0
  55.       end;
  56.    
  57.    add_first(element: like item) is
  58.       do
  59.          if first_link = Void then
  60.             !!first_link.make(element,Void,Void);
  61.             last_link := first_link;
  62.             upper := 1;
  63.             mem_idx := 1;
  64.             mem_lnk := first_link;
  65.          else
  66.             !!first_link.make(element,Void,first_link);
  67.             first_link.next.set_previous(first_link);
  68.             upper := upper + 1;
  69.             mem_idx := mem_idx + 1;
  70.          end;
  71.       ensure then
  72.          upper = 1 + old upper 
  73.       end;
  74.  
  75.    add_last(element: like item) is
  76.       do
  77.          if first_link = Void then
  78.             !!first_link.make(element,Void,Void);
  79.             last_link := first_link;
  80.             upper := 1;
  81.             mem_idx := 1;
  82.             mem_lnk := first_link;
  83.          else
  84.             !!last_link.make(element,last_link,Void);
  85.             last_link.previous.set_next(last_link);
  86.             upper := upper + 1;
  87.          end;
  88.       end;
  89.  
  90.    add(element: like item; index: INTEGER) is
  91.       local
  92.          link: like first_link;
  93.       do
  94.          if index = 1 then
  95.             add_first(element);
  96.          elseif index = upper + 1 then
  97.             add_last(element);
  98.          else
  99.             if (index - 1) /= mem_idx then
  100.                go_item(index - 1);
  101.             end;
  102.             !!link.make(element,mem_lnk,mem_lnk.next);
  103.             link.next.set_previous(link);
  104.             mem_lnk.set_next(link);
  105.             upper := upper + 1;
  106.          end;
  107.       end;
  108.  
  109.    remove_first is
  110.       do
  111.          if upper = 1 then
  112.             make;
  113.          else
  114.             mem_lnk := first_link;
  115.             first_link := first_link.next;
  116.             first_link.set_previous(Void);
  117.             mem_lnk := first_link;
  118.             mem_idx := 1;
  119.             upper := upper - 1;
  120.          end;
  121.       end;
  122.  
  123.    remove(index: INTEGER) is
  124.       local
  125.          link: like first_link;
  126.       do
  127.          if index = 1 then
  128.             remove_first;
  129.          elseif index = upper then
  130.             remove_last;
  131.          else
  132.             if (index - 1) /= mem_idx then
  133.                go_item(index - 1);
  134.             end;
  135.             link := mem_lnk.next;
  136.             mem_lnk.set_next(link.next);
  137.             link.next.set_previous(mem_lnk);
  138.             upper := upper - 1;
  139.          end;
  140.       end;
  141.  
  142.    first: like item is
  143.       do
  144.          Result := first_link.item;
  145.       end;
  146.    
  147.    last: like item is
  148.       do
  149.          Result := last_link.item;
  150.       end;
  151.    
  152.    item, infix "@" (index: INTEGER): E is
  153.       do
  154.          if index /= mem_idx then
  155.             go_item(index);
  156.          end;
  157.          Result := mem_lnk.item;
  158.       end;
  159.    
  160.    put(element: like item; index: INTEGER) is
  161.       do
  162.          if index /= mem_idx then
  163.             go_item(index);
  164.          end;
  165.          mem_lnk.set_item(element);
  166.       end;
  167.    
  168.    count: INTEGER is
  169.       do
  170.          Result := upper;
  171.       end;
  172.    
  173.    set_all_with(v: like item) is
  174.       do
  175.          if first_link /= Void then
  176.             first_link.set_all_with(v);
  177.          end;
  178.       end;
  179.    
  180.    copy(other: like Current) is
  181.       do
  182.          from_collection(other);
  183.       end;
  184.    
  185.    is_equal(other: like Current): BOOLEAN is
  186.       local
  187.          lnk1, lnk2: like first_link;
  188.       do
  189.          if Current = other then
  190.             Result := true;
  191.          elseif upper = other.upper then
  192.             from
  193.                Result := true;
  194.                lnk1 := first_link;
  195.                lnk2 := other.first_link;
  196.             until
  197.                lnk1 = Void or not Result
  198.             loop
  199.                Result := equal_like(lnk1.item,lnk2.item);
  200.                lnk1 := lnk1.next;
  201.                lnk2 := lnk2.next;
  202.             end;
  203.          end;
  204.       end;
  205.  
  206.    index_of(x: like item): INTEGER is
  207.       do
  208.          from  
  209.             Result := lower;
  210.          until
  211.             (Result > upper) or else equal_like(x,item(Result))
  212.          loop
  213.             Result := Result + 1;
  214.          end;
  215.       end;
  216.    
  217.    fast_index_of(x: like item): INTEGER is
  218.       local
  219.          u: like upper;
  220.       do
  221.          from
  222.             Result := lower;
  223.             u := upper;
  224.          until
  225.             (Result > u) or else x = item(Result)
  226.          loop
  227.             Result := Result + 1;
  228.          end;
  229.       end;
  230.    
  231.    clear is
  232.       do
  233.          if first_link /= Void then
  234.             first_link := Void;
  235.             mem_idx := 0;
  236.             mem_lnk := Void;
  237.             upper := 0;
  238.             last_link := Void;
  239.          end;
  240.       ensure then
  241.          upper = 0
  242.       end;
  243.  
  244.    from_collection(model: COLLECTION[like item]) is
  245.       local
  246.          i, up: INTEGER;
  247.          lnk: like first_link;
  248.       do
  249.          if first_link = Void then
  250.             from
  251.                i := model.lower;
  252.                up := model.upper;
  253.             until
  254.                i > up
  255.             loop
  256.                add_last(model.item(i));
  257.                i := i + 1;
  258.             end;
  259.          else
  260.             from
  261.                lnk := first_link;
  262.                i := model.lower;
  263.                up := model.upper;
  264.             until
  265.                i > up
  266.             loop
  267.                if lnk = Void then
  268.                   add_last(model.item(i));
  269.                else
  270.                   lnk.set_item(model.item(i));
  271.                   lnk := lnk.next;
  272.                end;
  273.                i := i + 1;
  274.             end;
  275.             if lnk = first_link then
  276.                check
  277.                   model.count = 0
  278.                end;
  279.                clear;
  280.             elseif lnk /= Void then
  281.                i := model.count;
  282.                if mem_idx /= i then
  283.                   go_item(i);
  284.                end;
  285.                check
  286.                   lnk = mem_lnk.next
  287.                end;
  288.                mem_lnk.set_next(Void);
  289.                upper := i;
  290.                last_link := mem_lnk;
  291.             end;
  292.          end;
  293.       end;
  294.  
  295.    slice(low, up: INTEGER): like Current is
  296.       local
  297.          lnk: like first_link;
  298.          i: INTEGER;
  299.       do
  300.          from
  301.             !!Result.make;
  302.             if mem_idx /= low then
  303.                go_item(low);
  304.             end;
  305.             lnk := mem_lnk;
  306.             i := up - low + 1;
  307.          until
  308.             i = 0
  309.          loop
  310.             Result.add_last(lnk.item);
  311.             lnk := lnk.next;
  312.             i := i - 1;
  313.          end;
  314.       end;
  315.  
  316.    nb_occurrences(element: like item): INTEGER is
  317.       local
  318.          lnk: like first_link;
  319.       do
  320.          from
  321.             lnk := first_link;
  322.          until
  323.             lnk = Void
  324.          loop
  325.             if equal_like(element,lnk.item) then
  326.                Result := Result + 1;
  327.             end;
  328.             lnk := lnk.next;
  329.          end;
  330.       end;
  331.  
  332.    fast_nb_occurrences(element: like item): INTEGER is
  333.       local
  334.          lnk: like first_link;
  335.       do
  336.          from
  337.             lnk := first_link;
  338.          until
  339.             lnk = Void
  340.          loop
  341.             if element = lnk.item then
  342.                Result := Result + 1;
  343.             end;
  344.             lnk := lnk.next;
  345.          end;
  346.       end;
  347.  
  348.    force(element: E; index: INTEGER) is
  349.       local
  350.          v: like element;
  351.       do
  352.          from
  353.          until
  354.             index <= upper
  355.          loop
  356.             add_last(v);
  357.          end;
  358.          put(element,index);
  359.       end;
  360.  
  361.    all_cleared: BOOLEAN is
  362.       local
  363.          l: like first_link;
  364.          d: like item;
  365.       do
  366.          from
  367.             Result := true;
  368.             l := first_link;
  369.          until
  370.             not Result or else l = Void
  371.          loop
  372.             Result := d = l.item;
  373.             l := l.next;
  374.          end;
  375.       end;
  376.  
  377.    remove_last is
  378.       do
  379.          if upper = 1 then
  380.             make;
  381.          else
  382.             if upper - 1 /= mem_idx then
  383.                go_item(upper - 1);
  384.             end;
  385.             upper := upper - 1;
  386.             last_link := mem_lnk;
  387.             last_link.set_next(Void);
  388.          end;
  389.       end;
  390.  
  391.    replace_all(old_value, new_value: like item) is
  392.       local
  393.          i: INTEGER;
  394.       do
  395.          from
  396.             i := lower;
  397.          until 
  398.             i > upper
  399.          loop
  400.             if equal_like(item(i),old_value) then
  401.                put(new_value,i);
  402.             end;
  403.             i := i + 1;
  404.          end;
  405.       end;
  406.    
  407.    fast_replace_all(old_value, new_value: like item) is
  408.       local
  409.          i: INTEGER;
  410.       do
  411.          from 
  412.             i := lower;
  413.          until
  414.             i > upper
  415.          loop
  416.             if item(i) = old_value then
  417.                put(new_value, i);
  418.             end;
  419.             i := i + 1;
  420.          end;
  421.       end;
  422.  
  423. feature {NONE}
  424.  
  425.    go_item(index: INTEGER) is
  426.       require
  427.          valid_index(index);
  428.          mem_idx /= index;
  429.          mem_idx > 0;
  430.          mem_lnk /= Void
  431.       do
  432.          if index > mem_idx then
  433.             if (upper - index) < (index - mem_idx) then
  434.                from
  435.                   mem_idx := upper;
  436.                   mem_lnk := last_link;
  437.                until
  438.                   index = mem_idx
  439.                loop
  440.                   mem_lnk := mem_lnk.previous;
  441.                   mem_idx := mem_idx - 1;
  442.                end;
  443.             else
  444.                from
  445.                until
  446.                   index = mem_idx
  447.                loop
  448.                   mem_lnk := mem_lnk.next;
  449.                   mem_idx := mem_idx + 1;
  450.                end;
  451.             end
  452.          elseif (mem_idx - index) < (index - 1) then
  453.             from
  454.             until
  455.                index = mem_idx
  456.             loop
  457.                mem_lnk := mem_lnk.previous;
  458.                mem_idx := mem_idx - 1;
  459.             end;
  460.          else
  461.             from
  462.                mem_idx := 1;
  463.                mem_lnk := first_link;
  464.             until
  465.                index = mem_idx
  466.             loop
  467.                mem_lnk := mem_lnk.next;
  468.                mem_idx := mem_idx + 1;
  469.             end;
  470.          end;
  471.       ensure
  472.          mem_idx = index;
  473.          mem_lnk /= Void
  474.       end;
  475.  
  476. invariant
  477.  
  478.    empty_status:
  479.       first_link = Void implies 
  480.          (last_link = Void and upper = 0 and mem_idx = 0 
  481.           and mem_lnk = Void);
  482.  
  483.    not_empty_status:
  484.       first_link /= Void implies 
  485.          (last_link /= Void and upper > 0 and mem_idx > 0 
  486.           and mem_lnk /= Void);
  487.    
  488. end -- LINK2_LIST[E]
  489.