note description: "[ Decoding of arbitrary objects graphs between sessions of programs containing the same types or potentially different types (which can be mapped to the new type system via a correction mechanism,). It also basically takes care of potential reordering of attributes from one system to the other. ]" legal: "See notice at end of class." status: "See notice at end of class." date: "$Date: 2020-05-19 14:29:33 +0000 (Tue, 19 May 2020) $" revision: "$Revision: 104259 $" class SED_RECOVERABLE_DESERIALIZER create make feature {NONE} -- Initialization default_create -- Process instances of classes with no creation clause. -- (Default: do nothing.) -- (from ANY) do end make (a_deserializer: SED_READER_WRITER) -- Initialize current instance require -- from SED_SESSION_DESERIALIZER a_deserializer_not_void: a_deserializer /= Void a_deserializer_ready: a_deserializer.is_ready_for_reading do Precursor (a_deserializer) create mismatches.make (0) create mismatched_object.make (0) ensure -- from SED_SESSION_DESERIALIZER deserializer_set: deserializer = a_deserializer end feature -- Access deserializer: SED_READER_WRITER -- Serializer used to decode data -- (from SED_SESSION_DESERIALIZER) generating_type: TYPE [detachable SED_RECOVERABLE_DESERIALIZER] -- Type of current object -- (type of which it is a direct instance) -- (from ANY) external "built_in" ensure -- from ANY generating_type_not_void: Result /= Void end generator: STRING_8 -- Name of current object's generating class -- (base class of the type of which it is a direct instance) -- (from ANY) external "built_in" ensure -- from ANY generator_not_void: Result /= Void generator_not_empty: not Result.is_empty end last_decoded_object: detachable ANY -- Object decoded during last call to decode -- (from SED_SESSION_DESERIALIZER) last_exception: detachable EXCEPTION -- Last exception -- (from EXCEPTION_MANAGER) do Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.last_exception ensure -- from EXCEPTION_MANAGER instance_free: class end feature -- Comparison frozen deep_equal (a: detachable ANY; b: like arg #1): BOOLEAN -- Are a and b either both void -- or attached to isomorphic object structures? -- (from ANY) do if a = Void then Result := b = Void else Result := b /= Void and then a.is_deep_equal (b) end ensure -- from ANY instance_free: class shallow_implies_deep: standard_equal (a, b) implies Result both_or_none_void: (a = Void) implies (Result = (b = Void)) same_type: (Result and (a /= Void)) implies (b /= Void and then a.same_type (b)) symmetric: Result implies deep_equal (b, a) end frozen equal (a: detachable ANY; b: like arg #1): BOOLEAN -- Are a and b either both void or attached -- to objects considered equal? -- (from ANY) do if a = Void then Result := b = Void else Result := b /= Void and then a.is_equal (b) end ensure -- from ANY instance_free: class definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.is_equal (b)) end frozen is_deep_equal alias "≡≡≡" (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN -- Are Current and other attached to isomorphic object structures? -- (from ANY) require -- from ANY other_not_void: other /= Void external "built_in" ensure -- from ANY shallow_implies_deep: standard_is_equal (other) implies Result same_type: Result implies same_type (other) symmetric: Result implies other.is_deep_equal (Current) end is_equal (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN -- Is other attached to an object considered -- equal to current object? -- (from ANY) require -- from ANY other_not_void: other /= Void external "built_in" ensure -- from ANY symmetric: Result implies other ~ Current consistent: standard_is_equal (other) implies Result end frozen standard_equal (a: detachable ANY; b: like arg #1): BOOLEAN -- Are a and b either both void or attached to -- field-by-field identical objects of the same type? -- Always uses default object comparison criterion. -- (from ANY) do if a = Void then Result := b = Void else Result := b /= Void and then a.standard_is_equal (b) end ensure -- from ANY instance_free: class definition: Result = (a = Void and b = Void) or else ((a /= Void and b /= Void) and then a.standard_is_equal (b)) end frozen standard_is_equal alias "≜" (other: SED_RECOVERABLE_DESERIALIZER): BOOLEAN -- Is other attached to an object of the same type -- as current object, and field-by-field identical to it? -- (from ANY) require -- from ANY other_not_void: other /= Void external "built_in" ensure -- from ANY same_type: Result implies same_type (other) symmetric: Result implies other.standard_is_equal (Current) end feature {NONE} -- Status report is_attribute_removal_allowed: BOOLEAN -- Do we not trigger a mismatch when an attribute has been removed? is_checking_data_consistency: BOOLEAN -- After retrieving objects, should we check that all objects are consistent? is_conforming_mismatch_allowed: BOOLEAN -- Do we not trigger a mismatch when an attribute type in the stored system is -- different from the retrieving system but conforming? is_stopping_on_data_retrieval_error: BOOLEAN -- When retrieving objects, should we stop at the first occurrence of a mismatch? is_transient_retrieval_required: BOOLEAN -- Do we need to retrieve transient attribute with their default value? -- This is necessary for Session/Basic storing where we expect the same -- object layout. do Result := False end feature -- Status report conforms_to (other: ANY): BOOLEAN -- Does type of current object conform to type -- of other (as per Eiffel: The Language, chapter 13)? -- (from ANY) require -- from ANY other_not_void: other /= Void external "built_in" end error: detachable SED_ERROR obsolete "Use `errors' directly to find out errors encountered during retrieval. [2017-05-31]" -- Last error encountered during retrieval -- (from SED_SESSION_DESERIALIZER) do if attached errors as l_errors and then not l_errors.is_empty then Result := l_errors.last end end errors: detachable ARRAYED_LIST [SED_ERROR] -- (from SED_SESSION_DESERIALIZER) has_error: BOOLEAN -- Did we encounter an error during retrieval? -- (from SED_SESSION_DESERIALIZER) do Result := attached errors as l_errors and then not l_errors.is_empty end is_caught (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN -- If set, type of a_exception is raised. -- (from EXCEPTION_MANAGER) do Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_caught (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class not_is_ignored: Result = not is_ignored (a_exception) end is_ignorable (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN -- If set, type of a_exception is ignorable. -- (from EXCEPTION_MANAGER) do Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_ignorable (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class end is_ignored (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN -- If set, type of a_exception is not raised. -- (from EXCEPTION_MANAGER) do Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_ignored (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class not_is_caught: Result = not is_caught (a_exception) end is_raisable (a_exception: TYPE [detachable EXCEPTION]): BOOLEAN -- If set, type of a_exception is raisable. -- (from EXCEPTION_MANAGER) do Result := (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.is_raisable (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class end same_type (other: ANY): BOOLEAN -- Is type of current object identical to type of other? -- (from ANY) require -- from ANY other_not_void: other /= Void external "built_in" ensure -- from ANY definition: Result = (conforms_to (other) and other.conforms_to (Current)) end feature -- Status setting catch (a_exception: TYPE [detachable EXCEPTION]) -- Set type of a_exception is_caught. -- (from EXCEPTION_MANAGER) require -- from EXCEPTION_MANAGER a_exception_not_void: a_exception /= Void do (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.catch (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class is_ignored: not is_ignored (a_exception) end ignore (a_exception: TYPE [detachable EXCEPTION]) -- Ignore type of a_exception. -- (from EXCEPTION_MANAGER) require -- from EXCEPTION_MANAGER a_exception_not_void: a_exception /= Void is_ignorable: is_ignorable (a_exception) do (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.ignore (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class is_caught: is_ignored (a_exception) end set_is_ignored (a_exception: TYPE [detachable EXCEPTION]; a_ignored: BOOLEAN) -- Set type of a_exception to be a_ignored. -- (from EXCEPTION_MANAGER) require -- from EXCEPTION_MANAGER a_exception_not_void: a_exception /= Void a_ignored_implies_is_ignorable: a_ignored implies is_ignorable (a_exception) do (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.set_is_ignored (a_exception, a_ignored) ensure -- from EXCEPTION_MANAGER instance_free: class is_ignored_set: is_ignored (a_exception) = a_ignored end feature -- Duplication frozen clone (other: detachable ANY): like other obsolete "Use `twin' instead. [2017-05-31]" -- Void if other is void; otherwise new object -- equal to other -- -- For non-void other, clone calls copy; -- to change copying/cloning semantics, redefine copy. -- (from ANY) do if other /= Void then Result := other.twin end ensure -- from ANY instance_free: class equal: Result ~ other end copy (other: SED_RECOVERABLE_DESERIALIZER) -- Update current object using fields of object attached -- to other, so as to yield equal objects. -- (from ANY) require -- from ANY other_not_void: other /= Void type_identity: same_type (other) external "built_in" ensure -- from ANY is_equal: Current ~ other end frozen deep_clone (other: detachable ANY): like other obsolete "Use `deep_twin' instead. [2017-05-31]" -- Void if other is void: otherwise, new object structure -- recursively duplicated from the one attached to other -- (from ANY) do if other /= Void then Result := other.deep_twin end ensure -- from ANY instance_free: class deep_equal: deep_equal (other, Result) end frozen deep_copy (other: SED_RECOVERABLE_DESERIALIZER) -- Effect equivalent to that of: -- copy (other . deep_twin) -- (from ANY) require -- from ANY other_not_void: other /= Void do copy (other.deep_twin) ensure -- from ANY deep_equal: deep_equal (Current, other) end frozen deep_twin: SED_RECOVERABLE_DESERIALIZER -- New object structure recursively duplicated from Current. -- (from ANY) external "built_in" ensure -- from ANY deep_twin_not_void: Result /= Void deep_equal: deep_equal (Current, Result) end frozen standard_clone (other: detachable ANY): like other obsolete "Use `standard_twin' instead. [2017-05-31]" -- Void if other is void; otherwise new object -- field-by-field identical to other. -- Always uses default copying semantics. -- (from ANY) do if other /= Void then Result := other.standard_twin end ensure -- from ANY instance_free: class equal: standard_equal (Result, other) end frozen standard_copy (other: SED_RECOVERABLE_DESERIALIZER) -- Copy every field of other onto corresponding field -- of current object. -- (from ANY) require -- from ANY other_not_void: other /= Void type_identity: same_type (other) external "built_in" ensure -- from ANY is_standard_equal: standard_is_equal (other) end frozen standard_twin: SED_RECOVERABLE_DESERIALIZER -- New object field-by-field identical to other. -- Always uses default copying semantics. -- (from ANY) external "built_in" ensure -- from ANY standard_twin_not_void: Result /= Void equal: standard_equal (Result, Current) end frozen twin: SED_RECOVERABLE_DESERIALIZER -- New object equal to Current -- twin calls copy; to change copying/twinning semantics, redefine copy. -- (from ANY) external "built_in" ensure -- from ANY twin_not_void: Result /= Void is_equal: Result ~ Current end feature -- Basic operations frozen as_attached: attached SED_RECOVERABLE_DESERIALIZER obsolete "Remove calls to this feature. [2017-05-31]" -- Attached version of Current. -- (Can be used during transitional period to convert -- non-void-safe classes to void-safe ones.) -- (from ANY) do Result := Current end frozen decode (a_is_gc_enabled: BOOLEAN) -- Decode object graph stored in deserializer. -- (from SED_SESSION_DESERIALIZER) local l_count: NATURAL_32 l_mem: detachable like Memory l_is_collecting: BOOLEAN retried: BOOLEAN do if not retried then reset_errors if not a_is_gc_enabled then l_mem := Memory l_is_collecting := l_mem.collecting; l_mem.collection_off end l_count := deserializer.read_compressed_natural_32 create object_references.make_empty (l_count.to_integer_32 + 1) read_header (l_count) if not has_error then decode_objects (l_count) end else if attached last_exception as l_exception then add_error (Error_factory.new_exception_error (l_exception)) else add_error (Error_factory.new_internal_error ("An Unknown exception occurred in `decode'.")) end last_decoded_object := Void end if l_is_collecting and then l_mem /= Void then l_mem.collection_on end clear_internal_data rescue retried := True retry end frozen default: detachable SED_RECOVERABLE_DESERIALIZER -- Default value of object's type -- (from ANY) do end frozen default_pointer: POINTER -- Default value of type POINTER -- (Avoid the need to write p.default for -- some p of type POINTER.) -- (from ANY) do ensure -- from ANY instance_free: class end default_rescue -- Process exception for routines with no Rescue clause. -- (Default: do nothing.) -- (from ANY) do end frozen do_nothing -- Execute a null action. -- (from ANY) do ensure -- from ANY instance_free: class end feature {NONE} -- Implementation abstract_type (a_type_id: INTEGER_32): INTEGER_32 -- Abstract type of a_type_id. -- (from SED_UTILITIES) require -- from SED_UTILITIES a_type_id_non_negative: a_type_id >= 0 local l_spec_mapping: like Special_type_mapping do l_spec_mapping := Special_type_mapping; l_spec_mapping.search (a_type_id) if l_spec_mapping.found then Result := l_spec_mapping.found_item else Result := {REFLECTOR_CONSTANTS}.reference_type end end associated_mismatch (a_dtype: INTEGER_32): SED_TYPE_MISMATCH -- Associated mismatch for a_dtype. require a_dtype_non_negative: a_dtype >= 0 do if attached mismatches.item (a_dtype) as l_mis then check valid_mismatch: l_mis.type_id = a_dtype end Result := l_mis else create Result.make (a_dtype); mismatches.put (Result, a_dtype) end end attributes_map (a_dtype: INTEGER_32): HASH_TABLE [TUPLE [position: INTEGER_32; dtype: INTEGER_32], STRING_8] -- Attribute map for dynamic type a_dtype which records -- position and dynamic type for a given attribute name. require a_dtype_non_negative: a_dtype >= 0 local l_reflector: like reflector i, nb: INTEGER_32 do l_reflector := reflector from i := 1 nb := l_reflector.field_count_of_type (a_dtype) create Result.make (nb) nb := nb + 1 until i = nb loop Result.put ([i, l_reflector.field_static_type_of_type (i, a_dtype)], l_reflector.field_name_of_type (i, a_dtype)) i := i + 1 end ensure attributes_map_not_void: Result /= Void end decode_normal_object (a_reflected_object: REFLECTED_OBJECT) -- Decode an object represented by a_reflected_object. require -- from SED_SESSION_DESERIALIZER an_obj_not_void: a_reflected_object /= Void local l_deser: like deserializer i, nb: INTEGER_32 l_dtype, l_exp_dtype, l_new_offset: INTEGER_32 l_mismatch_info: SED_TYPE_MISMATCH l_info: detachable MISMATCH_INFORMATION l_check_for_non_void: BOOLEAN l_has_mismatch: BOOLEAN l_field_info: detachable TUPLE [old_name: STRING_8; new_name: STRING_8; old_attribute_type: INTEGER_32; new_attribute_type: INTEGER_32; old_position: INTEGER_32; new_position: INTEGER_32; is_changed: BOOLEAN; is_removed: BOOLEAN; is_attachment_check_required: BOOLEAN] l_exp: REFLECTED_REFERENCE_OBJECT do l_dtype := a_reflected_object.dynamic_type if not has_mismatch (l_dtype) then Precursor (a_reflected_object) else l_mismatch_info := associated_mismatch (l_dtype) if l_mismatch_info.has_version_mismatch then create l_info.make (l_mismatch_info.old_count); l_info.set_versions (l_mismatch_info.old_version, l_mismatch_info.new_version) end l_deser := deserializer from i := 1 nb := read_persistent_field_count (a_reflected_object) + 1 until i = nb loop l_field_info := l_mismatch_info.mismatches_by_stored_position.item (i) if l_field_info /= Void then l_check_for_non_void := l_field_info.is_attachment_check_required l_has_mismatch := l_field_info.is_changed or (not is_attribute_removal_allowed and then l_field_info.is_removed) if not l_has_mismatch then l_field_info := Void elseif l_info = Void then create l_info.make (l_mismatch_info.old_count) end else l_check_for_non_void := False end if l_field_info = Void then l_new_offset := new_attribute_offset (l_dtype, i) inspect a_reflected_object.field_type (l_new_offset) when {REFLECTOR_CONSTANTS}.boolean_type then a_reflected_object.set_boolean_field (l_new_offset, l_deser.read_boolean) when {REFLECTOR_CONSTANTS}.character_8_type then a_reflected_object.set_character_8_field (l_new_offset, l_deser.read_character_8) when {REFLECTOR_CONSTANTS}.character_32_type then a_reflected_object.set_character_32_field (l_new_offset, l_deser.read_character_32) when {REFLECTOR_CONSTANTS}.natural_8_type then a_reflected_object.set_natural_8_field (l_new_offset, l_deser.read_natural_8) when {REFLECTOR_CONSTANTS}.natural_16_type then a_reflected_object.set_natural_16_field (l_new_offset, l_deser.read_natural_16) when {REFLECTOR_CONSTANTS}.natural_32_type then a_reflected_object.set_natural_32_field (l_new_offset, l_deser.read_natural_32) when {REFLECTOR_CONSTANTS}.natural_64_type then a_reflected_object.set_natural_64_field (l_new_offset, l_deser.read_natural_64) when {REFLECTOR_CONSTANTS}.integer_8_type then a_reflected_object.set_integer_8_field (l_new_offset, l_deser.read_integer_8) when {REFLECTOR_CONSTANTS}.integer_16_type then a_reflected_object.set_integer_16_field (l_new_offset, l_deser.read_integer_16) when {REFLECTOR_CONSTANTS}.integer_32_type then a_reflected_object.set_integer_32_field (l_new_offset, l_deser.read_integer_32) when {REFLECTOR_CONSTANTS}.integer_64_type then a_reflected_object.set_integer_64_field (l_new_offset, l_deser.read_integer_64) when {REFLECTOR_CONSTANTS}.real_32_type then a_reflected_object.set_real_32_field (l_new_offset, l_deser.read_real_32) when {REFLECTOR_CONSTANTS}.real_64_type then a_reflected_object.set_real_64_field (l_new_offset, l_deser.read_real_64) when {REFLECTOR_CONSTANTS}.pointer_type then a_reflected_object.set_pointer_field (l_new_offset, l_deser.read_pointer) when {REFLECTOR_CONSTANTS}.reference_type then if has_reference_with_copy_semantics then if l_deser.read_boolean then l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32) if l_exp_dtype < 0 then raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!")) else create l_exp.make (reflector.new_instance_of (l_exp_dtype)) decode_normal_object (l_exp); a_reflected_object.set_reference_field (l_new_offset, l_exp.object) if l_check_for_non_void then l_check_for_non_void := False end end else a_reflected_object.set_reference_field (l_new_offset, read_reference) end else a_reflected_object.set_reference_field (l_new_offset, read_reference) end if l_check_for_non_void and then a_reflected_object.reference_field (l_new_offset) = Void then if l_info = Void then create l_info.make (l_mismatch_info.old_count) end; l_info.put (Void, a_reflected_object.field_name (l_new_offset)) end when {REFLECTOR_CONSTANTS}.expanded_type then l_deser.read_compressed_integer_32.do_nothing decode_normal_object (a_reflected_object.expanded_field (l_new_offset)) else check False end end else if l_info = Void then create l_info.make (l_mismatch_info.old_count) end inspect abstract_type (l_field_info.old_attribute_type) when {REFLECTOR_CONSTANTS}.boolean_type then l_info.put (l_deser.read_boolean, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.character_8_type then l_info.put (l_deser.read_character_8, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.character_32_type then l_info.put (l_deser.read_character_32, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.natural_8_type then l_info.put (l_deser.read_natural_8, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.natural_16_type then l_info.put (l_deser.read_natural_16, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.natural_32_type then l_info.put (l_deser.read_natural_32, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.natural_64_type then l_info.put (l_deser.read_natural_64, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.integer_8_type then l_info.put (l_deser.read_integer_8, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.integer_16_type then l_info.put (l_deser.read_integer_16, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.integer_32_type then l_info.put (l_deser.read_integer_32, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.integer_64_type then l_info.put (l_deser.read_integer_64, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.real_32_type then l_info.put (l_deser.read_real_32, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.real_64_type then l_info.put (l_deser.read_real_64, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.pointer_type then l_info.put (l_deser.read_pointer, l_field_info.new_name) when {REFLECTOR_CONSTANTS}.reference_type then if has_reference_with_copy_semantics then if l_deser.read_boolean then l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32) if l_exp_dtype < 0 then raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!")) else create l_exp.make (reflector.new_instance_of (l_exp_dtype)) decode_normal_object (l_exp); l_info.put (l_exp.object, l_field_info.new_name) end else l_info.put (read_reference, l_field_info.new_name) end else l_info.put (read_reference, l_field_info.new_name) end when {REFLECTOR_CONSTANTS}.expanded_type then l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32) if l_exp_dtype < 0 then raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!")) else create l_exp.make (reflector.new_instance_of (l_exp_dtype)) decode_normal_object (l_exp); l_info.put (l_exp.object, l_field_info.new_name) end else check False end end end i := i + 1 end end if l_info /= Void then mismatched_object.extend ([a_reflected_object.object, l_info]) end end frozen decode_object (is_root: BOOLEAN) -- Decode one object and store it in last_decoded_object if is_root. -- (from SED_SESSION_DESERIALIZER) local l_deser: like deserializer l_reflected_object: like reflected_object l_obj: detachable ANY l_nat32: NATURAL_32 do l_deser := deserializer l_reflected_object := reflected_object l_nat32 := l_deser.read_compressed_natural_32 check l_nat32_valid: l_nat32 < {INTEGER_32}.max_value.as_natural_32 end l_obj := object_references.item (l_nat32.to_integer_32); l_reflected_object.set_object (l_obj) if l_reflected_object.is_special then decode_special (l_obj, abstract_type (l_reflected_object.generic_dynamic_type (1))) elseif l_reflected_object.is_tuple then decode_tuple (l_obj) else decode_normal_object (l_reflected_object) end if is_root then last_decoded_object := l_obj end end decode_objects (a_count: NATURAL_32) -- Decode a_count object from deserializer and store root object in last_decoded_object. require -- from SED_SESSION_DESERIALIZER a_count_positive: a_count > 0 local i, nb: INTEGER_32 do Precursor (a_count) from mismatched_object.start until mismatched_object.after loop safe_mismatch_correction (mismatched_object.item.object, mismatched_object.item.info); mismatched_object.forth end if is_checking_data_consistency then from i := 0 nb := object_references.upper until i > nb loop if attached object_references.item (i) as l_obj and then not is_object_valid (l_obj, True) then add_error (Error_factory.new_invalid_object_error (l_obj)) end i := i + 1 end end end frozen decode_special (an_obj: ANY; an_item_type: INTEGER_32) -- Decode SPECIAL object of element type an_item_type in an_obj. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER an_obj_not_void: an_obj /= Void an_obj_is_special: attached {SPECIAL [detachable ANY]} an_obj local nb: INTEGER_32 do nb := deserializer.read_compressed_integer_32 inspect an_item_type when {REFLECTOR_CONSTANTS}.boolean_type then if attached {SPECIAL [BOOLEAN]} an_obj as l_spec_boolean then decode_special_boolean (l_spec_boolean, nb) else check l_spec_boolean_not_void: False end end when {REFLECTOR_CONSTANTS}.character_8_type then if attached {SPECIAL [CHARACTER_8]} an_obj as l_spec_character_8 then decode_special_character_8 (l_spec_character_8, nb) else check l_spec_character_8_not_void: False end end when {REFLECTOR_CONSTANTS}.character_32_type then if attached {SPECIAL [CHARACTER_32]} an_obj as l_spec_character_32 then decode_special_character_32 (l_spec_character_32, nb) else check l_spec_character_32_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_8_type then if attached {SPECIAL [NATURAL_8]} an_obj as l_spec_natural_8 then decode_special_natural_8 (l_spec_natural_8, nb) else check l_spec_natural_8_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_16_type then if attached {SPECIAL [NATURAL_16]} an_obj as l_spec_natural_16 then decode_special_natural_16 (l_spec_natural_16, nb) else check l_spec_natural_16_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_32_type then if attached {SPECIAL [NATURAL_32]} an_obj as l_spec_natural_32 then decode_special_natural_32 (l_spec_natural_32, nb) else check l_spec_natural_32_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_64_type then if attached {SPECIAL [NATURAL_64]} an_obj as l_spec_natural_64 then decode_special_natural_64 (l_spec_natural_64, nb) else check l_spec_natural_64_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_8_type then if attached {SPECIAL [INTEGER_8]} an_obj as l_spec_integer_8 then decode_special_integer_8 (l_spec_integer_8, nb) else check l_spec_integer_8_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_16_type then if attached {SPECIAL [INTEGER_16]} an_obj as l_spec_integer_16 then decode_special_integer_16 (l_spec_integer_16, nb) else check l_spec_integer_16_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_32_type then if attached {SPECIAL [INTEGER_32]} an_obj as l_spec_integer_32 then decode_special_integer_32 (l_spec_integer_32, nb) else check l_spec_integer_32_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_64_type then if attached {SPECIAL [INTEGER_64]} an_obj as l_spec_integer_64 then decode_special_integer_64 (l_spec_integer_64, nb) else check l_spec_integer_64_not_void: False end end when {REFLECTOR_CONSTANTS}.real_32_type then if attached {SPECIAL [REAL_32]} an_obj as l_spec_real_32 then decode_special_real_32 (l_spec_real_32, nb) else check l_spec_real_32_not_void: False end end when {REFLECTOR_CONSTANTS}.real_64_type then if attached {SPECIAL [REAL_64]} an_obj as l_spec_real_64 then decode_special_real_64 (l_spec_real_64, nb) else check l_spec_real_64_not_void: False end end when {REFLECTOR_CONSTANTS}.pointer_type then if attached {SPECIAL [POINTER]} an_obj as l_spec_pointer then decode_special_pointer (l_spec_pointer, nb) else check l_spec_pointer_not_void: False end end else check an_item_type_valid: an_item_type = {REFLECTOR_CONSTANTS}.reference_type end if attached {SPECIAL [detachable ANY]} an_obj as l_spec_any then decode_special_reference (l_spec_any, nb) else check l_spec_any_not_void: False end end end end frozen decode_special_boolean (a_spec: SPECIAL [BOOLEAN]; a_count: INTEGER_32) -- Decode SPECIAL [BOOLEAN]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_boolean) i := i + 1 end end frozen decode_special_character_32 (a_spec: SPECIAL [CHARACTER_32]; a_count: INTEGER_32) -- Decode SPECIAL [CHARACTER_32]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_character_32) i := i + 1 end end frozen decode_special_character_8 (a_spec: SPECIAL [CHARACTER_8]; a_count: INTEGER_32) -- Decode SPECIAL [CHARACTER_8]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_character_8) i := i + 1 end end frozen decode_special_integer_16 (a_spec: SPECIAL [INTEGER_16]; a_count: INTEGER_32) -- Decode SPECIAL [INTEGER_16]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_integer_16) i := i + 1 end end frozen decode_special_integer_32 (a_spec: SPECIAL [INTEGER_32]; a_count: INTEGER_32) -- Decode SPECIAL [INTEGER]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_integer_32) i := i + 1 end end frozen decode_special_integer_64 (a_spec: SPECIAL [INTEGER_64]; a_count: INTEGER_32) -- Decode SPECIAL [INTEGER_64]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_integer_64) i := i + 1 end end frozen decode_special_integer_8 (a_spec: SPECIAL [INTEGER_8]; a_count: INTEGER_32) -- Decode SPECIAL [INTEGER_8]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_integer_8) i := i + 1 end end frozen decode_special_natural_16 (a_spec: SPECIAL [NATURAL_16]; a_count: INTEGER_32) -- Decode SPECIAL [NATURAL_16]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_natural_16) i := i + 1 end end frozen decode_special_natural_32 (a_spec: SPECIAL [NATURAL_32]; a_count: INTEGER_32) -- Decode SPECIAL [NATURAL_32]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_natural_32) i := i + 1 end end frozen decode_special_natural_64 (a_spec: SPECIAL [NATURAL_64]; a_count: INTEGER_32) -- Decode SPECIAL [NATURAL_64]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_natural_64) i := i + 1 end end frozen decode_special_natural_8 (a_spec: SPECIAL [NATURAL_8]; a_count: INTEGER_32) -- Decode SPECIAL [NATURAL_8]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_natural_8) i := i + 1 end end frozen decode_special_pointer (a_spec: SPECIAL [POINTER]; a_count: INTEGER_32) -- Decode SPECIAL [POINTER]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_pointer) i := i + 1 end end frozen decode_special_real_32 (a_spec: SPECIAL [REAL_32]; a_count: INTEGER_32) -- Decode SPECIAL [REAL_32]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_real_32) i := i + 1 end end frozen decode_special_real_64 (a_spec: SPECIAL [REAL_64]; a_count: INTEGER_32) -- Decode SPECIAL [REAL_64]. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_spec_not_void: a_spec /= Void local i: INTEGER_32 l_deser: like deserializer do from l_deser := deserializer until i = a_count loop a_spec.extend (l_deser.read_real_64) i := i + 1 end end frozen decode_special_reference (a_spec: SPECIAL [detachable ANY]; a_count: INTEGER_32) -- Decode SPECIAL of reference. -- (from SED_SESSION_DESERIALIZER) local i: INTEGER_32 l_has_copy_semantics_item: BOOLEAN l_deser: like deserializer l_exp_dtype: INTEGER_32 l_exp: REFLECTED_REFERENCE_OBJECT do l_deser := deserializer if version >= {SED_VERSIONS}.version_7_3 then l_has_copy_semantics_item := l_deser.read_boolean end if not l_has_copy_semantics_item then from until i = a_count loop a_spec.force (read_reference, i) i := i + 1 end else from until i = a_count loop if l_deser.read_boolean then l_exp_dtype := new_dynamic_type_id (l_deser.read_compressed_integer_32) if l_exp_dtype < 0 then raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!")) else create l_exp.make (reflector.new_instance_of (l_exp_dtype)) decode_normal_object (l_exp); a_spec.force (l_exp.object, i) end else a_spec.force (read_reference, i) end i := i + 1 end end end frozen decode_tuple (an_obj: ANY) -- Decode TUPLE object. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER an_obj_not_void: an_obj /= Void an_obj_is_tuple: attached {TUPLE} an_obj local l_deser: like deserializer i, nb: INTEGER_32 do l_deser := deserializer if attached {TUPLE} an_obj as l_tuple then from i := 1 nb := l_tuple.count + 1 until i = nb loop inspect l_deser.read_natural_8 when {TUPLE}.boolean_code then l_tuple.put_boolean (l_deser.read_boolean, i) when {TUPLE}.character_8_code then l_tuple.put_character_8 (l_deser.read_character_8, i) when {TUPLE}.character_32_code then l_tuple.put_character_32 (l_deser.read_character_32, i) when {TUPLE}.natural_8_code then l_tuple.put_natural_8 (l_deser.read_natural_8, i) when {TUPLE}.natural_16_code then l_tuple.put_natural_16 (l_deser.read_natural_16, i) when {TUPLE}.natural_32_code then l_tuple.put_natural_32 (l_deser.read_natural_32, i) when {TUPLE}.natural_64_code then l_tuple.put_natural_64 (l_deser.read_natural_64, i) when {TUPLE}.integer_8_code then l_tuple.put_integer_8 (l_deser.read_integer_8, i) when {TUPLE}.integer_16_code then l_tuple.put_integer_16 (l_deser.read_integer_16, i) when {TUPLE}.integer_32_code then l_tuple.put_integer_32 (l_deser.read_integer_32, i) when {TUPLE}.integer_64_code then l_tuple.put_integer_64 (l_deser.read_integer_64, i) when {TUPLE}.real_32_code then l_tuple.put_real_32 (l_deser.read_real_32, i) when {TUPLE}.real_64_code then l_tuple.put_real_64 (l_deser.read_real_64, i) when {TUPLE}.pointer_code then l_tuple.put_pointer (l_deser.read_pointer, i) when {TUPLE}.reference_code then l_tuple.put_reference (read_reference, i) else check False end end i := i + 1 end end end has_mismatch (a_dtype: INTEGER_32): BOOLEAN -- Is there a mismatch triggered for a_dtype? require a_dtype_non_negative: a_dtype >= 0 do Result := mismatches.has (a_dtype) end is_object_valid (an_obj: ANY; a_verify_invariant: BOOLEAN): BOOLEAN -- Is object content valid, i.e. are all attached attributes really attached? local l_reflected_object: like reflected_object l_reflector: like reflector i, nb: INTEGER_32 retried: BOOLEAN do if not retried then from l_reflected_object := reflected_object l_reflector := reflector; l_reflected_object.set_object (an_obj) i := 1 nb := l_reflected_object.field_count Result := True until i > nb or not Result loop if l_reflected_object.field_type (i) = {REFLECTOR_CONSTANTS}.reference_type then Result := not l_reflector.is_attached_type (l_reflected_object.field_static_type (i)) or else l_reflected_object.reference_field (i) /= Void end i := i + 1 end if a_verify_invariant then an_obj.do_nothing end else Result := False end rescue retried := True retry end Is_special_flag: NATURAL_8 = 1 -- (from SED_UTILITIES) Is_tuple_flag: NATURAL_8 = 2 -- Various flags for storing objects -- (from SED_UTILITIES) Is_void_safe: BOOLEAN -- Is current system compiled in void-safe mode? -- (from SED_UTILITIES) once Result := {SPECIAL [ANY]} /= {SPECIAL [detachable ANY]} end Memory: MEMORY -- Access to MEMORY features without having to create a new instance each time. -- (from SED_SESSION_DESERIALIZER) once create Result ensure -- from SED_SESSION_DESERIALIZER memory_not_void: Result /= Void end frozen new_special_instance (a_dtype, a_item_type, a_count: INTEGER_32): SPECIAL [detachable ANY] -- Create new special instance of a special object whose dynamic -- type is a_dtype, whose element abstract type is a_item_type -- and of count a_count. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_dtype_non_negative: a_dtype >= 0 a_item_type_non_negative: a_item_type >= 0 a_count_non_negative: a_count >= 0 do inspect a_item_type when {REFLECTOR_CONSTANTS}.boolean_type then create {SPECIAL [BOOLEAN]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.character_8_type then create {SPECIAL [CHARACTER_8]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.character_32_type then create {SPECIAL [CHARACTER_32]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.natural_8_type then create {SPECIAL [NATURAL_8]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.natural_16_type then create {SPECIAL [NATURAL_16]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.natural_32_type then create {SPECIAL [NATURAL_32]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.natural_64_type then create {SPECIAL [NATURAL_64]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.integer_8_type then create {SPECIAL [INTEGER_8]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.integer_16_type then create {SPECIAL [INTEGER_16]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.integer_32_type then create {SPECIAL [INTEGER_32]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.integer_64_type then create {SPECIAL [INTEGER_64]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.real_32_type then create {SPECIAL [REAL_32]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.real_64_type then create {SPECIAL [REAL_64]} Result.make_empty (a_count) when {REFLECTOR_CONSTANTS}.pointer_type then create {SPECIAL [POINTER]} Result.make_empty (a_count) else Result := reflector.new_special_any_instance (a_dtype, a_count) end ensure -- from SED_SESSION_DESERIALIZER new_special_instance_not_void: Result /= Void end read_attributes (a_dtype: INTEGER_32) -- Read attribute description for a_dtype where a_dtype is a dynamic type -- from the current system. local l_deser: like deserializer l_reflector: like reflector l_map: like attributes_map l_mapping: SPECIAL [INTEGER_32] l_old_name, l_new_name: STRING_8 l_old_dtype, l_dtype: INTEGER_32 i, nb, l_not_founds: INTEGER_32 l_old_count, l_new_count: INTEGER_32 a: like attributes_mapping l_attribute_type: INTEGER_32 do l_deser := deserializer l_reflector := reflector l_old_count := l_deser.read_compressed_natural_32.to_integer_32 l_new_count := l_reflector.persistent_field_count_of_type (a_dtype) if l_old_count /= l_new_count then associated_mismatch (a_dtype).add_attribute_count_mismatch (l_old_count, l_new_count) end from i := 1 l_map := attributes_map (a_dtype) nb := l_old_count + 1 create l_mapping.make_empty (nb); l_mapping.extend (0) until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_dtype := new_dynamic_type_id (l_old_dtype) l_old_name := l_deser.read_string_8 l_new_name := if attached attribute_name_translator as translation then translation (l_old_name, a_dtype) else l_old_name end if l_dtype >= 0 then if attached l_map.item (l_new_name) as l_item then l_attribute_type := l_item.dtype if l_attribute_type /= l_dtype then if is_conforming_mismatch_allowed then if not l_reflector.type_conforms_to (l_dtype, l_attribute_type) then if l_reflector.is_attached_type (l_attribute_type) and then l_reflector.type_conforms_to (l_dtype, l_reflector.detachable_type (l_attribute_type)) then associated_mismatch (a_dtype).add_void_safe_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position) else associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position) end end else if l_reflector.is_attached_type (l_attribute_type) then if l_reflector.detachable_type (l_attribute_type) = l_dtype then associated_mismatch (a_dtype).add_void_safe_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position) else associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position) end else if l_reflector.is_attached_type (l_dtype) and then l_reflector.detachable_type (l_dtype) = l_attribute_type then else associated_mismatch (a_dtype).add_attribute_mismatch (l_dtype, l_attribute_type, l_old_name, l_new_name, i, l_item.position) end end end end; l_mapping.extend (l_item.position) else l_not_founds := l_not_founds + 1 if not is_attribute_removal_allowed then associated_mismatch (a_dtype).add_removed_attribute (l_dtype, l_old_name, l_new_name, i) end; l_mapping.extend (-1) end else add_error (Error_factory.new_unknown_attribute_type_error (a_dtype, l_new_name)) end i := i + 1 end if l_old_count - l_not_founds < l_new_count then associated_mismatch (a_dtype).add_new_attribute_mismatch (l_new_count - (l_old_count - l_not_founds)) end check attached attributes_mapping as l_a then if not l_a.valid_index (a_dtype) then a := l_a.aliased_resized_area_with_default (Void, (a_dtype + 1).max (l_a.count * 2)) attributes_mapping := a else a := l_a end; a.put (l_mapping, a_dtype) end end frozen read_default_value (a_abstract_type: INTEGER_32) -- Read from the stream the default value that corresponds to a_abstract_type. -- (from SED_SESSION_DESERIALIZER) local l_deser: like deserializer do l_deser := deserializer inspect a_abstract_type when {REFLECTOR_CONSTANTS}.boolean_type then l_deser.read_boolean.do_nothing when {REFLECTOR_CONSTANTS}.character_8_type then l_deser.read_character_8.do_nothing when {REFLECTOR_CONSTANTS}.character_32_type then l_deser.read_character_32.do_nothing when {REFLECTOR_CONSTANTS}.natural_8_type then l_deser.read_natural_8.do_nothing when {REFLECTOR_CONSTANTS}.natural_16_type then l_deser.read_natural_16.do_nothing when {REFLECTOR_CONSTANTS}.natural_32_type then l_deser.read_natural_32.do_nothing when {REFLECTOR_CONSTANTS}.natural_64_type then l_deser.read_natural_64.do_nothing when {REFLECTOR_CONSTANTS}.integer_8_type then l_deser.read_integer_8.do_nothing when {REFLECTOR_CONSTANTS}.integer_16_type then l_deser.read_integer_16.do_nothing when {REFLECTOR_CONSTANTS}.integer_32_type then l_deser.read_integer_32.do_nothing when {REFLECTOR_CONSTANTS}.integer_64_type then l_deser.read_integer_64.do_nothing when {REFLECTOR_CONSTANTS}.real_32_type then l_deser.read_real_32.do_nothing when {REFLECTOR_CONSTANTS}.real_64_type then l_deser.read_real_64.do_nothing when {REFLECTOR_CONSTANTS}.pointer_type then l_deser.read_pointer.do_nothing when {REFLECTOR_CONSTANTS}.reference_type then l_deser.read_compressed_natural_32.do_nothing when {REFLECTOR_CONSTANTS}.expanded_type then l_deser.read_natural_8.do_nothing else check False end end end read_header (a_count: NATURAL_32) -- Read header which contains mapping between dynamic type and their -- string representation. require -- from SED_SESSION_DESERIALIZER True local i, nb: INTEGER_32 l_deser: like deserializer l_reflector: like reflector l_table: like dynamic_type_table l_old_dtype, l_new_dtype: INTEGER_32 l_old_type_str, l_new_type_str: STRING_8 l_old_version, l_new_version: detachable IMMUTABLE_STRING_8 do l_reflector := reflector l_deser := deserializer read_settings if version < {SED_VERSIONS}.version_6_6 then raise_fatal_error (Error_factory.new_format_mismatch (version, {SED_VERSIONS}.version_6_6)) end nb := l_deser.read_compressed_natural_32.to_integer_32 create l_table.make_filled (0, nb) create attributes_mapping.make_filled (Void, nb) from i := 0 until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_old_type_str := l_deser.read_string_8 l_new_type_str := if attached class_type_translator as translation then translation (l_old_type_str) else l_old_type_str end l_new_dtype := l_reflector.dynamic_type_from_string (l_new_type_str) if l_new_dtype >= 0 then if not l_table.valid_index (l_old_dtype) then l_table := l_table.aliased_resized_area_with_default (0, (l_old_dtype + 1).max (l_table.count * 2)) end; l_table.put (l_new_dtype, l_old_dtype) else add_error (Error_factory.new_missing_type_error (l_old_type_str, l_new_type_str)) end if l_deser.read_boolean then l_old_version := l_deser.read_immutable_string_8 else l_old_version := Void end if l_new_dtype /= -1 then l_new_version := l_reflector.storable_version_of_type (l_new_dtype) if l_old_version /~ l_new_version then associated_mismatch (l_new_dtype).add_version_mismatch (l_old_version, l_new_version) end end i := i + 1 end from i := 0 nb := l_deser.read_compressed_natural_32.to_integer_32 until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_old_type_str := l_deser.read_string_8 l_new_type_str := if attached class_type_translator as translation then translation (l_old_type_str) else l_old_type_str end l_new_dtype := l_reflector.dynamic_type_from_string (l_new_type_str) if l_new_dtype >= 0 then if not l_table.valid_index (l_old_dtype) then l_table := l_table.aliased_resized_area_with_default (0, (l_old_dtype + 1).max (l_table.count * 2)) end; l_table.put (l_new_dtype, l_old_dtype) else add_error (Error_factory.new_missing_type_error (l_old_type_str, l_new_type_str)) end i := i + 1 end dynamic_type_table := l_table from i := 0 nb := l_deser.read_compressed_natural_32.to_integer_32 until i = nb loop l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 if l_table.valid_index (l_old_dtype) then read_attributes (l_table.item (l_old_dtype)) else raise_fatal_error (Error_factory.new_internal_error ("Cannot read attributes data")) end i := i + 1 end read_object_table (a_count) end frozen read_object_table (a_count: NATURAL_32) -- Read object table if any, which has a_count objects. -- (from SED_SESSION_DESERIALIZER) local l_objs: like object_references l_deser: like deserializer l_reflector: like reflector l_mem: like Memory l_is_collecting: BOOLEAN l_nat32: NATURAL_32 l_dtype, l_old_dtype: INTEGER_32 i, nb: INTEGER_32 l_obj: ANY do if deserializer.read_boolean then l_mem := Memory l_is_collecting := l_mem.collecting l_deser := deserializer l_reflector := reflector l_objs := object_references; l_objs.extend (Current) from i := 0 nb := a_count.to_integer_32 until i = nb loop if l_is_collecting and then i // 2000 = 0 then l_mem.collection_off end l_old_dtype := l_deser.read_compressed_natural_32.to_integer_32 l_dtype := new_dynamic_type_id (l_old_dtype) if l_dtype >= 0 then l_nat32 := deserializer.read_compressed_natural_32 check l_nat32_valid: l_nat32 > 0 and l_nat32 < {INTEGER_32}.max_value.as_natural_32 end check valid_id: l_nat32.to_integer_32 = i + 1 end if l_deser.read_natural_8 = Is_special_flag then l_obj := new_special_instance (l_dtype, l_deser.read_compressed_integer_32, l_deser.read_compressed_integer_32) else l_obj := l_reflector.new_instance_of (l_dtype) end; l_objs.extend (l_obj) else raise_fatal_error (Error_factory.new_internal_error ("Cannot read object type. Corrupted data!")) end i := i + 1 end if l_is_collecting then l_mem.collection_on end else raise_fatal_error (Error_factory.new_format_mismatch_66) end end read_persistent_field_count (a_reflected_object: REFLECTED_OBJECT): INTEGER_32 -- Number of fields we are going to read from a_reflected_object in the the retrieved system. local l_dtype: INTEGER_32 do l_dtype := a_reflected_object.dynamic_type if attached attributes_mapping as l_map and then l_map.valid_index (l_dtype) and then attached l_map.item (l_dtype) as l_entry then Result := l_entry.count - 1 else raise_fatal_error (Error_factory.new_internal_error ("Cannot retrieve stored count")) end end frozen read_reference: detachable ANY -- Read reference from the stream. -- (from SED_SESSION_DESERIALIZER) local l_nat32: NATURAL_32 do l_nat32 := deserializer.read_compressed_natural_32 if l_nat32 /= 0 then check l_nat32_valid: l_nat32 < {INTEGER_32}.max_value.as_natural_32 end Result := object_references.item (l_nat32.to_integer_32) end end frozen read_settings -- Read various settings of serialized data. -- (from SED_SESSION_DESERIALIZER) do if is_store_settings_enabled then version := deserializer.read_compressed_natural_32 if version >= {SED_VERSIONS}.version_7_3 then has_reference_with_copy_semantics := deserializer.read_boolean else has_reference_with_copy_semantics := False end else version := {SED_VERSIONS}.version_5_6 has_reference_with_copy_semantics := False end end safe_mismatch_correction (an_obj: ANY; a_mismatch_information: MISMATCH_INFORMATION) -- Try to apply {MISMATCH_CORRECTOR}.correct_mismatch to an_obj using a_mismatch_information -- to solve the mismatch. local retried: BOOLEAN l_check, l_mismatch_called: BOOLEAN do if not retried then if attached {MISMATCH_CORRECTOR} an_obj as l_corrector then l_mismatch_called := True l_check := {ISE_RUNTIME}.check_assert (False); a_mismatch_information.put (an_obj.generating_type.name, {MISMATCH_INFORMATION}.type_name_key); Mismatch_information.copy (a_mismatch_information); l_corrector.correct_mismatch l_check := {ISE_RUNTIME}.check_assert (l_check) if not is_object_valid (an_obj, False) then add_error (Error_factory.new_invalid_object_error (an_obj)) end else add_error (Error_factory.new_object_mismatch_error (an_obj)) end else if l_mismatch_called then l_check := {ISE_RUNTIME}.check_assert (l_check) end add_error (Error_factory.new_object_mismatch_error (an_obj)) end rescue retried := True retry end Special_type_mapping: HASH_TABLE [INTEGER_32, INTEGER_32] -- Mapping betwwen dynamic type of SPECIAL instances -- to abstract element types. -- (from SED_UTILITIES) once create Result.make (10); Result.put ({REFLECTOR_CONSTANTS}.boolean_type, ({BOOLEAN}).type_id); Result.put ({REFLECTOR_CONSTANTS}.character_8_type, ({CHARACTER_8}).type_id); Result.put ({REFLECTOR_CONSTANTS}.character_32_type, ({CHARACTER_32}).type_id); Result.put ({REFLECTOR_CONSTANTS}.natural_8_type, ({NATURAL_8}).type_id); Result.put ({REFLECTOR_CONSTANTS}.natural_16_type, ({NATURAL_16}).type_id); Result.put ({REFLECTOR_CONSTANTS}.natural_32_type, ({NATURAL_32}).type_id); Result.put ({REFLECTOR_CONSTANTS}.natural_64_type, ({NATURAL_64}).type_id); Result.put ({REFLECTOR_CONSTANTS}.integer_8_type, ({INTEGER_8}).type_id); Result.put ({REFLECTOR_CONSTANTS}.integer_16_type, ({INTEGER_16}).type_id); Result.put ({REFLECTOR_CONSTANTS}.integer_32_type, ({INTEGER_32}).type_id); Result.put ({REFLECTOR_CONSTANTS}.integer_64_type, ({INTEGER_64}).type_id); Result.put ({REFLECTOR_CONSTANTS}.real_32_type, ({REAL_32}).type_id); Result.put ({REFLECTOR_CONSTANTS}.real_64_type, ({REAL_64}).type_id); Result.put ({REFLECTOR_CONSTANTS}.pointer_type, ({POINTER}).type_id) ensure -- from SED_UTILITIES special_type_mapping_not_void: Result /= Void end feature {EXCEPTIONS} -- Backward compatibility support exception_from_code (a_code: INTEGER_32): detachable EXCEPTION -- Create exception object from a_code -- (from EXCEPTION_MANAGER) do ensure -- from EXCEPTION_MANAGER instance_free: class end type_of_code (a_code: INTEGER_32): detachable TYPE [EXCEPTION] -- Exception type of a_code -- (from EXCEPTION_MANAGER) do ensure -- from EXCEPTION_MANAGER instance_free: class end feature {NONE} -- Cleaning clear_internal_data -- Clear all allocated data do Precursor {SED_BASIC_DESERIALIZER} attributes_mapping := Void; mismatches.wipe_out; mismatched_object.wipe_out end feature -- Correction correct_mismatch -- Attempt to correct object mismatch using Mismatch_information. -- (from MISMATCH_CORRECTOR) local l_msg: STRING_32 l_exc: EXCEPTIONS do create l_msg.make_from_string_general ("Mismatch: ") create l_exc; l_msg.append (generating_type.name_32); l_exc.raise_retrieval_exception (l_msg) end Mismatch_information: MISMATCH_INFORMATION -- Original attribute values of mismatched object -- (from MISMATCH_CORRECTOR) once create Result end feature {NONE} -- Implementation: Access dynamic_type_table: detachable SPECIAL [INTEGER_32] -- Mapping between old dynamic types and new ones. -- (from SED_SESSION_DESERIALIZER) Error_factory: SED_ERROR_FACTORY -- Once access to the error factory. -- (from SED_SESSION_DESERIALIZER) once create Result ensure -- from SED_SESSION_DESERIALIZER result_not_void: Result /= Void end has_reference_with_copy_semantics: BOOLEAN -- Does retrieved data contain references with copy semantics? -- (from SED_SESSION_DESERIALIZER) is_store_settings_enabled: BOOLEAN -- Are settings stored? -- By default not for SED_INDEPENDENT_DESERIALIZER. -- (from SED_SESSION_DESERIALIZER) do Result := True end frozen new_dynamic_type_id (a_old_type_id: INTEGER_32): INTEGER_32 -- Given a_old_type_id, dynamic type id in stored system, retrieve dynamic -- type id in current system. Return -1 if not found. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_old_type_id_non_negative: a_old_type_id >= 0 do if attached dynamic_type_table as t then if a_old_type_id < t.count then Result := t.item (a_old_type_id) else Result := -1 end else Result := a_old_type_id end ensure -- from SED_SESSION_DESERIALIZER minus_one_of_non_negative: Result >= -1 end object_references: SPECIAL [ANY] -- Mapping between reference ID and the associated object. -- (from SED_SESSION_DESERIALIZER) reflected_object: REFLECTED_REFERENCE_OBJECT -- Facilities to inspect objects. -- (from SED_SESSION_DESERIALIZER) reflector: REFLECTOR -- Facilities to inspect. -- (from SED_SESSION_DESERIALIZER) version: NATURAL_32 -- Internal version of the storable being retrieved (See SED_VERSIONS for possible values). -- (from SED_SESSION_DESERIALIZER) feature {NONE} -- Implementation: Settings add_error (a_error: SED_ERROR) -- Assign a_error to error. -- (from SED_SESSION_DESERIALIZER) local l_new_errors: like errors do if attached errors as l_errors then l_errors.extend (a_error) else create l_new_errors.make (10); l_new_errors.extend (a_error) errors := l_new_errors end ensure -- from SED_SESSION_DESERIALIZER error_set: attached errors as l_errors and then l_errors.has (a_error) end raise_fatal_error (a_error: SED_ERROR) -- Add a_error to errors and raise an exception to terminate retrieval -- because the error is beyond recovery. -- (from SED_SESSION_DESERIALIZER) local l_failure: SERIALIZATION_FAILURE do add_error (a_error) create l_failure; l_failure.set_description (a_error.message); l_failure.raise ensure -- from SED_SESSION_DESERIALIZER error_set: attached errors as l_errors and then l_errors.has (a_error) end reset_errors -- Remove all errors for a new retrieval -- (from SED_SESSION_DESERIALIZER) do errors := Void ensure -- from SED_SESSION_DESERIALIZER errors_reset: errors = Void end set_error (a_error: SED_ERROR) obsolete "Use `add_error' instead. [2017-05-31]" -- Assign a_error to error. -- (from SED_SESSION_DESERIALIZER) do add_error (a_error) ensure -- from SED_SESSION_DESERIALIZER error_set: error = a_error end feature {NONE} -- Implementation: access attribute_name_translator: detachable FUNCTION [STRING_8, INTEGER_32, STRING_8] -- Provide a mapping for an attribute name for a give type ID. attributes_mapping: detachable SPECIAL [detachable SPECIAL [INTEGER_32]] -- Mapping for each dynamic type id between old attribute location -- and new attribute location. class_type_translator: detachable FUNCTION [STRING_8, STRING_8] -- Provide a mapping between a class type from the storable to a class type -- in the retrieving system. mismatched_object: ARRAYED_LIST [TUPLE [object: ANY; info: MISMATCH_INFORMATION]] -- List of all mismatched objects found during retrieval. mismatches: HASH_TABLE [SED_TYPE_MISMATCH, INTEGER_32] -- Set of mismatches recorded during retrieval indexed by dynamic types. new_attribute_offset (a_new_type_id, a_old_offset: INTEGER_32): INTEGER_32 -- Given attribute offset a_old_offset in the stored object whose dynamic type id -- is now a_new_type_id, retrieve new offset in a_new_type_id. require -- from SED_SESSION_DESERIALIZER a_new_type_id_non_negative: a_new_type_id >= 0 a_old_offset_positive: a_old_offset > 0 do if attached attributes_mapping as l_map and then l_map.valid_index (a_new_type_id) and then attached l_map.item (a_new_type_id) as l_entry and then l_entry.valid_index (a_old_offset) then Result := l_entry.item (a_old_offset) end ensure -- from SED_SESSION_DESERIALIZER new_attribute_offset_non_negative: Result >= 0 end feature -- Output Io: STD_FILES -- Handle to standard file setup -- (from ANY) once create Result; Result.set_output_default ensure -- from ANY instance_free: class io_not_void: Result /= Void end out: STRING_8 -- New string containing terse printable representation -- of current object -- (from ANY) do Result := tagged_out ensure -- from ANY out_not_void: Result /= Void end print (o: detachable ANY) -- Write terse external representation of o -- on standard output. -- (from ANY) local s: READABLE_STRING_8 do if attached o then s := o.out if attached {READABLE_STRING_32} s as s32 then Io.put_string_32 (s32) elseif attached {READABLE_STRING_8} s as s8 then Io.put_string (s8) else Io.put_string_32 (s.as_string_32) end end ensure -- from ANY instance_free: class end frozen tagged_out: STRING_8 -- New string containing terse printable representation -- of current object -- (from ANY) external "built_in" ensure -- from ANY tagged_out_not_void: Result /= Void end feature -- Platform Operating_environment: OPERATING_ENVIRONMENT -- Objects available from the operating system -- (from ANY) once create Result ensure -- from ANY instance_free: class operating_environment_not_void: Result /= Void end feature -- Raise raise (a_exception: EXCEPTION) -- Raise a_exception. -- (from EXCEPTION_MANAGER) require -- from EXCEPTION_MANAGER a_exception_not_void: a_exception /= Void a_exception_is_raisable: a_exception.is_raisable do (create {EXCEPTION_MANAGER_FACTORY}).Exception_manager.raise (a_exception) ensure -- from EXCEPTION_MANAGER instance_free: class end feature {NONE} -- Retrieval frozen internal_correct_mismatch -- Called from runtime to perform a proper dynamic dispatch on correct_mismatch -- from MISMATCH_CORRECTOR. -- (from ANY) local l_msg: STRING_32 l_exc: EXCEPTIONS do if attached {MISMATCH_CORRECTOR} Current as l_corrector then l_corrector.correct_mismatch else create l_msg.make_from_string ("Mismatch: ".as_string_32) create l_exc; l_msg.append (generating_type.name_32); l_exc.raise_retrieval_exception (l_msg) end end feature -- Settings allow_attribute_removal -- Set is_attribute_removal_allowed to True. do is_attribute_removal_allowed := True ensure is_attribute_removal_allowed_set: is_attribute_removal_allowed end allow_conforming_mismatches -- Set is_conforming_mismatch_allowed to True. do is_conforming_mismatch_allowed := True ensure is_conforming_mismatch_allowed_set: is_conforming_mismatch_allowed end continue_on_data_retrieval_error -- Set is_attribute_removal_allowed to False. do is_stopping_on_data_retrieval_error := False ensure is_stopping_on_data_retrieval_error_set: not is_stopping_on_data_retrieval_error end disallow_attribute_removal -- Set is_attribute_removal_allowed to False. do is_attribute_removal_allowed := False ensure is_attribute_removal_allowed_set: not is_attribute_removal_allowed end disallow_conforming_mismatches -- Set is_conforming_mismatch_allowed to False. do is_conforming_mismatch_allowed := False ensure is_conforming_mismatch_allowed_set: not is_conforming_mismatch_allowed end set_attribute_name_translator (a_translator: like attribute_name_translator) -- Set attribute_name_translator with a_translator. do attribute_name_translator := a_translator ensure attribute_name_translator_set: attribute_name_translator = a_translator end set_class_type_translator (a_translator: like class_type_translator) -- Set class_type_translator with a_translator. do class_type_translator := a_translator ensure class_type_translator_set: class_type_translator = a_translator end set_deserializer (a_deserializer: like deserializer) -- Set deserializer with a_deserializer. -- (from SED_SESSION_DESERIALIZER) require -- from SED_SESSION_DESERIALIZER a_deserializer_not_void: a_deserializer /= Void a_deserializer_ready: a_deserializer.is_ready_for_reading do deserializer := a_deserializer ensure -- from SED_SESSION_DESERIALIZER deserializer_set: deserializer = a_deserializer end set_is_checking_data_consistency (v: like is_checking_data_consistency) -- Set is_checking_data_consistency with v. do is_checking_data_consistency := v ensure is_checking_data_consistency_set: is_checking_data_consistency = v end stop_on_data_retrieval_error -- Set is_stopping_on_data_retrieval_error to False. do is_stopping_on_data_retrieval_error := True ensure is_stopping_on_data_retrieval_error_set: is_stopping_on_data_retrieval_error end invariant -- from SED_SESSION_DESERIALIZER reflector_not_void: reflector /= Void reflected_object_not_void: reflected_object /= Void deserializer_not_void: deserializer /= Void object_references_not_void: object_references /= Void -- from ANY reflexive_equality: standard_is_equal (Current) reflexive_conformance: conforms_to (Current) note library: "EiffelBase: Library of reusable components for Eiffel." copyright: "Copyright (c) 1984-2020, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class SED_RECOVERABLE_DESERIALIZER
Generated by ISE EiffelStudio