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: "Circular chains, without commitment to a particular representation";
	status: "See notice at end of class";
	names: circular, ring, sequence;
	access: index, cursor, membership;
	contents: generic;
	date: "$Date: 2007-03-30 11:10:11 -0800 (Fri, 30 Mar 2007) $";
	revision: "$Revision: 95354 $"

deferred class CIRCULAR [G]

inherit
	CHAIN [G]
		redefine
			remove, forth, back, before, after, off, move, go_i_th, valid_cursor_index, exhausted, first, last, index
		end

feature -- Access

	first: G is
			-- Item at position currently defined as first
		local
			pos: INTEGER
		do
			pos := standard_index;
			start;
			Result := item;
			move (pos - 1)
		end;

	index: INTEGER is
			-- Current cursor index, with respect to position
			-- currently defined as first
		local
			first_ind, std_ind: INTEGER;
			p: CURSOR
		do
			p := cursor;
			std_ind := standard_index;
			start;
			first_ind := standard_index;
			Result := std_ind - first_ind + 1;
			if Result < 0 then
				Result := count + Result
			end;
			move (Result - 1);
			go_to (p)
		end;

	last: like first is
			-- Item at position currently defined as last
		local
			pos: INTEGER
		do
			pos := standard_index;
			finish;
			Result := item;
			start;
			move (pos - 1)
		end;

feature -- Status report

	valid_cursor_index (i: INTEGER): BOOLEAN is
			-- Is i a possible cursor position?
		do
			Result := (i >= 0) and (i <= count)
		ensure
			valid_cursor_index_definition: Result = ((i >= 0) and (i <= count))
		end;

	after: BOOLEAN is
			-- Is there no valid cursor position to the right of cursor?
		do
			Result := empty and standard_after
		ensure
			empty_and_std_after: Result = (empty and standard_after)
		end;

	before: BOOLEAN is
			-- Is there no valid cursor position to the right of cursor?
		do
			Result := empty and standard_before
		ensure
			empty_and_std_before: Result = (empty and standard_before)
		end;

	off: BOOLEAN is
			-- Is there no current item?
		do
			Result := empty
		ensure
			only_when_empty: Result = empty
		end;

	exhausted: BOOLEAN is
			-- Has structure been completely explored?
		do
			Result := empty or internal_exhausted
		end;

feature -- Cursor movement

	forth is
			-- Move cursor to next item, cyclically.
		do
			if islast then
				internal_exhausted := true
			end;
			standard_forth;
			if standard_after then
				standard_start
			end
		ensure
			moved_forth_at_end: (old index = count) implies (index = 1)
		end;

	back is
			-- Move cursor to previous item, cyclically.
		do
			if isfirst then
				internal_exhausted := true
			end;
			standard_back;
			if standard_before then
				standard_finish
			end
		end;

	move (i: INTEGER) is
			-- Move cursor to i-th item from current position,
			-- cyclically.
		local
			real_move, counter, start_index: INTEGER
		do
			if i /= 0 and count > 0 then
				start_index := index;
				real_move := i \\ count;
				if real_move < 0 then
					real_move := count + real_move
				end;
				from
				until
					counter = real_move
				loop
					forth;
					counter := counter + 1
				end;
				if (start_index + i > count) or (start_index + i < 1) then
					internal_exhausted := true
				end
			end
		end;

	go_i_th (i: INTEGER) is
			-- Move cursor to i-th position from current start, cyclically.
		require
			index_big_enough: i >= 1;
			not_empty: notempty
		do
			start;
			move (i - 1)
		end;

	set_start is
			-- Define current position as the first.
		require
			not_empty: notempty
		deferred
		end;

feature -- Removal

	remove is
			-- Remove item at cursor position.
			-- Move cursor to right neighbor (cyclically).
			-- If removed item was at current starting position,
			-- move starting position to right neighbor.
		do
			fix_start_for_remove;
			standard_remove;
			if standard_after then
				finish
			elseif standard_before then
				start
			end
		end;

feature {CIRCULAR} -- Implementation

	fix_start_for_remove is
			-- Before deletion, update starting position if necessary.
		deferred
		end;

	internal_exhausted: BOOLEAN;
			-- Has last forth or back operation exhausted the structure?

	standard_after: BOOLEAN is
			-- Is there no valid cursor position to the right of cursor?
			-- (Non-cyclically)
		deferred
		end;

	standard_back is
			-- Move cursor to previous element, non-cyclically.
		deferred
		end;

	standard_before: BOOLEAN is
			-- Is there no valid cursor position to the left of cursor?
			-- (Non-cyclically)
		deferred
		end;

	standard_finish is
			-- Move cursor to last element.
		deferred
		end;

	standard_forth is
			-- Move cursor to next element, non-cyclically.
		deferred
		end;

	standard_isfirst: BOOLEAN is
			-- Is cursor at first position, non-cyclically?
		deferred
		end;

	standard_islast: BOOLEAN is
			-- Is cursor at last position, non-cyclically?
		deferred
		end;

	standard_move (i: INTEGER) is
			-- Move cursor to i-th element, non-cyclically.
		deferred
		end;

	standard_go_i_th (i: INTEGER) is
			-- Move cursor to i-th element, non-cyclically.
		deferred
		end;

	standard_index: INTEGER is
			-- Current cursor index, non-cyclically
		deferred
		end;

	standard_remove is
			-- Remove, non-cyclically.
		deferred
		end;

	standard_search (v: like first) is
			-- Search non-cyclically.
		deferred
		end;

	standard_start is
			-- Move cursor to first element.
		deferred
		end;

invariant

	not_before_unless_empty: before implies empty;
	not_after_unless_empty: after implies empty;
	not_off_unless_empty: off implies empty;

end -- class CIRCULAR