note description: "A package file." author: "Louis Marchand" date: "Thu, 02 Apr 2015 03:58:25 +0000" revision: "2.0" class CPF_PACKAGE_FILE inherit GAME_FILE rename make as make_obsolete export {NONE} append, basic_store, copy_to, create_read_write, extend, fill, force, general_store, independent_store, make_create_read_write, make_obsolete, make_open_append, make_open_read, make_open_read_append, make_open_read_write, make_with_name, make_with_path, new_line, open_append, open_read_append, open_read_write, open_write, prune_all, put, put_boolean, put_character, put_double, put_integer, put_integer_8, put_integer_16, put_integer_32, put_integer_64, put_natural_8, put_natural_16, put_natural_32, put_natural_64, put_managed_pointer, put_natural, put_natural_16_big_endian, put_natural_16_little_endian, put_natural_32_big_endian, put_natural_32_little_endian, put_natural_64_big_endian, put_natural_64_little_endian, put_new_line, put_real, putreal, putdouble, putbool, putchar, putint, putstring, recreate_read_write, reopen_append, reopen_read_append, reopen_read_write, reopen_write {FILE} put_string redefine prunable end create make, make_thread_safe, make_open, make_open_tread_safe feature {NONE} -- Initialization make (a_filename: READABLE_STRING_GENERAL) -- Initialisation of the package file do make_with_name (a_filename) create {ARRAYED_LIST [POINTER]} cpf_infos.make (0) create {ARRAYED_LIST [TUPLE [pos: INTEGER_32; length: INTEGER_32]]} sub_files_infos.make (0) is_thread_safe := False is_valid := False end make_thread_safe (a_filename: READABLE_STRING_GENERAL) -- Initialisation of the package file with thread safe mecanisme do make (a_filename) is_thread_safe := True ensure make_thread_safe_mutex_valid: internal_mutex.is_set end make_open (a_filename: READABLE_STRING_GENERAL) -- Initialisation and opening of the package file do make (a_filename) open end make_open_tread_safe (a_filename: READABLE_STRING_GENERAL) -- Initialisation and opening of the package file with thread safe mecanisme do make_thread_safe (a_filename) open end feature -- Access is_valid: BOOLEAN -- Is Current a valid package file open -- Open the package file -- A package file is always read-only local l_temp_ptr: POINTER do open_read is_valid := True process_cpf_file if is_valid then select_sub_file (0) cpf_infos := create {ARRAYED_LIST [POINTER]}.make (sub_files_count) from sub_files_infos.start until sub_files_infos.exhausted loop l_temp_ptr := l_temp_ptr.memory_alloc (Custom_package_file_infos_size) {CPF_EXTERNAL}.set_custom_package_infos_struct_file_ptr (l_temp_ptr, file_pointer) {CPF_EXTERNAL}.set_custom_package_infos_struct_start_offset (l_temp_ptr, sub_files_infos.item.pos.to_integer_64) {CPF_EXTERNAL}.set_custom_package_infos_struct_total_size (l_temp_ptr, sub_files_infos.item.length.to_integer_64); cpf_infos.extend (l_temp_ptr); sub_files_infos.forth end select_sub_file (0) end end select_sub_file (a_index: INTEGER_32) -- In Current, go to the sub-file identified by a_index require cpf_file_is_valid: is_valid do if a_index = 0 then current_sub_file_first_position := 0 current_sub_file_count := count go_in_current_sub_file (0) else current_sub_file_first_position := sub_files_infos.at (a_index).pos current_sub_file_count := sub_files_infos.at (a_index).length go_in_current_sub_file (0) end end current_sub_file_index: INTEGER_32 -- Retreive the index of the sub-file that the cursor is presently in. require cpf_file_is_valid: is_valid local l_is_found: BOOLEAN do Result := 0 from l_is_found := False; sub_files_infos.start until l_is_found or else sub_files_infos.exhausted loop if position >= sub_files_infos.item.pos and then position < sub_files_infos.item.pos + sub_files_infos.item.length then Result := sub_files_infos.index l_is_found := True end; sub_files_infos.forth end end is_position_in_selected_sub_file: BOOLEAN -- True if the present position in Current is in the sub-file that is selected require cpf_file_is_valid: is_valid do Result := position >= current_sub_file_first_position and then position <= current_sub_file_last_position end current_sub_file_position: INTEGER_32 -- Return the current stream offset (position) in the file. require cpf_file_is_valid: is_valid file_index_is_in_file: is_position_in_selected_sub_file do Result := position - current_sub_file_first_position end go_in_current_sub_file (a_offset: INTEGER_32) -- Place the stream offset at offset position after the begining of the file. -- The offset value must be posifive. require cpf_file_is_valid: is_valid file_seek_from_begining_offset_positive: a_offset >= 0 and then a_offset <= current_sub_file_last_position do go (a_offset + current_sub_file_first_position) ensure position = a_offset end move_in_current_sub_file (a_offset: INTEGER_32) -- Place the stream offset at offset position after (or before if offset is negative) the index. require cpf_file_is_valid: is_valid file_seek_from_index_is_in_file: is_position_in_selected_sub_file file_seek_from_index__is_valid: (a_offset >= 0 and then a_offset <= current_sub_file_last_position - position) or else (a_offset < 0 and then a_offset.abs <= position) do go_in_current_sub_file (a_offset + current_sub_file_first_position) end recede_in_current_sub_file (a_offset: INTEGER_32) -- Place the stream offset at offset position before the end of the file. -- The offset value must be negative. require custom_file_seek_from_end_offset_negative: a_offset <= 0 cpf_file_is_valid: is_valid do go (current_sub_file_last_position + a_offset) end current_sub_file_first_position: INTEGER_32 -- The position in Current that the present sub-file start current_sub_file_last_position: INTEGER_32 -- The position in Current that the present sub-file end require cpf_file_is_valid: is_valid do Result := current_sub_file_first_position + current_sub_file_count - 1 end current_sub_file_count: INTEGER_32 -- The number of byte of the present sub-file file_index: INTEGER_32 -- The index identifier of the presently selected sub-file feature -- CPF informations sub_files_infos: LIST [TUPLE [pos: INTEGER_32; length: INTEGER_32]] -- Position and length of every sub files in the package file sub_files_count: INTEGER_32 -- The number of sub-file inside Current require cpf_file_is_valid: is_valid do Result := sub_files_infos.count end prunable: BOOLEAN -- Is there an item to be removed? do Result := False end feature {CPF_RESSOURCE_MANAGER} -- The C pointer to the file infos structure internal_pointer: POINTER -- The internal pointer of the package file C structure require cpf_file_is_valid: is_valid current_sub_file_index /= 0 do Result := cpf_infos.at (current_sub_file_index) end feature {NONE} -- Implementation - Routine process_cpf_file -- Valid that Current is a valid CPF file and retreive the informations -- of the file. local nbr: NATURAL_16 pos, length: NATURAL_32 i: INTEGER_32 do go (0) read_natural_8 if last_natural_8 /= 67 then is_valid := False end read_natural_8 if last_natural_8 /= 80 then is_valid := False end read_natural_8 if last_natural_8 /= 70 then is_valid := False end if can_read_16 then read_natural_16_big_endian nbr := last_natural_16 sub_files_infos := create {ARRAYED_LIST [TUPLE [pos: INTEGER_32; length: INTEGER_32]]}.make (nbr.to_integer_32) from i := 1 until i > nbr.to_integer_32 or not is_valid loop if can_read_32 then read_natural_32_big_endian pos := last_natural_32 if can_read_32 then read_natural_32_big_endian length := last_natural_32; sub_files_infos.extend ([pos.to_integer_32, length.to_integer_32]) i := i + 1 else is_valid := False end else is_valid := False end end else is_valid := False end end feature {NONE} -- Implemetntation - Variables cpf_infos: LIST [POINTER] -- The internal CustomPackageFileInfos C structures Custom_package_file_infos_size: INTEGER_32 -- The size in byte of a CustomPackageFileInfos C structure once Result := {CPF_EXTERNAL}.c_sizeof_custom_package_file_infos end invariant file_stream_ptr_not_null: not file_pointer.is_default_pointer end -- class CPF_PACKAGE_FILE
Generated by ISE EiffelStudio