home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_std / collection.e < prev    next >
Text File  |  1999-06-05  |  13KB  |  472 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. deferred class COLLECTION[E]
  13. -- 
  14. -- Common abstract definition of a sequentiable collection of 
  15. -- objects. Such a collection is traversable using a simple 
  16. -- INTEGER index from `lower' to `upper'. Items can be added,
  17. -- changed or removed.
  18. -- 
  19. -- The SmallEiffel standard library (lib_std) provides four
  20. -- implementations : ARRAY[E], FIXED_ARRAY[E], LINK_LIST[E] 
  21. -- and LINK2_LIST[E]. All implementations have exactly the 
  22. -- same behavior. Switching from one implementation to another 
  23. -- only change the memory used and the execution time.
  24. --
  25.  
  26. inherit
  27.    ANY
  28.       undefine copy, is_equal
  29.       redefine fill_tagged_out_memory
  30.       end;
  31.  
  32. feature -- Indexing :
  33.  
  34.    lower: INTEGER is
  35.          -- Lower index bound.
  36.       deferred
  37.       end;
  38.  
  39.    upper: INTEGER is
  40.          -- Upper index bound.
  41.       deferred
  42.       end;
  43.  
  44.    frozen valid_index(index: INTEGER): BOOLEAN is
  45.          -- True when `index' is valid (ie. inside actual 
  46.          -- bounds of the collection).
  47.       do
  48.          Result := lower <= index and then index <= upper;
  49.       ensure      
  50.          Result = (lower <= index and then index <= upper);
  51.       end;
  52.  
  53. feature -- Counting :
  54.  
  55.    count: INTEGER is
  56.          -- Number of elements actually stored in the collection.
  57.       deferred
  58.       ensure
  59.          Result = upper - lower + 1
  60.       end;
  61.  
  62.    empty: BOOLEAN is
  63.          -- Is collection empty?
  64.       do
  65.          Result := (count = 0);
  66.       end;
  67.  
  68. feature -- Accessing :
  69.  
  70.    item, infix "@" (index: INTEGER): E is
  71.          -- Item at position `index'.
  72.       require
  73.          valid_index(index)
  74.       deferred
  75.       end;
  76.  
  77.    first: like item is
  78.          -- The very `first' item.
  79.       require
  80.          count >= 1
  81.       deferred
  82.       ensure
  83.          Result = item(lower)
  84.       end;
  85.    
  86.    last: like item is
  87.          -- The `last' item.
  88.       require
  89.          count >= 1
  90.       deferred
  91.       ensure
  92.          Result = item(upper)
  93.       end;
  94.  
  95. feature -- Writing :
  96.  
  97.    put(element: like item; index: INTEGER) is
  98.          -- Put `element' at position `index'.
  99.       require
  100.          valid_index(index)
  101.       deferred
  102.       ensure
  103.          item(index) = element;
  104.          count = old count
  105.       end;
  106.  
  107.    swap(i1, i2: INTEGER) is
  108.          -- Swap item at index `i1' with item at index `i2'.
  109.       require
  110.          valid_index(i1);
  111.          valid_index(i2)
  112.       local
  113.          tmp: like item;
  114.       do
  115.          tmp := item(i1);
  116.          put(item(i2),i1);
  117.          put(tmp,i2);
  118.       ensure
  119.          item(i1) = old item(i2);
  120.          item(i2) = old item(i1);
  121.          count = old count
  122.       end;
  123.  
  124.    set_all_with(v: like item) is
  125.          -- Set all items with value `v'.
  126.       deferred
  127.       ensure
  128.          count = old count
  129.       end;
  130.    
  131.    set_slice_with(v: like item; lower_index, upper_index: INTEGER) is
  132.          -- Set all items in range [`lower_index' .. `upper_index'] with `v'.
  133.       require
  134.          lower_index <= upper_index;
  135.          valid_index(lower_index);
  136.          valid_index(upper_index)
  137.       local
  138.          i: INTEGER;
  139.       do
  140.          from  
  141.             i := lower_index;
  142.          until
  143.             i > upper_index
  144.          loop
  145.             put(v,i);
  146.             i := i + 1;
  147.          end;      
  148.       ensure
  149.          count = old count
  150.       end;
  151.    
  152.    clear_all is
  153.          -- Set all items to default values.
  154.          -- The `count' is not affected (see also `clear').
  155.       local
  156.          value: like item;
  157.       do
  158.          set_all_with(value);
  159.       ensure
  160.          count = old count;
  161.          all_cleared
  162.       end;
  163.    
  164. feature -- Adding :
  165.  
  166.    add_first(element: like item) is
  167.          -- Add a new item in first position : `count' is increased by 
  168.          -- one and all other items are shifted right.
  169.       deferred
  170.       ensure
  171.          first = element;
  172.          count = 1 + old count;
  173.          lower = old lower;
  174.          upper = 1 + old upper
  175.       end;
  176.  
  177.    add_last(element: like item) is
  178.          -- Add a new item at the end : `count' is increased by one.
  179.       deferred
  180.       ensure
  181.          last = element;
  182.          count = 1 + old count;
  183.          lower = old lower;
  184.          upper = 1 + old upper
  185.       end;
  186.  
  187.    add(element: like item; index: INTEGER) is
  188.          -- Add a new `element' at rank `index' : `count' is increased 
  189.          -- by one and range [`index' .. `upper'] is shifted right
  190.          -- by one position.
  191.       require
  192.          lower <= index;
  193.          index <= upper + 1
  194.       deferred
  195.       ensure
  196.          item(index) = element;
  197.          count = 1 + old count;
  198.          upper = 1 + old upper
  199.       end;
  200.  
  201. feature -- Modification :
  202.  
  203.    force(element: E; index: INTEGER) is
  204.          -- Put `element' at position `index'. Collection is
  205.          -- resized if `index' is not inside current bounds.
  206.          -- New bounds are initialized with default values.
  207.       require
  208.          index >= lower
  209.       deferred
  210.       ensure
  211.          valid_index(index); 
  212.          item(index) = element
  213.       end;
  214.  
  215.    from_collection(model: COLLECTION[like item]) is
  216.       -- Initialize the current object with the contents of `model'.
  217.       require
  218.          model /= Void
  219.       deferred
  220.       ensure
  221.          count = model.count;
  222.       end;
  223.  
  224. feature -- Removing :
  225.  
  226.    remove_first is
  227.          -- Remove the `first' element of the collection.
  228.       require
  229.          not empty
  230.       deferred
  231.       ensure
  232.          count = (old count) - 1;
  233.          (lower = (old lower) + 1) xor (upper = (old upper) - 1) 
  234.       end;
  235.  
  236.    remove(index: INTEGER) is
  237.          -- Remove the item at position `index'. Followings items
  238.          -- are shifted left by one position.
  239.       require
  240.          valid_index(index)
  241.       deferred
  242.       ensure
  243.          count = (old count) - 1;
  244.          upper = (old upper) - 1;
  245.       end;
  246.  
  247.    remove_last is
  248.          -- Remove the `last' item.
  249.       require
  250.          not empty;
  251.       deferred
  252.       ensure
  253.          count = (old count) - 1;
  254.          upper = (old upper) - 1
  255.       end;
  256.  
  257.    clear is
  258.          -- Discard all items in order to make it `empty'.
  259.          -- See also `clear_all'.
  260.       deferred
  261.       ensure
  262.          empty;
  263.       end;
  264.  
  265. feature -- Looking and Searching :
  266.  
  267.    has(x: like item): BOOLEAN is
  268.          -- Look for `x' using `equal' for comparison.
  269.          -- Also consider `fast_has' to choose the most appropriate.
  270.       do
  271.          Result := valid_index(index_of(x));
  272.       end;
  273.    
  274.    fast_has(x: like item): BOOLEAN is
  275.          -- Look for `x' using basic `=' for comparison.
  276.          -- Also consider `has' to choose the most appropriate.
  277.       do
  278.          Result := valid_index(fast_index_of(x));
  279.       end;
  280.    
  281.    index_of(element: like item): INTEGER is
  282.          -- Give the index of the first occurrence of `element' using
  283.          -- `is_equal' for comparison.
  284.          -- Answer `upper + 1' when `element' is not inside.
  285.          -- Also consider `fast_index_of' to choose the most appropriate.
  286.       deferred
  287.       ensure
  288.          lower <= Result;
  289.          Result <= upper + 1;
  290.          Result <= upper implies equal(element,item(Result));
  291.       end;
  292.    
  293.    fast_index_of(element: like item): INTEGER is
  294.          -- Give the index of the first occurrence of `element' using
  295.          -- basic `=' for comparison.
  296.          -- Answer `upper + 1' when `element' is not inside.
  297.          -- Also consider `index_of' to choose the most appropriate.
  298.       deferred
  299.       ensure
  300.          lower <= Result;
  301.          Result <= upper + 1;
  302.          Result <= upper implies element = item(Result);
  303.       end;
  304.    
  305. feature -- Looking and comparison :
  306.  
  307.    all_cleared: BOOLEAN is
  308.          -- Are all items set to the default value ?
  309.       deferred
  310.       end;
  311.  
  312.    nb_occurrences(element: like item): INTEGER is
  313.          -- Number of occurrences of `element' using `equal' for comparison.
  314.          -- Also consider `fast_nb_occurences' to choose the most appropriate.
  315.       deferred
  316.       ensure
  317.          Result >= 0
  318.       end;
  319.       
  320.    fast_nb_occurrences(element: like item): INTEGER is
  321.          -- Number of occurrences of `element' using basic `=' for comparison.
  322.          -- Also consider `nb_occurences' to choose the most appropriate.
  323.       deferred
  324.       ensure
  325.          Result >= 0;
  326.       end;
  327.       
  328. feature -- Printing :
  329.  
  330.    frozen fill_tagged_out_memory is
  331.       local
  332.          i: INTEGER;
  333.          v: like item;
  334.       do
  335.          tagged_out_memory.append("lower: "); 
  336.          lower.append_in(tagged_out_memory);
  337.          tagged_out_memory.append(" upper: "); 
  338.          upper.append_in(tagged_out_memory);
  339.          tagged_out_memory.append(" [");
  340.          from  
  341.             i := lower;
  342.          until
  343.             i > upper or else tagged_out_memory.count > 2048
  344.          loop
  345.             v := item(i);
  346.             if v = Void then
  347.                tagged_out_memory.append("Void");
  348.             else
  349.                v.out_in_tagged_out_memory;
  350.             end;
  351.             if i < upper then
  352.                tagged_out_memory.extend(' ');
  353.             end;
  354.             i := i + 1;
  355.          end;
  356.          if i <= upper then
  357.             tagged_out_memory.append(" ..."); 
  358.          end;
  359.          tagged_out_memory.extend(']'); 
  360.       end;
  361.  
  362. feature -- Other Features :
  363.  
  364.    replace_all(old_value, new_value: like item) is
  365.          -- Replace all occurences of the element `old_value' by `new_value' 
  366.          -- using `equal' for comparison.
  367.          -- See also `fast_replace_all' to choose the apropriate one.
  368.       deferred
  369.       ensure
  370.          count = old count;
  371.          nb_occurrences(old_value) = 0
  372.       end;
  373.    
  374.    fast_replace_all(old_value, new_value: like item) is
  375.          -- Replace all occurences of the element `old_value' by `new_value' 
  376.          -- using operator `=' for comparison.
  377.          -- See also `replace_all' to choose the apropriate one.
  378.       deferred
  379.       ensure
  380.          count = old count;
  381.          fast_nb_occurrences(old_value) = 0
  382.       end;
  383.  
  384.    move(lower_index, upper_index, distance: INTEGER) is
  385.          -- Move range `lower_index' .. `upper_index' by `distance' 
  386.          -- positions. Negative distance moves towards lower indices.
  387.          -- Free places get default values.
  388.       require
  389.          lower_index <= upper_index;
  390.          valid_index(lower_index);
  391.          valid_index(lower_index + distance);
  392.          valid_index(upper_index);
  393.          valid_index(upper_index + distance)
  394.       local
  395.          default_value: like item;
  396.          i: INTEGER;
  397.       do
  398.          if distance = 0 then
  399.          elseif distance < 0 then
  400.             from  
  401.                i := lower_index;
  402.             until
  403.                i > upper_index
  404.             loop
  405.                put(item(i),i + distance);
  406.                put(default_value,i);
  407.                i := i + 1;
  408.             end;
  409.          else
  410.             from  
  411.                i := upper_index;
  412.             until
  413.                i < lower_index
  414.             loop
  415.                put(item(i),i + distance);
  416.                put(default_value,i);
  417.                i := i - 1;
  418.             end;
  419.          end;
  420.       ensure
  421.          count = old count
  422.       end;
  423.  
  424.    slice(low, up: INTEGER): like Current is
  425.          -- Create a new collection initialized with elements of
  426.          -- range `low'..`up'. Result has the same dynamic type 
  427.          -- as Current collection. The `lower' index of the new 
  428.          -- collection is the same as `lower' of Current.
  429.       require
  430.          valid_index(low);
  431.          valid_index(up);
  432.          low <= up
  433.       deferred
  434.       ensure
  435.          same_type(Result);
  436.          Result.count = up - low + 1;
  437.          Result.lower = lower
  438.       end;
  439.  
  440. feature -- The Guru section :
  441.  
  442.    free is
  443.          -- Free the memory used by the Current COLLECTION (objects
  444.          -- pointed by the Current COLLECTION are not affected). 
  445.          -- Assume you don't use Current any more. 
  446.       obsolete "Since release -0.81, the Garbage Collector is %
  447.                %implemented. This feature will be soon removed."
  448.       deferred
  449.       end;
  450.    
  451. feature {NONE}
  452.  
  453.    frozen equal_like(e1, e2: like item): BOOLEAN is
  454.          -- Note: this feature is called to avoid calling `equal'
  455.          -- on expanded types (no automatic conversion to 
  456.          -- corresponding reference type).
  457.       do
  458.          if e1.is_basic_expanded_type then
  459.             Result := e1 = e2;
  460.          elseif e1.is_expanded_type then
  461.             Result := e1.is_equal(e2);
  462.          elseif e1 = e2 then
  463.             Result := true;
  464.          elseif e1 = Void or else e2 = Void then
  465.          else
  466.             Result := e1.is_equal(e2);
  467.          end;
  468.       end;
  469.  
  470. end -- COLLECTION[E]
  471.  
  472.