class ECD_CHAIN

(source code)

description

A CHAIN with items that can be stored and retrieved from memory buffer reader/writer conforming to EL_MEMORY_READER_WRITER

note
	description: "[
		A ${CHAIN} with items that can be stored and retrieved from memory buffer reader/writer
		conforming to ${EL_MEMORY_READER_WRITER}
	]"

	author: "Finnian Reilly"
	copyright: "Copyright (c) 2001-2022 Finnian Reilly"
	contact: "finnian at eiffel hyphen loop dot com"

	license: "MIT license (See: en.wikipedia.org/wiki/MIT_License)"
	date: "2024-07-27 12:13:51 GMT (Saturday 27th July 2024)"
	revision: "2"

deferred class
	ECD_CHAIN [G]

inherit
	CHAIN [G]
		rename
			append as append_sequence
		export
			{ANY} remove
		undefine
			-- Status query
			is_equal, isfirst, islast, valid_index, is_inserted, readable, there_exists, has,
			-- Element change
			append_sequence, copy, prune_all, prune, move, put_i_th, swap, force,
			-- Cursor movement
			start, finish, go_i_th, search,
			-- Access
			at, first, last, off, i_th, remove, index_of, new_cursor,
			-- Basic operations
			do_all, do_if, for_all
		end

	EL_FILE_PERSISTENT
		redefine
			make_from_file
		end

	EL_MODULE_FILE_SYSTEM

	EL_SHARED_PROGRESS_LISTENER

feature {NONE} -- Initialization

	make_chain_implementation (a_count: INTEGER)
		deferred
		end

	make_default
		do
			create file_path
			reader_writer := new_reader_writer
			create header.make
			make_chain_implementation (0)
		end

	make_from_file (a_file_path: FILE_PATH)
		local
			l_file: like new_file
		do
			make_default
			Precursor (a_file_path)

			if file_path.exists then
				l_file := new_file (file_path)
				l_file.open_read
				header.set_from_file (l_file)

				if header.version /= software_version then
					on_version_mismatch (header.version)
				end
				make_chain_implementation (header.stored_count)
			else
				make_chain_implementation (0)
				create l_file.make_open_write (file_path)
				put_header (l_file)
				header.set_version (software_version)
			end
			l_file.close

			retrieve
		end

feature -- Access

	software_version: NATURAL
		-- Format of application version.
		deferred
		end

feature -- Measurement

	undeleted_count: INTEGER
		do
			Result := count
		end

feature -- Basic operations

	store_as (a_file_path: like file_path)
		do
			File_system.make_directory (a_file_path.parent)
			if attached new_file (a_file_path) as l_file and then attached reader_writer as l_writer then
				on_open_write
				l_file.open_write
				l_writer.set_for_writing

				put_header (l_file)

				from start until after loop
					write_item (l_writer, l_file)
					forth
				end
				l_file.close
			end
		end

feature {NONE} -- Event handler

	on_delete
		deferred
		end

	on_open_read
		do
		end

	on_open_write
		do
		end

	on_version_mismatch (actual_version: NATURAL)
		do
			reader_writer.set_data_version (actual_version)
		end

feature {NONE} -- Implementation

	new_file (a_file_path: like file_path): RAW_FILE
		do
			create Result.make_with_name (a_file_path)
		end

	put_header (file: RAW_FILE)
		do
			file.put_natural_32 (software_version)
			file.put_integer (undeleted_count)
		end

	retrieve
		local
			i, item_count: INTEGER
		do
			item_count := header.stored_count
			if item_count > 0 then
				if attached new_file (file_path) as l_file then
					on_open_read
					l_file.open_read
					if attached reader_writer as l_reader then
						l_reader.set_for_reading

						-- Skip header
						l_file.move (header.size_of)

						from i := 1 until i > item_count or l_file.end_of_file loop
							extend (new_stored_item (l_reader, l_file))
							progress_listener.notify_tick
							i := i + 1
						end
						l_file.close
					end
				end
			end
		ensure
			correct_stored_count: count = header.stored_count
		end

	stored_successfully (file: like new_file): BOOLEAN
		local
			i, l_count: INTEGER
		do
			file.read_natural -- Version
			file.read_integer	-- Record count
			l_count := file.last_integer
			from until i = l_count or file.end_of_file loop
				file.read_integer -- Count
				if not file.end_of_file then
					file.move (file.last_integer)
				end
				i := i + 1
			end
			Result := i = undeleted_count
		end

feature {NONE} -- Deferred

	new_reader_writer: EL_MEMORY_READER_WRITER
		deferred
		end

	new_stored_item (reader: like new_reader_writer; file: RAW_FILE): like item
		deferred
		end

	write_item (writer: like new_reader_writer; file: RAW_FILE)
		deferred
		end

feature {NONE} -- Internal atttributes

	header: ECD_CHAIN_HEADER

	reader_writer: like new_reader_writer

end