-----------------------------------------------------------
--                   Eiffel/S libraries                  --
-----------------------------------------------------------
--               Copyright (C) 1991 - 1993               --
--                           by                          --
--                   SiG Computer GmbH                   --
--                  All rights reserved                  --
-----------------------------------------------------------
-- Release : 1.3 - October 1993                          --
-----------------------------------------------------------
-- Authors : Lambert Strether & Michael Schweitzer       --
-----------------------------------------------------------
  
class   ARRAY [G]
                        -- General purpose arrays
inherit
    ANY
        redefine
            is_equal, copy
    end
-----------------------------------------------------------
creation {ANY}
    make
-----------------------------------------------------------
feature {ANY}   -- Features which modify the array
-----------------------------------------------------------

    make (minindex, maxindex : INTEGER) is
                        -- Allocate array. If minindex <= maxindex,
                        -- index range is minindex .. maxindex. Other-
                        -- wise the array is empty.
        require
            meaningful_count : maxindex >= minindex - 1
        do
            !!special.make (maxindex - minindex + 1)
            lower := minindex
            store := special.at (minindex)
        end
-----------------------------------------------------------

    resize (new_min, new_max : INTEGER) is
                        -- Resize array.
                        -- No elements will be lost in the intersection
                        -- of [lower, upper] and [new_min, new_max].
                        -- New positions will be initialized with appropriate 
                        -- default values.
        require
            meaningful_count : new_max >= new_min - 1

        local
            new_count : INTEGER
        do
            new_count := new_max - new_min + 1

            special.resize_and_copy (new_count, lower - new_min)

            store := special.at (new_min)
            lower := new_min
        end
-----------------------------------------------------------

    reindex (new_lower : INTEGER) is
                        -- Change index interval so that
                        -- it starts at `new_lower'. No
                        -- elements will be lost.
        do
            lower := new_lower
            store := special.at (new_lower)        

        ensure
            bounds_adjusted : lower = new_lower and then
                              upper = new_lower + count - 1
        end
-----------------------------------------------------------

    clear_all is
                        -- Set all items to default values.
        do
            special.clear (0, count - 1)
        end
-----------------------------------------------------------

    wipe_out is
                        -- Empty the array, discard all items.
        do
            resize (lower, lower - 1)
        end
-----------------------------------------------------------

    copy (other : ARRAY [G]) is
                        -- Copy `other' elementwise onto Current.
        do
            if special = Void then
                !!special.make (0)
            end

            special.copy (other.special)
            lower := other.lower
            store := special.at (lower)
        end
-----------------------------------------------------------

    put (element : G, index : INTEGER) is
                        -- Put `element' at position `index'.
        require
            inside_bounds : lower <= index and then index <= upper
        do
            special.put (element, index - lower)
        ensure
            item_in_place : item (index) = element
        end
-----------------------------------------------------------

    force (element : G, index : INTEGER) is
                        -- Put `element' at position `index'.
                        -- Resize array, if `index' is not
                        -- inside current bounds.
        do
            if index < lower then
                resize (index, upper)
            else
                if index > upper then
                    resize (lower, index)
                end
            end
            put (element, index)
        ensure
            bounds_adjusted : lower <= index and then index <= upper
            item_in_place   : item (index) = element
        end
-----------------------------------------------------------

    insert (element : G, index : INTEGER) is
                        -- Insert `element' after position `index'.
                        -- Element at position `upper' will be lost!
        require
            inside_bounds : lower - 1 <= index and then index < upper
                            -- Note: Insertion is AFTER `index'!

        do
            if index < upper - 1 then
                move (index + 1, upper - 1, 1)
            end
                
            put (element, index + 1)
        end
-----------------------------------------------------------

    remove (index : INTEGER) is
                        -- Remove element at position `index'.
                        -- Elements after `index' will move
                        -- one position left (=towards lower indices).
                        -- Element at position `upper' is set to default
                        -- value.
        require
            inside_bounds : lower <= index and then index <= upper
                        -- Note : Position `upper' will be set to
                        --        appropriate default value.
        local
            c : INTEGER
        do
            if index < upper then
                move (index + 1, upper, -1)
            else
                c := count - 1
                special.clear (c, c)
            end
        end
-----------------------------------------------------------

    move (lower_index, upper_index, distance : INTEGER) is
                        -- Move Range `lower_index' .. `upper_index'
                        -- by `distance' positions. Negative
                        -- distance moves towards lower indices.
                        -- Free places get default values.
        require
            non_empty_range      : lower_index <= upper_index
            inside_bounds_before : lower       <= lower_index
                                        and then
                                   upper_index <= upper
            inside_bounds_after :  lower       <= lower_index + distance
                                        and then
                                   upper_index + distance <= upper
        do
            special.move (lower_index - lower, upper_index - lower, distance)
        end
-----------------------------------------------------------
feature {ANY}   -- Features which don't modify the array
-----------------------------------------------------------

    infix "@", item (index : INTEGER) : G is
                        -- Item at position `index'.
        require
            inside_bounds : lower <= index and then index <= upper
        do
            Result := special.item (index - lower)
        end
-----------------------------------------------------------

    lower : INTEGER     -- Lower index bound

-----------------------------------------------------------

    upper : INTEGER is
                        -- Upper index bound
        do
            Result := special.count + lower - 1
        end
-----------------------------------------------------------

    count : INTEGER is
                        -- Length of index interval.
        do
            Result := special.count
        end
-----------------------------------------------------------

    size : INTEGER is   -- For compatiblity only
                        -- Length of index interval.
        do
            Result := special.count
        end
-----------------------------------------------------------

    empty : BOOLEAN is
                        -- Is array empty?
        do
            Result := (count = 0)
        end
-----------------------------------------------------------

    all_cleared : BOOLEAN is
                        -- Are all items set to default values?

        do
            Result := special.all_cleared
        end
-----------------------------------------------------------

    is_equal (other : ARRAY [G]) : BOOLEAN is
                        -- Test if Current and `other' are
                        -- elementwise equal.
        do
            Result := (lower = other.lower) and then
                      special.is_equal (other.special)
        end
-----------------------------------------------------------

    to_external : POINTER is
                        -- Pointer to actual storage area.
        do
            Result := special.store
        end
-----------------------------------------------------------
feature {ARRAY}
-----------------------------------------------------------

    store   : POINTER       -- For internal use only
    special : ES3_SPEC [G]  -- For internal use only

-----------------------------------------------------------

    frozen ra_es3_spec : ES3_SPEC [G] is

        do
            store  := special.at (lower)
            Result := special
        end
-----------------------------------------------------------

end -- class ARRAY [G]

