note description: "Encoding of arbitrary objects graphs between sessions of a same program." 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_BASIC_SERIALIZER create make feature {NONE} -- Initialization default_create -- Process instances of classes with no creation clause. -- (Default: do nothing.) -- (from ANY) do end make (a_serializer: SED_READER_WRITER) -- Initialize current instance -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_serializer_not_void: a_serializer /= Void a_serializer_ready: a_serializer.is_ready_for_writing do create reflector create reflected_object.make (reflector) create object_indexes.make (1) traversable := Breadth_first_traversable serializer := a_serializer set_version ({SED_VERSIONS}.version_7_3) ensure -- from SED_SESSION_SERIALIZER serializer_set: serializer = a_serializer end feature -- Access generating_type: TYPE [detachable SED_BASIC_SERIALIZER] -- 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 root_object: detachable ANY -- Root object of object graph -- (from SED_SESSION_SERIALIZER) do Result := traversable.root_object end serializer: SED_READER_WRITER -- Serializer used to encode data -- (from SED_SESSION_SERIALIZER) 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_BASIC_SERIALIZER): 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_BASIC_SERIALIZER): 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_BASIC_SERIALIZER): 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 -- 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 is_root_object_set: BOOLEAN -- Is root object of object graph set? -- (from SED_SESSION_SERIALIZER) is_traversing_mode_set: BOOLEAN -- Is traversing mode set? -- (from SED_SESSION_SERIALIZER) do Result := traversable /= Void 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 {NONE} -- Status report has_reference_with_copy_semantics: BOOLEAN -- Does serialized data have some reference with copy semantics? -- If none, we optimize the serialization of references by not emitting -- a boolean switch each time we refer to an object. -- (from SED_SESSION_SERIALIZER) is_store_settings_enabled: BOOLEAN -- Are settings stored? -- By default not for SED_INDEPENDENT_SERIALIZER. -- (from SED_SESSION_SERIALIZER) do Result := True end feature -- Element change set_breadth_first_traversing_mode -- Change graph traversing to breadth first. -- (from SED_SESSION_SERIALIZER) do traversable := Breadth_first_traversable ensure -- from SED_SESSION_SERIALIZER traversing_mode_set: is_traversing_mode_set breadth_first_mode: attached {OBJECT_GRAPH_BREADTH_FIRST_TRAVERSABLE} traversable end set_depth_first_traversing_mode -- Change graph traversing to depth first. -- (from SED_SESSION_SERIALIZER) do traversable := Depth_first_traversable ensure -- from SED_SESSION_SERIALIZER traversing_mode_set: is_traversing_mode_set depth_first_mode: attached {OBJECT_GRAPH_DEPTH_FIRST_TRAVERSABLE} traversable end set_root_object (an_object: like root_object) -- Make 'an_object' the root_object. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER an_object_not_void: an_object /= Void traversing_mode_set: is_traversing_mode_set do traversable.set_root_object (an_object) is_root_object_set := True ensure -- from SED_SESSION_SERIALIZER root_object_set: root_object = an_object and is_root_object_set root_object_identity: root_object = traversable.root_object end set_serializer (a_serializer: like serializer) -- Set serializer with a_serializer. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_serializer_not_void: a_serializer /= Void a_serializer_ready: a_serializer.is_ready_for_writing do serializer := a_serializer ensure -- from SED_SESSION_SERIALIZER serializer_set: serializer = a_serializer 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_BASIC_SERIALIZER) -- 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_BASIC_SERIALIZER) -- 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_BASIC_SERIALIZER -- 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_BASIC_SERIALIZER) -- 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_BASIC_SERIALIZER -- 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_BASIC_SERIALIZER -- 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_BASIC_SERIALIZER 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 default: detachable SED_BASIC_SERIALIZER -- 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 frozen encode -- Encode object graph starting with the root object. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER traversing_mode_set: is_traversing_mode_set root_object_set: is_root_object_set local l_mem: detachable MEMORY l_is_collecting: BOOLEAN l_list_count: NATURAL_32 do if not {PLATFORM}.is_dotnet then create l_mem l_is_collecting := l_mem.collecting; l_mem.collection_off end; traversable.set_is_skip_transient (True); traversable.set_is_skip_copy_semantics_reference (True); traversable.traverse if attached traversable.visited_objects as l_list and then attached traversable.visited_types as l_type_table then has_reference_with_copy_semantics := traversable.has_reference_with_copy_semantics l_list_count := l_list.count.to_natural_32 if l_list.count > object_indexes.capacity then create object_indexes.make (l_list_count) end; serializer.write_compressed_natural_32 (l_list_count) write_header (l_list, l_type_table) encode_objects (l_list) end; traversable.wipe_out; object_indexes.wipe_out if l_mem /= Void and then l_is_collecting then l_mem.collection_on end 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 frozen encode_normal_object (a_reflected_object: REFLECTED_OBJECT) -- Encode normal object a_reflected_object. -- (from SED_SESSION_SERIALIZER) local i, nb: INTEGER_32 l_ser: like serializer l_exp: REFLECTED_COPY_SEMANTICS_OBJECT do from l_ser := serializer i := 1 nb := a_reflected_object.field_count + 1 until i = nb loop if not a_reflected_object.is_field_transient (i) then inspect a_reflected_object.field_type (i) when {REFLECTOR_CONSTANTS}.boolean_type then l_ser.write_boolean (a_reflected_object.boolean_field (i)) when {REFLECTOR_CONSTANTS}.character_8_type then l_ser.write_character_8 (a_reflected_object.character_8_field (i)) when {REFLECTOR_CONSTANTS}.character_32_type then l_ser.write_character_32 (a_reflected_object.character_32_field (i)) when {REFLECTOR_CONSTANTS}.natural_8_type then l_ser.write_natural_8 (a_reflected_object.natural_8_field (i)) when {REFLECTOR_CONSTANTS}.natural_16_type then l_ser.write_natural_16 (a_reflected_object.natural_16_field (i)) when {REFLECTOR_CONSTANTS}.natural_32_type then l_ser.write_natural_32 (a_reflected_object.natural_32_field (i)) when {REFLECTOR_CONSTANTS}.natural_64_type then l_ser.write_natural_64 (a_reflected_object.natural_64_field (i)) when {REFLECTOR_CONSTANTS}.integer_8_type then l_ser.write_integer_8 (a_reflected_object.integer_8_field (i)) when {REFLECTOR_CONSTANTS}.integer_16_type then l_ser.write_integer_16 (a_reflected_object.integer_16_field (i)) when {REFLECTOR_CONSTANTS}.integer_32_type then l_ser.write_integer_32 (a_reflected_object.integer_32_field (i)) when {REFLECTOR_CONSTANTS}.integer_64_type then l_ser.write_integer_64 (a_reflected_object.integer_64_field (i)) when {REFLECTOR_CONSTANTS}.real_32_type then l_ser.write_real_32 (a_reflected_object.real_32_field (i)) when {REFLECTOR_CONSTANTS}.real_64_type then l_ser.write_real_64 (a_reflected_object.real_64_field (i)) when {REFLECTOR_CONSTANTS}.pointer_type then l_ser.write_pointer (a_reflected_object.pointer_field (i)) when {REFLECTOR_CONSTANTS}.reference_type then if has_reference_with_copy_semantics then if a_reflected_object.is_copy_semantics_field (i) then l_ser.write_boolean (True) l_exp := a_reflected_object.copy_semantics_field (i); l_ser.write_compressed_integer_32 (l_exp.dynamic_type) encode_normal_object (l_exp) else l_ser.write_boolean (False) encode_reference (a_reflected_object.reference_field (i)) end else encode_reference (a_reflected_object.reference_field (i)) end when {REFLECTOR_CONSTANTS}.expanded_type then l_ser.write_compressed_integer_32 (a_reflected_object.dynamic_type) encode_normal_object (a_reflected_object.expanded_field (i)) else check False end end end i := i + 1 end end frozen encode_objects (a_list: ARRAYED_LIST [separate ANY]) -- Encode all objects referenced in a_list. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_list_not_void: a_list /= Void a_list_not_empty: not a_list.is_empty local l_reflected_object: like reflected_object l_ser: like serializer l_object_indexes: like object_indexes l_obj: separate ANY i, nb: INTEGER_32 l_area: SPECIAL [separate ANY] l_obj_index: NATURAL_32 do l_reflected_object := reflected_object l_ser := serializer l_object_indexes := object_indexes from l_area := a_list.area i := 0 nb := a_list.count until i = nb loop l_obj := l_area.item (i); l_reflected_object.set_object (l_obj) i := i + 1 l_obj_index := l_object_indexes.index (l_obj); l_ser.write_compressed_natural_32 (l_obj_index) check l_obj_index = i.as_natural_32 end if l_reflected_object.is_special then encode_special (l_obj, abstract_type (l_reflected_object.generic_dynamic_type (1))) elseif l_reflected_object.is_tuple then if attached {TUPLE} l_obj as l_tuple then encode_tuple_object (l_tuple) else check l_tuple_attached: False end end else encode_normal_object (l_reflected_object) end end end frozen encode_reference (an_object: detachable separate ANY) -- Encode reference to an_object. -- (from SED_SESSION_SERIALIZER) do if an_object /= Void then serializer.write_compressed_natural_32 (object_indexes.index (an_object)) else serializer.write_compressed_natural_32 (0) end end frozen encode_special (an_object: separate ANY; a_item_type: INTEGER_32) -- Encode an object which is a special object. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER an_object_not_void: an_object /= Void an_object_is_special: attached {separate SPECIAL [detachable ANY]} an_object a_item_type_non_negative: a_item_type >= 0 do inspect a_item_type when {REFLECTOR_CONSTANTS}.boolean_type then if attached {SPECIAL [BOOLEAN]} an_object as l_spec_boolean then encode_special_boolean (l_spec_boolean) else check l_spec_boolean_not_void: False end end when {REFLECTOR_CONSTANTS}.character_8_type then if attached {SPECIAL [CHARACTER_8]} an_object as l_spec_character_8 then encode_special_character_8 (l_spec_character_8) else check l_spec_character_8_not_void: False end end when {REFLECTOR_CONSTANTS}.character_32_type, {REFLECTOR_CONSTANTS}.natural_32_type then if attached {SPECIAL [CHARACTER_32]} an_object as l_spec_character_32 then encode_special_character_32 (l_spec_character_32) elseif attached {SPECIAL [NATURAL_32]} an_object as l_spec_natural_32 then encode_special_natural_32 (l_spec_natural_32) else check l_spec_natural_32_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_8_type then if attached {SPECIAL [NATURAL_8]} an_object as l_spec_natural_8 then encode_special_natural_8 (l_spec_natural_8) else check l_spec_natural_8_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_16_type then if attached {SPECIAL [NATURAL_16]} an_object as l_spec_natural_16 then encode_special_natural_16 (l_spec_natural_16) else check l_spec_natural_16_not_void: False end end when {REFLECTOR_CONSTANTS}.natural_64_type then if attached {SPECIAL [NATURAL_64]} an_object as l_spec_natural_64 then encode_special_natural_64 (l_spec_natural_64) else check l_spec_natural_64_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_8_type then if attached {SPECIAL [INTEGER_8]} an_object as l_spec_integer_8 then encode_special_integer_8 (l_spec_integer_8) else check l_spec_integer_8_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_16_type then if attached {SPECIAL [INTEGER_16]} an_object as l_spec_integer_16 then encode_special_integer_16 (l_spec_integer_16) else check l_spec_integer_16_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_32_type then if attached {SPECIAL [INTEGER_32]} an_object as l_spec_integer_32 then encode_special_integer_32 (l_spec_integer_32) else check l_spec_integer_32_not_void: False end end when {REFLECTOR_CONSTANTS}.integer_64_type then if attached {SPECIAL [INTEGER_64]} an_object as l_spec_integer_64 then encode_special_integer_64 (l_spec_integer_64) else check l_spec_integer_64_not_void: False end end when {REFLECTOR_CONSTANTS}.real_32_type then if attached {SPECIAL [REAL_32]} an_object as l_spec_real_32 then encode_special_real_32 (l_spec_real_32) else check l_spec_real_32_not_void: False end end when {REFLECTOR_CONSTANTS}.real_64_type then if attached {SPECIAL [REAL_64]} an_object as l_spec_real_64 then encode_special_real_64 (l_spec_real_64) else check l_spec_real_64_not_void: False end end when {REFLECTOR_CONSTANTS}.pointer_type then if attached {SPECIAL [POINTER]} an_object as l_spec_pointer then encode_special_pointer (l_spec_pointer) else check l_spec_pointer_not_void: False end end else check a_item_type_valid: a_item_type = {REFLECTOR_CONSTANTS}.reference_type end if attached {SPECIAL [detachable ANY]} an_object as l_spec_any then encode_special_reference (l_spec_any) else check l_spec_any_not_void: False end end end end frozen encode_special_boolean (a_spec: SPECIAL [BOOLEAN]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_boolean (a_spec.item (i)) i := i + 1 end end frozen encode_special_character_32 (a_spec: SPECIAL [CHARACTER_32]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_character_32 (a_spec.item (i)) i := i + 1 end end frozen encode_special_character_8 (a_spec: SPECIAL [CHARACTER_8]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_character_8 (a_spec.item (i)) i := i + 1 end end frozen encode_special_integer_16 (a_spec: SPECIAL [INTEGER_16]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_integer_16 (a_spec.item (i)) i := i + 1 end end frozen encode_special_integer_32 (a_spec: SPECIAL [INTEGER_32]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_integer_32 (a_spec.item (i)) i := i + 1 end end frozen encode_special_integer_64 (a_spec: SPECIAL [INTEGER_64]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_integer_64 (a_spec.item (i)) i := i + 1 end end frozen encode_special_integer_8 (a_spec: SPECIAL [INTEGER_8]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_integer_8 (a_spec.item (i)) i := i + 1 end end frozen encode_special_natural_16 (a_spec: SPECIAL [NATURAL_16]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_natural_16 (a_spec.item (i)) i := i + 1 end end frozen encode_special_natural_32 (a_spec: SPECIAL [NATURAL_32]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_natural_32 (a_spec.item (i)) i := i + 1 end end frozen encode_special_natural_64 (a_spec: SPECIAL [NATURAL_64]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_natural_64 (a_spec.item (i)) i := i + 1 end end frozen encode_special_natural_8 (a_spec: SPECIAL [NATURAL_8]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_natural_8 (a_spec.item (i)) i := i + 1 end end frozen encode_special_pointer (a_spec: SPECIAL [POINTER]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_pointer (a_spec.item (i)) i := i + 1 end end frozen encode_special_real_32 (a_spec: SPECIAL [REAL_32]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_real_32 (a_spec.item (i)) i := i + 1 end end frozen encode_special_real_64 (a_spec: SPECIAL [REAL_64]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_ser: like serializer do from nb := a_spec.count l_ser := serializer; l_ser.write_compressed_integer_32 (nb) until i = nb loop l_ser.write_real_64 (a_spec.item (i)) i := i + 1 end end frozen encode_special_reference (a_spec: SPECIAL [detachable ANY]) -- Encode a_spec. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_spec_not_void: a_spec /= Void local i, nb: INTEGER_32 l_reflected_object: like reflected_object l_exp: REFLECTED_COPY_SEMANTICS_OBJECT l_ser: like serializer l_has_copy_semantics: BOOLEAN do l_ser := serializer nb := a_spec.count; l_ser.write_compressed_integer_32 (nb) if version >= {SED_VERSIONS}.version_7_3 then from l_reflected_object := reflected_object; l_reflected_object.set_object (a_spec) until i = nb loop if l_reflected_object.is_special_copy_semantics_item (i) then l_has_copy_semantics := True i := nb - 1 end i := i + 1 end; l_ser.write_boolean (l_has_copy_semantics) if l_has_copy_semantics then from i := 0 until i = nb loop if l_reflected_object.is_special_copy_semantics_item (i) then l_ser.write_boolean (True) l_exp := l_reflected_object.special_copy_semantics_item (i); l_ser.write_compressed_integer_32 (l_exp.dynamic_type) encode_normal_object (l_exp) else l_ser.write_boolean (False) encode_reference (a_spec.item (i)) end i := i + 1 end end end if not l_has_copy_semantics then from i := 0 until i = nb loop encode_reference (a_spec.item (i)) i := i + 1 end end end frozen encode_tuple_object (a_tuple: TUPLE) -- Encode a TUPLE object. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_tuple_not_void: a_tuple /= Void local i, nb: INTEGER_32 l_code: NATURAL_8 l_ser: like serializer do from l_ser := serializer i := 1 nb := a_tuple.count + 1 until i = nb loop l_code := a_tuple.item_code (i); l_ser.write_natural_8 (l_code) inspect l_code when {TUPLE}.boolean_code then l_ser.write_boolean (a_tuple.boolean_item (i)) when {TUPLE}.character_8_code then l_ser.write_character_8 (a_tuple.character_8_item (i)) when {TUPLE}.character_32_code then l_ser.write_character_32 (a_tuple.character_32_item (i)) when {TUPLE}.natural_8_code then l_ser.write_natural_8 (a_tuple.natural_8_item (i)) when {TUPLE}.natural_16_code then l_ser.write_natural_16 (a_tuple.natural_16_item (i)) when {TUPLE}.natural_32_code then l_ser.write_natural_32 (a_tuple.natural_32_item (i)) when {TUPLE}.natural_64_code then l_ser.write_natural_64 (a_tuple.natural_64_item (i)) when {TUPLE}.integer_8_code then l_ser.write_integer_8 (a_tuple.integer_8_item (i)) when {TUPLE}.integer_16_code then l_ser.write_integer_16 (a_tuple.integer_16_item (i)) when {TUPLE}.integer_32_code then l_ser.write_integer_32 (a_tuple.integer_32_item (i)) when {TUPLE}.integer_64_code then l_ser.write_integer_64 (a_tuple.integer_64_item (i)) when {TUPLE}.real_32_code then l_ser.write_real_32 (a_tuple.real_32_item (i)) when {TUPLE}.real_64_code then l_ser.write_real_64 (a_tuple.real_64_item (i)) when {TUPLE}.pointer_code then l_ser.write_pointer (a_tuple.pointer_item (i)) when {TUPLE}.reference_code then encode_reference (a_tuple.reference_item (i)) else check False end end i := i + 1 end 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 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 write_header (a_list: ARRAYED_LIST [separate ANY]; a_type_table: HASH_TABLE [INTEGER_32, INTEGER_32]) -- Write header of storable. require -- from SED_SESSION_SERIALIZER a_list_not_void: a_list /= Void a_list_not_empty: not a_list.is_empty local l_ser: like serializer l_reflector: like reflector l_dtype: INTEGER_32 do write_settings l_ser := serializer from l_reflector := reflector; l_ser.write_compressed_natural_32 (a_type_table.count.to_natural_32); a_type_table.start until a_type_table.after loop l_dtype := a_type_table.item_for_iteration; l_ser.write_compressed_natural_32 (l_dtype.to_natural_32); l_ser.write_string_8 (l_reflector.type_name_8_of_type (l_dtype)); a_type_table.forth end write_object_table (a_list) end frozen write_object_table (a_list: ARRAYED_LIST [separate ANY]) -- Write mapping between object's reference ID in a_list with -- all the necessary information necessary to recreate it at a -- later time. -- (from SED_SESSION_SERIALIZER) require -- from SED_SESSION_SERIALIZER a_list_not_void: a_list /= Void a_list_not_empty: not a_list.is_empty local l_reflected_object: like reflected_object l_ser: like serializer l_object_indexes: like object_indexes i, nb: INTEGER_32 l_obj: separate ANY l_area: SPECIAL [separate ANY] do l_ser := serializer; l_ser.write_boolean (True) l_reflected_object := reflected_object l_object_indexes := object_indexes from l_area := a_list.area i := 0 nb := a_list.count until i = nb loop l_obj := l_area.item (i); l_reflected_object.set_object (l_obj) i := i + 1; l_ser.write_compressed_natural_32 (l_reflected_object.dynamic_type.to_natural_32); l_ser.write_compressed_natural_32 (l_object_indexes.index (l_obj)) if l_reflected_object.is_special then l_ser.write_natural_8 (Is_special_flag); l_ser.write_compressed_integer_32 (abstract_type (l_reflected_object.generic_dynamic_type (1))) if attached {ABSTRACT_SPECIAL} l_obj as l_abstract_spec then l_ser.write_compressed_integer_32 (l_abstract_spec.capacity) else check l_abstract_spec_attached: False end end elseif l_reflected_object.is_tuple then l_ser.write_natural_8 (Is_tuple_flag) else l_ser.write_natural_8 (0) end end end frozen write_settings -- (from SED_SESSION_SERIALIZER) do if is_store_settings_enabled then serializer.write_compressed_natural_32 (version); serializer.write_boolean (has_reference_with_copy_semantics) end end feature {NONE} -- Implementation: Access Breadth_first_traversable: OBJECT_GRAPH_BREADTH_FIRST_TRAVERSABLE -- Return an instance of OBJECT_GRAPH_BREADTH_FIRST_TRAVERSABLE. -- (from SED_SESSION_SERIALIZER) once Result := create {OBJECT_GRAPH_BREADTH_FIRST_TRAVERSABLE} end Depth_first_traversable: OBJECT_GRAPH_DEPTH_FIRST_TRAVERSABLE -- Return an instance of OBJECT_GRAPH_DEPTH_FIRST_TRAVERSABLE. -- (from SED_SESSION_SERIALIZER) once Result := create {OBJECT_GRAPH_DEPTH_FIRST_TRAVERSABLE} end object_indexes: SED_OBJECTS_TABLE -- Mapping between object and their associated index. -- (from SED_SESSION_SERIALIZER) reflected_object: REFLECTED_REFERENCE_OBJECT -- Facility to inspect object. -- (from SED_SESSION_SERIALIZER) reflector: REFLECTOR -- Facilities to inspect. -- (from SED_SESSION_SERIALIZER) traversable: OBJECT_GRAPH_TRAVERSABLE -- Object used for traversing object graph -- (from SED_SESSION_SERIALIZER) version: NATURAL_32 -- Internal version of the format (See SED_VERSIONS for possible values). -- (from SED_SESSION_SERIALIZER) feature {NONE} -- Implementation: Setting set_version (v: like version) -- Set version with v. -- (from SED_SESSION_SERIALIZER) do version := v 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 {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 invariant -- from SED_SESSION_SERIALIZER reflector_not_void: reflector /= Void reflected_object_not_void: reflected_object /= Void traversable_not_void: traversable /= Void serializer_not_void: serializer /= Void object_indexes_not_void: object_indexes /= 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_BASIC_SERIALIZER
Generated by ISE EiffelStudio