This site contains older material on Eiffel. For the main Eiffel page, see http://www.eiffel.com.

EiffelBase class
(HTML page generated by ISE Eiffel 4.2)

Eiffel Class
indexing
	description: "Lists implemented by resizable arrays";
	status: "See notice at end of class";
	names: sequence;
	representation: array;
	access: index, cursor, membership;
	size: fixed;
	contents: generic;
	date: "$Date: 2007-03-30 19:10:11 +0000 (Fri, 30 Mar 2007) $";
	revision: "$Revision: 95354 $"

class ARRAYED_LIST [G]

inherit
	ARRAY [G]
		rename
			force as force_i_th,
			item as i_th,
			make as array_make,
			put as put_i_th,
			wipe_out as array_wipe_out,
			count as array_count,
			bag_put as put,
			copy as array_copy
		export
			{NONE} all;
			{ARRAYED_LIST} array_make;
			{ANY} capacity
		undefine
			linear_representation, prunable, put, prune, consistent, occurrences, extendible, has, is_equal
		redefine
			extend, setup, prune_all, full, valid_index
		end;
	ARRAY [G]
		rename
			force as force_i_th,
			item as i_th,
			make as array_make,
			put as put_i_th,
			count as array_count,
			bag_put as put,
			copy as array_copy
		export
			{NONE} all;
			{ARRAYED_LIST} array_make;
			{ANY} capacity
		undefine
			linear_representation, prunable, full, put, prune, consistent, occurrences, extendible, has, is_equal
		redefine
			wipe_out, extend, setup, prune_all, valid_index
		select
			wipe_out
		end;
	DYNAMIC_LIST [G]
		undefine
			valid_index, infix "@", i_th, put_i_th, force, is_equal
		redefine
			first, last, swap, wipe_out, go_i_th, move, prunable, start, finish, count, prune, remove, setup, copy, put_left, merge_left, merge_right, duplicate, prune_all
		select
			count, copy
		end

creation
	make,
	make_filled

feature -- Initialization

	make (n: INTEGER) is
			-- Allocate list with n items.
			-- (n may be zero for empty list.)
		require
			valid_number_of_items: n >= 0
		do
			array_make (1, n)
		ensure
			correct_position: before
		end;

	make_filled (n: INTEGER) is
			-- Allocate list with n items.
			-- (n may be zero for empty list.)
			-- This list will be full.
		require
			valid_number_of_items: n >= 0
		do
			array_make (1, n);
			count := n
		ensure
			correct_position: before;
			filled: full
		end;

feature -- Access

	item: like first is
			-- Current item
		require
			index_is_valid: valid_index (index)
		do
			Result := area.item (index - 1)
		end;

	first: G is
			-- Item at first position
		do
			Result := area.item (0)
		end;

	last: like first is
			-- Item at last position
		do
			Result := area.item (count - 1)
		end;

	index: INTEGER;
			-- Index of item, if valid.

	cursor: CURSOR is
			-- Current cursor position
		do
			!ARRAYED_LIST_CURSOR! Result.make (index)
		end;

feature -- Measurement

	count: INTEGER;
			-- Number of items.

feature -- Status report

	prunable: BOOLEAN is
			-- May items be removed? (Answer: yes.)
		do
			Result := true
		end;

	full: BOOLEAN is
			-- Is structure filled to capacity? (Answer: no.)
		do
			Result := (count = capacity)
		end;

	valid_cursor (p: CURSOR): BOOLEAN is
			-- Can the cursor be moved to position p?
		local
			al_c: ARRAYED_LIST_CURSOR
		do
			al_c ?= p;
			if al_c /= void then
				Result := valid_cursor_index (al_c.index)
			end
		end;

	valid_index (i: INTEGER): BOOLEAN is
			-- Is i a valid index?
		do
			Result := (1 <= i) and (i <= count)
		end;

feature -- Comparison

	is_equal (other: like Current): BOOLEAN is
			--Is other equal to Current?
		local
			c1, c2: like cursor
		do
			if (count = other.count) and (object_comparison = other.object_comparison) then
				c1 := cursor;
				c2 := other.cursor;
				other.start;
				start;
				Result := true;
				if object_comparison then
					from
					until
						after or notResult
					loop
						Result := equal (item, other.item);
						forth;
						other.forth
					end
				else
					from
					until
						after or notResult
					loop
						Result := item = other.item;
						forth;
						other.forth
					end
				end;
				go_to (c1);
				other.go_to (c2)
			end
		end;

feature -- Cursor movement

	move (i: INTEGER) is
			-- Move cursor i positions.
		do
			index := index + i;
			if (index > count + 1) then
				index := count + 1
			elseif (index < 0) then
				index := 0
			end
		end;

	start is
			-- Move cursor to first position if any.
		do
			index := 1
		ensure
			after_when_empty: empty implies after
		end;

	finish is
			-- Move cursor to last position if any.
		do
			index := count
		ensure
			before_when_empty: empty implies before
		end;

	forth is
			-- Move cursor one position forward.
		do
			index := index + 1
		end;

	back is
			-- Move cursor one position backward.
		do
			index := index - 1
		end;

	go_i_th (i: INTEGER) is
			-- Move cursor to i-th position.
		do
			index := i
		end;

	go_to (p: CURSOR) is
			-- Move cursor to position p.
		local
			al_c: ARRAYED_LIST_CURSOR
		do
			al_c ?= p;
			check
				al_c /= void
			end;
			index := al_c.index
		end;

feature -- Transformation

	swap (i: INTEGER) is
			-- Exchange item at i-th position with item
			-- at cursor position.
		local
			old_item: like item
		do
			old_item := item;
			replace (area.item (i - 1));
			area.put (old_item, i - 1)
		end;

feature -- Element change

	put_front (v: like item) is
			-- Add v to the beginning.
			-- Do not move cursor.
		do
			if empty then
				extend (v)
			else
				insert (v, 1)
			end
		end;

	force (v: like item) is
			-- Add v to end.
			-- Do not move cursor.
			-- Was declared in ARRAYED_LIST as synonym of force and extend.
		do
			count := count + 1;
			force_i_th (v, count)
		end;

	extend (v: like item) is
			-- Add v to end.
			-- Do not move cursor.
			-- Was declared in ARRAYED_LIST as synonym of force and extend.
		do
			count := count + 1;
			force_i_th (v, count)
		end;

	put_left (v: like item) is
			-- Add v to the left of current position.
			-- Do not move cursor.
		do
			if after or empty then
				extend (v);
				index := index + 1
			else
				insert (v, index)
			end
		end;

	put_right (v: like item) is
			-- Add v to the right of current position.
			-- Do not move cursor.
		do
			if index = count then
				extend (v)
			else
				insert (v, index + 1)
			end
		end;

	replace (v: like first) is
			-- Replace current item by v.
		do
			put_i_th (v, index)
		end;

	merge_left (other: ARRAYED_LIST [G]) is
		local
			i, l_count: INTEGER
		do
			if notother.empty then
				resize (1, count + other.count);
				from
					i := count - 1;
					l_count := other.count
				until
					i < index - 1
				loop
					area.put (area.item (i), i + l_count);
					i := i - 1
				end;
				from
					other.start;
					i := index - 1
				until
					other.after
				loop
					area.put (other.item, i);
					i := i + 1;
					other.forth
				end;
				index := index + l_count;
				count := count + l_count;
				other.wipe_out
			end
		end;

	merge_right (other: ARRAYED_LIST [G]) is
		local
			old_index: INTEGER
		do
			old_index := index;
			index := index + 1;
			merge_left (other);
			index := old_index
		end;

feature -- Removal

	prune (v: like item) is
			-- Remove first occurrence of v, if any,
			-- after cursor position.
			-- Move cursor to right neighbor
			-- (or after if no right neighbor or vdoes not occur)
		do
			if before then
				index := 1
			end;
			if object_comparison then
				if v /= void then
					from
					until
						after or else (item /= void and then v.is_equal (item))
					loop
						forth
					end
				end
			else
				from
				until
					after or else item = v
				loop
					forth
				end
			end;
			if notafter then
				remove
			end
		end;

	remove is
			-- Remove current item.
			-- Move cursor to right neighbor
			-- (or after if no right neighbor)
		local
			i, j: INTEGER;
			default_value: G;
			l_count: INTEGER
		do
			if notoff then
				from
					i := index - 1;
					l_count := count - 1
				until
					i >= l_count
				loop
					j := i + 1;
					area.put (area.item (j), i);
					i := j
				end;
				put_i_th (default_value, count);
				count := count - 1
			end
		end;

	prune_all (v: like item) is
			-- Remove all occurrences of v.
			-- (Reference or object equality,
			-- based on object_comparison.)
			-- Leave cursor after.
		local
			i: INTEGER;
			val, default_value: like item
		do
			if object_comparison then
				if v /= void then
					from
						start
					until
						after or else (item /= void and then v.is_equal (item))
					loop
						index := index + 1
					end;
					from
						if notafter then
							i := index;
							index := index + 1
						end
					until
						after
					loop
						val := item;
						if val /= void and then notv.is_equal (val) then
							put_i_th (val, i);
							i := i + 1
						end;
						index := index + 1
					end
				end
			else
				from
					start
				until
					after or else (item = v)
				loop
					index := index + 1
				end;
				from
					if notafter then
						i := index;
						index := index + 1
					end
				until
					after
				loop
					val := item;
					if val /= v then
						put_i_th (val, i);
						i := i + 1
					end;
					index := index + 1
				end
			end;
			if i > 0 then
				index := i;
				from
				until
					i >= count
				loop
					put_i_th (default_value, i);
					i := i + 1
				end;
				count := index - 1
			end
		ensure
			is_after: after
		end;

	remove_left is
			-- Remove item to the left of cursor position.
			-- Do not move cursor.
		do
			index := index - 1;
			remove
		end;

	remove_right is
			-- Remove item to the right of cursor position
			-- Do not move cursor
		do
			index := index + 1;
			remove;
			index := index - 1
		end;

	wipe_out is
			-- Remove all items.
		do
			count := 0;
			index := 0;
			array_wipe_out
		end;

feature -- Duplication

	setup (other: like Current) is
			-- Prepare current object so that other
			-- can be easily copied into it.
			-- It is not necessary to call setup
			-- (since consistent is always true)
			-- but it will make copying quicker.
		do
			if other.empty then
				wipe_out
			else
				resize (1, other.count)
			end
		end;

	copy (other: like Current) is
		do
			if capacity < other.count then
				make_area (other.count);
				upper := other.count
			else
				make_area (capacity)
			end;
			count := other.count;
			object_comparison := other.object_comparison;
			subcopy (other, 1, other.count, 1)
		end;

	duplicate (n: INTEGER): like Current is
			-- Copy of sub-list beginning at current position
			-- and having min (n, count - index + 1) items.
		local
			pos: INTEGER
		do
			create Result.make (n.min (count - index + 1));
			from
				Result.start;
				pos := index
			until
				Result.count = Result.capacity
			loop
				Result.extend (item);
				forth
			end;
			Result.start;
			go_i_th (pos)
		end;

feature {NONE} --Internal

	insert (v: like item; pos: INTEGER) is
			-- Add v at pos, moving subsequent items
			-- to the right.
		require
			index_small_enough: pos <= count;
			index_large_enough: pos >= 1
		local
			i, j: INTEGER;
			p: INTEGER;
			last_value: like item;
			last_item: like item
		do
			if index >= pos then
				index := index + 1
			end;
			last_item := last;
			count := count + 1;
			force_i_th (last_item, count);
			from
				i := count - 2
			until
				i < pos
			loop
				j := i - 1;
				area.put (area.item (j), i);
				i := j
			end;
			put_i_th (v, pos)
		ensure
			new_count: count = old count + 1;
			insertion_done: i_th (pos) = v
		end;

	new_chain: like Current is
			-- unused
		do
		end;

invariant

	prunable: prunable;
	starts_from_one: lower = 1;

end -- class ARRAYED_LIST