From 60968612deb0e73f5a6a12e511d4d817fde7a77d Mon Sep 17 00:00:00 2001 From: Pierre Date: Thu, 12 Dec 2019 14:41:47 +0100 Subject: [PATCH] initial commit for github --- .clang-tidy | 65 + CMakeLists.txt | 144 + LICENSE | 376 +++ README.md | 198 ++ cmake/check_cmake_build_type.cmake | 12 + cmake/check_cmake_install_prefix.cmake | 20 + cmake/ddl-config.cmake.in | 45 + cmake/ddl4.1_replacements.txt | 132 + cmake/enable_multicore_compilation.cmake | 5 + cmake/migrate_to_ddl_4_1.cmake | 50 + cmake/migrate_to_ddl_4_1.sh.in | 19 + cmake/set_library_naming_conventions.cmake | 2 + cmake/use_integrated_debug_symbols.cmake | 12 + codec/access_element.h | 573 ++++ codec/bitserializer.cpp | 97 + codec/bitserializer.h | 750 +++++ codec/codec.cpp | 323 ++ codec/codec.h | 161 + codec/codec.sources | 29 + codec/codec_factory.cpp | 117 + codec/codec_factory.h | 147 + codec/element_accessor.cpp | 228 ++ codec/element_accessor.h | 83 + codec/pkg_codec.h | 32 + codec/static_codec.cpp | 198 ++ codec/static_codec.h | 181 ++ codec/struct_element.h | 115 + codec/struct_layout.cpp | 345 +++ codec/struct_layout.h | 87 + ddl.h | 31 + ddlgenerators/CMakeLists.txt | 3 + ddlgenerators/ddl2header/CMakeLists.txt | 30 + .../ddl2header/ddl2header_commandline.cpp | 79 + .../ddl2header/ddl2header_commandline.h | 47 + ddlgenerators/ddl2header/main.cpp | 66 + .../generator_library/CMakeLists.txt | 30 + .../generator_library/commandline.cpp | 126 + ddlgenerators/generator_library/commandline.h | 60 + .../generator_library/ddl_generator_core.cpp | 166 + .../generator_library/ddl_generator_core.h | 92 + .../ddl_generator_lib.sources | 45 + .../generator_library/ddl_manager.cpp | 396 +++ ddlgenerators/generator_library/ddl_manager.h | 93 + .../ddl_to_header_converter.cpp | 556 ++++ .../ddl_to_header_converter.h | 163 + .../headerrepresentation/header_base_intf.h | 47 + .../header_basic_type.cpp | 75 + .../headerrepresentation/header_basic_type.h | 85 + .../headerrepresentation/header_constant.cpp | 80 + .../headerrepresentation/header_constant.h | 97 + .../headerrepresentation/header_enum.cpp | 94 + .../headerrepresentation/header_enum.h | 111 + .../header_factorymethod_intf.h | 95 + .../headerrepresentation/header_header.cpp | 197 ++ .../headerrepresentation/header_header.h | 191 ++ .../headerrepresentation/header_importer.cpp | 1324 ++++++++ .../headerrepresentation/header_importer.h | 222 ++ .../headerrepresentation/header_printer.cpp | 381 +++ .../headerrepresentation/header_printer.h | 144 + .../headerrepresentation/header_struct.cpp | 114 + .../headerrepresentation/header_struct.h | 112 + .../header_struct_element.cpp | 172 ++ .../header_struct_element.h | 198 ++ .../header_to_ddl_converter.cpp | 441 +++ .../header_to_ddl_converter.h | 144 + .../headerrepresentation/header_type.cpp | 100 + .../headerrepresentation/header_type.h | 127 + .../headerrepresentation/header_typedef.cpp | 85 + .../headerrepresentation/header_typedef.h | 93 + .../header_visitor_intf.h | 105 + .../headerrepresentation/parserhelper.cpp | 253 ++ .../headerrepresentation/parserhelper.h | 79 + ddlgenerators/header2ddl/CMakeLists.txt | 30 + .../header2ddl/header2ddl_commandline.cpp | 82 + .../header2ddl/header2ddl_commandline.h | 49 + ddlgenerators/header2ddl/main.cpp | 110 + ddlrepresentation/ddl_common.h | 70 + ddlrepresentation/ddl_error.cpp | 50 + ddlrepresentation/ddl_error.h | 77 + ddlrepresentation/ddl_intf.h | 118 + ddlrepresentation/ddl_type.cpp | 72 + ddlrepresentation/ddl_type.h | 203 ++ ddlrepresentation/ddlalignment.cpp | 87 + ddlrepresentation/ddlalignment.h | 69 + ddlrepresentation/ddlbaseunit.cpp | 136 + ddlrepresentation/ddlbaseunit.h | 118 + ddlrepresentation/ddlbyteorder.cpp | 65 + ddlrepresentation/ddlbyteorder.h | 64 + ddlrepresentation/ddlcloner.cpp | 625 ++++ ddlrepresentation/ddlcloner.h | 69 + ddlrepresentation/ddlcompare.cpp | 1263 ++++++++ ddlrepresentation/ddlcompare.h | 309 ++ ddlrepresentation/ddlcomplex.cpp | 303 ++ ddlrepresentation/ddlcomplex.h | 275 ++ ddlrepresentation/ddlcontainer.cpp | 445 +++ ddlrepresentation/ddlcontainer.h | 335 +++ ddlrepresentation/ddldatatype.cpp | 300 ++ ddlrepresentation/ddldatatype.h | 330 ++ ddlrepresentation/ddldatatype_intf.h | 45 + ddlrepresentation/ddldescription.cpp | 1613 ++++++++++ ddlrepresentation/ddldescription.h | 1007 +++++++ ddlrepresentation/ddlelement.cpp | 475 +++ ddlrepresentation/ddlelement.h | 572 ++++ ddlrepresentation/ddlenum.cpp | 230 ++ ddlrepresentation/ddlenum.h | 206 ++ ddlrepresentation/ddlextdeclaration.cpp | 86 + ddlrepresentation/ddlextdeclaration.h | 93 + ddlrepresentation/ddlfactorymethod_intf.h | 124 + ddlrepresentation/ddlheader.cpp | 256 ++ ddlrepresentation/ddlheader.h | 253 ++ ddlrepresentation/ddlimporter.cpp | 2662 +++++++++++++++++ ddlrepresentation/ddlimporter.h | 394 +++ ddlrepresentation/ddlinspector.cpp | 1175 ++++++++ ddlrepresentation/ddlinspector.h | 287 ++ ddlrepresentation/ddlprefix.cpp | 107 + ddlrepresentation/ddlprefix.h | 119 + ddlrepresentation/ddlprinter.cpp | 631 ++++ ddlrepresentation/ddlprinter.h | 94 + ddlrepresentation/ddlproperty.cpp | 73 + ddlrepresentation/ddlproperty.h | 76 + ddlrepresentation/ddlrefunit.cpp | 130 + ddlrepresentation/ddlrefunit.h | 124 + ddlrepresentation/ddlrepair.cpp | 359 +++ ddlrepresentation/ddlrepair.h | 57 + ddlrepresentation/ddlresolver.cpp | 571 ++++ ddlrepresentation/ddlresolver.h | 103 + ddlrepresentation/ddlserializable_intf.h | 28 + ddlrepresentation/ddlstream.cpp | 251 ++ ddlrepresentation/ddlstream.h | 231 ++ ddlrepresentation/ddlstreammetatype.cpp | 151 + ddlrepresentation/ddlstreammetatype.h | 150 + ddlrepresentation/ddlstreamstruct.cpp | 121 + ddlrepresentation/ddlstreamstruct.h | 125 + ddlrepresentation/ddlunit.cpp | 247 ++ ddlrepresentation/ddlunit.h | 228 ++ ddlrepresentation/ddlunit_intf.h | 43 + ddlrepresentation/ddlversion.cpp | 175 ++ ddlrepresentation/ddlversion.h | 75 + ddlrepresentation/ddlvisitor_intf.h | 291 ++ ddlrepresentation/pkg_ddlrepresentation.h | 109 + .../pkg_ddlrepresentation.sources | 82 + doc/CMakeLists.txt | 57 + doc/changelog.md | 16 + doc/input/codec.md | 114 + doc/input/ddl3.xsd | 200 ++ doc/input/ddl4.xsd | 234 ++ doc/input/ddl_generators.md | 77 + doc/input/ddl_specification.md | 758 +++++ doc/input/mapping_configuration.xsd | 122 + doc/input/mapping_specification.md | 261 ++ doc/input/migration_4_1.md | 81 + doc/input/mpl.md | 376 +++ doc/input/oo-ddl.md | 63 + doc/input/used_licenses.md | 404 +++ doc/license/MPL2.0.txt | 376 +++ doc/run_doxygen.cmake.in | 49 + doc/static/ddl.html | 5 + legacy_error_macros.h | 31 + mapping/configuration/map_assignment.cpp | 364 +++ mapping/configuration/map_assignment.h | 194 ++ mapping/configuration/map_configuration.cpp | 1282 ++++++++ mapping/configuration/map_configuration.h | 577 ++++ mapping/configuration/map_header.cpp | 159 + mapping/configuration/map_header.h | 127 + mapping/configuration/map_source.cpp | 133 + mapping/configuration/map_source.h | 132 + mapping/configuration/map_target.cpp | 616 ++++ mapping/configuration/map_target.h | 248 ++ mapping/configuration/map_transformation.cpp | 600 ++++ mapping/configuration/map_transformation.h | 379 +++ mapping/configuration/map_trigger.cpp | 592 ++++ mapping/configuration/map_trigger.h | 365 +++ mapping/ddl_helper.cpp | 135 + mapping/ddl_helper.h | 88 + mapping/engine/data_trigger.cpp | 122 + mapping/engine/data_trigger.h | 109 + mapping/engine/element.cpp | 445 +++ mapping/engine/element.h | 116 + mapping/engine/mapping_engine.cpp | 423 +++ mapping/engine/mapping_engine.h | 162 + mapping/engine/mapping_environment_intf.h | 167 ++ mapping/engine/periodic_trigger.cpp | 69 + mapping/engine/periodic_trigger.h | 83 + mapping/engine/signal_trigger.cpp | 66 + mapping/engine/signal_trigger.h | 81 + mapping/engine/source.cpp | 427 +++ mapping/engine/source.h | 177 ++ mapping/engine/target.cpp | 379 +++ mapping/engine/target.h | 184 ++ mapping/engine/trigger.cpp | 41 + mapping/engine/trigger.h | 86 + mapping/mapping.sources | 53 + mapping/pkg_mapping.h | 28 + serialization/pkg_serialization.h | 27 + serialization/serialization.cpp | 55 + serialization/serialization.h | 80 + serialization/serialization.sources | 14 + test/CMakeLists.txt | 46 + test/README.md | 9 + test/_common/CMakeLists.txt | 4 + test/_common/adtf_compat.h | 142 + test/_common/compat.h | 32 + test/_doc/ddl_test.html | 5 + test/codec/files/hca.description | 147 + test/codec/src/CMakeLists.txt | 32 + test/codec/src/tester_bitserializer.cpp | 484 +++ test/codec/src/tester_codec.cpp | 992 ++++++ .../src/tester_mediacoder_regression.cpp | 2306 ++++++++++++++ .../expected_files/expected_result_datatype.h | 27 + .../expected_result_existing_all.description | 133 + .../expected_result_existing_all.h | 118 + ...xpected_result_existing_struct.description | 137 + .../expected_result_existing_struct.h | 118 + .../expected_result_newfile_all.description | 133 + .../expected_result_newfile_all.h | 66 + ...expected_result_newfile_struct.description | 110 + .../expected_result_newfile_struct.h | 63 + .../files/original_files/base_all.description | 133 + .../files/original_files/base_all.h | 84 + .../files/original_files/enums.description | 56 + .../files/original_files/enums.h | 37 + test/ddlgenerators/src/CMakeLists.txt | 23 + .../src/tester_ddl_generators.cpp | 419 +++ test/ddlinspector/files/ArrayZero.description | 116 + .../files/DynArraySize.description | 123 + .../ddlinspector/files/NestedCaps.description | 152 + .../files/NestedNaming.description | 126 + .../files/StructElementNaming.description | 118 + .../files/StructNaming.description | 126 + .../ddlinspector/files/UnitNaming.description | 120 + test/ddlinspector/files/base_all2.description | 133 + .../files/base_all_duplicates.description | 136 + .../files/invalid_duplicate.description | 30 + test/ddlinspector/src/CMakeLists.txt | 17 + test/ddlinspector/src/tester_ddlinspector.cpp | 347 +++ test/ddlrepresentation/files/adtf.description | 94 + .../ddlrepresentation/files/adtf1.description | 93 + test/ddlrepresentation/files/adtf2.xml | 94 + .../files/adtf_1_02.description | 94 + .../files/adtf_1_0p.description | 93 + .../files/adtf_1_0p_out_expected.xml | 154 + .../files/adtf_1_0p_resolved_expected.xml | 36 + .../files/adtf_changed_expected.xml | 144 + .../files/adtf_dynamic.description | 99 + .../files/adtf_merged_expected.xml | 173 ++ .../files/adtf_merged_ovrwrt_expected.xml | 173 ++ .../files/adtf_min_max_default.description | 59 + .../files/adtf_out_expected.xml | 155 + .../files/adtf_recursion.description | 96 + .../files/adtf_resolved_expected.xml | 37 + .../files/adtf_v40.description | 44 + .../files/fep_driver.description | 127 + .../files/force_version_ddl-2.0.description | 103 + ...ersion_ddl-2.0_to_3.0_expected.description | 103 + .../files/force_version_ddl-3.0.description | 103 + .../invalid_numbits_attribute.description | 25 + .../files/no_structs.description | 28 + .../files/partial_expected.description | 118 + .../files/printer.description | 96 + .../files/test_insert.description | 81 + .../files/test_insert_results.description | 136 + .../files/test_insert_results_ref.description | 135 + .../files/unresolved_datatype.description | 24 + test/ddlrepresentation/src/CMakeLists.txt | 17 + test/ddlrepresentation/src/ddl_definitions.h | 680 +++++ .../src/tester_ddlrepresentation.cpp | 1695 +++++++++++ test/function/api/src/CMakeLists.txt | 8 + .../function/api/src/test_fixture_ddl_types.h | 54 + test/function/api/src/tester_ddl_types.cpp | 283 ++ .../files/adtf2.description | 137 + .../files/adtf_expected.h | 113 + .../headerrepresentation/files/array_header.h | 31 + .../files/array_header_expected.description | 110 + .../files/array_header_expected.h | 52 + .../files/commented_header.h | 38 + .../files/complex_header.h | 28 + .../files/complex_header_expected.description | 119 + .../files/complex_header_expected.h | 58 + .../complex_struct2_expected.description | 116 + .../files/constants_header.h | 7 + .../files/default_types_header.h | 5 + .../files/defines_header.h | 26 + .../files/faulty_header1.h | 5 + .../files/faulty_header2.h | 4 + .../files/faulty_header3.h | 4 + .../files/faulty_header4.h | 4 + .../files/faulty_header5.h | 9 + .../files/packing_header.h | 31 + .../files/packing_header_expected.description | 34 + .../files/packing_header_expected.h | 59 + .../files/simple_header.h | 19 + .../files/simple_header_expected.description | 40 + .../files/simple_header_expected.h | 38 + .../files/simple_header_result.description | 109 + .../files/typedef_header.h | 5 + .../files/typedef_header_expected.h | 27 + .../files/viRDBIcd.description | 551 ++++ test/headerrepresentation/files/viRDBIcd.h | 1737 +++++++++++ .../files/viRDBIcd_expected.description | 561 ++++ .../files/viRDBIcd_expected.h | 765 +++++ .../viRDBIcd_extract_expected.description | 152 + .../files/viRDBIcd_extract_expected.h | 99 + .../headerrepresentation/files/wrong_header.h | 19 + test/headerrepresentation/src/CMakeLists.txt | 25 + .../src/ddl_definitions.h | 616 ++++ .../src/tester_headerrepresentation.cpp | 956 ++++++ test/mapping/files/base.map | 52 + test/mapping/files/benchmark.description | 591 ++++ test/mapping/files/benchmark.map | 429 +++ test/mapping/files/benchmark2.map | 205 ++ test/mapping/files/engine.description | 147 + test/mapping/files/engine.map | 78 + test/mapping/files/engine_default.map | 24 + test/mapping/files/engine_directmapping.map | 35 + test/mapping/files/engine_macros.map | 26 + test/mapping/files/engine_transformations.map | 47 + test/mapping/files/engine_triggers.map | 31 + test/mapping/files/fep_test.map | 21 + test/mapping/files/merge.map | 19 + test/mapping/files/nok0.map | 21 + test/mapping/files/nok1.map | 21 + test/mapping/files/nok10.map | 21 + test/mapping/files/nok11.map | 20 + test/mapping/files/nok12.map | 22 + test/mapping/files/nok13.map | 17 + test/mapping/files/nok14.map | 17 + test/mapping/files/nok15.map | 17 + test/mapping/files/nok16.map | 17 + test/mapping/files/nok17.map | 21 + test/mapping/files/nok18.map | 22 + test/mapping/files/nok19.map | 22 + test/mapping/files/nok2.map | 21 + test/mapping/files/nok20.map | 22 + test/mapping/files/nok21.map | 21 + test/mapping/files/nok22.map | 21 + test/mapping/files/nok23.map | 21 + test/mapping/files/nok24.map | 21 + test/mapping/files/nok25.map | 21 + test/mapping/files/nok26.map | 21 + test/mapping/files/nok27.map | 21 + test/mapping/files/nok28.map | 28 + test/mapping/files/nok29.map | 28 + test/mapping/files/nok3.map | 11 + test/mapping/files/nok30.map | 28 + test/mapping/files/nok31.map | 28 + test/mapping/files/nok32.map | 28 + test/mapping/files/nok33.map | 24 + test/mapping/files/nok34.map | 23 + test/mapping/files/nok35.map | 23 + test/mapping/files/nok36.map | 23 + test/mapping/files/nok37.map | 23 + test/mapping/files/nok38.map | 23 + test/mapping/files/nok39.map | 24 + test/mapping/files/nok4.map | 20 + test/mapping/files/nok40.map | 31 + test/mapping/files/nok5.map | 20 + test/mapping/files/nok6.map | 20 + test/mapping/files/nok7.map | 16 + test/mapping/files/nok8.map | 5 + test/mapping/files/nok9.map | 5 + test/mapping/files/nok_merge0.map | 15 + test/mapping/files/nok_merge1.map | 16 + test/mapping/files/nok_merge2.map | 15 + test/mapping/files/nok_merge3.map | 17 + test/mapping/files/nok_merge4.map | 19 + test/mapping/files/test.description | 132 + ..._without_lateralcontrol_signal.description | 132 + test/mapping/src/CMakeLists.txt | 17 + test/mapping/src/tester_mapping.cpp | 1605 ++++++++++ test/private/install_complete/reference.yaml | 145 + 370 files changed, 68427 insertions(+) create mode 100644 .clang-tidy create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmake/check_cmake_build_type.cmake create mode 100644 cmake/check_cmake_install_prefix.cmake create mode 100644 cmake/ddl-config.cmake.in create mode 100644 cmake/ddl4.1_replacements.txt create mode 100644 cmake/enable_multicore_compilation.cmake create mode 100644 cmake/migrate_to_ddl_4_1.cmake create mode 100644 cmake/migrate_to_ddl_4_1.sh.in create mode 100644 cmake/set_library_naming_conventions.cmake create mode 100644 cmake/use_integrated_debug_symbols.cmake create mode 100644 codec/access_element.h create mode 100644 codec/bitserializer.cpp create mode 100644 codec/bitserializer.h create mode 100644 codec/codec.cpp create mode 100644 codec/codec.h create mode 100644 codec/codec.sources create mode 100644 codec/codec_factory.cpp create mode 100644 codec/codec_factory.h create mode 100644 codec/element_accessor.cpp create mode 100644 codec/element_accessor.h create mode 100644 codec/pkg_codec.h create mode 100644 codec/static_codec.cpp create mode 100644 codec/static_codec.h create mode 100644 codec/struct_element.h create mode 100644 codec/struct_layout.cpp create mode 100644 codec/struct_layout.h create mode 100644 ddl.h create mode 100644 ddlgenerators/CMakeLists.txt create mode 100644 ddlgenerators/ddl2header/CMakeLists.txt create mode 100644 ddlgenerators/ddl2header/ddl2header_commandline.cpp create mode 100644 ddlgenerators/ddl2header/ddl2header_commandline.h create mode 100644 ddlgenerators/ddl2header/main.cpp create mode 100644 ddlgenerators/generator_library/CMakeLists.txt create mode 100644 ddlgenerators/generator_library/commandline.cpp create mode 100644 ddlgenerators/generator_library/commandline.h create mode 100644 ddlgenerators/generator_library/ddl_generator_core.cpp create mode 100644 ddlgenerators/generator_library/ddl_generator_core.h create mode 100644 ddlgenerators/generator_library/ddl_generator_lib.sources create mode 100644 ddlgenerators/generator_library/ddl_manager.cpp create mode 100644 ddlgenerators/generator_library/ddl_manager.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_base_intf.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_basic_type.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_basic_type.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_constant.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_constant.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_enum.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_enum.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_factorymethod_intf.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_header.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_header.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_importer.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_importer.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_printer.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_printer.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_struct.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_struct.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_struct_element.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_struct_element.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_type.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_type.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_typedef.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_typedef.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/header_visitor_intf.h create mode 100644 ddlgenerators/generator_library/headerrepresentation/parserhelper.cpp create mode 100644 ddlgenerators/generator_library/headerrepresentation/parserhelper.h create mode 100644 ddlgenerators/header2ddl/CMakeLists.txt create mode 100644 ddlgenerators/header2ddl/header2ddl_commandline.cpp create mode 100644 ddlgenerators/header2ddl/header2ddl_commandline.h create mode 100644 ddlgenerators/header2ddl/main.cpp create mode 100644 ddlrepresentation/ddl_common.h create mode 100644 ddlrepresentation/ddl_error.cpp create mode 100644 ddlrepresentation/ddl_error.h create mode 100644 ddlrepresentation/ddl_intf.h create mode 100644 ddlrepresentation/ddl_type.cpp create mode 100644 ddlrepresentation/ddl_type.h create mode 100644 ddlrepresentation/ddlalignment.cpp create mode 100644 ddlrepresentation/ddlalignment.h create mode 100644 ddlrepresentation/ddlbaseunit.cpp create mode 100644 ddlrepresentation/ddlbaseunit.h create mode 100644 ddlrepresentation/ddlbyteorder.cpp create mode 100644 ddlrepresentation/ddlbyteorder.h create mode 100644 ddlrepresentation/ddlcloner.cpp create mode 100644 ddlrepresentation/ddlcloner.h create mode 100644 ddlrepresentation/ddlcompare.cpp create mode 100644 ddlrepresentation/ddlcompare.h create mode 100644 ddlrepresentation/ddlcomplex.cpp create mode 100644 ddlrepresentation/ddlcomplex.h create mode 100644 ddlrepresentation/ddlcontainer.cpp create mode 100644 ddlrepresentation/ddlcontainer.h create mode 100644 ddlrepresentation/ddldatatype.cpp create mode 100644 ddlrepresentation/ddldatatype.h create mode 100644 ddlrepresentation/ddldatatype_intf.h create mode 100644 ddlrepresentation/ddldescription.cpp create mode 100644 ddlrepresentation/ddldescription.h create mode 100644 ddlrepresentation/ddlelement.cpp create mode 100644 ddlrepresentation/ddlelement.h create mode 100644 ddlrepresentation/ddlenum.cpp create mode 100644 ddlrepresentation/ddlenum.h create mode 100644 ddlrepresentation/ddlextdeclaration.cpp create mode 100644 ddlrepresentation/ddlextdeclaration.h create mode 100644 ddlrepresentation/ddlfactorymethod_intf.h create mode 100644 ddlrepresentation/ddlheader.cpp create mode 100644 ddlrepresentation/ddlheader.h create mode 100644 ddlrepresentation/ddlimporter.cpp create mode 100644 ddlrepresentation/ddlimporter.h create mode 100644 ddlrepresentation/ddlinspector.cpp create mode 100644 ddlrepresentation/ddlinspector.h create mode 100644 ddlrepresentation/ddlprefix.cpp create mode 100644 ddlrepresentation/ddlprefix.h create mode 100644 ddlrepresentation/ddlprinter.cpp create mode 100644 ddlrepresentation/ddlprinter.h create mode 100644 ddlrepresentation/ddlproperty.cpp create mode 100644 ddlrepresentation/ddlproperty.h create mode 100644 ddlrepresentation/ddlrefunit.cpp create mode 100644 ddlrepresentation/ddlrefunit.h create mode 100644 ddlrepresentation/ddlrepair.cpp create mode 100644 ddlrepresentation/ddlrepair.h create mode 100644 ddlrepresentation/ddlresolver.cpp create mode 100644 ddlrepresentation/ddlresolver.h create mode 100644 ddlrepresentation/ddlserializable_intf.h create mode 100644 ddlrepresentation/ddlstream.cpp create mode 100644 ddlrepresentation/ddlstream.h create mode 100644 ddlrepresentation/ddlstreammetatype.cpp create mode 100644 ddlrepresentation/ddlstreammetatype.h create mode 100644 ddlrepresentation/ddlstreamstruct.cpp create mode 100644 ddlrepresentation/ddlstreamstruct.h create mode 100644 ddlrepresentation/ddlunit.cpp create mode 100644 ddlrepresentation/ddlunit.h create mode 100644 ddlrepresentation/ddlunit_intf.h create mode 100644 ddlrepresentation/ddlversion.cpp create mode 100644 ddlrepresentation/ddlversion.h create mode 100644 ddlrepresentation/ddlvisitor_intf.h create mode 100644 ddlrepresentation/pkg_ddlrepresentation.h create mode 100644 ddlrepresentation/pkg_ddlrepresentation.sources create mode 100644 doc/CMakeLists.txt create mode 100644 doc/changelog.md create mode 100644 doc/input/codec.md create mode 100644 doc/input/ddl3.xsd create mode 100644 doc/input/ddl4.xsd create mode 100644 doc/input/ddl_generators.md create mode 100644 doc/input/ddl_specification.md create mode 100644 doc/input/mapping_configuration.xsd create mode 100644 doc/input/mapping_specification.md create mode 100644 doc/input/migration_4_1.md create mode 100644 doc/input/mpl.md create mode 100644 doc/input/oo-ddl.md create mode 100644 doc/input/used_licenses.md create mode 100644 doc/license/MPL2.0.txt create mode 100644 doc/run_doxygen.cmake.in create mode 100644 doc/static/ddl.html create mode 100644 legacy_error_macros.h create mode 100644 mapping/configuration/map_assignment.cpp create mode 100644 mapping/configuration/map_assignment.h create mode 100644 mapping/configuration/map_configuration.cpp create mode 100644 mapping/configuration/map_configuration.h create mode 100644 mapping/configuration/map_header.cpp create mode 100644 mapping/configuration/map_header.h create mode 100644 mapping/configuration/map_source.cpp create mode 100644 mapping/configuration/map_source.h create mode 100644 mapping/configuration/map_target.cpp create mode 100644 mapping/configuration/map_target.h create mode 100644 mapping/configuration/map_transformation.cpp create mode 100644 mapping/configuration/map_transformation.h create mode 100644 mapping/configuration/map_trigger.cpp create mode 100644 mapping/configuration/map_trigger.h create mode 100644 mapping/ddl_helper.cpp create mode 100644 mapping/ddl_helper.h create mode 100644 mapping/engine/data_trigger.cpp create mode 100644 mapping/engine/data_trigger.h create mode 100644 mapping/engine/element.cpp create mode 100644 mapping/engine/element.h create mode 100644 mapping/engine/mapping_engine.cpp create mode 100644 mapping/engine/mapping_engine.h create mode 100644 mapping/engine/mapping_environment_intf.h create mode 100644 mapping/engine/periodic_trigger.cpp create mode 100644 mapping/engine/periodic_trigger.h create mode 100644 mapping/engine/signal_trigger.cpp create mode 100644 mapping/engine/signal_trigger.h create mode 100644 mapping/engine/source.cpp create mode 100644 mapping/engine/source.h create mode 100644 mapping/engine/target.cpp create mode 100644 mapping/engine/target.h create mode 100644 mapping/engine/trigger.cpp create mode 100644 mapping/engine/trigger.h create mode 100644 mapping/mapping.sources create mode 100644 mapping/pkg_mapping.h create mode 100644 serialization/pkg_serialization.h create mode 100644 serialization/serialization.cpp create mode 100644 serialization/serialization.h create mode 100644 serialization/serialization.sources create mode 100644 test/CMakeLists.txt create mode 100644 test/README.md create mode 100644 test/_common/CMakeLists.txt create mode 100644 test/_common/adtf_compat.h create mode 100644 test/_common/compat.h create mode 100644 test/_doc/ddl_test.html create mode 100644 test/codec/files/hca.description create mode 100644 test/codec/src/CMakeLists.txt create mode 100644 test/codec/src/tester_bitserializer.cpp create mode 100644 test/codec/src/tester_codec.cpp create mode 100644 test/codec/src/tester_mediacoder_regression.cpp create mode 100644 test/ddlgenerators/files/expected_files/expected_result_datatype.h create mode 100644 test/ddlgenerators/files/expected_files/expected_result_existing_all.description create mode 100644 test/ddlgenerators/files/expected_files/expected_result_existing_all.h create mode 100644 test/ddlgenerators/files/expected_files/expected_result_existing_struct.description create mode 100644 test/ddlgenerators/files/expected_files/expected_result_existing_struct.h create mode 100644 test/ddlgenerators/files/expected_files/expected_result_newfile_all.description create mode 100644 test/ddlgenerators/files/expected_files/expected_result_newfile_all.h create mode 100644 test/ddlgenerators/files/expected_files/expected_result_newfile_struct.description create mode 100644 test/ddlgenerators/files/expected_files/expected_result_newfile_struct.h create mode 100644 test/ddlgenerators/files/original_files/base_all.description create mode 100644 test/ddlgenerators/files/original_files/base_all.h create mode 100644 test/ddlgenerators/files/original_files/enums.description create mode 100644 test/ddlgenerators/files/original_files/enums.h create mode 100644 test/ddlgenerators/src/CMakeLists.txt create mode 100644 test/ddlgenerators/src/tester_ddl_generators.cpp create mode 100644 test/ddlinspector/files/ArrayZero.description create mode 100644 test/ddlinspector/files/DynArraySize.description create mode 100644 test/ddlinspector/files/NestedCaps.description create mode 100644 test/ddlinspector/files/NestedNaming.description create mode 100644 test/ddlinspector/files/StructElementNaming.description create mode 100644 test/ddlinspector/files/StructNaming.description create mode 100644 test/ddlinspector/files/UnitNaming.description create mode 100644 test/ddlinspector/files/base_all2.description create mode 100644 test/ddlinspector/files/base_all_duplicates.description create mode 100644 test/ddlinspector/files/invalid_duplicate.description create mode 100644 test/ddlinspector/src/CMakeLists.txt create mode 100644 test/ddlinspector/src/tester_ddlinspector.cpp create mode 100644 test/ddlrepresentation/files/adtf.description create mode 100644 test/ddlrepresentation/files/adtf1.description create mode 100644 test/ddlrepresentation/files/adtf2.xml create mode 100644 test/ddlrepresentation/files/adtf_1_02.description create mode 100644 test/ddlrepresentation/files/adtf_1_0p.description create mode 100644 test/ddlrepresentation/files/adtf_1_0p_out_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_1_0p_resolved_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_changed_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_dynamic.description create mode 100644 test/ddlrepresentation/files/adtf_merged_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_merged_ovrwrt_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_min_max_default.description create mode 100644 test/ddlrepresentation/files/adtf_out_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_recursion.description create mode 100644 test/ddlrepresentation/files/adtf_resolved_expected.xml create mode 100644 test/ddlrepresentation/files/adtf_v40.description create mode 100644 test/ddlrepresentation/files/fep_driver.description create mode 100644 test/ddlrepresentation/files/force_version_ddl-2.0.description create mode 100644 test/ddlrepresentation/files/force_version_ddl-2.0_to_3.0_expected.description create mode 100644 test/ddlrepresentation/files/force_version_ddl-3.0.description create mode 100644 test/ddlrepresentation/files/invalid_numbits_attribute.description create mode 100644 test/ddlrepresentation/files/no_structs.description create mode 100644 test/ddlrepresentation/files/partial_expected.description create mode 100644 test/ddlrepresentation/files/printer.description create mode 100644 test/ddlrepresentation/files/test_insert.description create mode 100644 test/ddlrepresentation/files/test_insert_results.description create mode 100644 test/ddlrepresentation/files/test_insert_results_ref.description create mode 100644 test/ddlrepresentation/files/unresolved_datatype.description create mode 100644 test/ddlrepresentation/src/CMakeLists.txt create mode 100644 test/ddlrepresentation/src/ddl_definitions.h create mode 100644 test/ddlrepresentation/src/tester_ddlrepresentation.cpp create mode 100644 test/function/api/src/CMakeLists.txt create mode 100644 test/function/api/src/test_fixture_ddl_types.h create mode 100644 test/function/api/src/tester_ddl_types.cpp create mode 100644 test/headerrepresentation/files/adtf2.description create mode 100644 test/headerrepresentation/files/adtf_expected.h create mode 100644 test/headerrepresentation/files/array_header.h create mode 100644 test/headerrepresentation/files/array_header_expected.description create mode 100644 test/headerrepresentation/files/array_header_expected.h create mode 100644 test/headerrepresentation/files/commented_header.h create mode 100644 test/headerrepresentation/files/complex_header.h create mode 100644 test/headerrepresentation/files/complex_header_expected.description create mode 100644 test/headerrepresentation/files/complex_header_expected.h create mode 100644 test/headerrepresentation/files/complex_struct2_expected.description create mode 100644 test/headerrepresentation/files/constants_header.h create mode 100644 test/headerrepresentation/files/default_types_header.h create mode 100644 test/headerrepresentation/files/defines_header.h create mode 100644 test/headerrepresentation/files/faulty_header1.h create mode 100644 test/headerrepresentation/files/faulty_header2.h create mode 100644 test/headerrepresentation/files/faulty_header3.h create mode 100644 test/headerrepresentation/files/faulty_header4.h create mode 100644 test/headerrepresentation/files/faulty_header5.h create mode 100644 test/headerrepresentation/files/packing_header.h create mode 100644 test/headerrepresentation/files/packing_header_expected.description create mode 100644 test/headerrepresentation/files/packing_header_expected.h create mode 100644 test/headerrepresentation/files/simple_header.h create mode 100644 test/headerrepresentation/files/simple_header_expected.description create mode 100644 test/headerrepresentation/files/simple_header_expected.h create mode 100644 test/headerrepresentation/files/simple_header_result.description create mode 100644 test/headerrepresentation/files/typedef_header.h create mode 100644 test/headerrepresentation/files/typedef_header_expected.h create mode 100644 test/headerrepresentation/files/viRDBIcd.description create mode 100644 test/headerrepresentation/files/viRDBIcd.h create mode 100644 test/headerrepresentation/files/viRDBIcd_expected.description create mode 100644 test/headerrepresentation/files/viRDBIcd_expected.h create mode 100644 test/headerrepresentation/files/viRDBIcd_extract_expected.description create mode 100644 test/headerrepresentation/files/viRDBIcd_extract_expected.h create mode 100644 test/headerrepresentation/files/wrong_header.h create mode 100644 test/headerrepresentation/src/CMakeLists.txt create mode 100644 test/headerrepresentation/src/ddl_definitions.h create mode 100644 test/headerrepresentation/src/tester_headerrepresentation.cpp create mode 100644 test/mapping/files/base.map create mode 100644 test/mapping/files/benchmark.description create mode 100644 test/mapping/files/benchmark.map create mode 100644 test/mapping/files/benchmark2.map create mode 100644 test/mapping/files/engine.description create mode 100644 test/mapping/files/engine.map create mode 100644 test/mapping/files/engine_default.map create mode 100644 test/mapping/files/engine_directmapping.map create mode 100644 test/mapping/files/engine_macros.map create mode 100644 test/mapping/files/engine_transformations.map create mode 100644 test/mapping/files/engine_triggers.map create mode 100644 test/mapping/files/fep_test.map create mode 100644 test/mapping/files/merge.map create mode 100644 test/mapping/files/nok0.map create mode 100644 test/mapping/files/nok1.map create mode 100644 test/mapping/files/nok10.map create mode 100644 test/mapping/files/nok11.map create mode 100644 test/mapping/files/nok12.map create mode 100644 test/mapping/files/nok13.map create mode 100644 test/mapping/files/nok14.map create mode 100644 test/mapping/files/nok15.map create mode 100644 test/mapping/files/nok16.map create mode 100644 test/mapping/files/nok17.map create mode 100644 test/mapping/files/nok18.map create mode 100644 test/mapping/files/nok19.map create mode 100644 test/mapping/files/nok2.map create mode 100644 test/mapping/files/nok20.map create mode 100644 test/mapping/files/nok21.map create mode 100644 test/mapping/files/nok22.map create mode 100644 test/mapping/files/nok23.map create mode 100644 test/mapping/files/nok24.map create mode 100644 test/mapping/files/nok25.map create mode 100644 test/mapping/files/nok26.map create mode 100644 test/mapping/files/nok27.map create mode 100644 test/mapping/files/nok28.map create mode 100644 test/mapping/files/nok29.map create mode 100644 test/mapping/files/nok3.map create mode 100644 test/mapping/files/nok30.map create mode 100644 test/mapping/files/nok31.map create mode 100644 test/mapping/files/nok32.map create mode 100644 test/mapping/files/nok33.map create mode 100644 test/mapping/files/nok34.map create mode 100644 test/mapping/files/nok35.map create mode 100644 test/mapping/files/nok36.map create mode 100644 test/mapping/files/nok37.map create mode 100644 test/mapping/files/nok38.map create mode 100644 test/mapping/files/nok39.map create mode 100644 test/mapping/files/nok4.map create mode 100644 test/mapping/files/nok40.map create mode 100644 test/mapping/files/nok5.map create mode 100644 test/mapping/files/nok6.map create mode 100644 test/mapping/files/nok7.map create mode 100644 test/mapping/files/nok8.map create mode 100644 test/mapping/files/nok9.map create mode 100644 test/mapping/files/nok_merge0.map create mode 100644 test/mapping/files/nok_merge1.map create mode 100644 test/mapping/files/nok_merge2.map create mode 100644 test/mapping/files/nok_merge3.map create mode 100644 test/mapping/files/nok_merge4.map create mode 100644 test/mapping/files/test.description create mode 100644 test/mapping/files/test_without_lateralcontrol_signal.description create mode 100644 test/mapping/src/CMakeLists.txt create mode 100644 test/mapping/src/tester_mapping.cpp create mode 100644 test/private/install_complete/reference.yaml diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..b8d011f --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,65 @@ +Checks: '-*,readability-identifier-naming,readability-braces-around-statements' +WarningsAsErrors: 'readability-identifier-naming*,readability-braces-around-statements*' +HeaderFilterRegex: '.*' +CheckOptions: + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.InlineNamespaceCase, value: lower_case } + + - { key: readability-identifier-naming.EnumConstantCase, value: lower_case } + - { key: readability-identifier-naming.ConstexprVariableCase, value: lower_case } + - { key: readability-identifier-naming.ConstantMemberCase, value: lower_case } + - { key: readability-identifier-naming.PrivateMemberCase, value: lower_case } + - { key: readability-identifier-naming.PrivateMemberPrefix, value: '_'} + - { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case } + - { key: readability-identifier-naming.ProtectedMemberPrefix, value: '_'} + - { key: readability-identifier-naming.PublicMemberCase, value: lower_case } + - { key: readability-identifier-naming.PublicMemberPrefix, value: ''} + - { key: readability-identifier-naming.MemberCase, value: lower_case } + + - { key: readability-identifier-naming.ClassConstantCase, value: lower_case } + - { key: readability-identifier-naming.ClassMemberCase, value: lower_case } + - { key: readability-identifier-naming.GlobalConstantCase, value: lower_case } + - { key: readability-identifier-naming.GlobalVariableCase, value: lower_case } + + - { key: readability-identifier-naming.LocalConstantCase, value: lower_case } + - { key: readability-identifier-naming.LocalVariableCase, value: lower_case } + + - { key: readability-identifier-naming.StaticConstantCase, value: lower_case } + - { key: readability-identifier-naming.StaticVariableCase, value: lower_case } + - { key: readability-identifier-naming.ConstantCase, value: lower_case } + - { key: readability-identifier-naming.VariableCase, value: lower_case } + - { key: readability-identifier-naming.ConstantParameterCase, value: lower_case } + - { key: readability-identifier-naming.ParameterPackCase, value: lower_case } + - { key: readability-identifier-naming.ParameterCase, value: lower_case } + - { key: readability-identifier-naming.AbstractClassCase, value: lower_case } + + - { key: readability-identifier-naming.StructCase, value: CamelCase } + + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.AbstractClassCase, value: CamelCase } + + - { key: readability-identifier-naming.UnionCase, value: CamelCase } # not specified + - { key: readability-identifier-naming.EnumCase, value: CamelCase } + + - { key: readability-identifier-naming.GlobalFunctionCase, value: camelCase } + - { key: readability-identifier-naming.ConstexprFunctionCase, value: camelCase } + - { key: readability-identifier-naming.FunctionCase, value: camelCase } + - { key: readability-identifier-naming.ConstexprMethodCase, value: camelCase } + - { key: readability-identifier-naming.VirtualMethodCase, value: camelCase } + - { key: readability-identifier-naming.ClassMethodCase, value: camelCase } + - { key: readability-identifier-naming.PrivateMethodCase, value: camelCase } + - { key: readability-identifier-naming.ProtectedMethodCase, value: camelCase } + - { key: readability-identifier-naming.PublicMethodCase, value: camelCase } + - { key: readability-identifier-naming.MethodCase, value: camelCase } + + - { key: readability-identifier-naming.TypedefCase, value: CamelCase } + - { key: readability-identifier-naming.UsingCase, value: CamelCase } # not specified + - { key: readability-identifier-naming.TypeAliasCase, value: CamelCase } # overrides using case + + + - { key: readability-identifier-naming.TypeTemplateParameterCase, value: UPPER_CASE } + - { key: readability-identifier-naming.ValueTemplateParameterCase, value: lower_case } + - { key: readability-identifier-naming.TemplateTemplateParameterCase, value: UPPER_CASE } + - { key: readability-identifier-naming.TemplateParameterCase, value: UPPER_CASE } + - { key: readability-identifier-naming.TypeAliasCase, value: CamelCase } # overrides using case + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ecd699a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,144 @@ +cmake_minimum_required(VERSION 3.8.2) # cxx_std_11 +project(ddl_library VERSION 4.4.0) + +# Disable extensions here and require the chosen CMAKE_CXX_STANDARD +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 11) + +# if Conan is used, we have to include the generated file and doing some basic setup +if(CONAN_COMPILER) + if ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo_multi.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo_multi.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo_multi.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo_multi.cmake) + else() + message(FATAL_ERROR "Conan build info can't be found.") + endif() + + if(CORTEX_WORKSPACE) + conan_basic_setup(TARGETS) + else() + conan_basic_setup(TARGETS NO_OUTPUT_DIRS) + endif() +endif() + +# Options ################################################# +option(ddl_cmake_enable_tests + "Enable tests - requires googletest (default: OFF)" + OFF) + +option(ddl_cmake_enable_installation + "Enable installation of the ddl library to CMAKE_INSTALL_PREFIX (default: OFF)" + OFF) + +option(ddl_cmake_enable_ddl_generator_tools + "Enable building of the two tools ddl2header and header2ddl (default: OFF)" + OFF) +# End Options ############################################# + +# Disable extensions here and require the chosen CMAKE_CXX_STANDARD (coming from e.g. Conan) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Check for default install prefix and cmake build type (UNIX) +include(./cmake/check_cmake_install_prefix.cmake) +include(./cmake/check_cmake_build_type.cmake) + +# Enable multicore compilation on Windows +include(./cmake/enable_multicore_compilation.cmake) + +# Use integrated debug symbols on Windows (avoiding PDBs) +include(./cmake/use_integrated_debug_symbols.cmake) + +# Set library name conventions +include(./cmake/set_library_naming_conventions.cmake) + +# Enable folders +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +# Add a_util dependency +find_package(a_util 5.4 REQUIRED) + +# Include sources +include(./ddlrepresentation/pkg_ddlrepresentation.sources) +include(./codec/codec.sources) +include(./serialization/serialization.sources) +include(./mapping/mapping.sources) + +add_library(ddl STATIC + ${DDLREPRESENTATION_CPP} + ${CODEC_CPP} + ${SERIALIZATION_CPP} + ${MAPPING_CPP} + + ${DDLREPRESENTATION_H} + ${CODEC_H} + ${SERIALIZATION_H} + ${MAPPING_CONFIGURATION_H} + ${MAPPING_ENGINE_H} + ${MAPPING_H} + ddl.h + legacy_error_macros.h +) +set_target_properties(ddl PROPERTIES FOLDER ddl) + +target_include_directories(ddl PUBLIC + $ + $ +) + +# a_util is public since its part of the ddl api +target_link_libraries(ddl PUBLIC a_util) +target_compile_features(ddl INTERFACE cxx_std_11) # C++11 for self and dependants +target_compile_options(ddl PRIVATE $<$:-fPIC>) + +# Create version config +include(CMakePackageConfigHelpers) +write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/cmake/ddl-config-version.cmake + COMPATIBILITY AnyNewerVersion) + +configure_file(cmake/ddl-config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/ddl/ddlConfig.cmake" +) + +if(ddl_cmake_enable_tests) + set(ddl_cmake_integrated_tests ON) + enable_testing() + add_subdirectory(test) +endif() + +add_subdirectory(ddlgenerators) + +if(ddl_cmake_enable_installation) + install(TARGETS ddl ARCHIVE DESTINATION lib) + + install(FILES ${DDLREPRESENTATION_INSTALL} DESTINATION include/${DDLREPRESENTATION_DIR}) + install(FILES ${CODEC_INSTALL} DESTINATION include/${CODEC_DIR}) + install(FILES ${SERIALIZATION_INSTALL} DESTINATION include/${SERIALIZATION_DIR}) + install(FILES ${MAPPING_CONFIGURATION_INSTALL} DESTINATION include/${MAPPING_DIR}/configuration) + install(FILES ${MAPPING_ENGINE_INSTALL} DESTINATION include/${MAPPING_DIR}/engine) + install(FILES ${MAPPING_INSTALL} DESTINATION include/${MAPPING_DIR}) + install(FILES ddl.h legacy_error_macros.h DESTINATION include) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/ddl-config-version.cmake DESTINATION cmake) + configure_file(cmake/ddl-config.cmake.in ${CMAKE_INSTALL_PREFIX}/cmake/ddl-config.cmake @ONLY) + install(FILES cmake/migrate_to_ddl_4_1.cmake cmake/ddl4.1_replacements.txt cmake/migrate_to_ddl_4_1.sh.in DESTINATION cmake) + install(FILES README.md DESTINATION .) +else() + # This allows a host product to use find_package from within the build-tree + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cmake/ddl-config.cmake "") +endif() +##this enables a post-install command, so this must be "Last Dir Standing"!!! +add_subdirectory(doc) + +# License Information must be delivered anyway! +install(FILES doc/license/MPL2.0.txt DESTINATION ./) +install(FILES doc/license/MPL2.0.txt DESTINATION doc/license) +install(FILES doc/input/used_licenses.md DESTINATION doc/license) +install(FILES doc/input/mpl.md DESTINATION doc/license) + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bec7bef --- /dev/null +++ b/LICENSE @@ -0,0 +1,376 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + + means + + a. that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + b. any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +### 2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +b. under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +### 2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +### 2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +a. for any code that a Contributor has removed from Covered Software; + or + +b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +### 2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +### 2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +### 2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +### 2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +### 3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +### 3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +a. such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +### 3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +### 3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +### 3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under +Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +6. Disclaimer of Warranty +------------------------- + +*Covered Software is provided under this License on an "as is" basis, +without warranty of any kind, either expressed, implied, or statutory, +including, without limitation, warranties that the Covered Software is +free of defects, merchantable, fit for a particular purpose or +non-infringing. The entire risk as to the quality and performance of the +Covered Software is with You. Should any Covered Software prove +defective in any respect, You (not any Contributor) assume the cost of +any necessary servicing, repair, or correction. This disclaimer of +warranty constitutes an essential part of this License. No use of any +Covered Software is authorized under this License except under this +disclaimer.* + +7. Limitation of Liability +-------------------------- + +*Under no circumstances and under no legal theory, whether tort +(including negligence), contract, or otherwise, shall any Contributor, +or anyone who distributes Covered Software as permitted above, be liable +to You for any direct, indirect, special, incidental, or consequential +damages of any character including, without limitation, damages for lost +profits, loss of goodwill, work stoppage, computer failure or +malfunction, or any and all other commercial damages or losses, even if +such party shall have been informed of the possibility of such damages. +This limitation of liability shall not apply to liability for death or +personal injury resulting from such party's negligence to the extent +applicable law prohibits such limitation. Some jurisdictions do not +allow the exclusion or limitation of incidental or consequential +damages, so this exclusion and limitation may not apply to You.* + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +### 10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in +Section 10.3, no one other than the license steward has the right to +modify or publish new versions of this License. Each version will be +given a distinguishing version number. + +### 10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +### 10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + +> This Source Code Form is subject to the terms of the Mozilla Public +> License, v. 2.0. If a copy of the MPL was not distributed with this +> file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + +> This Source Code Form is "Incompatible With Secondary Licenses", as +> defined by the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8413152 --- /dev/null +++ b/README.md @@ -0,0 +1,198 @@ +# DDL Library {#mainpage} + + +# Description + +The Data Defintion Language (DDL) Package provides utilities to handle data descriptions and data defined by these descriptions. + + #include + +* [DDL specification](doc/input/ddl_specification.md) ([link](@ref page_ddl_specification)) + + + + +_____________________ + +# DDL Library Parts + +This library contains following internal parts: + +## OO DDL + +A Memory Model for the DDL Language. + +* See [OO DDL Documentation](doc/input/oo-ddl.md) ([link](@ref page_oo_ddl)) + + ddlrepresentation/pkg_ddlrepresentation.h + + +## Codec API + +Access, decode and encode ddl described memory data. + +* See [Codec Documentation](doc/input/codec.md) ([link](@ref page_codec)) + + codec/pkg_codec.h + + +## DDL-2-header and header-2-DDL generation + +Generating a c-header file from DDL and vice versa. + +* See [DDL Generators](doc/input/ddl_generators.md)([link](@ref page_ddl_generators)) + + ddlgenerators/generatorlibrary + ddlgenerators/ddl2header + ddlgenerators/header2ddl + +## Mapping Functionality + +Map data from one DDL structure to another + +* See [Mapping specification](doc/input/mapping_specification.md)([link](@ref page_signal_mapping_spec)) + + mapping/pkg_mapping.h + +## DDL 4.1 migration process + +DDL version 4.1.0 introduced an updated coding style which led to changes in all APIs. + +* A migration guide is available at [Migration to 4.1](doc/input/migration_4_1.md) ([link](@ref page_migration_4_1)) + +________________________ + +# License Information + +This library is provided under [MPL 2.0](doc/input/mpl.md)([link](@ref page_mpl)). +Have also a look at doc/licence for all license information. + +See also [used licenses](doc/input/used_licenses.md)([link](@ref page_used_licenses)) for licenses of integrated libraries. + +________________________ + +# Change Log + +For change history have a look at [Change Log](doc/changelog.md)([link](@ref page_changelog)) +________________________ + +# Dependencies + +## a_util library + +The libraries above depend on the *a_util library* +See a_util repository at https://github.com/AEV + +## How to build + +### Build Environment + +The libraries are build and tested only under following compilers and operating systems: + +#### Windows 7 64 Bit + +* Visual Studio C++ 2015 Update 3.1 (Update 3 and KB3165756) + +#### Linux Ubuntu 16.04 LTS + +* On other distributions make at least sure that libc has version >= 2.23 and libstdc++ >= 6.0.21. +* gcc 5.4 + +### How to build + +If you can not reach the above online repositories the bundle of it is delivered within a separate download area or installation. +See [Delivered repository versions](@ref page_delivered_versions). + +#### Build a_util first + +The ADTF File Library will only build if a installation of a_utils library is provided. +Following libraries of the a_utils are necessary: +* a_util_concurrency +* a_util_memory +* a_util_regex +* a_util_strings +* a_util_datetime +* a_util_filesystem +* a_util_xml + +- Use CMAKE at least in version 3.5.1. +- Use the Release Branch \p "Release/a_util-version-branch" see [Delivered repository versions](@ref page_delivered_versions) +- Use CMakeLists.txt within the main directory as Source Directory +- Do not forget to set a CMAKE_INSTALL_PREFIX +- Build and install for Debug and Release + +#### Build ddl library + +- Use CMAKE at least in version 3.5.1. +- Use the Release Branch \p "Release/ddl-version-branch". see [Delivered repository versions](@ref page_delivered_versions) +- Use CMakeLists.txt within the main directory as Source Directory +- Do not forget to set a CMAKE_INSTALL_PREFIX +- Build and install for Debug and Release + +##### Cmake options and dependencies + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+a_util_DIR + +must be set to *a_util_install*/lib/cmake/a_util + +See a_util repository at https://github.com/AEV +
+ddl_cmake_enable_documentation ON/OFF + +choose wether a documentation is created or not + +dependency to a valid doxygen executable needed (see http://www.doxygen.nl/) +
+ddl_cmake_enable_tests ON/OFF + +choose wether the tests where build while building the libraries or not + +dependency to a valid gtest package needed (see https://github.com/google/googletest) +
+ddl_cmake_enable_generator_tools ON/OFF + +choose wether the tools must be build too + +
+ddl_cmake_enable_installation ON/OFF + +choose wether the tools must be build too + +
+ + + + + + + + + + \ No newline at end of file diff --git a/cmake/check_cmake_build_type.cmake b/cmake/check_cmake_build_type.cmake new file mode 100644 index 0000000..e925ec9 --- /dev/null +++ b/cmake/check_cmake_build_type.cmake @@ -0,0 +1,12 @@ +## Check build type and terminate cmake if none is given +if(UNIX) + if(NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";Debug;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";Release;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";RelWithDebInfo;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";MinSizeRel;") + message(FATAL_ERROR "'CMAKE_BUILD_TYPE' is either empty or set to an unknown build type") + endif(NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";Debug;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";Release;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";RelWithDebInfo;" AND + NOT ";${CMAKE_BUILD_TYPE};" STREQUAL ";MinSizeRel;") +endif(UNIX) diff --git a/cmake/check_cmake_install_prefix.cmake b/cmake/check_cmake_install_prefix.cmake new file mode 100644 index 0000000..fcb64bc --- /dev/null +++ b/cmake/check_cmake_install_prefix.cmake @@ -0,0 +1,20 @@ +## This must always be the first check when running cmake + +set(CURRENT_OPTION "ddl_cmake_enable_warn_on_default_cmake_install_prefix") +option(${CURRENT_OPTION} "Warn if 'CMAKE_INSTALL_PREFIX is set to default (default: ON)" ON) + +if(${CURRENT_OPTION}) + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR + ";${util_cmake_CMAKE_DEFAULT_INSTALL_PREFIX};" STREQUAL ";${CMAKE_INSTALL_PREFIX};") + message(WARNING "'CMAKE_INSTALL_PREFIX' is currently set to the default value. Suppress \ +this check by disabling '${CURRENT_OPTION}'") + + ## Enable warning for more than just the first run of cmake + set(util_cmake_CMAKE_DEFAULT_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE INTERNAL "") + else() + unset(util_cmake_CMAKE_DEFAULT_INSTALL_PREFIX) + endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR + ";${util_cmake_CMAKE_DEFAULT_INSTALL_PREFIX};" STREQUAL ";${CMAKE_INSTALL_PREFIX};") +endif(${CURRENT_OPTION}) + +unset(CURRENT_OPTION) diff --git a/cmake/ddl-config.cmake.in b/cmake/ddl-config.cmake.in new file mode 100644 index 0000000..95a4ba3 --- /dev/null +++ b/cmake/ddl-config.cmake.in @@ -0,0 +1,45 @@ +if(ddl_FOUND) + return() +endif() + +# Compute the installation prefix relative to this file. +get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) +get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) +if(_IMPORT_PREFIX STREQUAL "/") + set(_IMPORT_PREFIX "") +endif() + +# Add imported library target +add_library(ddl STATIC IMPORTED) + +if (WIN32) + set(_LIB_PREFIX "") + set(_LIB_ENDING "lib") +else() + set(_LIB_PREFIX "lib") + set(_LIB_ENDING "a") +endif() + +set_target_properties(ddl PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + INTERFACE_LINK_LIBRARIES "a_util" + INTERFACE_COMPILE_FEATURES "cxx_std_11" + + IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${_LIB_PREFIX}ddl@CMAKE_DEBUG_POSTFIX@.${_LIB_ENDING}" + IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${_LIB_PREFIX}ddl@CMAKE_RELEASE_POSTFIX@.${_LIB_ENDING}" + IMPORTED_LOCATION_RELWITHDEBINFO "${_IMPORT_PREFIX}/lib/${_LIB_PREFIX}ddl@CMAKE_RELWITHDEBINFO_POSTFIX@.${_LIB_ENDING}" + IMPORTED_LOCATION_MINSIZEREL "${_IMPORT_PREFIX}/lib/${_LIB_PREFIX}ddl@CMAKE_MINSIZEREL_POSTFIX@.${_LIB_ENDING}" +) + +set(ddl_INCLUDE_DIRS ${_IMPORT_PREFIX}/include) +set(ddl_LIBRARY_DIRS ${_IMPORT_PREFIX}/lib) +set(ddl_BINARY_DIRS ${_IMPORT_PREFIX}/bin) + +# Cleanup temporary variables. +unset(_LIB_ENDING) +unset(_IMPORT_PREFIX) + + +include("${CMAKE_CURRENT_LIST_DIR}/migrate_to_ddl_4_1.cmake") + +set(ddl_FOUND true) diff --git a/cmake/ddl4.1_replacements.txt b/cmake/ddl4.1_replacements.txt new file mode 100644 index 0000000..7337692 --- /dev/null +++ b/cmake/ddl4.1_replacements.txt @@ -0,0 +1,132 @@ +cBitSerializer;BitSerializer +cCodec;Codec +cCodecFactory;CodecFactory +cDDL;DDL +cDDLAlignment;DDLAlignment +cDDLAutoVec;DDLAutoVec +cDDLBaseunit;DDLBaseunit +cDDLByteorder;DDLByteorder +cDDLCloner;DDLCloner +cDDLComplex;DDLComplex +cDDLContainer;DDLContainer +cDDLContainerNoClone;DDLContainerNoClone +cDDLDataType;DDLDataType +cDDLDescription;DDLDescription +cDDLElement;DDLElement +cDDLEnum;DDLEnum +cDDLError;DDLError +cDDLExtDeclaration;DDLExtDeclaration +cDDLHeader;DDLHeader +cDDLHelper;DDLHelper +cDDLImporter;DDLImporter +cDDLInspector;DDLInspector +cDDLPrefix;DDLPrefix +cDDLPrinter;DDLPrinter +cDDLProperty;DDLProperty +cDDLRefUnit;DDLRefUnit +cDDLRepair;DDLRepair +cDDLResolver;DDLResolver +cDDLStream;DDLStream +cDDLStreamMetaType;DDLStreamMetaType +cDDLStreamStruct;DDLStreamStruct +cDDLUnit;DDLUnit +cDDLVersionHelper;DDLVersionHelper +cDataTrigger;DataTrigger +cDecoder;Decoder +cElementAccessor;ElementAccessor +cMapAssignment;MapAssignment +cMapConfiguration;MapConfiguration +cMapDataTrigger;MapDataTrigger +cMapEnumTableTransformation;MapEnumTableTransformation +cMapHeader;MapHeader +cMapPeriodicTrigger;MapPeriodicTrigger +cMapPolynomTransformation;MapPolynomTransformation +cMapSignalTrigger;MapSignalTrigger +cMapSource;MapSource +cMapTarget;MapTarget +cMapTransformationBase;MapTransformationBase +cMapTriggerBase;MapTriggerBase +cMappingEngine;MappingEngine +cPeriodicTrigger;PeriodicTrigger +cSignalTrigger;SignalTrigger +cSource;Source +cStaticCodec;StaticCodec +cStaticDecoder;StaticDecoder +cStructLayout;StructLayout +cTarget;Target +cTargetElement;TargetElement +cTriggerBase;TriggerBase +eByteorder;Byteorder +eDDLAlignment;DDLAlignment +eImporterMsgSeverity;ImporterMsgSeverity +sImporterMsg;ImporterMsg +tAssignments;Assignments +tConstants;Constants +tDDLBaseunitIt;DDLBaseunitIt +tDDLBaseunitVec;DDLBaseunitVec +tDDLComplexIt;DDLComplexIt +tDDLComplexVec;DDLComplexVec +tDDLDTIt;DDLDTIt +tDDLDTVec;DDLDTVec +tDDLElementIt;DDLElementIt +tDDLElementItConst;DDLElementItConst +tDDLElementVec;DDLElementVec +tDDLEnumIt;DDLEnumIt +tDDLEnumVec;DDLEnumVec +tDDLExtDeclarationIt;DDLExtDeclarationIt +tDDLExtDeclarationVec;DDLExtDeclarationVec +tDDLPrefixIt;DDLPrefixIt +tDDLPrefixVec;DDLPrefixVec +tDDLPropertyVec;DDLPropertyVec +tDDLRefUnitIt;DDLRefUnitIt +tDDLRefUnitVec;DDLRefUnitVec +tDDLStreamIt;DDLStreamIt +tDDLStreamMap;DDLStreamMap +tDDLStreamMapIt;DDLStreamMapIt +tDDLStreamMetaTypeVec;DDLStreamMetaTypeVec +tDDLStreamStructIt;DDLStreamStructIt +tDDLStreamStructVec;DDLStreamStructVec +tDDLStreamVec;DDLStreamVec +tDDLUnitIt;DDLUnitIt +tDDLUnitVec;DDLUnitVec +tDDLVec;DDLVec +tDataRepresentation;DataRepresentation +tDescriptionCheckFlags;DescriptionCheckFlags +tDynamicStructLayoutElement;DynamicStructLayoutElement +tEnumNameValueVec;EnumNameValueVec +tImporterMsgList;ImporterMsgList +tItemCheckFlags;ItemCheckFlags +tMapAssignmentList;MapAssignmentList +tMapConfigFlags;MapConfigFlags +tMapErrorList;MapErrorList +tMapSourceList;MapSourceList +tMapSourceNameList;MapSourceNameList +tMapStrConversionList;MapStrConversionList +tMapTargetList;MapTargetList +tMapTransformationList;MapTransformationList +tMapTriggerList;MapTriggerList +tMemoryBuffer;MemoryBuffer +tMemoryBuffer;MemoryBuffer +tSourceMap;SourceMap +tTargetElementList;TargetElementList +tTargetMap;TargetMap +tTargetRefList;TargetRefList +tTargetSet;TargetSet +tTriggerCounters;TriggerCounters +tTriggerMap;TriggerMap +tTriggers;Triggers +tTypeMap;TypeMap +DestroyDDL;destroyDDL +PLATFORM_NOT_SUPPORTED;platform_not_supported +PLATFORM_LITTLE_ENDIAN_8;plattform_little_endian_8 +PLATFORM_BIG_ENDIAN_8;platform_big_endian_8 +eNOE;e_noe +eLE;e_le +eBE;e_be +eSeverity;severity +strDesc;desc +eImporterInfo;importer_info +eImporterWarning;importer_warning +eImporterError;importer_error +MC_LOAD_MAPPING;mc_load_mapping +MC_MERGE_MAPPING;mc_merge_mapping diff --git a/cmake/enable_multicore_compilation.cmake b/cmake/enable_multicore_compilation.cmake new file mode 100644 index 0000000..aac6400 --- /dev/null +++ b/cmake/enable_multicore_compilation.cmake @@ -0,0 +1,5 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # enable multicore compilation + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") +endif() diff --git a/cmake/migrate_to_ddl_4_1.cmake b/cmake/migrate_to_ddl_4_1.cmake new file mode 100644 index 0000000..23061c6 --- /dev/null +++ b/cmake/migrate_to_ddl_4_1.cmake @@ -0,0 +1,50 @@ +function(ddl_migrate_4_1) + set(options "") + set(oneValueArgs TARGET) + set(multiValueArgs "") + cmake_parse_arguments(CLANG_TIDY "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + get_target_property(inc_dirs ${CLANG_TIDY_TARGET} INCLUDE_DIRECTORIES) + get_target_property(target_sources ${CLANG_TIDY_TARGET} SOURCES) + get_target_property(target_folder ${CLANG_TIDY_TARGET} FOLDER) + get_target_property(link_libs ${CLANG_TIDY_TARGET} LINK_LIBRARIES) + + foreach(lib ${link_libs}) + get_target_property(lib_inc_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) + if(lib_inc_dirs) + list(APPEND inc_dirs ${lib_inc_dirs}) + endif() + endforeach(lib) + + foreach(inc ${inc_dirs}) + list(APPEND inc_list -isystem${inc}) + endforeach(inc) + + # filter headers that are included in sources + list(FILTER target_sources INCLUDE REGEX ".*\.cpp$") + + set(TIDY_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/run-clang-tidy-fix-${CLANG_TIDY_TARGET}.sh) + + string (REPLACE ";" " " target_sources_spaces "${target_sources}") + string (REPLACE ";" " " inc_list_spaces "${inc_list}") + + string (CONCAT TIDY_STRING + "${CONAN_BIN_DIRS_CLANG}/clang-tidy " + " ${target_sources_spaces} " + " -header-filter=.* " + " -fix " + " -fix-errors " + " -- " + " ${inc_list_spaces} " + " -std=c++14 " + " ${CMAKE_CXX_FLAGS} ") + + file(GENERATE OUTPUT ${TIDY_SCRIPT} CONTENT "${TIDY_STRING}") + + + set(REPLACEMENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + set(REPLACEMENTS_FILE ${ddl_INCLUDE_DIRS}/../cmake/ddl4.1_replacements.txt) + configure_file(${ddl_INCLUDE_DIRS}/../cmake/migrate_to_ddl_4_1.sh.in ${CMAKE_CURRENT_BINARY_DIR}/${CLANG_TIDY_TARGET}_migrate_to_ddl_4_1.sh @ONLY) + +endfunction(ddl_migrate_4_1) diff --git a/cmake/migrate_to_ddl_4_1.sh.in b/cmake/migrate_to_ddl_4_1.sh.in new file mode 100644 index 0000000..b43d265 --- /dev/null +++ b/cmake/migrate_to_ddl_4_1.sh.in @@ -0,0 +1,19 @@ +#!/bin/bash + +while IFS=';' read -ra line || [[ -n "$line" ]]; do + find @REPLACEMENT_DIR@ -type f -readable -writable -exec sed -i "s/\b${line[0]}\b/${line[1]}/g" {} \; +done < @REPLACEMENTS_FILE@ + +i="0" +CWD="$(pwd)" +cd "@CMAKE_CURRENT_SOURCE_DIR@" +chmod +x @TIDY_SCRIPT@ +while [ $i -lt 50 ]; do + @TIDY_SCRIPT@ 2>&1 | grep 'clang-tidy applied .* suggested fixes' + if [ $? != 0 ]; then + break + fi + i=$[$i+1] +done +@TIDY_SCRIPT@ +cd "$CWD" diff --git a/cmake/set_library_naming_conventions.cmake b/cmake/set_library_naming_conventions.cmake new file mode 100644 index 0000000..7574b37 --- /dev/null +++ b/cmake/set_library_naming_conventions.cmake @@ -0,0 +1,2 @@ +##differentiate between debug and release +set(CMAKE_DEBUG_POSTFIX "d${CMAKE_RELEASE_POSTFIX}") diff --git a/cmake/use_integrated_debug_symbols.cmake b/cmake/use_integrated_debug_symbols.cmake new file mode 100644 index 0000000..c547ad3 --- /dev/null +++ b/cmake/use_integrated_debug_symbols.cmake @@ -0,0 +1,12 @@ +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # compile with /Z7 to avoid pdb generation and integrate debug symbols + string(REGEX REPLACE "/Z[iI7]" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Z7") + string(REGEX REPLACE "/Z[iI7]" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Z7") + + string(REGEX REPLACE "/Z[iI7]" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7") + string(REGEX REPLACE "/Z[iI7]" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /Z7") +endif() diff --git a/codec/access_element.h b/codec/access_element.h new file mode 100644 index 0000000..8b4432c --- /dev/null +++ b/codec/access_element.h @@ -0,0 +1,573 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ +#ifndef DDL_STRUCT_ELEMENT_ACCESS_CLASS_HEADER +#define DDL_STRUCT_ELEMENT_ACCESS_CLASS_HEADER + +#include + +#include "struct_element.h" +#include "codec_factory.h" + +namespace ddl +{ + +namespace access_element +{ + +//define all needed error types and values locally +_MAKE_RESULT(-3, ERR_UNEXPECTED) +_MAKE_RESULT(-20, ERR_NOT_FOUND) + +namespace detail +{ + +/// For internal use only. @internal +template +static inline size_t getElementCount(const T& type) +{ + return type.getElementCount(); +} + +/// For internal use only. @internal +template +static inline a_util::result::Result getElement(const T& type, size_t element_index, const StructElement*& element) +{ + return type.getElement(element_index, element); +} + +/// For internal use only. @internal +template <> +inline size_t getElementCount(const CodecFactory& type) +{ + return type.getStaticElementCount(); +} + +/// For internal use only. @internal +template <> +inline a_util::result::Result getElement(const CodecFactory& type, size_t element_index, const StructElement*& element) +{ + return type.getStaticElement(element_index, element); +} + +/// For internal use only. @internal +template +a_util::result::Result find_complex_index(const T& decoder, const std::string& struct_name, + size_t& index, const char* post_fix) +{ + if (struct_name.empty()) + { + index = 0; + return a_util::result::SUCCESS; + } + + size_t element_count = getElementCount(decoder); + std::string prefix = struct_name + post_fix; + for (size_t element_index = 0; element_index < element_count; ++element_index) + { + const StructElement* element; + if (isOk(getElement(decoder, element_index, element))) + { + + if (a_util::strings::compare(element->name.c_str(), prefix.c_str(), 0, prefix.size()) == 0) + { + index = element_index; + return a_util::result::SUCCESS; + } + } + } + + return ERR_NOT_FOUND; +} + +} + +/** + * find the index of an element by name. + * @param[in] decoder The decoder or factory. + * @param[in] element_name The name of the element. + * @param[out] index The index of the found element. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result find_index(const T& decoder, const std::string& element_name, size_t& index) +{ + size_t element_count = detail::getElementCount(decoder); + for (size_t element_index = 0; element_index < element_count; ++element_index) + { + const StructElement* element; + if (isOk(detail::getElement(decoder, element_index, element))) + { + if (element->name == element_name) + { + index = element_index; + return a_util::result::SUCCESS; + } + } + } + + return ERR_NOT_FOUND; +} + +/** + * find the index of the first element of a sub-structure by name. + * @param[in] decoder The decoder or factory. + * @param[in] struct_name The name of the sub-structure. + * @param[out] index The index of the found element. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result find_struct_index(const T& decoder, const std::string& struct_name, size_t& index) +{ + return detail::find_complex_index(decoder, struct_name, index, "."); +} + +/** + * find the index of the first element of an array by name. + * @param[in] decoder The decoder or factory. + * @param[in] array_name The name of the array. + * @param[out] index The index of the found element. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result find_array_index(const T& decoder, const std::string& array_name, size_t& index) +{ + return detail::find_complex_index(decoder, array_name, index, "["); +} + +/** + * find the index of the first element after an array by name. + * @param[in] decoder The decoder or factory. + * @param[in] array_name The name of the array. + * @param[out] index The index of the found element. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result find_array_end_index(const T& decoder, const std::string& array_name, size_t& index) +{ + size_t element_count = detail::getElementCount(decoder); + std::string prefix = array_name + "["; + for (index += 1; index < element_count; ++index) + { + const StructElement* element; + if (isFailed(detail::getElement(decoder, index, element))) + { + return a_util::result::SUCCESS; + } + + if (a_util::strings::compare(element->name.c_str(), prefix.c_str(), 0, prefix.size()) != 0) + { + return a_util::result::SUCCESS; + } + } + + return a_util::result::SUCCESS; +} + +/** + * Get the value of an element by name. + * @param[in] decoder The decoder. + * @param[in] element_name The name of the element. + * @param[out] value The location where the value should be copied to. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result get_value(const T& decoder, const std::string& element_name, void* value) +{ + size_t element_index; + a_util::result::Result res = find_index(decoder, element_name, element_index); + if (a_util::result::isFailed(res)) return res; + + return decoder.getElementValue(element_index, value); +} + +/** + * Set the value of an element by name. + * @param[in] codec The codec. + * @param[in] element_name The name of the element. + * @param[in] value The location where the value should be copied from. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result set_value(T& codec, const std::string& element_name, const void* value) +{ + size_t element_index; + a_util::result::Result res = find_index(codec, element_name, element_index); + if (a_util::result::isFailed(res)) return res; + + return codec.setElementValue(element_index, value); +} + +/** + * Get the value of an element by name. + * @param[in] decoder The decoder. + * @param[in] element_name The name of the element. + * @retval The value of the element. + */ +template +a_util::variant::Variant get_value(const T& decoder, const std::string& element_name) +{ + a_util::variant::Variant result; + size_t element_index; + if (isOk(find_index(decoder, element_name, element_index))) + { + decoder.getElementValue(element_index, result); + } + return result; +} + +/** + * Set the value of an element by name. + * @param[in] codec The codec. + * @param[in] element_name The name of the element. + * @param[in] value The new value. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result set_value(T& codec, const std::string& element_name, const a_util::variant::Variant& value) +{ + size_t element_index; + a_util::result::Result res = find_index(codec, element_name, element_index); + if (a_util::result::isFailed(res)) return res; + + return codec.setElementValue(element_index, value); +} + +/** + * Get the value of an element by index. + * @param[in] decoder The decoder. + * @param[in] element_index The index of the element. + * @retval The value of the element. + */ +template +a_util::variant::Variant get_value(const T& decoder, size_t element_index) +{ + a_util::variant::Variant result; + if (isOk(decoder.getElementValue(element_index, result))) + { + return result; + } + + return a_util::variant::Variant(static_cast(0)); +} + +/** + * Get a pointer to an element by name. + * @param[in] decoder The decoder. + * @param[in] element_name The name of the element. + * @return Address of the element. + */ +template +const void* get_value_address(const T& decoder, const std::string& element_name) +{ + size_t element_index; + if (isOk(find_index(decoder, element_name, element_index))) + { + return decoder.getElementAddress(element_index); + } + + return NULL; +} + +/** + * Get a pointer to an element by name. + * @param[in] codec The codec. + * @param[in] element_name The name of the element. + * @return Address of the element. + */ +template +void* get_value_address(T& codec, const std::string& element_name) +{ + size_t element_index; + if (isOk(find_index(codec, element_name, element_index))) + { + return codec.getElementAddress(element_index); + } + + return NULL; +} + +/** + * Get a pointer to a sub-structure by name. + * @param[in] decoder The codec. + * @param[in] struct_name The name of the structure. + * @return Address of the sub-structure. + */ +template +const STRUCT* get_struct_address(const T& decoder, const std::string& struct_name) +{ + size_t element_index; + if (isOk(find_struct_index(decoder, struct_name, element_index))) + { + return reinterpret_cast(decoder.getElementAddress(element_index)); + } + + return NULL; +} + +/** + * Get a pointer to a sub-structure by name. + * @param[in] codec The codec. + * @param[in] struct_name The name of the structure. + * @return Address of the sub-structure. + */ +template +STRUCT* get_struct_address(T& codec, const std::string& struct_name) +{ + size_t element_index; + if (isOk(find_struct_index(codec, struct_name, element_index))) + { + return reinterpret_cast(codec.getElementAddress(element_index)); + } + + return NULL; +} + +/** + * Copy a sub-structure out of the structure. + * @param[in] decoder The decoder. + * @param[in] struct_name The name of the structure. + * @param[out] struct_value The location the sub-structure will be copied to. + * @retval ERR_NOT_FOUND No structure with the requested name was found. + */ +template +a_util::result::Result get_struct_value(const CODEC& decoder, const std::string& struct_name, T* struct_value) +{ + const T* address = get_struct_address(decoder, struct_name); + if (!address) + { + return ERR_NOT_FOUND; + } + + a_util::memory::copy(struct_value, sizeof(T), address, sizeof(T)); + return a_util::result::SUCCESS; +} + +/** + * Copy a sub-structure into the structure. + * @param[in] codec The codec. + * @param[in] struct_name The name of the structure. + * @param[in] struct_value The location the sub-structure will be copied from. + * @retval ERR_NOT_FOUND No structure with the requested name was found. + */ +template +a_util::result::Result set_struct_value(CODEC& codec, const std::string& struct_name, const T* struct_value) +{ + T* address = get_struct_address(codec, struct_name); + if (!address) + { + return ERR_NOT_FOUND; + } + + a_util::memory::copy(address, sizeof(T), struct_value, sizeof(T)); + return a_util::result::SUCCESS; +} + +/** + * Get a pointer to an array by name. + * @param[in] decoder The decoder. + * @param[in] array_name The name of the array. + * @return Address of the array. + */ +template +const ARRAY_TYPE* get_array_address(const T& decoder, const std::string& array_name) +{ + size_t element_index; + if (isOk(find_array_index(decoder, array_name, element_index))) + { + return reinterpret_cast(decoder.getElementAddress(element_index)); + } + + return NULL; +} + +/** + * Get a pointer to an array by name. + * @param[in] codec The codec. + * @param[in] array_name The name of the array. + * @return Address of the array. + */ +template +ARRAY_TYPE* get_array_address(T& codec, const std::string& array_name) +{ + size_t element_index; + if (isOk(find_array_index(codec, array_name, element_index))) + { + return reinterpret_cast(codec.getElementAddress(element_index)); + } + + return NULL; +} + +/** + * Get information about an array. + * @param[in] decoder The decoder. + * @param[in] array_name The name of the array. + * @param[out] start_address The address of the first element of the array. + * @param[out] size The amount of elements of the array. + * @retval ERR_NOT_FOUND No array with the requested name was found. + */ +template +a_util::result::Result get_array(const CODEC& decoder, const std::string& array_name, + const void*& start_address, size_t& size) +{ + size_t start_index = 0; + a_util::result::Result res = find_array_index(decoder, array_name, start_index); + if (a_util::result::isFailed(res)) return res; + + size_t end_index = start_index; + res = find_array_end_index(decoder, array_name, end_index); + if (a_util::result::isFailed(res)) return res; + + start_address = decoder.getElementAddress(start_index); + if (!start_address) + { + return ERR_UNEXPECTED; + } + + const void* end_adress = decoder.getElementAddress(end_index); + if (end_adress) + { + size = static_cast(end_adress) - + static_cast(start_address); + } + else + { + // it reaches til the end + size_t start_offset = static_cast(start_address) - + static_cast(decoder.getElementAddress(0)); + size = decoder.getBufferSize(decoder.getRepresentation()) - start_offset; + } + + return a_util::result::SUCCESS; +} + +/** + * Copy an array out of the structure. + * @param[in] decoder The decoder. + * @param[in] array_name The name of the array. + * @param[out] array_value The location the array will be copied to. + * @retval ERR_NOT_FOUND No array with the requested name was found. + */ +template +a_util::result::Result get_array_value(const CODEC& decoder, const std::string& array_name, T* array_value) +{ + const void* start_address; + size_t size; + a_util::result::Result res = get_array(decoder, array_name, start_address, size); + if (a_util::result::isFailed(res)) return res; + + a_util::memory::copy(array_value, size, start_address, size); + return a_util::result::SUCCESS; +} + +/** + * Set the value of the requested element to zero. + * @param[in] codec The codec. + * @param[in] element_name The name of the element. + * @retval ERR_NOT_FOUND No element with the requested name was found. + */ +template +a_util::result::Result reset(T& codec, const std::string& element_name) +{ + size_t element_index; + a_util::result::Result res = find_index(codec, element_name, element_index); + if (a_util::result::isFailed(res)) return res; + + uint64_t zero = 0; + return codec.setElementValue(element_index, &zero); +} + +///For internal use only. @internal +#define GET_ENUM_CASE(__variant_type, __data_type) \ +case a_util::variant::VT_##__variant_type:\ +{\ + __data_type xValue = value.get##__variant_type();\ + for (EnumType::const_iterator it = element->p_enum->begin(); it != element->p_enum->end(); ++it)\ + {\ + if (xValue == it->second.as##__variant_type())\ + {\ + return it->first;\ + }\ + }\ + break;\ +} + +/** + * Get the value of an element as a string, using enum value names if available. + * @param[in] decoder The decoder. + * @param[in] element The index of the element. + * @return A string representation of the value. + */ +template +std::string get_value_as_string(const T& decoder, size_t element_index) +{ + a_util::variant::Variant value; + const StructElement* element; + if (isOk(decoder.getElement(element_index, element))) + { + if (isOk(decoder.getElementValue(element_index, value))) + { + if (element->p_enum) + { + switch (value.getType()) + { + GET_ENUM_CASE(Bool, bool) + GET_ENUM_CASE(Int8, int8_t) + GET_ENUM_CASE(UInt8, uint8_t) + GET_ENUM_CASE(Int16, int16_t) + GET_ENUM_CASE(UInt16, uint16_t) + GET_ENUM_CASE(Int32, int32_t) + GET_ENUM_CASE(UInt32, uint32_t) + GET_ENUM_CASE(Int64, int64_t) + GET_ENUM_CASE(UInt64, uint64_t) + GET_ENUM_CASE(Float, float) + GET_ENUM_CASE(Double, double) + default: break; + } + } + } + } + + return value.asString(); +} + +/** + * Get the value of an element as a string, using enum value names if available. + * @param[in] decoder The decoder. + * @param[in] element_name The name of the element. + * @return A string representation of the value. + */ +template +std::string get_value_as_string(const T& decoder, const std::string& element_name) +{ + size_t element_index; + if (isOk(find_index(decoder, element_name, element_index))) + { + return get_value_as_string(decoder, element_index); + } + return ""; +} + +} + +} + +#endif + diff --git a/codec/bitserializer.cpp b/codec/bitserializer.cpp new file mode 100644 index 0000000..47f9acf --- /dev/null +++ b/codec/bitserializer.cpp @@ -0,0 +1,97 @@ +/** + * @file + * Raw memory related functionality + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "a_util/memory.h" +#include "bitserializer.h" + +using namespace a_util; +using namespace a_util::memory; + + +a_util::memory::Endianess a_util::memory::get_platform_endianess() +{ + uint32_t value = 0x01020304; + if (((unsigned char*)&value)[0] == 0x04 && + ((unsigned char*)&value)[2] == 0x02) + { + return bit_little_endian; + } + else if (((unsigned char*)&value)[0] == 0x01 && + ((unsigned char*)&value)[2] == 0x03) + { + return bit_big_endian; + } + else + { + throw std::runtime_error("unsupported endianess"); + } +} + +std::string a_util::memory::detail::formatBits(uint64_t value) +{ + std::string bit_string; + + for (int i = 0; i < (int)sizeof(uint64_t) * 8; i++) + { + if (i % 8 == 0) + { + bit_string += " | "; + } + bit_string += a_util::strings::toString((value >> (63 - i)) & 1); + } + + return bit_string; +} + +a_util::result::Result a_util::memory::detail::convertSignalEndianess(uint64_t *signal, Endianess endianess, size_t bit_length) +{ + if (bit_length > 8) // Signal is bigger than one byte + { + if (endianess != get_platform_endianess()) // Byteorder was different on writing platform + { + if (bit_length > (4 * 8)) // 64 Bit + { + // If the BE signal is shorter than 8 byte, make sure the value is aligned + // at the LSB end, seen from a BE viewpoint. + if (endianess == bit_big_endian) + { + *signal <<= (((8 * 8) - (bit_length)) / 8) * 8; + } + *reinterpret_cast(signal) = a_util::memory::swapEndianess(*reinterpret_cast(signal)); + } + else if (bit_length > (2 * 8)) // 32 Bit + { + // If the BE signal is shorter than 4 byte, make sure the value is aligned + // at the LSB end, seen from a BE viewpoint. + if (endianess == bit_big_endian) + { + *signal <<= (((4 * 8) - (bit_length)) / 8) * 8; + } + *reinterpret_cast(signal) = a_util::memory::swapEndianess(*reinterpret_cast(signal)); + } + else // 16 Bit + { + *reinterpret_cast(signal) = a_util::memory::swapEndianess(*reinterpret_cast(signal)); + } + } + } + + return a_util::result::SUCCESS; +} diff --git a/codec/bitserializer.h b/codec/bitserializer.h new file mode 100644 index 0000000..5f9c416 --- /dev/null +++ b/codec/bitserializer.h @@ -0,0 +1,750 @@ +/** + * @file + * Raw memory related functionality + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ +#ifndef A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED +#define A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED + +#include + +#include "a_util/memory.h" +#include "a_util/result.h" + +namespace a_util +{ +namespace memory +{ + +//define all needed error types and values locally +_MAKE_RESULT(-4, ERR_POINTER); +_MAKE_RESULT(-5, ERR_INVALID_ARG); + +/// Enum describing the endianess +typedef enum +{ + bit_little_endian = 1, + bit_big_endian = 2, +} Endianess; + +/** +* Returns the endianess of the platform +* @return See \ref Endianess +*/ +Endianess get_platform_endianess(); + +namespace detail +{ +/** +* Format the bit pattern of a uint64_t value to a string +* Used for debug purposes. +* +* @param [in] value The value to print. +* @retval The bitstring +*/ +std::string formatBits(uint64_t value); + +/** +* Convert the endianess of a signal by correctly swapping the byte order if required. +* The variable signal is a uint64_t, but the value that needs conversion might be smaller. +* The parameter bit_length determines if a 16, 32 or 64 value should be swapped. +* For a LE system, reading BE signals of 3, 5, 6 or 7 bytes length the value will be aligned +* within a 4 or 8 byte value before swapping bytes. +* +* @param [in,out] signal Pointer to the variable to store the read value in. +* @param [in] endianess Parameter describing the endianess of the bitfield to convert. +* @param [in] bit_length Number of bits to read. +* +* @return Returns a standard result code. +*/ +a_util::result::Result convertSignalEndianess(uint64_t *signal, Endianess endianess, size_t bit_length); + +/** +* Converter Base +* Contains the base methods used by all inheriting Converter classes. +*/ +template +class ConverterBase { +protected: + /** + * Read value from bitfield. + * Operating on a uint64_t copy to allow bit shifting and masking operations. + * + * @param [in] buffer Pointer to the memory buffer to read from. + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] value Pointer to the variable to store the read value in. + * @param [in] endianess Parameter describing the endianess of the bitfield to read from. + * + * @return Returns a standard result code. + */ + static a_util::result::Result readSignal(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value, + Endianess endianess = get_platform_endianess()) + { + /* + * offset_end offset_start + * _ ____ + * | | | | + * ....|...abcde|fghijklm|no......|.... Buffer (index 0 on the right end side) + * |_______________| + * bit_length ^ + * | + * start_bit + */ + + // 1) COPY relevant bytes of Buffer content to result variable. + uint64_t result = 0; // Result value + uint64_t ninth_byte = 0; // variable to eventually store a ninth byte from buffer + size_t bytes_to_read = 0; + copyBytesFromBuffer(buffer, &result, start_bit, bit_length, &ninth_byte, &bytes_to_read); + + // 2) TRIM unrelevant bits and SHIFT to align value. + + // Number of bits the start position is offset from 0 (0 for aligned signal) + size_t offset_start = start_bit % 8; + // Number of bits the end position is offset from the end of the last byte (0 for complete bytes) + size_t offset_end = (8 - ((start_bit + bit_length) % 8)) % 8; + + /********************************************************************************************** + * Distinguish between LE and BE operating systems to get the shift operations right * + **********************************************************************************************/ + // On LE System + if (get_platform_endianess() == bit_little_endian) + { + /* Use bit mask to remove bits on the higher end, which do not belong to the value to read. + * + * ...|...abcde|fghijklm|no......| => 000|000abcde|fghijklm|no......| + * + */ + cutLeadingBits(&result, bit_length + offset_start); + + /* Shift right to align start at position 0 (also trims the right end). + * + * 000|000abcde|fghijklm|no......| => 000|00000000|0abcdefg|hijklmno| + * + */ + result >>= offset_start; + + // Eventually get bits from the copied 9th byte. + if (ninth_byte > 0) // nothing to take care of if nothing was copied or all copied bits are 0. + { + // deleteAll unwanted bits from ninth byte. + cutLeadingBits(&ninth_byte, (8 - offset_end)); + size_t bit_size = sizeof(result) * 8; + // Shift requested bits from the 9th byte into the right position to be combined with result. + ninth_byte <<= (bit_size - offset_start); + // merge value together from all nine bytes. + result = result | ninth_byte; + } + + // BE Signal needs byte order swapping. + if (endianess == bit_big_endian) + { + // Only for reading partial bytes. Filling the missing bits differs from LE Signal. + if (bit_length % 8 != 0) + { + /* Shift left to align end position. + * + * 000|0abcdefg|hijklmno| => 000|abcdefgh|ijklmno0| + * + */ + result <<= (offset_end + offset_start) % 8; + + /* Shift bits within MSByte, filling the gap with 0s. + * + * 000|abcdefgh|ijklmno0| => 000|abcdefgh|0ijklmno| + * ^ ^ + * MSByte MSByte + */ + uint8_t *ms_byte = (uint8_t*)&result; + ms_byte[0] >>= (offset_end + offset_start) % 8; + } + + /* swap bytes to LE. + * + * 000|abcdefgh|0ijklmno| => 000|0ijklmno|abcdefgh| + * + */ + detail::convertSignalEndianess(&result, endianess, bit_length); + } + } + // On BE System + else + { + /* swap bytes to simulate LE shifting operations. + * + * |...abcde|fghijklm|no......|... => ...|no......|fghijklm|...abcde| + * + */ + detail::convertSignalEndianess(&result, bit_little_endian, sizeof(result) * 8); + + // LE Signal + if (endianess == bit_little_endian) + { + /* Use bit mask to remove bits on the higher end, which do not belong to the value to read. + * + * ...|no......|fghijklm|...abcde| => ...|no......|fghijklm|000abcde| + * + */ + cutLeadingBits(&result, (sizeof(result) * 8) - offset_end); // Cut away only offset_end bits. + + /* Shift right to align bits within LSByte (BE Shifting!). + * + * ...|no......|fghijklm|000abcde| => ...|hijklmno|0abcdefg|00000000| + * + */ + result >>= offset_start; + + /* Shift right to align LSByte on the left side (BE Shifting!). + * + * ...|hijklmno|0abcdefg|00000000| => |hijklmno|0abcdefg|000 + * + * Shift over all + * empty bytes = (all bits - occupied bits (bit_length) - already shifted bits) / number of bytes + */ + result >>= (((sizeof(result) * 8) - bit_length - offset_start) / sizeof(result)) * 8; + + // No further byte swap, because there has been one swap before the shift operations already. + } + // BE Signal + else + { + /* Shift left to align bits within LSByte (now rightmost byte because of byte swap). + * Also deletes bits from end offset. + * + * ...|no......|fghijklm|...abcde| => ...|........|ijklmno.|abcdefgh| + * + */ + result <<= offset_end; + + // Only for reading partial bytes. Filling the missing bits differs from LE Signal. + if (bit_length % 8 != 0) + { + /* Shift bits within MSByte to move 0s to the highest bits (also deleting all unwanted bits from start offset). + * + * ...|........|ijklmno.|abcdefgh| => ...|........|0ijklmno|abcdefgh| + * + */ + uint8_t *ms_byte = (uint8_t*)&result + (bit_length / 8); // position of the value's MSByte + ms_byte[0] >>= (offset_end + offset_start) % 8; // amount of unused bits within MSByte + } + + /* swap bytes back to BE + * + * ...|........|0ijklmno|abcdefgh| => |abcdefgh|0ijklmno|... + * + */ + detail::convertSignalEndianess(&result, bit_little_endian, sizeof(result) * 8); // Change the simulated LE value back + + /* Use bit mask to remove bits on the higher end, which do not belong to the value to read. + * + * |abcdefgh|0ijklmno|... => |abcdefgh|0ijklmno|000 + * + * Remove everything behind the value length plus the gap within MSByte. + */ + cutLeadingBits(&result, bit_length + (offset_end + offset_start) % 8); + } + } + + // Copy the resulting value to the target variable. No Casting! Data might be lost otherwise. + size_t sz = std::min(sizeof(*value), sizeof(result)); + a_util::memory::copy(value, sz, &result, sz); + + return a_util::result::SUCCESS; + } + + /** + * Write value to bitfield. + * Operating on a uint64_t copy to allow bit shifting and masking operations. + * + * @param [in] buffer Pointer to the memory buffer to write to. + * @param [in] start_bit Bit position to start writing to. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to write. + * @param [out] value Value to write to the bitfield. + * @param [in] endianess Parameter describing the endianess of the bitfield to write to. + * + * @return Returns a standard result code. + */ + static a_util::result::Result writeSignal(uint8_t *buffer, size_t start_bit, size_t bit_length, T value, + Endianess endianess = get_platform_endianess()) + { + // 1) Copy relevant bytes of Buffer content to be overwritten. + uint64_t buffer_copy = 0; + uint64_t ninth_byte = 0; // storage variable for the ninth bit from buffer + size_t bytes_to_read = 0; + copyBytesFromBuffer(buffer, &buffer_copy, start_bit, bit_length, &ninth_byte, &bytes_to_read); + + // 2) Erase Bits from Buffer copy that will be overwritten TODO: BE LE system difference important here? + // Number of bits the start position is offset from 0 + size_t offset_start = start_bit % 8; + // Number of bits the end position is offset from the end of the last byte + size_t offset_end = (8 - ((start_bit + bit_length) % 8)) % 8; + uint64_t mask_left = ~0ULL; + if ((bit_length + offset_start) >= (sizeof(mask_left) * 8)) + { + mask_left = 0; + } + else + { + mask_left = ~0ULL; + mask_left <<= (bit_length + offset_start); + } + uint64_t mask = ~0ULL; + mask <<= offset_start; + mask = ~mask; + mask |= mask_left; + + buffer_copy &= mask; + + // 3) Copy value to UInt64 variable to work with. + uint64_t signal; + a_util::memory::copy(&signal, sizeof(signal), &value, sizeof(signal)); + + // 4) Keep only nLength bits: Remove bits that should not be written to the Buffer. + cutLeadingBits(&signal, bit_length); + + // 5) Shift to align at start bit position. + int shift_amount = (int)offset_start; // Initialized to fit LE Signal shift + + // BE Signal + if (endianess == bit_big_endian) + { + // swap bytes + detail::convertSignalEndianess(&signal, endianess, bit_length); + // Remove gap for partial bytes within MSByte + uint8_t *ms_byte = (uint8_t*)&signal; + int ms_shift = (8 - (bit_length % 8)) % 8; + ms_byte[0] <<= ms_shift; + shift_amount -= ms_shift; + } + + // Copy most significant byte to ninth buffer byte before losing bits with the shift. + if ((offset_start + bit_length) > (sizeof(signal) * 8)) + { + uint64_t signal_for_ninth_byte = signal; + signal_for_ninth_byte >>= (sizeof(signal) - 1) * 8; + signal_for_ninth_byte >>= (8 - offset_start); // Only LE Signal + uint64_t mask = ~0ULL; + mask <<= (8 - offset_end); + ninth_byte &= mask; + ninth_byte |= signal_for_ninth_byte; + } + + if (shift_amount < 0) + { + signal >>= std::abs(shift_amount); + } + else + { + signal <<= shift_amount; + } + + // 7) Write bytes with integrated signal back to the buffer. + buffer_copy |= signal; + + size_t sz = std::min(bytes_to_read, sizeof(signal)); + a_util::memory::copy(buffer + (start_bit / 8), sz, &buffer_copy, sz); + + // Eventually copy ninth byte back to buffer + if (bytes_to_read > sizeof(signal)) + { + a_util::memory::copy(buffer + (start_bit / 8) + sizeof(signal), 1, &ninth_byte, 1); + } + + return a_util::result::SUCCESS; + } + + /** + * Set the highest bits of a uint64_t value to zero. The number of bit_length lowest bits + * remain unchanged. + * + * @param [out] value Pointer to the variable to trim. + * @param [in] bit_length Number of trailing bits to remain unchanged. + * + * @return Returns a standard result code. + */ + static a_util::result::Result cutLeadingBits(uint64_t *value, size_t bit_length) + { + size_t bit_size = (sizeof(*value) * 8); + if (bit_length < bit_size) + { + uint64_t mask = ~0ULL; + mask >>= (bit_size - bit_length); + *value &= mask; + } + + return a_util::result::SUCCESS; + } + + /** + * Copy bytes_to_read number of bytes from the buffer to value and ninth_byte. + * Determines how many bytes need to be copied to receive a copy of all bits in the range described + * by start_bit and bit_length. The maximum for bit_length is 64, but for unaligned values the range + * may exceed 8 bytes. In this case, the required ninth byte will be copied to ninth_byte. + * + * @param [in] buffer Pointer to the memory buffer to copy from. + * @param [out] value Pointer to the variable to store the copied value in. + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] ninth_byte Pointer to the variable to eventually store a copied ninth byte in. + * @param [out] bytes_to_read Number of bytes that need to be copied to attain all requested bits. + * + * @return Returns a standard result code. + */ + static a_util::result::Result copyBytesFromBuffer(uint8_t *buffer, uint64_t *value, size_t start_bit, size_t bit_length, uint64_t *ninth_byte, size_t *bytes_to_read) + { + // Byte within the buffer to start reading at + size_t start_byte = start_bit / 8; + + // Number of bits to read: signal length + bits to fill in the offset on both sides for unaligned signals + size_t bits_to_read = bit_length + (start_bit % 8); + if ((bits_to_read % 8) > 0) + { + bits_to_read += (8 - (bits_to_read % 8)); + } + // Number of bytes to read from the buffer + *bytes_to_read = bits_to_read / 8; + + // Copy up to 8 bytes to result + if (*bytes_to_read > (size_t)sizeof(*value)) + { + a_util::memory::copy(value, sizeof(*value), buffer + start_byte, sizeof(*value)); + } + else + { + a_util::memory::copy(value, *bytes_to_read, buffer + start_byte, *bytes_to_read); + } + + // The max signal size is 8 byte, but if the signal is not aligned, it might spread over 9 bytes. + + if (*bytes_to_read > sizeof(*value)) + { + // Get a copy of the most significant byte, which could not yet be saved to result + a_util::memory::copy(ninth_byte, 1, buffer + start_byte + sizeof(*value), 1); + } + + return a_util::result::SUCCESS; + } +}; + +/// Template converter class to differentiate between float, signed and unsigned integer values. +template class Converter; + +/// Partially specialized class for Unsigned Integers +template +class Converter : public ConverterBase +{ +public: + /** + * Read unsigned integer from bitfield. + * + * @param [in] buffer Pointer to the memory buffer to read from. + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] value Pointer to the variable to store the read value in. + * @param [in] endianess Parameter describing the endianess of the bitfield to read from. + * + * @return Returns a standard result code. + */ + static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value, + Endianess endianess) + { + return ConverterBase::readSignal(buffer, start_bit, bit_length, value, endianess); + } + + /** + * Write unsigned integer to bitfield. + * + * @param [in] buffer Pointer to the memory buffer to write to. + * @param [in] start_bit Bit position to start writing to. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to write. + * @param [out] value Value to write to the bitfield. + * @param [in] endianess Parameter describing the endianess of the bitfield to write to. + * + * @return Returns a standard result code. + */ + static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value, + Endianess endianess) + { + return ConverterBase::writeSignal(buffer, start_bit, bit_length, value, endianess); + } +}; + +/// Partially specialized class for Signed Integers +template +class Converter : public ConverterBase +{ +public: + /** + * Read signed integer from bitfield. + * + * @param [in] buffer Pointer to the memory buffer to read from. + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] value Pointer to the variable to store the read value in. + * @param [in] endianess Parameter describing the endianess of the bitfield to read from. + * + * @return Returns a standard result code. + */ + static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value, + Endianess endianess) + { + a_util::result::Result res = ConverterBase::readSignal(buffer, start_bit, bit_length, value, endianess); + if (res != a_util::result::SUCCESS) + { + return res; + } + + // replicate sign bit + *value <<= (sizeof(T) * 8) - bit_length; + *value >>= (sizeof(T) * 8) - bit_length; + return a_util::result::SUCCESS; + } + + /** + * Write signed integer to bitfield. + * + * @param [in] buffer Pointer to the memory buffer to write to. + * @param [in] start_bit Bit position to start writing to. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to write. + * @param [out] value Value to write to the bitfield. + * @param [in] endianess Parameter describing the endianess of the bitfield to write to. + * + * @return Returns a standard result code. + */ + static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value, + Endianess endianess) + { + // Nothing special to take care of for writing signed integers, compared to writing unsigned integers. + return ConverterBase::writeSignal(buffer, start_bit, bit_length, value, endianess); + } +}; + +/// Specialized class for Floats (Floats are always signed!) +template +class Converter : public ConverterBase +{ +public: + /** + * Read tFloat from bitfield. + * + * @param [in] buffer Pointer to the memory buffer to read from. + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] value Pointer to the variable to store the read value in. + * @param [in] endianess Parameter describing the endianess of the bitfield to read from. + * + * @return Returns a standard result code. + */ + static a_util::result::Result read(uint8_t *buffer, size_t start_bit, size_t bit_length, T* value, + Endianess endianess) + { + // Read only values of size tFloat + if (sizeof(T) * 8 == bit_length) + { + return ConverterBase::readSignal(buffer, start_bit, bit_length, value, endianess); + } + else + { + return ERR_INVALID_ARG; + } + } + + /** + * Write tFloat to bitfield. + * + * @param [in] buffer Pointer to the memory buffer to write to. + * @param [in] start_bit Bit position to start writing to. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to write. + * @param [out] value Value to write to the bitfield. + * @param [in] endianess Parameter describing the endianess of the bitfield to write to. + * + * @return Returns a standard result code. + */ + static a_util::result::Result write(uint8_t *buffer, size_t start_bit, size_t bit_length, T value, + Endianess endianess) + { + // Write only values of size tFloat + if (sizeof(T) * 8 == bit_length) + { + return ConverterBase::writeSignal(buffer, start_bit, bit_length, value, endianess); + } + else + { + return ERR_INVALID_ARG; + } + } +}; + +} // namespace detail + +/// Bit Serializer Class +class BitSerializer +{ +public: + /** + * Constructor + */ + BitSerializer(void* data, size_t data_size) : + _buffer(static_cast(data)), _buffer_bytes(data_size), + _buffer_bits(_buffer_bytes * 8) + { + } + + /** + * Default Constructor + */ + BitSerializer() : _buffer(NULL), _buffer_bytes(0), _buffer_bits(0) + { + } + + /** + * Read value from bitfield. Value can be of type tFloat or an unsigned or signed integer. + * + * ....|...*****|********|**......|.... Buffer (index 0 on the right end side) + * |_______________| + * bit_length ^ + * | + * start_bit + * + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [out] value Pointer to the variable to store the read value in. + * @param [in] endianess Parameter describing the endianess of the bitfield to read from. + * + * @return Returns a standard result code. + */ + template + a_util::result::Result read(size_t start_bit, size_t bit_length, T* value, + Endianess endianess = get_platform_endianess()) + { + // Check if in range + a_util::result::Result result_code = checkForInvalidArguments(start_bit, bit_length, sizeof(T)); + if (result_code != a_util::result::SUCCESS) + { + return result_code; + } + + // Call template function + detail::Converter::value, + std::is_floating_point::value> + ::read(_buffer, start_bit, bit_length, value, endianess); + + return a_util::result::SUCCESS; + } + + /** + * Write value to bitfield. Value can be of type tFloat or an unsigned or signed integer. + * + * ....|...*****|********|**......|.... Buffer (index 0 on the right end side) + * |_______________| + * bit_length ^ + * | + * start_bit + * + * @param [in] start_bit Bit position to start writing to. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to write. + * @param [out] value Value to write to the bitfield. + * @param [in] endianess Parameter describing the endianess of the bitfield to write to. + * + * @return Returns a standard result code. + */ + template + a_util::result::Result write(size_t start_bit, size_t bit_length, T value, + Endianess endianess = get_platform_endianess()) + { + // Check if in range + a_util::result::Result result_code = checkForInvalidArguments(start_bit, bit_length, sizeof(T)); + if (result_code != a_util::result::SUCCESS) + { + return result_code; + } + + // Call template function + detail::Converter::value, + std::is_floating_point::value> + ::write(_buffer, start_bit, bit_length, value, endianess); + + return a_util::result::SUCCESS; + } + +private: + /// internal buffer + uint8_t *_buffer; + /// size of internal buffer in bytes + size_t _buffer_bytes; + /// size of internal buffer in bits + size_t _buffer_bits; + + /** + * Check if the parameters for the reading and writing access are valid. + * The variable to read from or into might be too small and the accessed region of the memory buffer + * might be out of range. + * + * @param [in] start_bit Bit position to start reading from. The least significant bit + * has the index 0. + * @param [in] bit_length Number of bits to read. + * @param [in] size_variable Size of the variable to read into or write from. + * + * @return Returns a standard result code. + */ + a_util::result::Result checkForInvalidArguments(size_t start_bit, size_t bit_length, size_t size_variable) + { + if (!_buffer) + { + return ERR_POINTER; + } + + // Check invalid starting point + if (start_bit >= _buffer_bits) + { + return ERR_INVALID_ARG; + } + + // Check out of buffer bounds or length < 1 + if ((bit_length < 1) + || (_buffer_bits < start_bit + bit_length)) + { + return ERR_INVALID_ARG; + } + + // Check variable size + if (size_variable * 8 < bit_length) + { + return ERR_INVALID_ARG; + } + + return a_util::result::SUCCESS; + } + +}; + +} // namespace memory +} // namespace a_util + +#endif // A_UTILS_UTIL_MEMORY_BITSERIALIZER_INCLUDED diff --git a/codec/codec.cpp b/codec/codec.cpp new file mode 100644 index 0000000..6c3cde2 --- /dev/null +++ b/codec/codec.cpp @@ -0,0 +1,323 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "codec.h" + +#include "a_util/result/error_def.h" +#include "a_util/logging.h" +#include "legacy_error_macros.h" +#include "struct_layout.h" +#include "static_codec.h" +#include "element_accessor.h" +#include "access_element.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-10, ERR_INVALID_INDEX) + +static inline void BitToBytes(size_t& size) +{ + if (size % 8) + { + size = size/ 8 + 1; + } + else + { + size /= 8; + } +} + +Decoder::Decoder(const Decoder& oDecoder, const void* pData, size_t nDataSize, + DataRepresentation eRep): + StaticDecoder(oDecoder._layout, pData, nDataSize, eRep), + _dynamic_elements(oDecoder._dynamic_elements), + _buffer_sizes(oDecoder._buffer_sizes) +{ +} + +Decoder::Decoder(a_util::memory::shared_ptr pLayout, const void* pData, size_t nDataSize, + DataRepresentation eRep): + StaticDecoder(pLayout, pData, nDataSize, eRep), + _buffer_sizes(pLayout->getStaticBufferBitSizes()) +{ + if (_layout->hasDynamicElements()) + { + a_util::result::Result oResult = calculateDynamicElements(); + if (isFailed(oResult)) + { + LOG_ERROR("Failed to calculate dynamic elements"); + } + } + + BitToBytes(_buffer_sizes.deserialized); + BitToBytes(_buffer_sizes.serialized); +} + +a_util::result::Result Decoder::isValid() const +{ + RETURN_IF_FAILED(_layout->isValid()); + if (_data_size < getBufferSize(getRepresentation())) + { + return ERR_INVALID_ARG; + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result Decoder::calculateDynamicElements() +{ + _dynamic_elements.reset(new std::vector()); + + for (std::vector::const_iterator + itDynamicElement = _layout->getDynamicElements().begin(); + itDynamicElement != _layout->getDynamicElements().end(); ++ itDynamicElement) + { + RETURN_IF_FAILED(addDynamicElements(*itDynamicElement, _buffer_sizes, "")); + } + + return a_util::result::SUCCESS; +} + +void Decoder::moveToAlignment(size_t& bit_offset, size_t alignment) +{ + size_t nBitRest = bit_offset % 8; + if (nBitRest) + { + bit_offset += 8 - nBitRest; + } + + size_t nByteOffset = bit_offset / 8; + size_t nRest = nByteOffset % alignment; + if (nRest) + { + bit_offset += (alignment - nRest) * 8; + } +} + +a_util::result::Result Decoder::addDynamicElements(const DynamicStructLayoutElement& sDynamicElement, + Offsets& sOverallOffsets, + const std::string& strPrefix) +{ + moveToAlignment(sOverallOffsets.deserialized, sDynamicElement.alignment); + + if (sDynamicElement.isAlignmentElement()) + { + return a_util::result::SUCCESS; + } + + a_util::variant::Variant oArraySize((uint64_t)1); + bool bIsArray = sDynamicElement.isDynamicArray(); + if (bIsArray) + { + oArraySize = access_element::get_value(*this, + strPrefix + sDynamicElement.size_element_name); + } + size_t nArraySize = static_cast(oArraySize.asUInt64()); + + for (size_t nArrayIndex = 0; nArrayIndex < nArraySize; ++nArrayIndex) + { + RETURN_IF_FAILED(addDynamicElement(sDynamicElement, + bIsArray ? a_util::strings::format("[%d]", nArrayIndex) : "", + sOverallOffsets, strPrefix)); + } + + moveToAlignment(sOverallOffsets.deserialized, sDynamicElement.alignment); + + return a_util::result::SUCCESS; +} + +a_util::result::Result Decoder::addDynamicElement(const DynamicStructLayoutElement& sDynamicElement, + const std::string& strArrayIndex, + Offsets& sOverallOffsets, + const std::string& strPrefix) +{ + RETURN_IF_FAILED(addStaticStructElements(sDynamicElement, strArrayIndex, sOverallOffsets, strPrefix)); + RETURN_IF_FAILED(addDynamicStructElements(sDynamicElement, strArrayIndex, sOverallOffsets, strPrefix)); + + return a_util::result::SUCCESS; +} + +a_util::result::Result Decoder::addStaticStructElements(const DynamicStructLayoutElement& sDynamicElement, + const std::string& strArrayIndex, + Offsets& nOverallBitOffset, + const std::string& strPrefix) +{ + Offsets sStartOffsets = nOverallBitOffset; + for (std::vector::const_iterator itStaticElement = sDynamicElement.static_elements.begin(); + itStaticElement != sDynamicElement.static_elements.end(); ++itStaticElement) + { + StructLayoutElement sElement = *itStaticElement; + sElement.deserialized.bit_offset += sStartOffsets.deserialized; + sElement.serialized.bit_offset += sStartOffsets.serialized; + nOverallBitOffset.deserialized = sElement.deserialized.bit_offset + sElement.deserialized.bit_size; + nOverallBitOffset.serialized = sElement.serialized.bit_offset + sElement.serialized.bit_size; + if (!sElement.name.empty()) + { + sElement.name = a_util::strings::format("%s%s%s.%s", strPrefix.c_str(), + sDynamicElement.name.c_str(), + strArrayIndex.c_str(), + itStaticElement->name.c_str()); + } + else + { + // not part of a struct, just a plain array element + sElement.name = a_util::strings::format("%s%s%s", strPrefix.c_str(), + sDynamicElement.name.c_str(), + strArrayIndex.c_str()); + } + RETURN_IF_FAILED(addDynamicStructElement(sElement)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result Decoder::addDynamicStructElements(const DynamicStructLayoutElement& sDynamicElement, + const std::string& strArrayIndex, + Offsets& sOverallOffsets, + const std::string& strPrefix) +{ + std::string strChildPrefix = a_util::strings::format("%s%s%s.", strPrefix.c_str(), + sDynamicElement.name.c_str(), + strArrayIndex.c_str()); + for (std::vector::const_iterator + itDynamicChildElement = sDynamicElement.dynamic_elements.begin(); + itDynamicChildElement != sDynamicElement.dynamic_elements.end(); + ++itDynamicChildElement) + { + RETURN_IF_FAILED(addDynamicElements(*itDynamicChildElement, sOverallOffsets, strChildPrefix)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result Decoder::addDynamicStructElement(const StructLayoutElement& sElement) +{ + const Position& sPos = _element_accessor->getRepresentation() == deserialized ? + sElement.deserialized : sElement.serialized; + if (sPos.bit_offset + sPos.bit_size > _data_size * 8) + { + return ERR_INVALID_ARG; + } + + _dynamic_elements->push_back(sElement); + return a_util::result::SUCCESS; +} + +size_t Decoder::getElementCount() const +{ + if (_dynamic_elements) + { + return _layout->getStaticElements().size() + _dynamic_elements->size(); + } + + return _layout->getStaticElements().size(); +} + +size_t Decoder::getBufferSize(DataRepresentation eRep) const +{ + return eRep == deserialized ? + _buffer_sizes.deserialized : + _buffer_sizes.serialized; +} + +Codec Decoder::makeCodecFor(void* pData, size_t nDataSize, DataRepresentation eRep) const +{ + return Codec(*this, pData, nDataSize, eRep); +} + +const StructLayoutElement* Decoder::getLayoutElement(size_t nIndex) const +{ + const StructLayoutElement* pElement = NULL; + size_t nStaticElementCount = _layout->getStaticElements().size(); + if (nIndex < nStaticElementCount) + { + pElement = &_layout->getStaticElements()[nIndex]; + } + else if (_dynamic_elements && + nIndex - nStaticElementCount < _dynamic_elements->size()) + { + pElement = &(*_dynamic_elements)[nIndex - nStaticElementCount]; + } + + return pElement; +} + +Codec::Codec(a_util::memory::shared_ptr pLayout, void* pData, size_t nDataSize, + DataRepresentation eRep): + Decoder(pLayout, pData, nDataSize, eRep) +{ +} + +Codec::Codec(const Decoder& oDecoder, void* pData, size_t nDataSize, DataRepresentation eRep): + Decoder(oDecoder, pData, nDataSize, eRep) +{ +} + +a_util::result::Result Codec::setElementValue(size_t nIndex, const void* pValue) +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->setValue(*pElement, + const_cast(_data), + _data_size, + pValue); +} + +a_util::result::Result Codec::setElementValue(size_t nIndex, const a_util::variant::Variant& oValue) +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->setValue(*pElement, const_cast(_data), + _data_size, oValue); +} + +void* Codec::getElementAddress(size_t nIndex) +{ + return const_cast(StaticDecoder::getElementAddress(nIndex)); +} + +a_util::result::Result Codec::setConstants() +{ + if (_layout->hasEnums()) + { + size_t nElementCount = getElementCount(); + for (size_t nElement = 0; nElement < nElementCount; ++nElement) + { + const StructLayoutElement* pElement = getLayoutElement(nElement); + if (pElement->constant) + { + RETURN_IF_FAILED(_element_accessor->setValue(*pElement, const_cast(_data), + _data_size, *pElement->constant)); + } + } + } + + return a_util::result::SUCCESS; +} + +} diff --git a/codec/codec.h b/codec/codec.h new file mode 100644 index 0000000..ed10c09 --- /dev/null +++ b/codec/codec.h @@ -0,0 +1,161 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_CODEC_CLASS_HEADER +#define DDL_CODEC_CLASS_HEADER + +#include "a_util/result.h" + +#include "static_codec.h" + +namespace ddl +{ + +class Codec; + +/** + * Decoder for dynamic structures defined by a DDL definition. + */ +class Decoder: public StaticDecoder +{ + public: + /** + * @copydoc StaticDecoder::isValid + */ + virtual a_util::result::Result isValid() const; + + /** + * @copydoc StaticDecoder::getElementCount + */ + virtual size_t getElementCount() const; + + /** + * @param[in] rep The data representation for which the buffer size should be returned. + * @return The size of the structure in the requested data representation. + */ + size_t getBufferSize(DataRepresentation rep = deserialized) const; + + /** + * Create a new codec with the current dynamic structure layout for a new data buffer. + * @param[in] data The pointer to the new raw data. + * @param[in] data_size The size of the new raw data. + * @param[in] rep The representation that the data should be encoded in. + * @return A codec. + */ + Codec makeCodecFor(void* data, size_t data_size, DataRepresentation rep) const; + + protected: + friend class CodecFactory; + /// For internal use only. @internal + Decoder(a_util::memory::shared_ptr layout, const void* data, size_t data_size, + DataRepresentation rep); + /// For internal use only. @internal + Decoder(const Decoder& decoder, const void* data, size_t data_size, + DataRepresentation rep); + /// For internal use only. @internal + virtual const StructLayoutElement* getLayoutElement(size_t index) const; + + private: + /// For internal use only. @internal + a_util::result::Result calculateDynamicElements(); + /// For internal use only. @internal + a_util::result::Result addDynamicElements(const DynamicStructLayoutElement& dynamic_element, + Offsets& overall_offsets, + const std::string& prefix); + /// For internal use only. @internal + a_util::result::Result addDynamicElement(const DynamicStructLayoutElement& dynamic_element, + const std::string& array_index, + Offsets& overall_offsets, + const std::string& prefix); + /// For internal use only. @internal + a_util::result::Result addStaticStructElements(const DynamicStructLayoutElement& dynamic_element, + const std::string& array_index, + Offsets& overall_offsets, + const std::string& prefix); + /// For internal use only. @internal + a_util::result::Result addDynamicStructElements(const DynamicStructLayoutElement& dynamic_element, + const std::string& array_index, + Offsets& overall_offsets, + const std::string& prefix); + /// For internal use only. @internal + a_util::result::Result addDynamicStructElement(const StructLayoutElement& element); + /// For internal use only. @internal + void moveToAlignment(size_t& bit_offset, size_t alignment); + + protected: + /// For internal use only. @internal + a_util::memory::shared_ptr > _dynamic_elements; + /// For internal use only. @internal + Offsets _buffer_sizes; +}; + +/** + * Decoder for dynamic structures defined by a DDL definition. + * Currently the amount of dynamic elements is determined during construction + * only (by the current values in the structure). + */ +class Codec: public Decoder +{ + public: + /** + * Sets the current value of the given element by copying its data + * from the passed-in location. + * @param[in] index The index of the element. + * @param[in] value The location where the data should be copied from. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result setElementValue(size_t index, const void* value); + + /** + * Sets the current value of the given element to the given value. + * @param[in] index The index of the element. + * @param[in] value The value. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result setElementValue(size_t index, const a_util::variant::Variant& value); + + /** + * @param[in] index The index of the element. + * @return A pointer to the element or NULL in case of an error. + */ + void* getElementAddress(size_t index); + using StaticDecoder::getElementAddress; + + /** + * Sets all elements to their constant values defined in the DDL. + * @return Standard result. + */ + a_util::result::Result setConstants(); + + protected: + friend class CodecFactory; + friend class Decoder; + /// For internal use only. @internal + Codec(a_util::memory::shared_ptr layout, void* data, size_t data_size, + DataRepresentation rep); + /// For internal use only. @internal + Codec(const Decoder& decoder, void* data, size_t data_size, + DataRepresentation rep); +}; + + +} + +#endif diff --git a/codec/codec.sources b/codec/codec.sources new file mode 100644 index 0000000..dca0ec2 --- /dev/null +++ b/codec/codec.sources @@ -0,0 +1,29 @@ +set(CODEC_DIR codec) + +set(CODEC_H_PUBLIC + ${CODEC_DIR}/pkg_codec.h + ${CODEC_DIR}/struct_element.h + ${CODEC_DIR}/access_element.h + ${CODEC_DIR}/static_codec.h + ${CODEC_DIR}/codec.h + ${CODEC_DIR}/codec_factory.h + ${CODEC_DIR}/bitserializer.h +) +set(CODEC_H + ${CODEC_H_PUBLIC} + ${CODEC_DIR}/struct_layout.h + ${CODEC_DIR}/element_accessor.h +) + +set(CODEC_CPP + ${CODEC_DIR}/struct_layout.cpp + ${CODEC_DIR}/element_accessor.cpp + ${CODEC_DIR}/static_codec.cpp + ${CODEC_DIR}/codec.cpp + ${CODEC_DIR}/codec_factory.cpp + ${CODEC_DIR}/bitserializer.cpp +) + +set(CODEC_INSTALL ${CODEC_H_PUBLIC}) +source_group(${CODEC_DIR} FILES ${CODEC_H} ${CODEC_CPP}) + diff --git a/codec/codec_factory.cpp b/codec/codec_factory.cpp new file mode 100644 index 0000000..0116eb6 --- /dev/null +++ b/codec/codec_factory.cpp @@ -0,0 +1,117 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "struct_layout.h" +#include "codec_factory.h" + +#include "ddlrepresentation/ddl_error.h" +#include "ddlrepresentation/ddldescription.h" +#include "ddlrepresentation/ddlimporter.h" +#include "ddlrepresentation/ddlversion.h" + +namespace ddl +{ +//define all needed error types and values locally +_MAKE_RESULT(-10, ERR_INVALID_INDEX) +_MAKE_RESULT(-20, ERR_NOT_FOUND) +_MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + +static a_util::result::Result getDDL(const char* strMediaDescription, + a_util::memory::unique_ptr& pDDL) +{ + DDLVersion version_helper = DDLVersion::ddl_version_current; + + ddl::DDLImporter oImporter; + a_util::memory::unique_ptr pDefaultDescription( + ddl::DDLDescription::createDefault(version_helper, 4)); + + RETURN_DDLERROR_IF_FAILED_DESC(oImporter.setXML(strMediaDescription), oImporter.getErrorDesc()); + RETURN_DDLERROR_IF_FAILED_DESC(oImporter.createPartial(pDefaultDescription.get(), + version_helper), + oImporter.getErrorDesc()); + + pDDL.reset(oImporter.getDDL()); + return a_util::result::SUCCESS; +} + +CodecFactory::CodecFactory(): + _layout(new StructLayout()), + _constructor_result(ERR_NOT_INITIALIZED) +{ +} + +CodecFactory::CodecFactory(const char* strStructName, const char* strMediaDescription) +{ + a_util::memory::unique_ptr pDDL; + _constructor_result = getDDL(strMediaDescription, pDDL); + if(isOk(_constructor_result)) + { + DDLComplex* pStruct = pDDL->getStructByName(strStructName); + if (pStruct) + { + _layout.reset(new StructLayout(pStruct)); + _constructor_result = _layout->isValid(); + } + else + { + _constructor_result = ERR_NOT_FOUND; + } + } + + if (!_layout) + { + _layout.reset(new StructLayout()); + } +} + +CodecFactory::CodecFactory(const DDLComplex* pStruct): + _layout(new StructLayout(pStruct)) +{ + _constructor_result = _layout->isValid(); +} + +a_util::result::Result CodecFactory::isValid() const +{ + return _constructor_result; +} + +size_t CodecFactory::getStaticElementCount() const +{ + return _layout->getStaticElements().size(); +} + +a_util::result::Result CodecFactory::getStaticElement(size_t nIndex, const StructElement*& pElement) const +{ + if (nIndex >= getStaticElementCount()) + { + return ERR_INVALID_INDEX; + } + pElement = &_layout->getStaticElements()[nIndex]; + + return a_util::result::SUCCESS; +} + +size_t CodecFactory::getStaticBufferSize(DataRepresentation eRep) const +{ + return _layout->getStaticBufferSize(eRep); +} + + +} diff --git a/codec/codec_factory.h b/codec/codec_factory.h new file mode 100644 index 0000000..3b58a1d --- /dev/null +++ b/codec/codec_factory.h @@ -0,0 +1,147 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_CODEC_FACTORY_CLASS_HEADER +#define DDL_CODEC_FACTORY_CLASS_HEADER + +#include "codec.h" + +#include "ddlrepresentation/ddlcomplex.h" +#include "struct_element.h" +#include "static_codec.h" + + + +namespace ddl +{ + +/** + * Factory class for ddl codecs. + */ +class CodecFactory +{ + public: + /** + * Empty constructor. This exists to enable uninitialized member variables of this type + * that are move-assigned later on. + */ + CodecFactory(); + + /** + * Constructor that take a DDL string for initialization. + * @param[in] struct_name The name of the struct for which codecs should be generated. + * @param[in] media_description The DDL description. + */ + CodecFactory(const char* struct_name, + const char* media_description); + + /** + * Constructor that uses an OO-DDL struct for initialization. + * @param[in] ddl_struct The struct definition. + */ + CodecFactory(const DDLComplex* ddl_struct); + + /** + * Check if the factory is in a valid state. + * @return Any errors during construction. + */ + a_util::result::Result isValid() const; + + /** + * Creates a static decoder for the given data. + * @param[in] data The pointer to the raw data. + * @param[in] data_size The size of the raw data. + * @param[in] rep The representation that the data is encoded in. + * @return a static decoder. + */ + inline StaticDecoder makeStaticDecoderFor(const void* data, size_t data_size, + DataRepresentation rep = deserialized) const + { + return StaticDecoder(_layout, data, data_size, rep); + } + + /** + * Creates a static codec for the given data. + * @param[in] data The pointer to the raw data. + * @param[in] data_size The size of the raw data. + * @param[in] rep The representation that the data is encoded in. + * @return a static codec. + */ + inline StaticCodec makeStaticCodecFor(void* data, size_t data_size, + DataRepresentation rep = deserialized) const + { + return StaticCodec(_layout, data, data_size, rep); + } + + /** + * Creates a decoder for the given data. + * @param[in] data The pointer to the raw data. + * @param[in] data_size The size of the raw data. + * @param[in] rep The representation that the data is encoded in. + * @return a decoder. + */ + inline Decoder makeDecoderFor(const void* data, size_t data_size, + DataRepresentation rep = deserialized) const + { + return Decoder(_layout, data, data_size, rep); + } + + /** + * Creates a codec for the given data. + * @param[in] data The pointer to the raw data. + * @param[in] data_size The size of the raw data. + * @param[in] rep The representation that the data is encoded in. + * @return a codec. + */ + inline Codec makeCodecFor(void* data, size_t data_size, + DataRepresentation rep = deserialized) const + { + return Codec(_layout, data, data_size, rep); + } + + /** + * @return The amount of static elements contained in the handled structure. + */ + size_t getStaticElementCount() const; + + /** + * Access information about an element. + * @param[in] index The index of the element. + * @param[out] element Pointer that will be updated to point to the element information. + * @retval ERR_INVALID_INDEX Invalid index. + */ + a_util::result::Result getStaticElement(size_t index, const StructElement*& element) const; + + /** + * @param[in] rep The data representation for which the buffer size should be returned. + * @return The size of the structure in the requested data representation. + */ + size_t getStaticBufferSize(DataRepresentation rep = deserialized) const; + + private: + /// For internal use only. @internal The struct layout. + a_util::memory::shared_ptr _layout; + /// For internal use only. @internal The constructor result. + a_util::result::Result _constructor_result; +}; + +} + +#endif diff --git a/codec/element_accessor.cpp b/codec/element_accessor.cpp new file mode 100644 index 0000000..b3b93dd --- /dev/null +++ b/codec/element_accessor.cpp @@ -0,0 +1,228 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "a_util/result/error_def.h" +#include "a_util/variant.h" +#include "a_util/memory.h" +#include "element_accessor.h" +#include "legacy_error_macros.h" +#include "bitserializer.h" + +namespace ddl +{ + +//define all needed error types and values locally +_MAKE_RESULT(-5, ERR_INVALID_ARG) +_MAKE_RESULT(-19, ERR_NOT_SUPPORTED) + +template +a_util::result::Result get_typed_element_value(const StructLayoutElement& sElement, const void* pData, + size_t nDataSize, a_util::variant::Variant& oValue, + const ElementAccessor& oAccessor) +{ + T xValue; + RETURN_IF_FAILED(oAccessor.getValue(sElement, pData, nDataSize, &xValue)); + oValue = xValue; + return a_util::result::SUCCESS; +} + +#define GET_CASE_TYPE(__variant_type, __data_type) \ + case a_util::variant::__variant_type: \ +{ \ + return get_typed_element_value<__data_type>(sElement, pData, nDataSize, oValue, *this); \ +} + +template +a_util::result::Result set_typed_element_value(const StructLayoutElement& sElement, void* pData, + size_t nDataSize, const a_util::variant::Variant& oValue, + const ElementAccessor& oAccessor) +{ + T xHelper = oValue; + return oAccessor.setValue(sElement, pData, nDataSize, &xHelper); +} + +#define SET_CASE_TYPE(__variant_type, __data_type) \ + case a_util::variant::__variant_type: \ +{ \ + return set_typed_element_value<__data_type>(sElement, pData, nDataSize, oValue, *this); \ +} + +a_util::result::Result ElementAccessor::getValue(const StructLayoutElement& sElement, const void* pData, + size_t nDataSize, a_util::variant::Variant& oValue) const +{ + switch(sElement.type) + { + GET_CASE_TYPE(VT_Bool, bool) + GET_CASE_TYPE(VT_Int8, int8_t) + GET_CASE_TYPE(VT_UInt8, uint8_t) + GET_CASE_TYPE(VT_Int16, int16_t) + GET_CASE_TYPE(VT_UInt16, uint16_t) + GET_CASE_TYPE(VT_Int32, int32_t) + GET_CASE_TYPE(VT_UInt32, uint32_t) + GET_CASE_TYPE(VT_Int64, int64_t) + GET_CASE_TYPE(VT_UInt64, uint64_t) + GET_CASE_TYPE(VT_Float32, float) + GET_CASE_TYPE(VT_Float64, double) + default: return ERR_NOT_SUPPORTED; + } +} + +a_util::result::Result ElementAccessor::setValue(const StructLayoutElement& sElement, void* pData, + size_t nDataSize, const a_util::variant::Variant& oValue) const +{ + switch(sElement.type) + { + SET_CASE_TYPE(VT_Bool, bool) + SET_CASE_TYPE(VT_Int8, int8_t) + SET_CASE_TYPE(VT_UInt8, uint8_t) + SET_CASE_TYPE(VT_Int16, int16_t) + SET_CASE_TYPE(VT_UInt16, uint16_t) + SET_CASE_TYPE(VT_Int32, int32_t) + SET_CASE_TYPE(VT_UInt32, uint32_t) + SET_CASE_TYPE(VT_Int64, int64_t) + SET_CASE_TYPE(VT_UInt64, uint64_t) + SET_CASE_TYPE(VT_Float32, float) + SET_CASE_TYPE(VT_Float64, double) + default: return ERR_NOT_SUPPORTED; + } +} + +a_util::result::Result DeserializedAccessor::getValue(const StructLayoutElement& sElement, const void* pData, + size_t nDataSize, void* pElementValue) const +{ + assert(sElement.deserialized.bit_offset % 8 == 0); + assert(sElement.deserialized.bit_size % 8 == 0); + size_t nByteOffset = sElement.deserialized.bit_offset / 8; + size_t nByteSize = sElement.deserialized.bit_size / 8; + if (nDataSize < nByteOffset + nByteSize) + { + return ERR_INVALID_ARG; + } + a_util::memory::copy(pElementValue, nByteSize, + reinterpret_cast(static_cast(pData) + nByteOffset), + nByteSize); + return a_util::result::SUCCESS; +} + +a_util::result::Result DeserializedAccessor::setValue(const StructLayoutElement& sElement, void* pData, + size_t nDataSize, const void* pElementValue) const +{ + assert(sElement.deserialized.bit_offset % 8 == 0); + assert(sElement.deserialized.bit_size % 8 == 0); + size_t nByteOffset = sElement.deserialized.bit_offset / 8; + size_t nByteSize = sElement.deserialized.bit_size / 8; + if (nDataSize < nByteOffset + nByteSize) + { + return ERR_INVALID_ARG; + } + a_util::memory::copy(static_cast(pData) + nByteOffset, nByteSize, + pElementValue, + nByteSize); + return a_util::result::SUCCESS; +} + +const ElementAccessor& DeserializedAccessor::getInstance() +{ + static DeserializedAccessor oInstance; + return oInstance; +} + +const ElementAccessor& SerializedAccessor::getInstance() +{ + static SerializedAccessor oInstance; + return oInstance; +} + + +template +a_util::result::Result read_typed_bits(const StructLayoutElement& sElement, const void* pData, + size_t nDataSize, void* pElementValue) +{ + a_util::memory::BitSerializer oHelper(const_cast(pData), nDataSize); + return oHelper.read(sElement.serialized.bit_offset, sElement.serialized.bit_size, + reinterpret_cast(pElementValue), + (a_util::memory::Endianess)sElement.byte_order); +} + +#define GET_CASE_TYPE_SER(__variant_type, __data_type) \ + case a_util::variant::__variant_type: \ +{ \ + return read_typed_bits<__data_type>(sElement, pData, nDataSize, pElementValue); \ +} + +a_util::result::Result SerializedAccessor::getValue(const StructLayoutElement& sElement, const void* pData, + size_t nDataSize, void* pElementValue) const +{ + switch(sElement.type) + { + GET_CASE_TYPE_SER(VT_Bool, bool) + GET_CASE_TYPE_SER(VT_Int8, int8_t) + GET_CASE_TYPE_SER(VT_UInt8, uint8_t) + GET_CASE_TYPE_SER(VT_Int16, int16_t) + GET_CASE_TYPE_SER(VT_UInt16, uint16_t) + GET_CASE_TYPE_SER(VT_Int32, int32_t) + GET_CASE_TYPE_SER(VT_UInt32, uint32_t) + GET_CASE_TYPE_SER(VT_Int64, int64_t) + GET_CASE_TYPE_SER(VT_UInt64, uint64_t) + GET_CASE_TYPE_SER(VT_Float32, float) + GET_CASE_TYPE_SER(VT_Float64, double) + default: return ERR_NOT_SUPPORTED; + } +} + +template +a_util::result::Result write_typed_bits(const StructLayoutElement& sElement, void* pData, + size_t nDataSize, const void* pElementValue) +{ + a_util::memory::BitSerializer oHelper(pData, nDataSize); + return oHelper.write(sElement.serialized.bit_offset, sElement.serialized.bit_size, + *reinterpret_cast(pElementValue), + (a_util::memory::Endianess)sElement.byte_order); +} + +#define SET_CASE_TYPE_SER(__variant_type, __data_type) \ + case a_util::variant::__variant_type: \ +{ \ + return write_typed_bits<__data_type>(sElement, pData, nDataSize, pElementValue); \ +} + +a_util::result::Result SerializedAccessor::setValue(const StructLayoutElement& sElement, void* pData, + size_t nDataSize, const void* pElementValue) const +{ + switch(sElement.type) + { + SET_CASE_TYPE_SER(VT_Bool, bool) + SET_CASE_TYPE_SER(VT_Int8, int8_t) + SET_CASE_TYPE_SER(VT_UInt8, uint8_t) + SET_CASE_TYPE_SER(VT_Int16, int16_t) + SET_CASE_TYPE_SER(VT_UInt16, uint16_t) + SET_CASE_TYPE_SER(VT_Int32, int32_t) + SET_CASE_TYPE_SER(VT_UInt32, uint32_t) + SET_CASE_TYPE_SER(VT_Int64, int64_t) + SET_CASE_TYPE_SER(VT_UInt64, uint64_t) + SET_CASE_TYPE_SER(VT_Float32, float) + SET_CASE_TYPE_SER(VT_Float64, double) + default: return ERR_NOT_SUPPORTED; + } +} + + +} diff --git a/codec/element_accessor.h b/codec/element_accessor.h new file mode 100644 index 0000000..7c4faca --- /dev/null +++ b/codec/element_accessor.h @@ -0,0 +1,83 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_STRUCT_ELEMENT_ACCESS_PRIVATE_CLASS_HEADER +#define DDL_STRUCT_ELEMENT_ACCESS_PRIVATE_CLASS_HEADER + +#include "a_util/result.h" +#include "struct_layout.h" + +namespace ddl +{ + +class ElementAccessor +{ + public: + virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data, + size_t data_size, void* element_value) const = 0; + virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data, + size_t data_size, const void* element_value) const = 0; + + virtual DataRepresentation getRepresentation() const = 0; + + a_util::result::Result getValue(const StructLayoutElement& element, const void* data, + size_t data_size, a_util::variant::Variant& value) const; + + a_util::result::Result setValue(const StructLayoutElement& element, void* data, + size_t data_size, const a_util::variant::Variant& value) const; +}; + +class DeserializedAccessor: public ElementAccessor +{ + public: + virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data, + size_t data_size, void* element_value) const; + virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data, + size_t data_size, const void* element_value) const; + + virtual DataRepresentation getRepresentation() const + { + return deserialized; + } + + static const ElementAccessor& getInstance(); +}; + + +class SerializedAccessor: public ElementAccessor +{ + public: + virtual a_util::result::Result getValue(const StructLayoutElement& element, const void* data, + size_t data_size, void* element_value) const; + virtual a_util::result::Result setValue(const StructLayoutElement& element, void* data, + size_t data_size, const void* element_value) const; + + virtual DataRepresentation getRepresentation() const + { + return serialized; + } + + static const ElementAccessor& getInstance(); +}; + +} + +#endif + diff --git a/codec/pkg_codec.h b/codec/pkg_codec.h new file mode 100644 index 0000000..8f6c305 --- /dev/null +++ b/codec/pkg_codec.h @@ -0,0 +1,32 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef _DDL_CODEC_PKG_HEADER_ +#define _DDL_CODEC_PKG_HEADER_ + +#include "struct_element.h" +#include "static_codec.h" +#include "codec.h" +#include "codec_factory.h" +#include "access_element.h" +#include "bitserializer.h" + +#endif + diff --git a/codec/static_codec.cpp b/codec/static_codec.cpp new file mode 100644 index 0000000..c6b52d1 --- /dev/null +++ b/codec/static_codec.cpp @@ -0,0 +1,198 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "static_codec.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" +#include "element_accessor.h" + +namespace ddl +{ + +//define all needed error types and values locally +_MAKE_RESULT(-5, ERR_INVALID_ARG) +_MAKE_RESULT(-10, ERR_INVALID_INDEX) + +StaticDecoder::StaticDecoder(a_util::memory::shared_ptr pLayout, + const void* pData, size_t nDataSize, + DataRepresentation eRep): + _layout(pLayout), + _data(pData), + _data_size(nDataSize), + _element_accessor(eRep == deserialized ? + &DeserializedAccessor::getInstance() : + &SerializedAccessor::getInstance()) +{ +} + +a_util::result::Result StaticDecoder::isValid() const +{ + RETURN_IF_FAILED(_layout->isValid()); + if (_data_size < getStaticBufferSize(getRepresentation())) + { + return ERR_INVALID_ARG; + } + return a_util::result::SUCCESS; +} + +size_t StaticDecoder::getElementCount() const +{ + return _layout->getStaticElements().size(); +} + +a_util::result::Result StaticDecoder::getElement(size_t nIndex, const StructElement*& pElement) const +{ + pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result StaticDecoder::getElementValue(size_t nIndex, void* pValue) const +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->getValue(*pElement, _data, _data_size, pValue); +} + +a_util::result::Result StaticDecoder::getElementValue(size_t nIndex, a_util::variant::Variant& oValue) const +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->getValue(*pElement, _data, _data_size, oValue); +} + +const void* StaticDecoder::getElementAddress(size_t nIndex) const +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return NULL; + } + + size_t nBitPos = _element_accessor->getRepresentation() == deserialized ? + pElement->deserialized.bit_offset : + pElement->serialized.bit_offset; + + if (nBitPos % 8) + { + return NULL; + } + + size_t bit_size = _element_accessor->getRepresentation() == deserialized ? + pElement->deserialized.bit_size : + pElement->serialized.bit_size; + + if ((nBitPos / 8) + (bit_size / 8) + (bit_size % 8 ? 1 : 0) > + _data_size) + { + return NULL; + } + + return static_cast(_data) + (nBitPos / 8); +} + +const StructLayoutElement* StaticDecoder::getLayoutElement(size_t nIndex) const +{ + const StructLayoutElement* pElement = NULL; + if (nIndex < _layout->getStaticElements().size()) + { + pElement = &_layout->getStaticElements()[nIndex]; + } + + return pElement; +} + +size_t StaticDecoder::getStaticBufferSize(DataRepresentation eRep) const +{ + return _layout->getStaticBufferSize(eRep); +} + +DataRepresentation StaticDecoder::getRepresentation() const +{ + return _element_accessor->getRepresentation(); +} + +StaticCodec::StaticCodec(a_util::memory::shared_ptr pLayout, + void* pData, size_t nDataSize, DataRepresentation eRep): + StaticDecoder(pLayout, pData, nDataSize, eRep) +{ +} + +a_util::result::Result StaticCodec::setElementValue(size_t nIndex, const void* pValue) +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->setValue(*pElement, + const_cast(_data), + _data_size, + pValue); +} + +a_util::result::Result StaticCodec::setElementValue(size_t nIndex, const a_util::variant::Variant& oValue) +{ + const StructLayoutElement* pElement = getLayoutElement(nIndex); + if (!pElement) + { + return ERR_INVALID_INDEX; + } + return _element_accessor->setValue(*pElement, const_cast(_data), + _data_size, oValue); +} + +void* StaticCodec::getElementAddress(size_t nIndex) +{ + return const_cast(StaticDecoder::getElementAddress(nIndex)); +} + +a_util::result::Result StaticCodec::setConstants() +{ + if (_layout->hasEnums()) + { + size_t nElementCount = getElementCount(); + for (size_t nElement = 0; nElement < nElementCount; ++nElement) + { + const StructLayoutElement* pElement = getLayoutElement(nElement); + if (pElement->constant) + { + RETURN_IF_FAILED(_element_accessor->setValue(*pElement, const_cast(_data), + _data_size, *pElement->constant)); + } + } + } + + return a_util::result::SUCCESS; +} + + +} diff --git a/codec/static_codec.h b/codec/static_codec.h new file mode 100644 index 0000000..a6d9982 --- /dev/null +++ b/codec/static_codec.h @@ -0,0 +1,181 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_STATIC_CODEC_CLASS_HEADER +#define DDL_STATIC_CODEC_CLASS_HEADER + +#include "a_util/result.h" +#include "a_util/variant.h" +#include "a_util/memory.h" + +#include "struct_element.h" + +namespace ddl +{ + +class StructLayout; +class ElementAccessor; + +/** + * Decoder for static structures defined by a DDL definition. + */ +class StaticDecoder +{ + public: + /** + * Noncopyable + */ + StaticDecoder(const StaticDecoder&) = delete; + + /** + * Noncopyable + */ + StaticDecoder& operator=(const StaticDecoder&) = delete; + + /** + * Move constructor. + */ + StaticDecoder(StaticDecoder&&) = default; + + /** + * Move assignment operator. + */ + StaticDecoder& operator=(StaticDecoder&&) = default; + + /** + * @return Whether or not the decoder is valid. + * @retval ERR_INVALID_ARG The passed data is not large enough. + */ + virtual a_util::result::Result isValid() const; + + /** + * @return The amount of elements contained in the data structure. + */ + virtual size_t getElementCount() const; + + /** + * Access information about an element. + * @param[in] index The index of the element. + * @param[out] element Pointer that will be updated to point to the element information. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result getElement(size_t index, const StructElement*& element) const; + + /** + * Returns the current value of the given element by copying its data + * to the passed-in location. + * @param[in] index The index of the element. + * @param[out] value The location where the value should be copied to. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result getElementValue(size_t index, void* value) const; + + /** + * Returns the current value of the given element as a variant. + * @param[in] index The index of the element. + * @param[out] value The will be set to the current value. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result getElementValue(size_t index, a_util::variant::Variant& value) const; + + /** + * @param[in] index The index of the element. + * @return A pointer to the element or NULL in case of an error. + */ + const void* getElementAddress(size_t index) const; + + /** + * @param[in] rep The data representation for which the buffer size should be returned. + * @return The size of the structure in the requested data representation. + */ + size_t getStaticBufferSize(DataRepresentation rep = deserialized) const; + + /** + * @return The data representation which this decoder handles. + */ + DataRepresentation getRepresentation() const; + + protected: + friend class CodecFactory; + + /// For internal use only. @internal + StaticDecoder(a_util::memory::shared_ptr layout, + const void* data, size_t data_size, + DataRepresentation rep); + /// For internal use only. @internal + virtual const StructLayoutElement* getLayoutElement(size_t index) const; + + protected: + /// For internal use only. @internal + a_util::memory::shared_ptr _layout; + /// For internal use only. @internal + const void* _data; + /// For internal use only. @internal + size_t _data_size; + /// For internal use only. @internal + const ElementAccessor* _element_accessor; +}; + +/** + * Codec for static structures defined by a DDL definition. + */ +class StaticCodec: public StaticDecoder +{ + public: + /** + * Sets the current value of the given element by copying its data + * from the passed-in location. + * @param[in] index The index of the element. + * @param[in] value The location where the data should be copied from. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result setElementValue(size_t index, const void* value); + + /** + * Sets the current value of the given element to the given value. + * @param[in] index The index of the element. + * @param[in] value The value. + * @retval ERR_INVALID_INDEX Invalid element index. + */ + a_util::result::Result setElementValue(size_t index, const a_util::variant::Variant& value); + + /** + * @param[in] index The index of the element. + * @return A pointer to the element or NULL in case of an error. + */ + void* getElementAddress(size_t index); + using StaticDecoder::getElementAddress; + + /** + * Sets all elements to their constant values defined in the DDL. + * @return Standard result. + */ + a_util::result::Result setConstants(); + + private: + friend class CodecFactory; + /// For internal use only. @internal + StaticCodec(a_util::memory::shared_ptr layout, void* data, size_t data_size, + DataRepresentation rep); +}; + +} + +#endif diff --git a/codec/struct_element.h b/codec/struct_element.h new file mode 100644 index 0000000..3b0edda --- /dev/null +++ b/codec/struct_element.h @@ -0,0 +1,115 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_STRUCT_ELEMENT_CLASS_HEADER +#define DDL_STRUCT_ELEMENT_CLASS_HEADER + +#include +#include +#include "a_util/variant.h" +#include "a_util/result.h" + +namespace ddl +{ + +/** + * Enumeration for the data representation + */ +enum DataRepresentation +{ + serialized, ///< serialized data, i.e network, on disks, can msgs, ... + deserialized ///< deserialized data, c-structs, arrays, ... +}; + +/** + * Typedef for enumerations name -> value. + */ +typedef std::map EnumType; + +/** + * Information about an element accessible with a decoder or codec. + */ +struct StructElement +{ + std::string name; ///< The full name of the element. + a_util::variant::VariantType type; ///< The type of the element. + const EnumType* p_enum; ///< pointer to an enum, can be NULL. +}; + +// The following classes are for internal use only + +/** + * \cond INTERNAL + */ + +struct Position +{ + size_t bit_offset; + size_t bit_size; +}; + +struct StructLayoutElement: public StructElement +{ + Position deserialized; + Position serialized; + int byte_order; + const a_util::variant::Variant* constant; +}; + +struct DynamicStructLayoutElement +{ + std::string name; + size_t alignment; + std::string size_element_name; + std::vector static_elements; + std::vector dynamic_elements; + + DynamicStructLayoutElement() = default; + + DynamicStructLayoutElement(size_t alignment): + alignment(alignment) + { + } + + bool isAlignmentElement() const + { + return name.empty(); + } + + bool isDynamicArray() const + { + return !size_element_name.empty(); + } +}; + +struct Offsets +{ + size_t deserialized; + size_t serialized; +}; + +/** + * \endcond INTERNAL + */ + +} + +#endif + diff --git a/codec/struct_layout.cpp b/codec/struct_layout.cpp new file mode 100644 index 0000000..f028695 --- /dev/null +++ b/codec/struct_layout.cpp @@ -0,0 +1,345 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "struct_layout.h" + +#include + +namespace ddl +{ +//define all needed error types and values locally +_MAKE_RESULT(-5, ERR_INVALID_ARG) +_MAKE_RESULT(-19, ERR_NOT_SUPPORTED) +_MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + +StructLayout::StructLayout(const DDLComplex* pStruct) +{ + _static_buffer_sizes.deserialized = 0; + _static_buffer_sizes.serialized = 0; + _calculations_result = calculate(pStruct); +} + +StructLayout::StructLayout(): + _calculations_result(ERR_NOT_INITIALIZED) +{ + _static_buffer_sizes.deserialized = 0; + _static_buffer_sizes.serialized = 0; +} + +#define IF_TYPE(__type, __vtype, __size) \ + if (strType == __type) \ +{ \ + type = a_util::variant::__vtype;\ + nTypeSize = __size; \ + return a_util::result::SUCCESS; \ +} + +static a_util::result::Result getType(const std::string& strType, a_util::variant::VariantType& type, size_t& nTypeSize) +{ + IF_TYPE("tBool", VT_Bool, 8) + else IF_TYPE("tChar", VT_Int8, 8) + else IF_TYPE("tInt8", VT_Int8, 8) + else IF_TYPE("tUInt8", VT_UInt8, 8) + else IF_TYPE("tInt16", VT_Int16, 16) + else IF_TYPE("tUInt16", VT_UInt16, 16) + else IF_TYPE("tInt32", VT_Int32, 32) + else IF_TYPE("tUInt32", VT_UInt32, 32) + else IF_TYPE("tInt64", VT_Int64, 64) + else IF_TYPE("tUInt64", VT_UInt64, 64) + else IF_TYPE("tFloat32", VT_Float32, 32) + else IF_TYPE("tFloat64", VT_Float64, 64) + + return ERR_NOT_SUPPORTED; +} + +class cConverter +{ + public: + cConverter(std::vector& static_elements, + std::vector& dynamic_elements, + std::map& oEnums): + m_bDynamicSectionStarted(false), + _static_elements(static_elements), + _dynamic_elements(dynamic_elements), + _enums(oEnums) + { + m_sOffsets.deserialized = 0; + m_sOffsets.serialized = 0; + } + + a_util::result::Result Convert(DDLComplex* pStruct) + { + return addStruct(pStruct, "", m_sOffsets.serialized, pStruct->getDDLVersion() >= DDLVersion::ddl_version_30); + } + + Offsets getStaticBufferBitSizes() + { + return m_sOffsets; + } + + private: + + // we are not using a standard visitor pattern because we would have to recreate a stack + // for passing along all the additional parameters + a_util::result::Result Add(IDDLDataType* pType, const std::string& strFullName, size_t& nSerializedOffset, + int byte_order, int nNumBits, const std::string& strConstant, bool is_last_array_element) + { + DDLDataType* pPODType = dynamic_cast(pType); + DDLEnum* p_enum = dynamic_cast(pType); + EnumType* pCodecEnum = NULL; + if (p_enum) + { + pPODType = dynamic_cast(p_enum->getTypeObject()); + pCodecEnum = GetCodecEnum(p_enum); + } + + if (pPODType) + { + return AddPODElement(pPODType, strFullName, nSerializedOffset, byte_order, + nNumBits, pCodecEnum, strConstant); + } + else + { + DDLComplex* pStruct = dynamic_cast(pType); + if (pStruct) + { + return addStruct(pStruct, strFullName, nSerializedOffset, + // prior to DDL 3.0 the last array element is not padded to the alignment + !is_last_array_element || pStruct->getDDLVersion() >= DDLVersion::ddl_version_30); + } + + return ERR_INVALID_ARG; + } + } + + EnumType* GetCodecEnum(DDLEnum* p_enum) + { + std::map::iterator itEnum = _enums.find(p_enum->getName()); + if (itEnum == _enums.end()) + { + EnumType oCodecEnum; + const EnumNameValueVec& vecValues = p_enum->getValues(); + for (EnumNameValueVec::const_iterator it = vecValues.begin(); it != vecValues.end(); ++it) + { + oCodecEnum.insert(std::make_pair(it->first, a_util::variant::Variant(it->second.c_str()))); + } + itEnum = _enums.insert(std::make_pair(p_enum->getName(), oCodecEnum)).first; + } + return &itEnum->second; + } + + a_util::result::Result AddPODElement(DDLDataType* pDataType, const std::string& strFullName, + size_t& nSerializedOffset, int byte_order, int nNumBits, + EnumType* p_enum, + const std::string& strConstant) + { + StructLayoutElement sElement; + sElement.name = strFullName; + RETURN_IF_FAILED(getType(pDataType->getName(), sElement.type, sElement.deserialized.bit_size)); + sElement.deserialized.bit_offset = m_sOffsets.deserialized; + sElement.serialized.bit_offset = nSerializedOffset; + sElement.serialized.bit_size = nNumBits ? nNumBits : pDataType->getNumBits(); + sElement.byte_order = byte_order; + sElement.p_enum = p_enum; + sElement.constant = FindConstant(strConstant); + _static_elements.push_back(sElement); + + m_sOffsets.deserialized += sElement.deserialized.bit_size; + nSerializedOffset += sElement.serialized.bit_size; + return a_util::result::SUCCESS; + } + + const a_util::variant::Variant* FindConstant(const std::string& strConstant) + { + if (!strConstant.empty()) + { + for (std::map::const_iterator it = _enums.begin(); it != _enums.end(); ++it) + { + EnumType::const_iterator itValue = it->second.find(strConstant); + if (itValue != it->second.end()) + { + return &itValue->second; + } + } + } + + return NULL; + } + + a_util::result::Result addStruct(DDLComplex* pStruct, const std::string& strFullName, size_t& nSerializedOffset, bool resize_to_alignment) + { + std::string strStructPrefix = (!strFullName.empty()) ? strFullName + "." : ""; + + bool bWasDynamicSectionStartedBefore = m_bDynamicSectionStarted; + size_t nStructBaseOffset = m_sOffsets.deserialized; + + size_t nMaxSerializedOffset = nSerializedOffset; + DDLElementVec& vecElements = pStruct->getElements(); + for (DDLElementVec::iterator it = vecElements.begin(); it != vecElements.end(); ++it) + { + size_t nElementOffset = nSerializedOffset; + RETURN_IF_FAILED(addElement(*it, strStructPrefix, + nElementOffset, + nStructBaseOffset)); + nMaxSerializedOffset = std::max(nMaxSerializedOffset, nElementOffset); + } + nSerializedOffset = nMaxSerializedOffset; + + if (resize_to_alignment) + { + MoveOffsetToAlignment(pStruct->getAlignment(), nStructBaseOffset); + } + + if (m_bDynamicSectionStarted && !bWasDynamicSectionStartedBefore) + { + // add an alignment marker to ensure that the next element starts at the + // correct position + _dynamic_elements.push_back(pStruct->getAlignment()); + } + + return a_util::result::SUCCESS; + } + + void MoveOffsetToAlignment(DDLAlignment::AlignmentType eAlignment, size_t alignment_base_offset) + { + size_t nRelativeOffset = m_sOffsets.deserialized - alignment_base_offset; + size_t nBitRest = nRelativeOffset % 8; + if (nBitRest) + { + nRelativeOffset += 8 - nBitRest; + } + + size_t nByteOffset = nRelativeOffset / 8; + size_t nRest = nByteOffset % eAlignment; + if (nRest) + { + nRelativeOffset += (eAlignment - nRest) * 8; + } + m_sOffsets.deserialized = alignment_base_offset + nRelativeOffset; + } + + a_util::result::Result addElement(DDLElement* pElement, const std::string& strStructPrefix, size_t& nSerializedOffset, size_t nStructBaseOffset) + { + if (!m_bDynamicSectionStarted) + { + m_bDynamicSectionStarted = pElement->getArraysize() == 0; + } + + if (!m_bDynamicSectionStarted) + { + MoveOffsetToAlignment(pElement->getAlignment(), nStructBaseOffset); + nSerializedOffset += pElement->getBytepos() * 8 + pElement->getBitpos(); + } + + size_t nArraySize = std::max(pElement->getArraysize(), 1u); + for (size_t nArrayIndex = 0; nArrayIndex < nArraySize; ++nArrayIndex) + { + std::string strCurrentElementName = strStructPrefix + pElement->getName(); + if (nArraySize > 1) + { + strCurrentElementName += a_util::strings::format("[%d]", nArrayIndex); + } + + if (!m_bDynamicSectionStarted) + { + RETURN_IF_FAILED(Add(pElement->getTypeObject(), strCurrentElementName, + nSerializedOffset, pElement->getByteorder(), + pElement->getNumBits(), + pElement->getConstantValue(), + nArrayIndex == nArraySize - 1)); + } + else + { + RETURN_IF_FAILED(addDynamicElement(pElement, strCurrentElementName, strStructPrefix)); + } + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result addDynamicElement(const DDLElement* pElement, const std::string& strFullName, + const std::string& strStructPrefix) + { + DynamicStructLayoutElement sDynamicElement; + + cConverter oChildConverter(sDynamicElement.static_elements, + sDynamicElement.dynamic_elements, + _enums); + size_t nDummy = 0; + RETURN_IF_FAILED(oChildConverter.Add(pElement->getTypeObject(), "", + nDummy, pElement->getByteorder(), + pElement->getNumBits(), + pElement->getConstantValue(), + false)); + + sDynamicElement.name = strFullName; + sDynamicElement.alignment = pElement->getAlignment(); + + if (pElement->getArraysize() == 0) + { + if (pElement->getArraySizeSource().empty()) + { + return ERR_INVALID_ARG; + } + + sDynamicElement.size_element_name = strStructPrefix + pElement->getArraySizeSource(); + } + + _dynamic_elements.push_back(sDynamicElement); + + return a_util::result::SUCCESS; + } + + protected: + Offsets m_sOffsets; + bool m_bDynamicSectionStarted; + std::vector& _static_elements; + std::vector& _dynamic_elements; + std::map& _enums; +}; + +a_util::result::Result StructLayout::calculate(const DDLComplex* pStruct) +{ + cConverter oConverter(_static_elements, + _dynamic_elements, + _enums); + RETURN_IF_FAILED(oConverter.Convert(const_cast(pStruct))); + _static_buffer_sizes = oConverter.getStaticBufferBitSizes(); + + return a_util::result::SUCCESS; +} + +size_t StructLayout::getStaticBufferSize(DataRepresentation eRep) const +{ + size_t nResult = eRep == deserialized ? + _static_buffer_sizes.deserialized : + _static_buffer_sizes.serialized; + if (nResult % 8) + { + return nResult / 8 + 1; + } + return nResult / 8; +} + +} + diff --git a/codec/struct_layout.h b/codec/struct_layout.h new file mode 100644 index 0000000..85f60a0 --- /dev/null +++ b/codec/struct_layout.h @@ -0,0 +1,87 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef DDL_STRUCT_LAYOUT_CLASS_HEADER +#define DDL_STRUCT_LAYOUT_CLASS_HEADER + +#include "struct_element.h" + +namespace ddl +{ + +class DDLComplex; + +/** + * @internal + * This class is for internal use only. + */ +class StructLayout +{ + public: + StructLayout(); + StructLayout(const DDLComplex* ddl_struct); + + a_util::result::Result isValid() const + { + return _calculations_result; + } + + const std::vector& getStaticElements() const + { + return _static_elements; + } + + const std::vector& getDynamicElements() const + { + return _dynamic_elements; + } + + bool hasDynamicElements() const + { + return !_dynamic_elements.empty(); + } + + bool hasEnums() const + { + return !_enums.empty(); + } + + const Offsets& getStaticBufferBitSizes() const + { + return _static_buffer_sizes; + } + + size_t getStaticBufferSize(DataRepresentation rep) const; + + private: + a_util::result::Result calculate(const DDLComplex* ddl_struct); + + private: + std::vector _static_elements; + std::vector _dynamic_elements; + std::map _enums; + Offsets _static_buffer_sizes; + a_util::result::Result _calculations_result; +}; + +} + +#endif + diff --git a/ddl.h b/ddl.h new file mode 100644 index 0000000..cd5cbfc --- /dev/null +++ b/ddl.h @@ -0,0 +1,31 @@ +/** + * @file + * Package header for DDL + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _PACKAGE_DDL_HEADER_ +#define _PACKAGE_DDL_HEADER_ + #include "ddlrepresentation/ddl_common.h" + + // Include individual DDL modules + #include "ddlrepresentation/pkg_ddlrepresentation.h" + #include "codec/pkg_codec.h" + #include "serialization/pkg_serialization.h" + #include "mapping/pkg_mapping.h" + +#endif // _PACKAGE_DDL_HEADER_ diff --git a/ddlgenerators/CMakeLists.txt b/ddlgenerators/CMakeLists.txt new file mode 100644 index 0000000..1ada913 --- /dev/null +++ b/ddlgenerators/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(generator_library) +add_subdirectory(ddl2header) +add_subdirectory(header2ddl) diff --git a/ddlgenerators/ddl2header/CMakeLists.txt b/ddlgenerators/ddl2header/CMakeLists.txt new file mode 100644 index 0000000..59fd056 --- /dev/null +++ b/ddlgenerators/ddl2header/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PROJECT_NAME ddl2header) + +set(SOURCES + main.cpp + ddl2header_commandline.h + ddl2header_commandline.cpp + ${DDL_GENERATOR_COMMON} + ${HEADER_PRESENTATION_H} + ${HEADER_PRESENTATION_CPP} +) + +if (WIN32) + #list(APPEND SOURCES native_resource.rc) +endif (WIN32) + +add_executable(${PROJECT_NAME} WIN32 ${SOURCES}) + +target_link_libraries(${PROJECT_NAME} + ddl + ddl_generator +) + +if(MSVC) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/SUBSYSTEM:console") +endif(MSVC) + +install(TARGETS ${PROJECT_NAME} DESTINATION ./bin/debug CONFIGURATIONS Debug) +install(TARGETS ${PROJECT_NAME} DESTINATION ./bin CONFIGURATIONS Release RelWithDebInfo) + +set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER ddl/utils) diff --git a/ddlgenerators/ddl2header/ddl2header_commandline.cpp b/ddlgenerators/ddl2header/ddl2header_commandline.cpp new file mode 100644 index 0000000..487ea73 --- /dev/null +++ b/ddlgenerators/ddl2header/ddl2header_commandline.cpp @@ -0,0 +1,79 @@ +/** +* @file +* @copyright +* @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "ddl2header_commandline.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} +using namespace ddl_generator::oo; + +namespace ddl +{ + DDL2HeaderCommandLine::DDL2HeaderCommandLine(): CommandLine() + { + _cli |= getNamespaceOpt(); + _cli |= getDisplaceableStringOpt(); + } + + std::string DDL2HeaderCommandLine::getNamespace() + { + return _opt_namespace; + } + + std::string DDL2HeaderCommandLine::getDisplaceableString() + { + return _opt_displaceable_string; + } + + void DDL2HeaderCommandLine::printExamples() + { + std::cout << std::endl << "If the target header file exists already the descriptions will be merged." << std::endl; + std::cout << "This can lead to data loss in the existing header file." << std::endl << std::endl; + std::cout << "examples: " << std::endl; + std::cout << " --headerfile=c:/myHeaderFile.h " << + "--descriptionfile=c:/myDescriptionFile.description"; + std::cout << std::endl << " or" << std::endl; + std::cout << " --headerfile=c:/myHeaderFile.h " << + "--descriptionfile=c:/myDescriptionFile.description "; + std::cout << "-struct=tMyStruct" << std::endl; + } + + clara::Opt DDL2HeaderCommandLine::getNamespaceOpt() + { + return clara::Opt(_opt_namespace, "name") + ["-n"]["--namespace"] + ("[Optional] Place all generated elements in this namespace"); + } + + clara::Opt DDL2HeaderCommandLine::getDisplaceableStringOpt() + { + return clara::Opt(_opt_displaceable_string, "string") + ["--displace"] + (" [Optional] Remove this string from beginning of all element names."); + + } + +} diff --git a/ddlgenerators/ddl2header/ddl2header_commandline.h b/ddlgenerators/ddl2header/ddl2header_commandline.h new file mode 100644 index 0000000..b6c63e3 --- /dev/null +++ b/ddlgenerators/ddl2header/ddl2header_commandline.h @@ -0,0 +1,47 @@ +/** +* @file +* @copyright +* @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef _DDL2HEADER_COMMAND_LINE_H_ +#define _DDL2HEADER_COMMAND_LINE_H_ + +#include "commandline.h" + +namespace ddl +{ + class DDL2HeaderCommandLine: public ddl::CommandLine + { + + public: + DDL2HeaderCommandLine(); + + std::string getNamespace(); + std::string getDisplaceableString(); + + protected: + void printExamples(); + + clara::Opt getNamespaceOpt(); + clara::Opt getDisplaceableStringOpt(); + + std::string _opt_namespace; + std::string _opt_displaceable_string; + + }; +} +#endif + diff --git a/ddlgenerators/ddl2header/main.cpp b/ddlgenerators/ddl2header/main.cpp new file mode 100644 index 0000000..348a9f5 --- /dev/null +++ b/ddlgenerators/ddl2header/main.cpp @@ -0,0 +1,66 @@ +/** + * @file + * Launcher. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include +#include "ddl2header_commandline.h" + +namespace ddl_generator +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) +} +} +using namespace ddl_generator::oo; + + +int main(int argc, char* argv[]) +{ + ddl::DDL2HeaderCommandLine cmdLine; + if (a_util::result::isFailed(cmdLine.parseArgs(argc, argv))) + { + return ERR_INVALID_ARG.getCode(); + } + + if (cmdLine.isHelpRequested()) + { + cmdLine.printHelp(); + return ERR_NOERROR.getCode(); + } + + if (a_util::result::isFailed(cmdLine.checkMandatoryArguments())) + { + return ERR_INVALID_ARG.getCode(); + } + + DDLUtilsCore core; + a_util::result::Result res = core.generateHeaderFile(cmdLine.getDescriptionFile(), + cmdLine.getHeaderFile(), cmdLine.getStruct(), cmdLine.getNamespace(), + cmdLine.getDisplaceableString()); + if (a_util::result::isFailed(res)) + { + LOG_ERROR("Error: An error occured during generating the header file."); + } + return res.getErrorCode(); +} + diff --git a/ddlgenerators/generator_library/CMakeLists.txt b/ddlgenerators/generator_library/CMakeLists.txt new file mode 100644 index 0000000..2cb4632 --- /dev/null +++ b/ddlgenerators/generator_library/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################################## +# Common Package Integration File for the LIB - ddl generator +# +# +################################################################## + +################################################################## +# Section for required other package to compile +find_package(Clara REQUIRED) #enable INTERFACE target Clara + +include(ddl_generator_lib.sources) +include_directories(${DDL_GENERATOR_LIB_INCLUDE_DIR}) + +set(SOURCES + ${DDL_GENERATOR_COMMON} + ${HEADER_PRESENTATION_H} + ${HEADER_PRESENTATION_CPP} +) + +add_library(ddl_generator STATIC ${SOURCES}) + +target_include_directories(ddl_generator PUBLIC + $ +) + +target_link_libraries(ddl_generator + ddl Clara) + + +set_target_properties(ddl_generator PROPERTIES FOLDER ddl/utils) \ No newline at end of file diff --git a/ddlgenerators/generator_library/commandline.cpp b/ddlgenerators/generator_library/commandline.cpp new file mode 100644 index 0000000..36ac931 --- /dev/null +++ b/ddlgenerators/generator_library/commandline.cpp @@ -0,0 +1,126 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include "commandline.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} +using namespace ddl_generator::oo; + +namespace ddl +{ + + CommandLine::CommandLine() + { + _cli |= clara::Help(_showhelp); + _cli |= getHeaderFileOpt(); + _cli |= getDescriptionFileOpt(); + _cli |= getStructOpt(); + } + + + CommandLine::~CommandLine() + { + } + + a_util::result::Result CommandLine::parseArgs(int argc, char* argv[]) + { + auto result = _cli.parse(clara::Args(argc, argv)); + if (!result) + { + std::cerr << "Error in command line: " << result.errorMessage() << std::endl; + return ERR_INVALID_ARG; + } + return ERR_NOERROR; + } + + bool CommandLine::isHelpRequested() + { + return _showhelp; + } + + void CommandLine::printHelp() + { + std::cout << _cli << std::endl; + printExamples(); + } + + a_util::result::Result CommandLine::checkMandatoryArguments() + { + a_util::result::Result result = ERR_NOERROR; + if (_opt_header_file.empty()) + { + std::cerr << "Error: No option 'headerfile' is set. " << + "Please use option '--help' for further information." << std::endl; + result = ERR_INVALID_ARG; + } + if (_opt_description_file.empty()) + { + std::cerr << "Error: No option 'descriptionfile' is set. " << + "Please use option '--help' for further information." << std::endl; + result = ERR_INVALID_ARG; + } + return result; + } + + std::string CommandLine::getHeaderFile() + { + return _opt_header_file; + } + + std::string CommandLine::getDescriptionFile() + { + return _opt_description_file; + } + + std::string CommandLine::getStruct() + { + return _opt_struct; + } + + clara::Opt CommandLine::getHeaderFileOpt() + { + return clara::Opt(_opt_header_file, "file") + ["-f"]["--headerfile"] + ("[Mandatory] The path to the header file."); + } + + clara::Opt CommandLine::getDescriptionFileOpt() + { + return clara::Opt(_opt_description_file, "file") + ["-d"]["--descriptionfile"] + ("[Mandatory] The path to the description file."); + } + + clara::Opt CommandLine::getStructOpt() + { + return clara::Opt(_opt_struct, "structName") + ["-s"]["--struct"] + ("[Optional] Just create the description file for the given struct " + "of the header file."); + } +} diff --git a/ddlgenerators/generator_library/commandline.h b/ddlgenerators/generator_library/commandline.h new file mode 100644 index 0000000..8584f0c --- /dev/null +++ b/ddlgenerators/generator_library/commandline.h @@ -0,0 +1,60 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _DDL_COMMAND_LINE_H_ +#define _DDL_COMMAND_LINE_H_ + +#include +#include + +namespace ddl +{ + class CommandLine + { + public: + CommandLine(); + virtual ~CommandLine(); + + a_util::result::Result parseArgs(int argc, char* argv[]); + bool isHelpRequested(); + void printHelp(); + virtual a_util::result::Result checkMandatoryArguments(); + + std::string getHeaderFile(); + std::string getDescriptionFile(); + std::string getStruct(); + + protected: + + virtual void printExamples() = 0; + + clara::Opt getHeaderFileOpt(); + clara::Opt getDescriptionFileOpt(); + clara::Opt getStructOpt(); + + + clara::Parser _cli; + bool _showhelp = false; + std::string _opt_header_file; + std::string _opt_description_file; + std::string _opt_struct; + }; +} +#endif + diff --git a/ddlgenerators/generator_library/ddl_generator_core.cpp b/ddlgenerators/generator_library/ddl_generator_core.cpp new file mode 100644 index 0000000..3484140 --- /dev/null +++ b/ddlgenerators/generator_library/ddl_generator_core.cpp @@ -0,0 +1,166 @@ +/** + * @file + * Implementation of core + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddl_generator_core.h" +#include + +namespace ddl_generator +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) +} +} +using namespace ddl_generator::oo; + +/*Helper function*/ +a_util::result::Result checkIfFileExists(const a_util::filesystem::Path& path) +{ + if (!a_util::filesystem::exists(path)) + { + return ERR_PATH_NOT_FOUND; + } + + return ERR_NOERROR; +} + + +/*DDLUtilsCore*/ +DDLUtilsCore::DDLUtilsCore() +{ + _ddl_manager = NULL; +} + +DDLUtilsCore::~DDLUtilsCore() +{ + delete _ddl_manager; + _ddl_manager = NULL; +} + +a_util::result::Result DDLUtilsCore::generateDescriptionFile(const a_util::filesystem::Path& header_path, + const a_util::filesystem::Path& description_path, + const ddl::DDLVersion& version /* 4.0 */, const std::string struct_name /*= ""*/) +{ + // check if description file still exists and struct has to be added + if (a_util::result::isOk(checkIfFileExists(description_path))) + { + std::string error_msg; + if (a_util::result::isFailed(setDescription(description_path, error_msg))) + { + LOG_INFO(error_msg.c_str()); + return (ERR_INVALID_FILE); + } + ddl::DDLVersion existing_version = _ddl_manager->getDDL()->getHeader()->getLanguageVersion(); + if (existing_version > version) + { + LOG_ERROR(a_util::strings::format( + "Exising description file has a newer Version (%s) as the requested Version (%s). Version downgrade is not possible!", + existing_version.toString().c_str(), version.toString().c_str()).c_str()); + return ERR_FAILED; + } + } + + std::string error_msg; + if (a_util::result::isFailed(setDescriptionFromHeader(header_path, description_path, + error_msg, version, struct_name))) + { + LOG_INFO(error_msg.c_str()); + return ERR_FAILED; + } + if (a_util::result::isFailed(_ddl_manager->searchForStructs())) + { + LOG_INFO("Info: No structs found in description file."); + return ERR_FAILED; + } + + // create description file + if (a_util::result::isFailed(_ddl_manager->printToDDLFile(description_path, error_msg))) + { + LOG_INFO("Error: Could not create file. %s", error_msg.c_str()); + return ERR_FAILED; + } + + LOG_INFO("Success: Description file created."); + return ERR_NOERROR; +} + +a_util::result::Result DDLUtilsCore::generateHeaderFile(const a_util::filesystem::Path& description_path, + const a_util::filesystem::Path& header_path, const std::string struct_name /*= ""*/, + const std::string name_space /*= ""*/, const std::string displace /*= ""*/) +{ + // check if description file still exists and struct has to be added + if (a_util::result::isOk(checkIfFileExists(header_path))) + { + std::string error_msg; + if (a_util::result::isFailed(setDescriptionFromHeader(header_path, description_path, error_msg))) + { + LOG_INFO(error_msg.c_str()); + return ERR_FAILED; + } + } + + std::string error_msg; + if (a_util::result::isFailed(setDescription(description_path, error_msg, struct_name))) + { + LOG_INFO(error_msg.c_str()); + return (ERR_INVALID_FILE); + } + + if (a_util::result::isFailed(_ddl_manager->printToHeaderFile(header_path, error_msg, name_space, displace))) + { + LOG_INFO("Error: Could not create header file. %s", error_msg.c_str()); + return (ERR_FAILED); + } + + LOG_INFO("Success: Header file created."); + return ERR_NOERROR; +} + +a_util::result::Result DDLUtilsCore::setDescription(const a_util::filesystem::Path& description_path, + std::string& error_msg, const std::string struct_name) +{ + if (!_ddl_manager) + { + _ddl_manager = new DDLManager(); + } + return _ddl_manager->mergeWithDDLFile(description_path, error_msg, struct_name); +} + +a_util::result::Result DDLUtilsCore::setDescriptionFromHeader(const a_util::filesystem::Path& header_path, + const a_util::filesystem::Path& description_path, std::string& error_msg, + const ddl::DDLVersion& version /*= 4.0*/, const std::string struct_name /*= ""*/) +{ + if (!_ddl_manager) + { + _ddl_manager = new DDLManager(); + } + + a_util::result::Result result = _ddl_manager->mergeWithHeaderFile(header_path, error_msg, version, struct_name); + if (a_util::result::isFailed(result)) + { + LOG_INFO("Error: Could not read header file '%s'.", header_path.toString().c_str()); + } + return result; +} diff --git a/ddlgenerators/generator_library/ddl_generator_core.h b/ddlgenerators/generator_library/ddl_generator_core.h new file mode 100644 index 0000000..1f5011a --- /dev/null +++ b/ddlgenerators/generator_library/ddl_generator_core.h @@ -0,0 +1,92 @@ +/** + * @file + * Implementation of core + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_GENERATOR_H +#define DDL_GENERATOR_H + +#include + +#include "ddl_manager.h" + +#define EXTENSION_DESCRIPTIONFILE "DESCRIPTION" +#define EXTENSION_HEADERFILE "H" + +class DDLUtilsCore +{ + +public: + /** + * CTOR + * @param [in] + */ + DDLUtilsCore(); + + /** + * DTOR + */ + ~DDLUtilsCore(); + + /** + * Create new ddl file from header file + * @param[in] header_path - path to the header file + * @param[in] description_path - path to the ddl file + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result generateDescriptionFile(const a_util::filesystem::Path& header_path, + const a_util::filesystem::Path& description_path, const ddl::DDLVersion& version = ddl::DDLVersion::ddl_version_current, + const std::string struct_name = ""); + /** + * Create new header file from ddl file + * @param[in] description_path - path to the ddl file + * @param[in] header_path - path to the header file + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result generateHeaderFile(const a_util::filesystem::Path& description_path, + const a_util::filesystem::Path& header_path, const std::string struct_name = "", const std::string name_space = "", const std::string displace = ""); + +private: + /** + * Add existing ddl file + * @param[in] description_path - path to the ddl file + * @param[out] error_msg - error message, gives more information if it failed + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result setDescription(const a_util::filesystem::Path& description_path, + std::string& error_msg, const std::string struct_name = ""); + /** + * Create new ddl file from header file + * @param[in] header_path - path to the header file + * @param[in] description_path - path to the new ddl file + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result setDescriptionFromHeader(const a_util::filesystem::Path& header_path, + const a_util::filesystem::Path& description_path, std::string& error_msg, + const ddl::DDLVersion& version = ddl::DDLVersion::ddl_version_current, const std::string struct_name = ""); + +private: + /// Mamanger map + DDLManager* _ddl_manager; +}; + +#endif //DDL_GENERATOR_H diff --git a/ddlgenerators/generator_library/ddl_generator_lib.sources b/ddlgenerators/generator_library/ddl_generator_lib.sources new file mode 100644 index 0000000..b5b5841 --- /dev/null +++ b/ddlgenerators/generator_library/ddl_generator_lib.sources @@ -0,0 +1,45 @@ + +set(HEADER_PRESENTATION_DIRECTORY_NAME headerrepresentation) +set(HEADER_PRESENTATION_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/${HEADER_PRESENTATION_DIRECTORY_NAME}) +set(DDL_GENERATOR_LIB_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}) + +set(HEADER_PRESENTATION_H ${HEADER_PRESENTATION_DIRECTORY}/ddl_to_header_converter.h + ${HEADER_PRESENTATION_DIRECTORY}/header_basic_type.h + ${HEADER_PRESENTATION_DIRECTORY}/header_constant.h + ${HEADER_PRESENTATION_DIRECTORY}/header_enum.h + ${HEADER_PRESENTATION_DIRECTORY}/header_header.h + ${HEADER_PRESENTATION_DIRECTORY}/header_importer.h + ${HEADER_PRESENTATION_DIRECTORY}/header_printer.h + ${HEADER_PRESENTATION_DIRECTORY}/header_struct.h + ${HEADER_PRESENTATION_DIRECTORY}/header_struct_element.h + ${HEADER_PRESENTATION_DIRECTORY}/header_to_ddl_converter.h + ${HEADER_PRESENTATION_DIRECTORY}/header_type.h + ${HEADER_PRESENTATION_DIRECTORY}/header_typedef.h + ${HEADER_PRESENTATION_DIRECTORY}/header_visitor_intf.h + ${HEADER_PRESENTATION_DIRECTORY}/header_factorymethod_intf.h + ${HEADER_PRESENTATION_DIRECTORY}/header_base_intf.h + ${HEADER_PRESENTATION_DIRECTORY}/parserhelper.h) + +set(HEADER_PRESENTATION_CPP + ${HEADER_PRESENTATION_DIRECTORY}/ddl_to_header_converter.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_basic_type.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_constant.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_enum.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_header.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_importer.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_printer.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_struct.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_struct_element.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_to_ddl_converter.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_type.cpp + ${HEADER_PRESENTATION_DIRECTORY}/header_typedef.cpp + ${HEADER_PRESENTATION_DIRECTORY}/parserhelper.cpp) + +set(DDL_GENERATOR_COMMON + ${CMAKE_CURRENT_LIST_DIR}/ddl_manager.h + ${CMAKE_CURRENT_LIST_DIR}/ddl_manager.cpp + ${CMAKE_CURRENT_LIST_DIR}/ddl_generator_core.h + ${CMAKE_CURRENT_LIST_DIR}/ddl_generator_core.cpp + ${CMAKE_CURRENT_LIST_DIR}/commandline.h + ${CMAKE_CURRENT_LIST_DIR}/commandline.cpp) + \ No newline at end of file diff --git a/ddlgenerators/generator_library/ddl_manager.cpp b/ddlgenerators/generator_library/ddl_manager.cpp new file mode 100644 index 0000000..c76619a --- /dev/null +++ b/ddlgenerators/generator_library/ddl_manager.cpp @@ -0,0 +1,396 @@ +/** + * @file + * Implementation of FEP MDE core + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddl_manager.h" +#include +#include "headerrepresentation/header_header.h" +#include "headerrepresentation/header_importer.h" +#include "headerrepresentation/header_to_ddl_converter.h" +#include "headerrepresentation/header_printer.h" +#include "headerrepresentation/ddl_to_header_converter.h" +#include + +namespace ddl_generator +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) +} +} + +using namespace ddl_generator::oo; + +DDLManager::DDLManager() +{ + _ddl_description = NULL; +} + +DDLManager::~DDLManager() +{ + if (NULL != _ddl_description) + { + ddl::DDLImporter::destroyDDL(_ddl_description); + _ddl_description = NULL; + } +} + +a_util::result::Result DDLManager::setDefaultDDL() +{ + if (_ddl_description == NULL) + { + _ddl_description = ddl::DDLDescription::createDefault(); + _ddl_description->getHeader()->setDescription("Generated with AEV Media Description Editor"); + } + return ERR_NOERROR; +} + +a_util::result::Result DDLManager::mergeWithDDLFile(const a_util::filesystem::Path& ddl_path, std::string& error_msg, const std::string& struct_name) +{ + if (!a_util::filesystem::exists(ddl_path)) + { + error_msg = a_util::strings::format("Description file '%s' not found.", ddl_path.toString().c_str()); + return ERR_PATH_NOT_FOUND; + } + + ddl::DDLImporter ddl_importer; + if (isFailed(ddl_importer.setFile(ddl_path))) + { + error_msg = a_util::strings::format("Error in File '%s': %s", ddl_path.getLastElement().toString().c_str(), ddl_importer.getErrorDesc().c_str()); + return ERR_FAILED; + } + ; + if (a_util::result::isFailed(ddl_importer.createNew())) + { + error_msg = ddl_importer.getErrorDesc(); + return ERR_INVALID_FILE; + } + + ddl::DDLDescription* imported_description = ddl_importer.getDDL(); + + a_util::result::Result res = ERR_NOERROR; + + // merge if dll already exists + if (struct_name.size() == 0) + { + if (_ddl_description == NULL) + { + _ddl_description = imported_description; + } + else + { + res = _ddl_description->merge(*imported_description, 2U); + // Destroy DDL + if (NULL != imported_description) + { + ddl::DDLImporter::destroyDDL(imported_description); + imported_description = NULL; + } + } + } + else + { + // get struct from description file + res = findStructRecursively(imported_description, struct_name); + if (a_util::result::isFailed(res)) + { + error_msg = a_util::strings::format("Error: Struct '%s' not found.", struct_name.c_str()); + } + // Destroy DDL + if (NULL != imported_description) + { + ddl::DDLImporter::destroyDDL(imported_description); + imported_description = NULL; + } + + } + + if (NULL == _ddl_description) + { + res = ERR_POINTER; + } + + return res; +} + +a_util::result::Result DDLManager::mergeWithHeaderFile( + const a_util::filesystem::Path& header_path, std::string& error_msg, + const ddl::DDLVersion& version /*= 4.0*/, const std::string& struct_name) +{ + if (!a_util::filesystem::exists(header_path)) + { + error_msg = a_util::strings::format("Headerfile '%s' not found", header_path.toString().c_str()); + return ERR_PATH_NOT_FOUND; + } + + ddl::HeaderImporter importer; + ddl::HeaderTypesVec* default_types = ddl::HeaderImporter::getDefaultTypes(); + if (isFailed((importer.setFileName(header_path)))) + { + return ERR_FAILED; + } + if (isFailed((importer.setKnownTypes(default_types)))) + { + return ERR_FAILED; + } + if (isFailed((importer.createNew()))) + { + error_msg = importer.getLastError(); + return ERR_FAILED; + } + if (importer.getLastError().length() > 0) + { + LOG_ERROR(importer.getLastError().c_str()); + return ERR_INVALID_FILE; + } + ddl::Header* header = importer.getHeader(); + if (NULL == header) + { + return ERR_POINTER; + } + + ddl::DDLDescription* tmp_desc = NULL; + a_util::result::Result res = ERR_NOERROR; + if (struct_name.size() == 0) + { + // create DDL from header file + ddl::HeaderToDDLConverter converter; + if (isFailed((converter.visit(header)))) + { + return ERR_FAILED; + } + if (isFailed((converter.createNew(version)))) + { + return ERR_FAILED; + } + tmp_desc = converter.getDDL(); + if (NULL == tmp_desc) + { + res = ERR_POINTER; + } + } + else + { + // get struct from header file + ddl::HeaderStructs header_structs = header->getStructs(); + ddl::HeaderStruct* found_struct = NULL; + for (ddl::HeaderStructs::const_iterator it_struct = header_structs.begin(); + it_struct != header_structs.end(); + it_struct++) + { + if (0 == struct_name.compare((*it_struct)->getName())) + { + found_struct = *it_struct; + break; + } + } + + // check if struct is available in header file + if (NULL == found_struct) + { + error_msg = a_util::strings::format("Error: Struct '%s' not found in header file.", struct_name.c_str()); + res = ERR_INVALID_FILE; + } + else + { + // create DDL from struct of header file + ddl::HeaderToDDLConverter converter; + if (isFailed((converter.visit(found_struct)))) + { + return ERR_FAILED; + } + if (isFailed((converter.createNew(version)))) + { + return ERR_FAILED; + } + tmp_desc = converter.getDDL(); + if (NULL == tmp_desc) + { + res = ERR_POINTER; + } + } + } + + + if (NULL != _ddl_description) + { + if (NULL != tmp_desc) + { + res = _ddl_description->merge(*tmp_desc); + } + } + else + { + _ddl_description = tmp_desc; + } + + if (NULL != header) + { + importer.DestroyHeader(); + header = NULL; + } + for (ddl::HeaderTypesVec::iterator it = default_types->begin(); it != default_types->end(); it++) + { + delete *it; + *it = NULL; + } + default_types->clear(); + delete default_types; + default_types = NULL; + + return res; +} + +ddl::DDLDescription* DDLManager::getDDL() +{ + return _ddl_description; +} + +a_util::result::Result DDLManager::printToDDLFile(const a_util::filesystem::Path& ddl_path, std::string& error_msg) +{ + ddl::DDLPrinter ddl_printer; + if (a_util::result::isFailed(ddl_printer.visitDDL(_ddl_description))) + { + return ERR_POINTER; + } + if (a_util::result::isFailed(ddl_printer.toFile(ddl_path))) + { + return (ERR_INVALID_FILE); + } + + return ERR_NOERROR; +} + +a_util::result::Result DDLManager::printToHeaderFile(const a_util::filesystem::Path& header_file, std::string& error_msg, + const std::string name_space /** = ""*/, const std::string displace /** = ""*/) +{ + + // Create header from ddl + ddl::DDLToHeaderConverter converter; + converter.setDisplaceableString(displace); + ddl::HeaderTypesVec* default_types = NULL; + default_types = ddl::HeaderImporter::getDefaultTypes(); + converter.setKnownTypes(default_types); + if (a_util::result::isFailed(converter.visitDDL(_ddl_description))) + { + error_msg = converter.getError(); + return ERR_FAILED; + } + if (isFailed((converter.createNew()))) + { + error_msg = converter.getError(); + return ERR_FAILED; + } + ddl::Header* header = converter.getHeader(); + if (NULL == header) + { + return ERR_POINTER; + } + // create header file + ddl::HeaderPrinter printer; + printer.SetNamespace(name_space); + if (a_util::result::isFailed(printer.visit(header))) + { + return (ERR_INVALID_FILE); + } + if (a_util::result::isFailed(printer.writeToFile(header_file))) + { + return (ERR_FAILED); + } + + return ERR_NOERROR; +} + +a_util::result::Result DDLManager::searchForStructs() +{ + ddl::DDLComplexVec ddl_structs = _ddl_description->getStructs(); + if (0 == ddl_structs.size()) + { + return (ERR_INVALID_FILE); + } + return ERR_NOERROR; +} + +ddl::ImporterMsgList DDLManager::checkValidity() +{ + ddl::ImporterMsgList msg_list = ddl::DDLInspector::checkValidyOfNestedStructs(_ddl_description); + if (!(msg_list.size() > 0)) + { + ddl::DDLInspector ddl_inspector(false); + ddl_inspector.visitDDL(_ddl_description); + msg_list = ddl_inspector.getSuggestions(); + } + return msg_list; +} + + +a_util::result::Result DDLManager::findStructRecursively(ddl::DDLDescription* description, const std::string &struct_name) +{ + if (NULL != _ddl_description && NULL != _ddl_description->getStructByName(struct_name)) + { + // struct was already added, skip + return ERR_NOERROR; + } + a_util::result::Result res = ERR_NOERROR; + + ddl::DDLComplexVec ddl_structs = description->getStructs(); + ddl::DDLComplex* found_struct = NULL; + for (ddl::DDLComplexVec::const_iterator it_struct = ddl_structs.begin(); + it_struct != ddl_structs.end(); it_struct++) + { + if (0 == a_util::strings::compare(struct_name.c_str(), (*it_struct)->getName().c_str())) + { + found_struct = new ddl::DDLComplex(**it_struct); + break; + } + } + // check if struct is available in description file + if (NULL == found_struct) + { + return ERR_INVALID_FILE; + } + + if (NULL == _ddl_description) + { + _ddl_description = ddl::DDLDescription::createDefault(); + } + _ddl_description->addStruct(found_struct); + + // add child-structs + for (auto it_element = found_struct->getElements().begin(); it_element != found_struct->getElements().end(); it_element++) + { + ddl::DDLElement* element = *it_element; + const std::string element_name = element->getTypeObject()->getName(); + if (element->getTypeObject()->isComplex()) + { + if (isFailed(findStructRecursively(description, element_name))) + { + return ERR_INVALID_FILE; + } + element->setType(_ddl_description->getStructByName(element_name)); + } + } + + return ERR_NOERROR; +} diff --git a/ddlgenerators/generator_library/ddl_manager.h b/ddlgenerators/generator_library/ddl_manager.h new file mode 100644 index 0000000..3936c07 --- /dev/null +++ b/ddlgenerators/generator_library/ddl_manager.h @@ -0,0 +1,93 @@ +/** + * @file + * Implementation of FEP MDE core + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include + +#ifndef DDL_MANAGER_H +#define DDL_MANAGER_H + + +class DDLManager +{ + +public: + /** + * CTOR + * @param [in] + */ + DDLManager(); + + /** + * DTOR + */ + ~DDLManager(); + + /// Set default ddl + a_util::result::Result setDefaultDDL(); + /** + * Nerge with ddl file, or with default ddl if empty + * @param[in] ddl_path - path to the ddl file + * @param[out] error_msg - error message, gives more information if it failed + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result mergeWithDDLFile(const a_util::filesystem::Path& ddl_path, std::string& error_msg, const std::string& struct_name = ""); + /** + * Nerge with ddl file, or with default ddl if empty + * @param[in] header_path - path to the header file + * @param[in] struct_name - merge only this struct to the existing ddl + * @retval ERR_NOERROR Everything went as expected. + */ + a_util::result::Result mergeWithHeaderFile(const a_util::filesystem::Path& header_path, std::string& error_msg, + const ddl::DDLVersion& version = ddl::DDLVersion::ddl_version_current, const std::string& struct_name = ""); + /// Getter for ddl representation + ddl::DDLDescription* getDDL(); + /// Print to ddl file + a_util::result::Result printToDDLFile(const a_util::filesystem::Path& ddl_path, std::string& error_msg); + /// Print to header file + a_util::result::Result printToHeaderFile(const a_util::filesystem::Path& header_file, std::string& error_msg, + const std::string name_space = "", const std::string displace = ""); + /// Search if the file contains structs + a_util::result::Result searchForStructs(); + /** + * Verify if the file is valid and write some errors and warnings + * @retval message list + */ + ddl::ImporterMsgList checkValidity(); + +private: + + /** find struct struct_name in description. + * Recursively add all child-structs of struct_name as well + * @param[in] description description to search in + * @param[in] struct_name name of struct so search for + * @retval result + */ + a_util::result::Result findStructRecursively(ddl::DDLDescription* description, const std::string &struct_name); + +private: + /// File name + a_util::filesystem::Path _filename; + /// ddl representation + ddl::DDLDescription* _ddl_description; + +}; + +#endif //DDL_MANAGER_H diff --git a/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.cpp b/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.cpp new file mode 100644 index 0000000..4f976ec --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.cpp @@ -0,0 +1,556 @@ +/** + * @file + * Description is missing. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + + +#include +#include "ddl_to_header_converter.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-19, ERR_NOT_SUPPORTED) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) + } +} + +using namespace ddl; + +namespace ddl +{ + + using namespace ddl_generator::oo; + DDLToHeaderConverter::DDLToHeaderConverter() + { + _header = NULL; + _known_types = NULL; + } + + DDLToHeaderConverter::~DDLToHeaderConverter() + { } + + a_util::result::Result DDLToHeaderConverter::setKnownTypes(const HeaderTypesVec* types) + { + _known_types = types; + return ERR_NOERROR; + } + + const std::string& DDLToHeaderConverter::getError() + { + return _error_string; + } + + a_util::result::Result DDLToHeaderConverter::visitDDL(const DDLDescription *description) + { + // visit EVERYTHING and let the individual visit() method decide what to do. + DDLBaseunitVec base_units = description->getBaseunits(); + for (DDLBaseunitIt iter = base_units.begin(); + iter != base_units.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLDTVec data_types = description->getDatatypes(); + for (DDLDTIt iter = data_types.begin(); + iter != data_types.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLEnumVec enums = description->getEnums(); + for (DDLEnumIt iter = enums.begin(); + iter != enums.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLPrefixVec prefixes = description->getPrefixes(); + description->getHeader()->accept(this); + for (DDLPrefixIt iter = prefixes.begin(); + iter != prefixes.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLStreamVec streams = description->getStreams(); + for (DDLStreamIt iter = streams.begin(); + iter != streams.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLComplexVec structs = description->getStructs(); + for (DDLComplexIt iter = structs.begin(); + iter != structs.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + DDLUnitVec units = description->getUnits(); + for (DDLUnitIt iter = units.begin(); + iter != units.end(); + iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLHeader *header) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLDataType *data_type) + { + // Make sure, that the header type exists + if (findTypeByName(data_type->getName()) == NULL) + { + _error_string.append("Types that are not part of ADTF or stdint.h are not supported ("); + _error_string.append(data_type->getName()); + _error_string.append(").\n"); + return (ERR_NOT_FOUND); + } + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLComplex *ddl_struct) + { + if (findTypeByName(ddl_struct->getName()) == NULL) + { + // Add the type, so if its referenced by one of its member, there will be no infinite loop. + HeaderStruct* header_struct = new HeaderStruct(ddl_struct->getName()); + header_struct->setName(cleanUpName(ddl_struct->getName())); + header_struct->setComment(ddl_struct->getComment()); + _structs.push_back(header_struct); + // parse all elements of the struct + DDLElementVec ddl_elements = ddl_struct->getElements(); + for (DDLElementIt iter = ddl_elements.begin(); + iter != ddl_elements.end(); + iter++) + { + (*iter)->accept(this); + HeaderStructElement* header_element = new HeaderStructElement(); + if ((*iter)->isDynamic()) + { + // Not supported ATM + _error_string.append("Dynamic arrays are not supported.\n"); + return ERR_NOT_SUPPORTED; + } + else + { + header_element->setArraySize((*iter)->getArraysize()); + } + header_element->setIsConst(false); + header_element->setIsPointer(false); + header_element->setIsStatic(false); + header_element->setName(cleanUpName((*iter)->getName())); + header_element->setType(findTypeByName(cleanUpName((*iter)->getTypeObject()->getName()))); + header_element->setDescription((*iter)->getDescription()); + header_element->setComment((*iter)->getComment()); + header_struct->addElement(header_element); + // Alignment + // Only two cases are supported at the moment: + // either the alignment of the element is the same as the default alignment of its type + // or the alignment of the element is smaller than the default alignment of its type and + // is the same as the parent structs alignment. + if (header_element->getType()->getPacking() == fromAlignment((*iter)->getAlignment()) || + (header_element->getType()->getPacking() > fromAlignment((*iter)->getAlignment()) && + (*iter)->getAlignment() == ddl_struct->getAlignment())) + { + // It's Okay, nothing to do here + } + else + { + _error_string.append("This alignment cannot be mapped to c-structs ("); + _error_string.append(ddl_struct->getName()); + _error_string.append("."); + _error_string.append((*iter)->getName()); + _error_string.append(").\n"); + _structs.pop_back(); + delete header_struct; + return ERR_NOT_SUPPORTED; + } + } + // Setting packing after adding elements, so packing wont be recalculated inside the object + header_struct->setPacking(fromAlignment(ddl_struct->getAlignment())); + // Move this struct to the end, so that all needed types are defined front up. + _structs.erase(std::find(_structs.begin(), _structs.end(), header_struct)); + _structs.push_back(header_struct); + } + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLStream *stream) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLUnit *unit) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLBaseunit *base_unit) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLExtDeclaration *ext_declaration) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLElement *element) + { + return (element->getTypeObject()->accept(this)); + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLPrefix *prefix) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLRefUnit *ref_unit) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLStreamStruct *stream_struct) + { + return ERR_NOERROR; + } + + + a_util::result::Result DDLToHeaderConverter::visit(const DDLEnum *ddl_enum) + { + // Check the type + if (isFailed((ddl_enum->getTypeObject()->accept(this)))) + { + return ERR_FAILED; + } + + bool is_integer_enum = isEnumIntegral(ddl_enum); + + if (is_integer_enum) + { + if (findTypeByName(ddl_enum->getName()) == NULL) + { + HeaderEnum* new_enum = new HeaderEnum(cleanUpName(ddl_enum->getName())); + + for (auto value_iter = ddl_enum->getValues().begin(); value_iter != ddl_enum->getValues().end(); value_iter++) + { + const std::string& name = value_iter->first; + const std::string& value = value_iter->second; + + new_enum->addValue(a_util::strings::toInt32(value), name); + } + + _enums.push_back(new_enum); + } + return ERR_NOERROR; + } + else + { + // Non integer enums not possible in header. In that case we add the type as a typedef + // and define the values as constants of that type + + // Add a typedef if not existing + if (findTypeByName(ddl_enum->getName()) == NULL) + { + _typedefs.push_back(new HeaderTypedef(cleanUpName(ddl_enum->getName()), + findTypeByName(ddl_enum->getType()))); + } + const HeaderType* enum_type = findTypeByName(ddl_enum->getName()); + + for (auto value_iter = ddl_enum->getValues().begin(); value_iter != ddl_enum->getValues().end(); value_iter++) + { + const std::string& name = value_iter->first; + const std::string& value = value_iter->second; + HeaderConstant* constant = new HeaderConstant(); + constant->setName(name); + constant->setType(enum_type); + constant->reset(value.c_str()); + _constants.push_back(constant); + } + return ERR_NOERROR; + } + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLProperty* ddl_property) + { + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::visit(const DDLStreamMetaType* stream_meta_type) + { + return ERR_NOERROR; + } + + Header* DDLToHeaderConverter::getHeader() + { + return _header; + } + + a_util::result::Result DDLToHeaderConverter::createNew() + { + // This instance has no responsibility for the object. + _header = new Header(); + _error_string = ""; + BuildTypedefs(); + BuildConstants(); + buildStructs(); + buildEnums(); + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::DestroyHeader() + { + if (_header != NULL) + { + delete _header; + } + + for (HeaderTypedefs::iterator iter = _typedefs.begin(); + iter != _typedefs.end(); + iter++) + { + delete *iter; + } + _typedefs.clear(); + + for (HeaderConstants::iterator iter = _constants.begin(); + iter != _constants.end(); + iter++) + { + delete *iter; + } + _constants.clear(); + + for (HeaderStructs::iterator iter = _structs.begin(); + iter != _structs.end(); + iter++) + { + delete *iter; + } + _structs.clear(); + + for (auto iter = _enums.begin(); + iter != _enums.end(); + iter++) + { + delete *iter; + } + _enums.clear(); + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::BuildTypedefs() + { + for (HeaderTypedefs::iterator iter = _typedefs.begin(); + iter != _typedefs.end(); + iter++) + { + _header->addTypedef(*iter); + } + _typedefs.clear(); + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::BuildConstants() + { + for (HeaderConstants::iterator iter = _constants.begin(); + iter != _constants.end(); + iter++) + { + _header->addConstant(*iter); + } + _constants.clear(); + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::buildStructs() + { + for (HeaderStructs::iterator iter = _structs.begin(); + iter != _structs.end(); + iter++) + { + _header->addStruct(*iter); + } + _structs.clear(); + return ERR_NOERROR; + } + + a_util::result::Result DDLToHeaderConverter::buildEnums() + { + for (auto iter = _enums.begin(); + iter != _enums.end(); + iter++) + { + _header->addEnum(*iter); + } + _enums.clear(); + return ERR_NOERROR; + } + + const HeaderType* DDLToHeaderConverter::findTypeByName(const std::string &name) + { + const HeaderType* result = NULL; + if (_known_types != NULL) + { + result = findTypeByName(*_known_types, name); + } + if (result == NULL) + { + result = findTypeByName(_typedefs, name); + } + if (result == NULL) + { + result = findTypeByName(_structs, name); + } + if (result == NULL) + { + result = findTypeByName(_enums, name); + } + return result; + } + + template + const HeaderType* DDLToHeaderConverter::findTypeByName(const std::vector &vec, + const std::string &name) + { + const HeaderType* result = NULL; + for (typename std::vector::const_iterator iter = vec.begin(); + iter != vec.end(); + iter++) + { + if ((*iter)->getName().compare(name) == 0) + { + result = *iter; + break; + } + } + return result; + } + + + size_t DDLToHeaderConverter::fromAlignment(DDLAlignment::AlignmentType alignment) + { + size_t result = 0; + switch (alignment) + { + case DDLAlignment::e_invalid: + result = 1; + break; + case DDLAlignment::e1: + result = 1; + break; + case DDLAlignment::e2: + result = 2; + break; + case DDLAlignment::e4: + result = 4; + break; + case DDLAlignment::e8: + result = 8; + break; + case DDLAlignment::e16: + result = 16; + break; + case DDLAlignment::e32: + result = 32; + break; + case DDLAlignment::e64: + result = 64; + break; + } + return result; + } + + std::string DDLToHeaderConverter::cleanUpName(const std::string &name) + { + std::string result = name; + if (_displace.length() > 0) + { + if (result.find(_displace) == 0) + { + result.erase(0, _displace.length()); + } + } + const std::string allowed_characters = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890"; + + for (size_t idx = 0; idx < result.size(); idx++) + { + if (allowed_characters.find(result.at(idx)) == std::string::npos) + { + result[idx] = '_'; + } + } + return result; + } + + bool DDLToHeaderConverter::isEnumIntegral(const DDLEnum *ddl_enum) const + { + for (auto iter = ddl_enum->getValues().begin(); iter != ddl_enum->getValues().end(); iter++) + { + if (!a_util::strings::isInt32(iter->second)) + { + return false; + } + } + return true; + } + + void DDLToHeaderConverter::setDisplaceableString(std::string displace) + { + _displace = displace; + } + +} diff --git a/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.h b/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.h new file mode 100644 index 0000000..fcf7dc3 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/ddl_to_header_converter.h @@ -0,0 +1,163 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_DDL_TO_HEADER_CONVERTER_H_INCLUDED +#define HEADER_DDL_TO_HEADER_CONVERTER_H_INCLUDED + +#include "header_type.h" +#include "header_factorymethod_intf.h" +#include "header_importer.h" +#include "header_header.h" + +namespace ddl +{ + +typedef std::vector HeaderConstTypes; + +/** + * This class generates a header from a DDL. + * Use this class by first visiting the element(s) of the DDL you want to be part of your DDL, + * then call createNew() to create the header from the previously parsed header elements. + */ +class DDLToHeaderConverter : public IDDLVisitor, public IHeaderFactory +{ +public: + /** + * CTOR + */ + DDLToHeaderConverter(); + + /** + * DTOR + */ + virtual ~DDLToHeaderConverter(); + + /** + * The method setKnownTypes adds a list of already known types. + * These types can be referenced by any member inside the new header. + * Please be aware, that neither the importer object nor the + * resulting header object will own the types. The resulting + * header object will only reference them. So the resulting header + * must be deleted before the types are deleted. + * + * @param [in] types A list of types already know to the system. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result setKnownTypes(const HeaderTypesVec* types); + + /** + * The method getError returns the error messages that occurred during parsing. + * + * @returns The error messages. + */ + const std::string& getError(); + + void setDisplaceableString(std::string displace); + + +public: // implements IDDLVisitor + a_util::result::Result visitDDL(const DDLDescription *description); + a_util::result::Result visit(const DDLHeader *header); + a_util::result::Result visit(const DDLDataType *data_type); + a_util::result::Result visit(const DDLComplex *ddl_struct); + a_util::result::Result visit(const DDLStream *stream); + a_util::result::Result visit(const DDLUnit *unit); + a_util::result::Result visit(const DDLBaseunit *base_unit); + a_util::result::Result visit(const DDLExtDeclaration *ext_declaration); + a_util::result::Result visit(const DDLElement *element); + a_util::result::Result visit(const DDLPrefix *prefix); + a_util::result::Result visit(const DDLRefUnit *ref_unit); + a_util::result::Result visit(const DDLStreamStruct *stream_struct); + a_util::result::Result visit(const DDLEnum *ddl_enum); + a_util::result::Result visit(const DDLProperty* ddl_property); + a_util::result::Result visit(const DDLStreamMetaType* stream_meta_type); + +public: // implements IHeaderFactory + Header* getHeader(); + a_util::result::Result createNew(); + a_util::result::Result DestroyHeader(); + a_util::result::Result BuildTypedefs(); + a_util::result::Result BuildConstants(); + a_util::result::Result buildStructs(); + a_util::result::Result buildEnums(); + +private: + /// The header to be created + Header* _header; + /// The known types + const HeaderTypesVec* _known_types; + /// The Typedefs found during parsing + HeaderTypedefs _typedefs; + /// The structs found during parsing + HeaderStructs _structs; + /// The constants found during parsing + HeaderConstants _constants; + /// The enums found during parsing + HeaderEnums _enums; + + /// Collecting all error messages here. + std::string _error_string; + + /// String that should be removed at the beginning of element names + std::string _displace; + + /** + * The method findTypeByName searches m_vecTypes for a type by the given name. + * + * @param [in] name The name of the type to be found. + * @returns A pointer to the type if found, NULL otherwise. + */ + const HeaderType* findTypeByName(const std::string &name); + + /** + * The method findTypeByName helps finding a type in a vector containin pointer to + * header types. + * + * @param [in] vec The vector to be looked through. + * @param [in] name The name of the type to be found + * @returns A pointer to the type if found, NULL otherwise. + */ + template + const HeaderType* findTypeByName(const std::vector &vec, const std::string &name); + + /** + * The method fromAlignment calculates the packing from an alignment value. + * + * @param [in] alignment The alignment value + * @returns The packing value, 0 if no matching packing or e0 was found. + */ + size_t fromAlignment(DDLAlignment::AlignmentType alignment); + + /** + * The method cleanUpName replaces all non letter/number/underscore characters from + * the passed string with underscores and returns the result as a new string. + * + * @param [in] name The string to be cleaned up. + * @returns A string only containing letters, numbers and underscores. + */ + std::string cleanUpName(const std::string &name); + + bool isEnumIntegral(const DDLEnum *ddl_enum) const; + +}; + +} + +#endif // HEADER_DDL_TO_HEADER_CONVERTER_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_base_intf.h b/ddlgenerators/generator_library/headerrepresentation/header_base_intf.h new file mode 100644 index 0000000..7286b81 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_base_intf.h @@ -0,0 +1,47 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ +#ifndef HEADER_INTF_H_INCLUDED +#define HEADER_INTF_H_INCLUDED + +namespace ddl +{ + + class IHeaderVisitor; + + /** + * Basic interface class for object representation of a C header. + * E.g. it provides the accept() method for the Visitor design-pattern. + */ + class IHeaderBase + { + public: + /** + * Acceptance method for Visitor design-pattern. + * @param[in] visitor - Pointer to Visitor instance + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_INITIALISED The object was not or not correctly + * initialized + */ + virtual a_util::result::Result accept (IHeaderVisitor * visitor) const = 0; + }; + +} // namespace ddl + +#endif // HEADER_INTF_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_basic_type.cpp b/ddlgenerators/generator_library/headerrepresentation/header_basic_type.cpp new file mode 100644 index 0000000..8a8801e --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_basic_type.cpp @@ -0,0 +1,75 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_basic_type.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + + +namespace ddl +{ + +HeaderBasicType::HeaderBasicType() : HeaderType(), _bit_size(0) +{ } + +HeaderBasicType::HeaderBasicType(const std::string &name, size_t packing, size_t bit_size) + : HeaderType(name, packing), _bit_size(bit_size) +{ } + +HeaderBasicType::HeaderBasicType(const HeaderBasicType& other) + : HeaderType(other), _bit_size(other._bit_size) +{ } + +HeaderBasicType::~HeaderBasicType() +{ } + +a_util::result::Result HeaderBasicType::accept(IHeaderVisitor *visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} + +a_util::result::Result HeaderBasicType::setBitsize_t(size_t bit_size) +{ + _bit_size = bit_size; + return ERR_NOERROR; +} + +size_t HeaderBasicType::getBitsize_t() const +{ + return _bit_size; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_basic_type.h b/ddlgenerators/generator_library/headerrepresentation/header_basic_type.h new file mode 100644 index 0000000..ef44daa --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_basic_type.h @@ -0,0 +1,85 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_BASE_TYPE_H_INCLUDED +#define HEADER_BASE_TYPE_H_INCLUDED +#include "header_type.h" + +namespace ddl +{ + + /** + * Representation of a basic type in a header. + */ + class HeaderBasicType : public HeaderType + { + public: + /** + * Default CTOR + */ + HeaderBasicType(); + + /** + * CTOR + * + * @param [in] name The name of the type. + * @param [in] packing The packing of the type + * @param [in] bit_size The size f the type in bit. + */ + HeaderBasicType(const std::string &name, size_t packing, size_t bit_size); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderBasicType(const HeaderBasicType& other); + + /** + * DTOR + */ + virtual ~HeaderBasicType(); + + /** + * The method setBitsize_t sets the size of the type in bit. + * + * @param [in] bit_size The size in bit. + * @returns Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setBitsize_t(size_t bit_size); + + /** + * The method getBitsize_t returns the size of the basic type in bit. + * + * @returns The size in bit. + */ + size_t getBitsize_t() const; + + + public: //implements HeaderType + + virtual a_util::result::Result accept(IHeaderVisitor *visitor) const; + + private: + /// Stores the size of the basic type in bit + size_t _bit_size; + }; + +} // namespace ddl + +#endif // HEADER_BASE_TYPE_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_constant.cpp b/ddlgenerators/generator_library/headerrepresentation/header_constant.cpp new file mode 100644 index 0000000..740b771 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_constant.cpp @@ -0,0 +1,80 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_constant.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + + +namespace ddl +{ + +HeaderConstant::HeaderConstant() : a_util::variant::Variant() +{ } + +HeaderConstant::HeaderConstant(const HeaderConstant& other) : a_util::variant::Variant(other), _name(other._name) +{ } + +HeaderConstant::~HeaderConstant() +{ } + +const std::string& HeaderConstant::getName() const +{ + return _name; +} + +a_util::result::Result HeaderConstant::setName(const std::string& name) +{ + _name = name; + return ERR_NOERROR; +} + +a_util::result::Result HeaderConstant::setType(const HeaderType* type) +{ + _type = type; + return ERR_NOERROR; +} + +const HeaderType* HeaderConstant::getType() const +{ + return _type; +} + +a_util::result::Result HeaderConstant::accept(IHeaderVisitor *visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_constant.h b/ddlgenerators/generator_library/headerrepresentation/header_constant.h new file mode 100644 index 0000000..0876842 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_constant.h @@ -0,0 +1,97 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_CONSTANT_H_INCLUDED +#define HEADER_CONSTANT_H_INCLUDED + +#include "header_base_intf.h" +#include "header_type.h" + +namespace ddl +{ + + /** + * Representation of a constant in a header. + * @remark + * This class is intended to represent a primitive type constant. + * Although the current architecture supports setting the type + * of the constant to a struct, it would not make much sense. + */ + class HeaderConstant : public IHeaderBase, public a_util::variant::Variant + { + public: + /** + * Default CTOR + */ + HeaderConstant(); + + /** + * Copy CTOR + * @param [in] other The other constant to copy from. + */ + HeaderConstant(const HeaderConstant& other); + + /** + * DTOR + */ + virtual ~HeaderConstant(); + + /** + * This method gives access to the name of the type. + * @return The name of the element. + */ + const std::string& getName() const; + + /** + * This method gives access to the name of the type. + * @param [in] name The name of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setName(const std::string& name); + + /** + * The method getType gives access to the type of the constant. + * + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + const HeaderType* getType() const; + + + /** + * The method setType sets the type of the constant + * + * @param [in] type A pointer to the type of the constant. This class will not own the pointer. + * @returns Standard result code. + * @retval ERR_NOERROR Will always be returned. + */ + a_util::result::Result setType(const HeaderType* type); + + public: // implements IHeaderBase + a_util::result::Result accept(IHeaderVisitor *visitor) const; + + private: + /// The name of the constant. + std::string _name; + /// The type of the constant + const HeaderType* _type; + }; +} // namespace ddl + +#endif // HEADER_CONSTANT_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_enum.cpp b/ddlgenerators/generator_library/headerrepresentation/header_enum.cpp new file mode 100644 index 0000000..cec159a --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_enum.cpp @@ -0,0 +1,94 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_enum.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + +namespace ddl +{ + + HeaderEnum::HeaderEnum() : HeaderType(), _enum_values() + { } + + HeaderEnum::HeaderEnum(std::string name, size_t packing /*= 4*/) + : HeaderType(name, packing), _enum_values() + { } + + HeaderEnum::HeaderEnum(HeaderEnum& other) + : HeaderType(other), _enum_values() + { } + + HeaderEnum::~HeaderEnum() + { } + + const HeaderEnumValueMap& HeaderEnum::getValues() const + { + return _enum_values; + } + + a_util::result::Result HeaderEnum::addValue(int32_t value, const std::string& name) + { + if (_enum_values.count(value) != 0) + { + // non unique key + return ERR_INVALID_ARG; + } + _enum_values[value] = name; + return ERR_NOERROR; + } + + + a_util::result::Result HeaderEnum::removeValue( int32_t value ) + { + HeaderEnumValueMap::iterator iter = _enum_values.find(value); + if (iter == _enum_values.end()) + { + return ERR_NOT_FOUND; + } + + _enum_values.erase(iter); + return ERR_NOERROR; + } + + + a_util::result::Result HeaderEnum::accept(IHeaderVisitor *visitor) const + { + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); + } + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_enum.h b/ddlgenerators/generator_library/headerrepresentation/header_enum.h new file mode 100644 index 0000000..9a92657 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_enum.h @@ -0,0 +1,111 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + +#ifndef HEADER_ENUM_H_INCLUDED +#define HEADER_ENUM_H_INCLUDED + +#include "header_base_intf.h" +#include "header_type.h" +#include +#include + +namespace ddl +{ + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic ignored "-Wattributes" // standard type attributes are ignored when used in templates +#endif + + typedef std::map HeaderEnumValueMap; + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic warning "-Wattributes" // standard type attributes are ignored when used in templates +#endif + + /** + * Representation of a enum in a header. + * The class calculates its own packing from its children + * every time one or more children have been added or removed. + * To override the calculated packing, set the packing value AFTER adding + * children. + */ + class HeaderEnum : public HeaderType + { + public: + /** + * Default CTOR + */ + HeaderEnum(); + + /** + * CTOR + * @param [in] name The name of the struct. + * @param [in] packing The packing of the struct. + * The struct takes ownership of the passed elements. + */ + HeaderEnum(std::string name, + size_t packing = 4); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderEnum(HeaderEnum& other); + + /** + * DTOR + */ + virtual ~HeaderEnum(); + + /** + * This method gives access to the values of the enum. + * @return The enum values as a map. + */ + const HeaderEnumValueMap& getValues() const; + + /** + * Add a value to this enum + * @param[in] value The enum value (must be unique for this enum) + * @param[in] name the name + */ + a_util::result::Result addValue(int32_t value, const std::string& name); + + + /** + * Remove a value from this enum. + * @param [in] key The key of the element to be removed. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + * @retval ERR_NOT_FOUND No element with this key was found. + */ + a_util::result::Result removeValue(int32_t value); + + public: // implements cHeaderBaseType + + a_util::result::Result accept(IHeaderVisitor *visitor) const; + + private: + + HeaderEnumValueMap _enum_values; + }; +} // namespace ddl + +#endif // HEADER_ENUM_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_factorymethod_intf.h b/ddlgenerators/generator_library/headerrepresentation/header_factorymethod_intf.h new file mode 100644 index 0000000..61d8e54 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_factorymethod_intf.h @@ -0,0 +1,95 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_FACTORY_H_INCLUDED +#define HEADER_FACTORY_H_INCLUDED + +namespace ddl +{ + class Header; + + /** + * Abstract base class/interface for Factory Method design-pattern. + */ + class IHeaderFactory + { + public: + /** + * Getter for the header object. + * @return the header object + * @attention The caller/user has the responsibility for the created + * header object! Especially take this aspect into consideration in + * matters of the deallocation of memory! + */ + virtual Header* getHeader() = 0; + + /** + * Method to build up a new header hierarchy. + * This will internally create a new header. An existing old header + * will not be deleted. So make sure to have taken responsibility of all + * previously created headers by calling getHeader(). + * @retval ERR_NOT_INITIALISED Not yet initialized + * @retval ERR_UNKNOWN_FORMAT Expected header hierarchy not found + * @retval ERR_FAILED Some other error occurred. + * was not found. + */ + virtual a_util::result::Result createNew() = 0; + + /** + * The method DestroyHeader destroys the header object and all contained objects. + * + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + virtual a_util::result::Result DestroyHeader() = 0; + + /** + * Method to build a typedef object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected header hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable + */ + virtual a_util::result::Result BuildTypedefs() = 0; + + /** + * Method to build a constants object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected header hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. struct) + */ + virtual a_util::result::Result BuildConstants() = 0; + + /** + * Method to build a structs object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected header hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. base type) + * @retval ERR_UNKNOWN Not all firstly unknown structs have been + * resolved + */ + virtual a_util::result::Result buildStructs() = 0; + + /** + * Method to build a enum object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected header hierarchy not found + * resolved + */ + virtual a_util::result::Result buildEnums() = 0; + }; + +} // namespace ddl + +#endif // HEADER_FACTORY_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_header.cpp b/ddlgenerators/generator_library/headerrepresentation/header_header.cpp new file mode 100644 index 0000000..3aaeaa5 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_header.cpp @@ -0,0 +1,197 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_header.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + + +namespace ddl +{ + +Header::Header() +{ } + +Header::Header(const Header &other) +{ + _name = other._name; + for (HeaderTypedefs::const_iterator iter = other._typedefs.begin(); iter != other._typedefs.end(); iter++) + { + _typedefs.push_back(new HeaderTypedef(*(*iter))); + } + for (HeaderConstants::const_iterator iter = other._constants.begin(); iter != other._constants.end(); iter++) + { + _constants.push_back(new HeaderConstant(*(*iter))); + } + for (HeaderStructs::const_iterator iter = other._structs.begin(); iter != other._structs.end(); iter++) + { + _structs.push_back(new HeaderStruct(*(*iter))); + } + for (auto iter = other._enums.begin(); iter != other._enums.end(); iter++) + { + _enums.push_back(new HeaderEnum(*(*iter))); + } +} + +Header::~Header() +{ + for (HeaderTypedefs::iterator iter = _typedefs.begin(); iter != _typedefs.end(); iter++) + { + delete *iter; + } + _typedefs.clear(); + for (HeaderConstants::iterator iter = _constants.begin(); iter != _constants.end(); iter++) + { + delete *iter; + } + _constants.clear(); + for (HeaderStructs::iterator iter = _structs.begin(); iter != _structs.end(); iter++) + { + delete *iter; + } + _structs.clear(); + + for (auto iter = _enums.begin(); iter != _enums.end(); iter++) + { + delete *iter; + } + _enums.clear(); +} + + +const std::string& Header::getName() const +{ + return _name; +} + +a_util::result::Result Header::setName(const std::string& name) +{ + _name = name; + return ERR_NOERROR; +} + +const HeaderTypedefs& Header::getTypedefs() const +{ + return _typedefs; +} + +a_util::result::Result Header::addTypedef(HeaderTypedef* header_typedef) +{ + _typedefs.push_back(header_typedef); + return ERR_NOERROR; +} + +a_util::result::Result Header::removeTypedef(const std::string &name) +{ + for (HeaderTypedefs::iterator iter = _typedefs.begin(); iter != _typedefs.end(); iter++) + { + if ((*iter)->getName() == name) + { + delete *iter; + _typedefs.erase(iter); + return ERR_NOERROR; + } + } + return (ERR_NOT_FOUND); +} + +const HeaderConstants& Header::getConstants() const +{ + return _constants; +} + +a_util::result::Result Header::addConstant(HeaderConstant* constant) +{ + _constants.push_back(constant); + return ERR_NOERROR; +} + +a_util::result::Result Header::removeConstant(const std::string &name) +{ + for (HeaderConstants::iterator iter = _constants.begin(); iter != _constants.end(); iter++) + { + if ((*iter)->getName() == name) + { + delete *iter; + _constants.erase(iter); + return ERR_NOERROR; + } + } + return (ERR_NOT_FOUND); +} + +const HeaderStructs& Header::getStructs() const +{ + return _structs; +} + +a_util::result::Result Header::addStruct(HeaderStruct* header_struct) +{ + _structs.push_back(header_struct); + return ERR_NOERROR; +} + +a_util::result::Result Header::removeStruct(const std::string &name) +{ + for (HeaderStructs::iterator iter = _structs.begin(); iter != _structs.end(); iter++) + { + if ((*iter)->getName() == name) + { + delete *iter; + _structs.erase(iter); + return ERR_NOERROR; + } + } + return (ERR_NOT_FOUND); +} + +const HeaderEnums& Header::getEnums() const +{ + return _enums; +} + +a_util::result::Result Header::addEnum(HeaderEnum* header_enum) +{ + _enums.push_back(header_enum); + return ERR_NOERROR; +} + +a_util::result::Result Header::accept(IHeaderVisitor * visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_header.h b/ddlgenerators/generator_library/headerrepresentation/header_header.h new file mode 100644 index 0000000..d34581a --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_header.h @@ -0,0 +1,191 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_HEADER_H_INCLUDED +#define HEADER_HEADER_H_INCLUDED + +#include "header_base_intf.h" +#include "header_typedef.h" +#include "header_constant.h" +#include "header_struct.h" +#include "header_enum.h" +#include "header_visitor_intf.h" + +namespace ddl +{ + + /** + * Container type of basic type objects + */ + typedef std::vector HeaderTypedefs; + + /** + * Container type of constants objects + */ + typedef std::vector HeaderConstants; + + /** + * Container type of struct objects + */ + typedef std::vector HeaderStructs; + + /** + * Container type of enum objects + */ + typedef std::vector HeaderEnums; + + /** + * Main class representing a whole header file + */ + class Header : public IHeaderBase + { + public: + /** + * CTOR + */ + Header(); + + /** + * Copy CTOR. This will make a full copy of the other header. + * @param [in] other The other header this instance will be a copy of. + */ + Header(const Header &other); + + /** + * DTOR + */ + virtual ~Header(); + + /** + * This method gives access to the name of the type. + * @return The name of the element. + */ + const std::string& getName() const; + + /** + * This method gives access to the name of the type. + * @param [in] name The name of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setName(const std::string& name); + + /** + * This method gives access to the list of typedefs from the header. + * @returns The list of typedefs + */ + const HeaderTypedefs& getTypedefs() const; + + /** + * This method adds a typedef to the internal list of typedefs. + * @param [in] type_def The typedef to be added. The class takes ownership of the object. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + */ + a_util::result::Result addTypedef(HeaderTypedef* type_def); + + /** + * This method removes a typedef from the internal list of typedefs. + * @param [in] name The name of the typedef to be removed. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + * @retval ERR_NOT_FOUND No typedef with this name was found. + */ + a_util::result::Result removeTypedef(const std::string &name); + + /** + * This method gives access to the list of constants from the header. + * @returns The list of constants. + */ + const HeaderConstants& getConstants() const; + + /** + * This method adds a constant to the internal list of constants. + * @param [in] constant The constant to be added. The class takes ownership of the object. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + */ + a_util::result::Result addConstant(HeaderConstant* constant); + + /** + * This method removes a constant from the internal list of constants. + * @param [in] strName The name of the constant to be removed. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + * @retval ERR_NOT_FOUND No constant with this name was found. + */ + a_util::result::Result removeConstant(const std::string &name); + + /** + * This method gives access to the list of structs from the header. + * @returns The list of structs + */ + const HeaderStructs& getStructs() const; + + /** + * This method adds a struct to the internal list of structs. + * @param [in] pStruct The struct to be added. The class takes ownership of the object. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + */ + a_util::result::Result addStruct(HeaderStruct* header_struct); + + /** + * This method removes a struct from the internal list of structs. + * @param [in] strName The name of the struct to be removed. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + * @retval ERR_NOT_FOUND No struct with this name was found. + */ + a_util::result::Result removeStruct(const std::string &name); + + /** + * This method gives access to the list of enums from the header. + * @returns The list of enums + */ + const HeaderEnums& getEnums() const; + + /** + * This method adds an enum to the internal list of enums. + * @param [in] p_enum The enum to be added. The class takes ownership of the object. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + */ + a_util::result::Result addEnum(HeaderEnum* header_enum); + + + public: // implementation of IHeaderBase + virtual a_util::result::Result accept(IHeaderVisitor * visitor) const; + + private: + /// The name of the header (i.e. file name) + std::string _name; + /// The list of typedefs. + HeaderTypedefs _typedefs; + /// The list of constants. + HeaderConstants _constants; + /// The list of structs. + HeaderStructs _structs; + /// The list of enums + HeaderEnums _enums; + + }; + +} // namespace ddl + +#endif // HEADER_HEADER_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_importer.cpp b/ddlgenerators/generator_library/headerrepresentation/header_importer.cpp new file mode 100644 index 0000000..0517991 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_importer.cpp @@ -0,0 +1,1324 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_importer.h" +#include "header_basic_type.h" +#include "header_typedef.h" +#include "header_header.h" +#include "parserhelper.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-36, ERR_UNKNOWN_FORMAT) + _MAKE_RESULT(-37, ERR_NOT_INITIALISED) + _MAKE_RESULT(-38, ERR_FAILED) + } +} + +using namespace ddl_generator::oo; + +using namespace ddl; + + +namespace ddl +{ +#define AMOUNT_OF_TOKENS 3 + //#define AMOUNT_OF_SINGLE_SEPARATORS 27 + const std::string g_tokens[AMOUNT_OF_TOKENS] = { "struct", "enum", "union" }; + const std::string g_single_separators = "{}[]#()<>%:;.?*+-/�&|�!=,\\\"�;"; + const std::string g_name_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"; + + + class HeaderParserHelper + { + public: + /** + * CTOR + */ + HeaderParserHelper() {}; + + /** + * DTOR + */ + virtual ~HeaderParserHelper() {}; + + /** + * The method skipToNextContent skips comments and whitespace + * until the next code fragment or the end of the file is reached. + * + * @param [in] src Pass a pointer to a string, + * returns a pointer to the next character in the string, + * that is part of the code. + */ + static void skipToNextContent(const char* &src) + { + const char* current = NULL; + const char* forward_search = NULL; + while (current != src) + { + current = src; + forward_search = src; + skipComment(src, getNextElement(forward_search)); + ddl_generator::skipWhitespace(src); + } + } + + /** + * The method isValidName checks whether a string is a valid name for either a variable or a type. + * Used definition: + * Must start with a letter oder an underscore. + * Second to last character can be a number, letter or underscore. + * + * @param [in] name The name to be analyzed. + * @returns True if the name is valid, false otherwise. + */ + static bool isValidName(const std::string &name) + { + a_util::regex::RegularExpression reg_ex("^[_a-zA-Z][_a-zA-Z0-9]*$"); + int consumed; + return reg_ex.match(name, a_util::regex::RegularExpression::AT_Both, consumed); + } + + /** + * The method skipBlock skips the next block. + * Example: + * bla = 5; + * typedef struct { + * int a; + * }; + * The function skips to the semicolon after the last parenthesis. + * + * @param [in, out] src The source to be skipped, points to the next character after the parenthesis. + */ + static void skipBlock(const char* &src) + { + uint64_t depth = 0; + while (*src != '\0' && *src != '{') + { + src++; + } + depth++; + while (*src != '\0') + { + if (*src == '{') + { + depth++; + } + else if (*src == '}') + { + depth--; + if (depth == 0) + { + src++; + break; + } + } + src++; + } + } + + /** + * The method exitBlock exists from the current block; + * Example + * blubb = 5; + * bla blubber; + * } + * The method jumps to the character after the parenthesis. + * + * @param [in] src The string to be analyzed, returns a pointer to the character after the parenthesis + * of the current block or to the end of the string. + */ + static void exitBlock(const char* &src) + { + while (*src != '\0') + { + if (*src == '}') + { + src++; + break; + } + if (*src == '{') + { + skipBlock(src); + } + else + { + src++; + } + } + } + + /** + * The function getNextElement extracts the next c++ element. + * This can be a whole word like a type name or a single character like + * a plus sign or the beginning/end of a comment line //, / * or * / + * (cannot write the "comment close" without space or it would break the code of this file) + * This function will not check any validity. So Names like "123onetwothree" are allowed. + * + * @param [in, out] src The string to be analyzed, returns a pointer to the character after found element. + * @returns A string containing the element. + */ + static std::string getNextElement(const char* &src) + { + std::string result = ""; + while (*src != '\0') + { + //Check for a number or a name + if (g_name_chars.find(*src) != std::string::npos) + { + result.push_back(*src); + src++; + while (g_name_chars.find(*src) != std::string::npos) + { + result.push_back(*src); + src++; + } + break; + } + // Check for a single character like +, - and so on + else if (g_single_separators.find(*src) != std::string::npos) + { + result = *src; + src++; + // Check for comment + if (result == "/") + { + if (*src == '/' || *src == '*') + { + result.push_back(*src); + src++; + } + } + else if (result == "*") + { + if (*src == '/') + { + result.push_back(*src); + src++; + } + } + //Check for escape character + else if (result == "\\") + { + result.push_back(*src); + src++; + } + break; + } + else + { + // Probably just space or newlines. If anything else has not been captured by this algorithm, + // please add it here or where it fits. + src++; + } + } + return result; + } + + /** + * The function getNextCodeElement extracts the next c++ element outside a comment. + * This can be a whole word like a type name or a single character like + * a plus sign. + * This function will not check any validity. So Names like "123onetwothree" are allowed. + * This function assumes that it is outside a comment. + * + * @param [in, out] src The string to be analyzed, returns a pointer to the character after found element. + * @returns A string containing the element. + */ + static std::string getNextCodeElement(const char* &src) + { + std::string result; + while (*src != '\0') + { + result = getNextElement(src); + if (result == "/*" || result == "//") + { + skipComment(src, result); + } + else + { + break; + } + } + return result; + } + + /** + * The method skipComment skips a comment. Use in conjunction with getNextElement(). + * + * @param [in, out] p A pointer to the string containing the comment. + The pointer will point to the first character after the comment. + * @param [in] comment_begin The string containing the begin of the comment. + * if the string does not contain a comment beginning (line // or / *) + * nothing will be skipped. + */ + static void skipComment(const char* &src, const std::string &comment_begin) + { + if (comment_begin == "//") + { + skipEOL(src); + } + else if (comment_begin == "/*") + { + while ((getNextElement(src) != "*/") && (*src != '\0')) + { + } + } + } + + /** + * The method SkipToEOL [...] + * + * @param [in, out] src A pointer to the string containing the comment. + The pointer will point to the first character after the EOL character (0x0A). + */ + static void skipEOL(const char* &src) + { + while (*src != '\n' && *src != '\0') + { + src++; + } + src++; + } + }; + + + HeaderImporter::HeaderImporter() + { + _types = NULL; + _header = NULL; + _default_type = NULL; + } + + HeaderImporter::~HeaderImporter() + { + _types = NULL; + _header = NULL; + _default_type = NULL; + } + + a_util::result::Result HeaderImporter::setHeaderString(const std::string &source) + { + _input_file = a_util::filesystem::Path(); + _header_source = source; + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::setFileName(const a_util::filesystem::Path &filename) + { + _header_source = ""; + _input_file = filename; + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::setKnownTypes(const HeaderTypesVec* types) + { + _types = types; + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::setDefaultIntegerType(const HeaderType* type) + { + _default_type = type; + return ERR_NOERROR; + } + + HeaderTypesVec* HeaderImporter::getDefaultTypes() + { + HeaderBasicType* basic_type = NULL; + HeaderTypesVec* types = new HeaderTypesVec(); + + // Remark: t-Types(for example tBool, tUInt32) are keeped for compliance with old versions + + basic_type = new HeaderBasicType("bool", 1, 8); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("tBool", basic_type)); + + basic_type = new HeaderBasicType("char", 1, 8); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("tChar", basic_type)); + + basic_type = new HeaderBasicType("uint8_t", 1, 8); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("unsigned char", basic_type)); + types->push_back(new HeaderTypedef("tUInt8", basic_type)); + types->push_back(new HeaderTypedef("uint_least8_t", basic_type)); + types->push_back(new HeaderTypedef("uint_least8_t", basic_type)); + types->push_back(new HeaderTypedef("uint_fast8_t", basic_type)); + + basic_type = new HeaderBasicType("int8_t", 1, 8); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("signed char", basic_type)); + types->push_back(new HeaderTypedef("char", basic_type)); + types->push_back(new HeaderTypedef("tInt8", basic_type)); + types->push_back(new HeaderTypedef("int_least8_t", basic_type)); + types->push_back(new HeaderTypedef("int_least8_t", basic_type)); + types->push_back(new HeaderTypedef("int_fast8_t", basic_type)); + + basic_type = new HeaderBasicType("uint16_t", 2, 16); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("unsigned short", basic_type)); + types->push_back(new HeaderTypedef("tUInt16", basic_type)); + types->push_back(new HeaderTypedef("uint_least16_t", basic_type)); + + basic_type = new HeaderBasicType("int16_t", 2, 16); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("signed short", basic_type)); + types->push_back(new HeaderTypedef("short", basic_type)); + types->push_back(new HeaderTypedef("tInt16", basic_type)); + types->push_back(new HeaderTypedef("int_least16_t", basic_type)); + + basic_type = new HeaderBasicType("uint32_t", 4, 32); + types->push_back(basic_type); +#ifdef __ADTF32 + types->push_back(new HeaderTypedef("unsigned long", basic_type)); +#endif + types->push_back(new HeaderTypedef("unsigned int", basic_type)); + types->push_back(new HeaderTypedef("tUInt32", basic_type)); + types->push_back(new HeaderTypedef("uint_least32_t", basic_type)); + types->push_back(new HeaderTypedef("uint_fast16_t", basic_type)); + types->push_back(new HeaderTypedef("uint_fast32_t", basic_type)); + + basic_type = new HeaderBasicType("int32_t", 4, 32); + types->push_back(basic_type); +#ifdef __ADTF32 + types->push_back(new HeaderTypedef("signed long", basic_type)); + types->push_back(new HeaderTypedef("long", basic_type)); +#endif + types->push_back(new HeaderTypedef("signed int", basic_type)); + types->push_back(new HeaderTypedef("int", basic_type)); + types->push_back(new HeaderTypedef("tInt32", basic_type)); + types->push_back(new HeaderTypedef("int_least32_t", basic_type)); + types->push_back(new HeaderTypedef("int_fast16_t", basic_type)); + types->push_back(new HeaderTypedef("int_fast32_t", basic_type)); + + basic_type = new HeaderBasicType("uint64_t", 8, 64); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("unsigned long", basic_type)); + types->push_back(new HeaderTypedef("unsigned long long", basic_type)); + types->push_back(new HeaderTypedef("unsigned __int64", basic_type)); + types->push_back(new HeaderTypedef("tUInt64", basic_type)); + types->push_back(new HeaderTypedef("uint_least64_t", basic_type)); + types->push_back(new HeaderTypedef("uint_least64_t", basic_type)); + + basic_type = new HeaderBasicType("int64_t", 8, 64); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("signed long", basic_type)); + types->push_back(new HeaderTypedef("long", basic_type)); + types->push_back(new HeaderTypedef("signed long long", basic_type)); + types->push_back(new HeaderTypedef("long long", basic_type)); + types->push_back(new HeaderTypedef("signed __int64", basic_type)); + types->push_back(new HeaderTypedef("__int64", basic_type)); + types->push_back(new HeaderTypedef("tInt64", basic_type)); + types->push_back(new HeaderTypedef("int_least64_t", basic_type)); + types->push_back(new HeaderTypedef("int_least64_t", basic_type)); + + basic_type = new HeaderBasicType("float", 4, 32); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("tFloat32", basic_type)); + + basic_type = new HeaderBasicType("double", 8, 64); + + types->push_back(basic_type); + types->push_back(new HeaderTypedef("tFloat64", basic_type)); + + // tFloat128 is not supported, because type is deprecated + /*basic_type = new HeaderBasicType("tFloat128", 4, 128); + types->push_back(basic_type); + types->push_back(new HeaderTypedef("long double", basic_type));*/ + + return types; + } + + Header * HeaderImporter::getHeader() + { + return _header; + } + + a_util::result::Result HeaderImporter::createNew() + { + if (_header_source == "" && _input_file.getLastElement().isEmpty()) + { + return ERR_NOT_INITIALISED; + } + if (!_input_file.getLastElement().isEmpty()) + { + if (a_util::filesystem::readTextFile(_input_file, _header_source) != a_util::filesystem::OK) + { + return (ERR_FAILED); + } + } + + _last_error = ""; + // Old header will not be destroyed since caller is responsible for the pointer. + _header = new Header(); + _header->setName(_input_file.getLastElement()); + if (isFailed((BuildTypedefs()))) + { + return ERR_FAILED; + } + if (isFailed((BuildConstants()))) + { + return ERR_FAILED; + } + if (isFailed(buildEnums())) + { + return ERR_FAILED; + } + if (isFailed((buildStructs()))) + { + return ERR_FAILED; + } + if (_last_error.length() > 0) + { + return ERR_FAILED; + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::DestroyHeader() + { + delete _header; + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::BuildTypedefs() + { + if (_header == NULL) + { + return ERR_POINTER; + } + const char* pos = _header_source.c_str(); + while (*pos != '\0') + { + std::string next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "typedef") + { + std::string original_name; + std::string new_name; + std::string token; + if (a_util::result::isOk(parseTypedef(pos, token, original_name, new_name))) + { + const HeaderType* original_type = findKnownType(original_name); + if (original_type != NULL) + { + HeaderTypedef* new_type = new HeaderTypedef(new_name, original_type); + _header->addTypedef(new_type); + } + else + { + addErrorDescription(std::string("Unknown type name: ").append(original_name), pos); + } + } + } + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::BuildConstants() + { + if (_header == NULL) + { + return ERR_POINTER; + } + + // Only constants with integers as values will be accepted, since they are needed for the size of arrays. + // Buildup of a constant: + // const Type Name = number; + // #define NAME number + const char* pos = _header_source.c_str(); + while (*pos != '\0') + { + std::string next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "const") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (HeaderParserHelper::isValidName(next_word)) + { + std::string type_name = next_word; + if (type_name == "signed" || type_name == "unsigned") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + type_name.append(" "); + type_name.append(next_word); + } + // Look for the type in the list of known types. + const HeaderType* type = findKnownType(next_word); + next_word = HeaderParserHelper::getNextCodeElement(pos); + // Pointers will be ignored, so next element has to be the variable name + if (HeaderParserHelper::isValidName(next_word)) + { + std::string name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "=") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + // Anything but integers will be ignored since constants are only only useful for the parser, + // if an array size refers to them. + if (a_util::strings::isInt64(next_word)) + { + int64_t value = a_util::strings::toInt64(next_word); + next_word = HeaderParserHelper::getNextCodeElement(pos); + // No fancy values like 34+32 or 866+other_const will be accepted at the moment, so we expect a semicolon now. + if (next_word == ";") + { + //Yeah! We found a constant with an int. + HeaderConstant* constant = new HeaderConstant(); + constant->setName(name); + constant->setType(type); + constant->reset(value); + _header->addConstant(constant); + } + } + } + } + } + } + else if (next_word == "#") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "define") + { + // Look for end of line (ignoring multiline defines) + const char* eol_pos = pos; + HeaderParserHelper::skipEOL(eol_pos); + next_word = HeaderParserHelper::getNextCodeElement(pos); + std::string const_name = next_word; + // Still same line? + if (pos <= eol_pos) + { + const char* tmp_pos = pos; + + // a #define doesn't necessarily have a value. so maybe + // we're already in the next line and mistakenly analyze + // the next statement already. this most likely breaks the + // parsing process, because this "next_word" would be lost. + // so don't consume the next word until we're sure to have a + // value + next_word = HeaderParserHelper::getNextCodeElement(tmp_pos); + if (tmp_pos <= eol_pos) + { + // everything ok, go on exploring this header + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + + // Still same line? Did we find an int? + if (pos <= eol_pos && a_util::strings::isInt64(next_word)) + { + int64_t value = a_util::strings::toInt64(next_word); + // Check if the next word is not in the same line anymore or eof is reached. + // Allowed is only /*...*/ comments. + // We must not increase pos, since otherwise a "#define" or "const" + // from the next line could be skipped. + next_word = HeaderParserHelper::getNextElement(tmp_pos); + while (tmp_pos < eol_pos && next_word == "/*") + { + HeaderParserHelper::skipComment(tmp_pos, next_word); + next_word = HeaderParserHelper::getNextElement(tmp_pos); + } + if (tmp_pos > eol_pos || *tmp_pos == '\0') + { + const HeaderType* type = findKnownType("tUInt64"); + if (_default_type != NULL) + { + type = _default_type; + } + if (type != NULL) + { + HeaderConstant* constant = new HeaderConstant(); + constant->setName(const_name); + constant->setType(type); + constant->reset(value); + _header->addConstant(constant); + } + } + } + } + } + } + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::buildStructs() + { + // The following types of definitions will raise our parsing attention: + // 1. struct original_name {..}; + // 2. typedef struct {..} typedef_name; + // 3. typedef struct original_name {..} typedef_name; + // #3 will result in a type entry and a typedef entry in the header, since both names refer to the same type + // Not supported are unnamed structs, like the following: + // 4. struct {..} name; + // 5. struct {..}; + // 6. typedef struct {..}; + const char* pos = _header_source.c_str(); + // This pack information could be extracted as a configurable setting later + std::vector pack_stack; + // Set default packing depending n compiler used +#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__ADTF64)) + pack_stack.push_back(8); +#else +#if defined(__GNUC__) & defined(__ADTF32) + pack_stack.push_back(4); +#else + //unknown compiler / platform + pack_stack.push_back(4); +#endif +#endif + while (*pos != '\0') + { + char tmp = *pos; + bool is_typedef = false; + std::string next_word = HeaderParserHelper::getNextCodeElement(pos); + // Packing identification + if (next_word == "#") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "pragma") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "pack") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == "(") + { + std::string command; + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (!a_util::strings::isInt64(next_word)) + { + if (next_word == "push" || next_word == "pop") + { + command = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word == ",") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + } + else + { + addErrorDescription("Cannot parse pragma, only push and pop are supported.", pos); + } + } + if (command == "pop") + { + if (next_word == ")") + { + if (pack_stack.size() > 1) + { + pack_stack.pop_back(); + } + else + { + addErrorDescription("Too many pragma pop.", pos); + } + } + else + { + addErrorDescription("Pragma pop is missing a closing parenthesis.", pos); + } + } + else + { + if (a_util::strings::isInt64(next_word)) + { + if (command == "") + { + pack_stack[pack_stack.size() - 1] = a_util::strings::toInt64(next_word); + } + else if (command == "push") + { + pack_stack.push_back(a_util::strings::toInt64(next_word)); + } + else { + addErrorDescription(a_util::strings::format("Unknown pragma command %s.", command.c_str()), pos); + } + } + else + { + addErrorDescription("Unknown value found within pragma, expected a number.", pos); + } + } + } + } + } + } + // Check for typedef of #2 or #3 + if (next_word == "typedef") + { + is_typedef = true; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + // Check for #1 - #3 + if (next_word == "struct") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + // Check for #1 or #3 + std::string original_name; + std::string typedef_name; + if (next_word != "{") + { + original_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + if (next_word == "{") + { + HeaderStructElementVec elements = extractStructElements(pos); + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word != ";") + { + if (!is_typedef) + { + addErrorDescription("Cannot parse struct.", pos); + } + else + { + //check for #2 or #3 + if (HeaderParserHelper::isValidName(next_word)) + { + typedef_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + else + { + addErrorDescription("The typedef struct is unreadable.", pos); + } + } + } + HeaderStruct* header_struct = new HeaderStruct(); + if (original_name.size() != 0) + { + header_struct->setName(original_name); + if (is_typedef && typedef_name.size() != 0) + { + _header->addTypedef(new HeaderTypedef(typedef_name, header_struct)); + } + } + else + { + header_struct->setName(typedef_name); + } + // Check for not #4 - #6 + if (header_struct->getName().size() != 0 && !(is_typedef && typedef_name.size() == 0)) + { + for (HeaderStructElementVec::const_iterator iter = elements.begin(); iter != elements.end(); iter++) + { + header_struct->addElement(*iter); + } + // Set current packing within struct if current packing is smaller than the native packing of the struct + if (header_struct->getPacking() > pack_stack.back()) + { + header_struct->setPacking(pack_stack.back()); + } + _header->addStruct(header_struct); + } + else + { + addErrorDescription("Cannot interpret this struct, no name given.", pos); + // Clean up allocated memory + delete header_struct; + for (HeaderStructElementVec::const_iterator iter = elements.begin(); iter != elements.end(); iter++) + { + delete *iter; + } + } + } + else + { + addErrorDescription("Cannot interpret this struct.", pos); + return ERR_UNKNOWN_FORMAT; + } + } + else + { + // No typedef for a struct it seems. + } + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderImporter::buildEnums() + { + // The following types of definitions will raise our parsing attention: + // 1. enum original_name {..}; + // 2. typedef enum {..} typedef_name; + // 3. typedef enum original_name {..} typedef_name; + // #3 will result in a type entry and a typedef entry in the header, since both names refer to the same type + // Not supported are unnamed enums, like the following: + // 4. enum {..} name; + // 5. enum {..}; + // 6. typedef enum {..}; + const char* pos = _header_source.c_str(); + + while (*pos != '\0') + { + char tmp = *pos; + bool is_typedef = false; + std::string next_word = HeaderParserHelper::getNextCodeElement(pos); + + // Check for typedef of #2 or #3 + if (next_word == "typedef") + { + is_typedef = true; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + // Check for #1 - #3 + if (next_word == "enum") + { + next_word = HeaderParserHelper::getNextCodeElement(pos); + // Check for #1 or #3 + std::string original_name; + std::string typedef_name; + if (next_word != "{") + { + original_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + if (next_word == "{") + { + HeaderEnumValueMap enum_values = extractEnumValues(pos); + next_word = HeaderParserHelper::getNextCodeElement(pos); + if (next_word != ";") + { + if (!is_typedef) + { + addErrorDescription("Cannot parse enum.", pos); + } + else + { + //check for #2 or #3 + if (HeaderParserHelper::isValidName(next_word)) + { + typedef_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(pos); + } + else + { + addErrorDescription("The typedef enum is unreadable.", pos); + } + } + } + HeaderEnum* header_enum = new HeaderEnum(); + if (original_name.size() != 0) + { + header_enum->setName(original_name); + if (is_typedef && typedef_name.size() != 0) + { + _header->addTypedef(new HeaderTypedef(typedef_name, header_enum)); + } + } + else + { + header_enum->setName(typedef_name); + } + // Check for not #4 - #6 + if (header_enum->getName().size() != 0) + { + for (auto iter = enum_values.begin(); iter != enum_values.end(); iter++) + { + header_enum->addValue(iter->first, iter->second); + } + _header->addEnum(header_enum); + } + else + { + addErrorDescription("Cannot interpret this enum, no name given.", pos); + // Clean up allocated memory + delete header_enum; + } + } + else + { + addErrorDescription("Cannot interpret this enum.", pos); + return ERR_UNKNOWN_FORMAT; + } + } + else + { + // No typedef for a enum it seems. + } + } + return ERR_NOERROR; + } + + + const std::string& HeaderImporter::getLastError() const + { + return _last_error; + } + + const HeaderType* HeaderImporter::findKnownType(const std::string &name) const + { + const HeaderType* type = NULL; + // Search for name in know types + for (HeaderTypesVec::const_iterator iter = _types->begin(); iter != _types->end(); iter++) + { + if ((*iter)->getName() == name) + { + type = *iter; + break; + } + } + if (type == NULL) + { + // If not found in the known types, look in the already parsed typedefs for the type. + const HeaderTypedefs typedefs = _header->getTypedefs(); + for (HeaderTypedefs::const_iterator iter = typedefs.begin(); iter != typedefs.end(); iter++) + { + if ((*iter)->getName() == name) + { + type = *iter; + break; + } + } + } + if (type == NULL) + { + // If not found in the already parsed typedefs, look in the already parsed structs for the type. + const HeaderStructs structs = _header->getStructs(); + for (HeaderStructs::const_iterator iter = structs.begin(); iter != structs.end(); iter++) + { + if ((*iter)->getName() == name) + { + type = *iter; + break; + } + } + } + if (type == NULL) + { + // If not found in the already parsed typedefs or structs look in the already parsed enums for the type. + const HeaderEnums enums = _header->getEnums(); + for (auto iter = enums.begin(); iter != enums.end(); iter++) + { + if ((*iter)->getName() == name) + { + type = *iter; + break; + } + } + } + return type; + } + + HeaderStructElementVec HeaderImporter::extractStructElements(const char* &pos) + { + // Copied over from the adtfcodec/cc_header.cpp implementation + // modified to fit current requirements. + std::string next_element; + std::set structs; + HeaderStructElementVec elements; + + while (*pos != '\0') + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element.compare("}") == 0) + { + break; + } + // Extract type + std::string type_name = next_element; + if (!HeaderParserHelper::isValidName(type_name)) + { + addErrorDescription(std::string("Unexpected string ").append(type_name), pos); + } + else + { + if (type_name == "signed" || type_name == "unsigned") + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (HeaderParserHelper::isValidName(next_element)) + { + type_name.append(" "); + type_name.append(next_element); + } + else + { + addErrorDescription(std::string("Unexpected string ").append(type_name), pos); + HeaderParserHelper::exitBlock(pos); + break; + } + } + const HeaderType* type = findKnownType(type_name); + if (type != NULL) + { + // Type successfully identified, try to extract member name + next_element = HeaderParserHelper::getNextCodeElement(pos); + // No pointer support yet + if (next_element == "*") + { + addErrorDescription("No pointers supported yet", pos); + HeaderParserHelper::exitBlock(pos); + break; + } + if (!HeaderParserHelper::isValidName(next_element)) + { + addErrorDescription(std::string("Invalid member name ").append(next_element), pos); + HeaderParserHelper::exitBlock(pos); + break; + } + std::string element_name = next_element; + // try to extract array info + size_t len = 1; + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element == "[") + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (!a_util::strings::isInt64(next_element)) + { + // Is it a constant`? + if (HeaderParserHelper::isValidName(next_element)) + { + bool found = false; + HeaderConstants constants = _header->getConstants(); + for (HeaderConstants::const_iterator iter = constants.begin(); iter != constants.end(); iter++) + { + if ((*iter)->getName() == next_element) + { + found = true; + if ((*iter)->asInt64() > 0) + { + len = (*iter)->asInt64(); + } + else + { + addErrorDescription("Array size type is not int", pos); + HeaderParserHelper::exitBlock(pos); + break; + } + break; + } + } + if (!found) + { + addErrorDescription("Array size value could not be found", pos); + HeaderParserHelper::exitBlock(pos); + break; + } + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element != "]") + { + addErrorDescription(std::string("Unexpected string ").append(next_element), pos); + } + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element != ";") + { + addErrorDescription(std::string("Unexpected string ").append(next_element), pos); + } + } + else + { + addErrorDescription(std::string("Invalid array size ").append(next_element), pos); + HeaderParserHelper::exitBlock(pos); + break; + } + } + else + { + len = a_util::strings::toInt32(next_element); + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element != "]") + { + addErrorDescription(std::string("Unexpected string ").append(next_element), pos); + } + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element != ";") + { + addErrorDescription(std::string("Unexpected string ").append(next_element), pos); + } + } + } + else if (next_element != ";") + { + addErrorDescription(std::string("Missing ; at end of struct member"), pos); + HeaderParserHelper::exitBlock(pos); + break; + } + HeaderStructElement* element = new HeaderStructElement(); + element->setType(type); + element->setName(element_name); + element->setArraySize(len); + // No pointer element recognition implemented yet + element->setIsPointer(false); + // No static element recognition implemented yet + element->setIsStatic(false); + // No const element recognition implemented yet + element->setIsConst(false); + elements.push_back(element); + } + else + { + addErrorDescription(std::string("Unknown type name: ").append(type_name), pos); + do + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + } while (next_element != ";" && next_element != "}"); + } + } + } + return elements; + } + + a_util::result::Result HeaderImporter::addErrorDescription(const std::string &description, const char* pos) + { + const char* search_pos = _header_source.c_str(); + uint64_t line_number = 1; + while (*search_pos != '\0') + { + if (search_pos >= pos) + { + break; + } + else if (*search_pos == '\n') + { + line_number++; + } + search_pos++; + } + if (_last_error.size() != 0) + { + _last_error.append("\n"); + } + _last_error.append(a_util::strings::format("Error: \"%s\" at Line %d", description.c_str(), line_number)); + return ERR_NOERROR; + } + + + a_util::result::Result HeaderImporter::parseTypedef(const char* &pos, std::string &token, std::string &original_type_name, std::string& new_type_name) + { + // We found a possible candidate for a new typedef + // We can have the following cases: + // 1 typedef token{... + // 2 typedef token {... + // 3 typedef token Bla{... + // 4 typedef token Bla {... + // 5 typedef token Bla Blubb; + // 6 typedef Bla Blubb; + // We are looking only for the last two. + const char* working_pos = pos; + std::string local_token; + // Check if first word if its a token + std::string next_word = HeaderParserHelper::getNextCodeElement(working_pos); + for (uint64_t idx = 0; idx < AMOUNT_OF_TOKENS; idx++) + { + if (g_tokens[idx] == next_word) + { + local_token = next_word; + next_word = HeaderParserHelper::getNextCodeElement(working_pos); + break; + } + } + // Now there have to be two valid names and one semicolon. Lets check it out! + if (HeaderParserHelper::isValidName(next_word)) + { + std::string local_original_type_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(working_pos); + if (HeaderParserHelper::isValidName(next_word)) + { + std::string local_new_type_name = next_word; + next_word = HeaderParserHelper::getNextCodeElement(working_pos); + if (next_word.compare(";") == 0) + { + // Yes!!! we found a valid typedef, case #5 or #6 + new_type_name = local_new_type_name; + original_type_name = local_original_type_name; + token = local_token; + pos = working_pos; + return ERR_NOERROR; + } + } + } + return ERR_UNKNOWN_FORMAT; + } + + HeaderEnumValueMap HeaderImporter::extractEnumValues(const char* &pos) + { + std::string next_element; + HeaderEnumValueMap values; + int32_t next_idx = 0; + + while (*pos != '\0') + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element.compare("}") == 0) + { + break; + } + // Extract type + std::string value_name = next_element; + if (!HeaderParserHelper::isValidName(value_name)) + { + addErrorDescription(std::string("Unexpected string ").append(value_name), pos); + } + else + { + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element == "," || next_element == "}") + { + values[next_idx++] = value_name; + } + else if (next_element == "=") + { + std::string index = HeaderParserHelper::getNextCodeElement(pos); + if (index == "-") + { + index += HeaderParserHelper::getNextCodeElement(pos); + } + int32_t idx = a_util::strings::toInt32(index); + if (values.count(idx) > 0) + { + addErrorDescription(std::string("Duplicate value in enum ").append(index), pos); + } + else + { + values[idx] = value_name; + next_idx = (std::max)(++next_idx, ++idx); //extra parantheses since msvc defines a max macro somewhere... + } + + next_element = HeaderParserHelper::getNextCodeElement(pos); + if (next_element != "," && next_element != "}") + { + addErrorDescription(std::string("Unexpected token ").append(next_element), pos); + } + } + else + { + addErrorDescription(std::string("Unexpected token ").append(next_element), pos); + } + + if (next_element == "}") + { + break; + } + } + } + return values; + } + +} //namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_importer.h b/ddlgenerators/generator_library/headerrepresentation/header_importer.h new file mode 100644 index 0000000..3a9d17f --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_importer.h @@ -0,0 +1,222 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_IMPORTER_H_INCLUDED +#define HEADER_IMPORTER_H_INCLUDED + +#include "header_factorymethod_intf.h" +#include "header_type.h" +#include "header_struct.h" +#include "header_enum.h" +#include "header_header.h" + +namespace ddl +{ + +/** + * Container type for header types. + */ +typedef std::vector HeaderTypesVec; + +/** + * The class HeaderImporter imports headers from file or string. + * The following settings can be performed regarding the import itself + * Default integer type: see setDefaultIntegerType() + */ + +class HeaderImporter : IHeaderFactory +{ +public: + + HeaderImporter(); + virtual ~HeaderImporter(); + + /** + * The method SetSourceString sets the text that will be parsed. + * Any filename previously set with setFileName will be ignored. + * + * @param [in] source The header string that will be parsed. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_UNKNOWN_FORMAT Could not parse the string because it is not a valid header file. + */ + a_util::result::Result setHeaderString(const std::string &source); + + /** + * The method setFileName sets the path to the file that will be parsed. + * Any string previously set with setHeaderString will be ignored. + * + * @param [in] filename The path to the file. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result setFileName(const a_util::filesystem::Path &filename); + + /** + * The method setKnownTypes adds a list of already known types. + * These types can be referenced by any member inside the header. + * Please be aware, that neither the importer object nor the + * resulting header object will own the types. The resulting + * header object will only reference them. So the resulting header + * must be deleted before the types are deleted. + * + * @param [in] types A list of types already know to the system. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result setKnownTypes(const HeaderTypesVec* types); + + /** + * The method GetErrors gives access to the last error that occurred. + * + * @returns The last error + */ + const std::string& getLastError() const; + + /** + * The method setDefaultIntegerType sets the type to be used for constants defined by + * \#define CONST_NAME 123. + * The class does not take ownership of the type. + * If no type is set, the createNew() method will try to find the type "tUInt64" within the known + * types and use this one. + * + * @remark You could pass a pointer from the known types list (setKnownTypes) for best consistency. + * + * @param [in] type The type to use for defines. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result setDefaultIntegerType(const HeaderType* type); + + /** + * The method getDefaultTypes creates a list of know types. The ADTF types will be treated as + * THE basic types (so "tFloat32" is the most basic type and not "float"). + * The list will contain the ADTF types and types from stdint.h. + * This list can be used with setKnownTypes() + * + * @returns A list of all known basic types. The caller will be the owner of the object. + */ + static HeaderTypesVec* getDefaultTypes(); + + + +public: // implements IHeaderFactory + + virtual Header * getHeader(); + + virtual a_util::result::Result createNew(); + + virtual a_util::result::Result DestroyHeader(); + + virtual a_util::result::Result BuildTypedefs(); + + virtual a_util::result::Result BuildConstants(); + + virtual a_util::result::Result buildStructs(); + + virtual a_util::result::Result buildEnums(); + +private: + /** + * The method findKnownType searches all lists with known types + * (typedefs and types in _header and other types from _types) + * for a type with the passed name + * + * @param [in] name The name of the type to be found. + * @returns A pointer to the found type. If no type was found, the function returns NULL. + */ + const HeaderType* findKnownType(const std::string &name) const; + + /** + * The function extractStructElements parses a block that defines a struct + * for elements. + * The function expects the passed pointer to point to the next character + * after the { character. After execution, the \a pos will point to the first + * character after the closing } character. + * The function does not keep the ownership of the elements inside the resulting vector. + * The caller is responsible to delete these elements. + * The order of the elements corresponds the order in the struct. + * + * @param [in,out] pos A pointer to the first character of the + opening "{" character of the struct block. + The pointer will point to the first character + after the closing "}" of the block. + * @returns A vector of all found struct elements. + */ + HeaderStructElementVec extractStructElements(const char* &pos); + + /** + * The method addErrorDescription adds a description string to the internal error string. + * It will try to extract the line number from the position of the source string. + * + * @param [in] description The error description to be added. + * @param [in] pos A pointer to the position inside the source string where the error occurred. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result addErrorDescription(const std::string &description, const char* pos); + + /** + * The method parseTypedef parses a typedef that does redefine an existing type. + * + * @param [inout] pos A pointer to the first character after the word "typedef". + After invocation of this method, this pointer will point to + the first character after the final ";" of the typedef. + If no typedef could be parsed successfully, the pos will not be altered. + * @param [out] new_type_name The name of new type + * @param [out] originalTypeName The name of the original type + * @param [out] token The token if available (like struct or enum) + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + * @retval ERR_UNKNOWN_FORMAT If a typedef could not be identified. + */ + a_util::result::Result parseTypedef(const char* &pos, std::string &token, std::string &original_type_name, std::string& new_type_name); + + /** + * The function extractEnumValues parses a block that defines a enum + * for it's values. + * The function expects the passed pointer to point to the next character + * after the { character. After execution, the \a pos will point to the first + * character after the closing } character. + * + * @param [in,out] pos A pointer to the first character of the + opening "{" character of the struct block. + The pointer will point to the first character + after the closing "}" of the block. + * @returns A map of all found enum values. + */ + HeaderEnumValueMap extractEnumValues(const char* &pos); + +private: + /// The internal header being build up. + Header* _header; + /// The file to be parsed + a_util::filesystem::Path _input_file; + /// The string to be parsed + std::string _header_source; + /// A list of already know types + const HeaderTypesVec* _types; + /// The last error that occurred + std::string _last_error; + /// The default integer type that will be used for defines, see also setDefaultIntegerType() + const HeaderType* _default_type; +}; +} + +#endif //HEADER_IMPORTER_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_printer.cpp b/ddlgenerators/generator_library/headerrepresentation/header_printer.cpp new file mode 100644 index 0000000..266e57f --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_printer.cpp @@ -0,0 +1,381 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_printer.h" +#include "header_header.h" +#include "header_basic_type.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-27, ERR_OPEN_FAILED) + _MAKE_RESULT(-38, ERR_FAILED) + } +} + +using namespace ddl_generator::oo; + +using namespace ddl; + +namespace ddl +{ + +HeaderPrinter::HeaderPrinter() : _header(NULL) +{ } + +HeaderPrinter::~HeaderPrinter() +{ } + +a_util::result::Result HeaderPrinter::writeToFile(const a_util::filesystem::Path &filename) +{ + std::string guarded_header_output = addHeaderGuards(filename, _header_output); + if (a_util::filesystem::writeTextFile(filename, guarded_header_output) != a_util::filesystem::OK) + { + return (ERR_OPEN_FAILED); + } + return ERR_NOERROR; +} + +const std::string& HeaderPrinter::getHeader() +{ + return _header_output; +} + +a_util::result::Result HeaderPrinter::visit(const Header* header) +{ + _header = header; + _header_output = ""; + _header_output.append("// This is a generated file, changes to it may be overwritten in the future.\n\n"); + + if (_name_space.length() > 0) + { + _header_output.append(a_util::strings::format("namespace %s\n{\n", _name_space.c_str())); + } + + HeaderTypedefs typedefs = header->getTypedefs(); + for (HeaderTypedefs::iterator iter = typedefs.begin(); iter != typedefs.end(); iter++) + { + if (isFailed((appendType(*iter)))) + { + return ERR_FAILED; + } + } + + HeaderEnums enums = header->getEnums(); + for (auto iter = enums.begin(); iter != enums.end(); iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + + HeaderStructs structs = header->getStructs(); + for (HeaderStructs::iterator iter = structs.begin(); iter != structs.end(); iter++) + { + if (isFailed((appendType(*iter)))) + { + return ERR_FAILED; + } + } + HeaderConstants constants = header->getConstants(); + for (HeaderConstants::iterator iter = constants.begin(); iter != constants.end(); iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + + if (isFailed((printUnknownTypes()))) + { + return ERR_FAILED; + } + + if (_name_space.length() > 0) + { + _header_output.append(a_util::strings::format("} // namespace %s\n", _name_space.c_str())); + } + + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderBasicType* basic_type) +{ + CollectType(basic_type, true); + _header_output.append("// The following type is assumed to be known:\n"); + _header_output.append("// "); + _header_output.append(basic_type->getName()); + _header_output.append("\n\n"); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderTypedef* type_def) +{ + printDescription(type_def); + // Set known first, so no infinite loop will occur when looking for base type + CollectType(type_def, true); + appendType(type_def->getOriginalType()); + _header_output.append(a_util::strings::format("typedef %s %s;\n\n", + type_def->getOriginalType()->getName().c_str(), type_def->getName().c_str())); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderConstant* constant) +{ + appendType(constant->getType()); + _header_output.append("const "); + _header_output.append(constant->getType()->getName()); + _header_output.append(" "); + _header_output.append(constant->getName()); + _header_output.append(" = "); + _header_output.append(constant->asString()); + _header_output.append(";\n\n"); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderStruct* header_struct) +{ + printDescription(header_struct); + // Set known first, so no infinite loop will occur when looking for base type + CollectType(header_struct, true); + // Make sure all types are already defined + HeaderStructElementVec elements = header_struct->getElements(); + for (HeaderStructElementVec::iterator iter = elements.begin(); iter != elements.end(); iter++) + { + appendType((*iter)->getType()); + } + _header_output.append(a_util::strings::format("#pragma pack(push,%d)\n", header_struct->getPacking())); + _header_output.append("typedef struct\n{\n"); + for (HeaderStructElementVec::iterator iter = elements.begin(); iter != elements.end(); iter++) + { + if (isFailed(((*iter)->accept(this)))) + { + return ERR_FAILED; + } + } + _header_output.append(a_util::strings::format("} %s;\n", header_struct->getName().c_str())); + _header_output.append("#pragma pack(pop)\n\n"); + CollectType(header_struct, true); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderStructElement* header_struct) +{ + if (!header_struct || !header_struct->getType()) + { + return ERR_INVALID_ARG; + } + printDescription(header_struct->getDescription(), header_struct->getComment(), true); + appendType(header_struct->getType()); + _header_output.append(" "); + if (header_struct->isStatic()) + { + _header_output.append("static "); + } + if (header_struct->isConst()) + { + _header_output.append("const "); + } + _header_output.append(header_struct->getType()->getName()); + if (header_struct->isPointer()) + { + _header_output.append("* "); + } + _header_output.append(" "); + _header_output.append(header_struct->getName()); + if (header_struct->getArraySize() > 1) + { + _header_output.append(a_util::strings::format("[%d]", header_struct->getArraySize())); + } + _header_output.append(";\n"); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::visit(const HeaderEnum* header_enum) +{ + CollectType(header_enum, true); + printDescription(header_enum); + _header_output.append("typedef enum {\n"); + for (auto iter = header_enum->getValues().begin(); iter != header_enum->getValues().end(); iter++) + { + _header_output.append(a_util::strings::format(" %s=%i,\n", iter->second.c_str(), iter->first)); + } + if (header_enum->getValues().size() > 0) + { + // remove last ',' since some versions of C/C++ don't allow trailing commas in enums + _header_output.resize(_header_output.length() - 2); + } + _header_output.append(a_util::strings::format("\n} %s;\n\n", header_enum->getName().c_str())); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::appendType(const HeaderType* type) +{ + // See if we already know this type and therefore have printed it already + for (HeaderConstTypes::iterator iter = _known_types.begin(); iter != _known_types.end(); iter++) + { + if (*iter == type) + { + return ERR_NOERROR; + } + } + // Search the header for the type. + if (_header != NULL) + { + for (HeaderTypedefs::const_iterator iter = _header->getTypedefs().begin(); iter != _header->getTypedefs().end(); iter++) + { + if (*iter == type) + { + // Found it, append it + return ((*iter)->accept(this)); + } + } + for (HeaderStructs::const_iterator iter = _header->getStructs().begin(); iter != _header->getStructs().end(); iter++) + { + if (*iter == type) + { + // Found it, append it + return ((*iter)->accept(this)); + } + } + } + // Nothing found so far, so type is unknown + CollectType(type, false); + return (ERR_NOT_FOUND); +} + +a_util::result::Result HeaderPrinter::CollectType(const ddl::HeaderType* type, bool is_known) +{ + if (is_known) + { + if (std::find(_known_types.begin(), _known_types.end(), type) == + _known_types.end()) + { + _known_types.push_back(type); + } + } + else + { + if (std::find(_unknown_types.begin(), _unknown_types.end(), type) == + _unknown_types.end()) + { + _unknown_types.push_back(type); + } + } + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::printUnknownTypes() +{ + // visit all types that are in the unknown types set but not in the knowN types set + HeaderConstTypes vec = _unknown_types; + for (HeaderConstTypes::iterator iter = vec.begin(); iter != vec.end(); iter++) + { + if (std::find(_known_types.begin(), _known_types.end(), *iter) == _known_types.end()) + { + (*iter)->accept(this); + } + } + if (vec.size() != _unknown_types.size()) + { + printUnknownTypes(); + } + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::printDescription(const std::string& description, const std::string& comment, bool indent) +{ + if (description.length() == 0 && comment.length() == 0) + { + return ERR_NOERROR; + } + + std::string indent_string; + if (indent) + { + indent_string = " "; + } + + _header_output.append(indent_string); + _header_output.append("/**\n"); + if (description.length() > 0) + { + _header_output.append(a_util::strings::format("%s * %s\n", indent_string.c_str(), description.c_str())); + } + if (comment.length() > 0) + { + _header_output.append(a_util::strings::format("%s * %s\n", indent_string.c_str(), comment.c_str())); + } + _header_output.append(indent_string); + _header_output.append("*/\n"); + return ERR_NOERROR; +} + +a_util::result::Result HeaderPrinter::printDescription(const HeaderType* type) +{ + return printDescription(type->getDescription(), type->getComment()); +} + +bool invalidHeaderChar(char c) +{ + bool is_num = (c >= '0' && c <= '9'); + bool is_uppercase_alpha = (c >= 'A' && c <= 'Z'); + bool is_lowercase_alpha = (c >= 'a' && c <= 'z'); + bool is_allowed_punctuation = (c == '.' || c == '_' || c == '-'); + return !(is_num || is_uppercase_alpha || is_lowercase_alpha || is_allowed_punctuation); +} + +std::string HeaderPrinter::addHeaderGuards(const a_util::filesystem::Path &filename, const std::string &unguarded_header_content) +{ + std::string guard_name = filename.getLastElement().toString(); + guard_name.erase(std::remove_if(guard_name.begin(), guard_name.end(), invalidHeaderChar), guard_name.end()); + std::replace(guard_name.begin(), guard_name.end(), '.', '_'); + std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(), ::toupper); + + std::string output; + + output.append("#ifndef "); + output.append(guard_name + "\n"); + output.append("#define "); + output.append(guard_name + "\n\n"); + + output.append(unguarded_header_content); + + output.append("\n#endif //"); + output.append(guard_name + "\n"); + + return output; +} + +void HeaderPrinter::SetNamespace(std::string name_space) +{ + _name_space = name_space; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_printer.h b/ddlgenerators/generator_library/headerrepresentation/header_printer.h new file mode 100644 index 0000000..26f8e3a --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_printer.h @@ -0,0 +1,144 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include "header_type.h" +#include "header_visitor_intf.h" + +namespace ddl +{ + /** + * Vector type for type objects + */ + typedef std::vector HeaderConstTypes; + + /** + * This class creates the header file string. + * @remark The class will not take ownership of any pointers passed. + */ + class HeaderPrinter : public IHeaderVisitor + { + public: + + /** + * Constructor + */ + HeaderPrinter(); + + /** + * Destructor + */ + virtual ~HeaderPrinter(); + + /** + * The method writeToFile writes the header string to the specified file. + * Existing files will be overwritten. + * + * @param [in] filename The path of the file to write to. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_OPEN_FAILED The file could not be opened. + * @retval ERR_PATH_NOT_FOUND The directory containing the file does not exist. + */ + a_util::result::Result writeToFile(const a_util::filesystem::Path &filename); + + /** + * The method getHeader returns the textual representation of the header. + * If no header has been parsed yet, the string will be empty. + * + * @returns The header as a string. + */ + const std::string& getHeader(); + + public: // implements IHeaderVisitor + a_util::result::Result visit(const Header* header); + + a_util::result::Result visit(const HeaderBasicType* basic_type); + + a_util::result::Result visit(const HeaderTypedef* type_def); + + a_util::result::Result visit(const HeaderConstant* constant); + + a_util::result::Result visit(const HeaderStruct* header_struct); + + a_util::result::Result visit(const HeaderStructElement* struct_element); + + a_util::result::Result visit(const HeaderEnum* header_enum); + + void SetNamespace(const std::string name_space); + + private: + + /** + * The method appendType looks for a type identified by its name. + * If the type is found, it is visited for printing. + * + * @param [in] strName The type. + * @returns Standard result code. + * @retval ERR_NOERROR The type was found and appended + * @retval ERR_NOT_FOUND The type could not be found + */ + a_util::result::Result appendType(const HeaderType* type); + + /** + * The method CollectType can be used for collecting types that occur during printing. + * This method is used to fill the list of known and unknown types. + * A type is unknown, if its just used, and known, if its defined. + * + * @param [in] type The type to be collected. The class does not take ownership of the type. + * @param [in] is_known Whether this type is known or not. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result CollectType(const HeaderType* type, bool is_known); + + /** + * The method printUnknownTypes prints the names of all types that occured during parsing + * and are not defined inside the header. + * + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result printUnknownTypes(); + + /** + * Helper method to print the description and/or comment of a type to the header. + * Only prints anything if either description or comment are non empty + */ + a_util::result::Result printDescription(const std::string& description, const std::string& comment, bool indent = false); + + /** + * Helper method to print the description and/or comment of a type to the header. + * Only prints anything if either description or comment are non empty + */ + a_util::result::Result printDescription(const HeaderType* type); + + /// The header to be parsed + const Header* _header; + /// The string containing the output of the printer + std::string _header_output; + /// The vector of known types + HeaderConstTypes _known_types; + /// The vector of unknown types + HeaderConstTypes _unknown_types; + + std::string _name_space; + + static std::string addHeaderGuards(const a_util::filesystem::Path &filename, const std::string &ungarded_header_content); + }; +} diff --git a/ddlgenerators/generator_library/headerrepresentation/header_struct.cpp b/ddlgenerators/generator_library/headerrepresentation/header_struct.cpp new file mode 100644 index 0000000..0c2beb8 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_struct.cpp @@ -0,0 +1,114 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ +#include +#include "header_struct.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + +namespace ddl +{ + +HeaderStruct::HeaderStruct() : HeaderType() +{ } + +HeaderStruct::HeaderStruct( std::string name, size_t packing /*= 4*/, HeaderStructElementVec header_elements /*= tHeaderElementVec()*/ ) + : HeaderType(name, packing), _header_elements(header_elements) +{ } + +HeaderStruct::HeaderStruct( HeaderStruct& other ) + : HeaderType(other) +{ + for (HeaderStructElementVec::iterator iter = other._header_elements.begin(); iter != other._header_elements.end(); iter++) + { + _header_elements.push_back(new HeaderStructElement(*(*iter))); + } +} + +HeaderStruct::~HeaderStruct() +{ + for (HeaderStructElementVec::iterator iter = _header_elements.begin(); iter != _header_elements.end(); iter++) + { + delete *iter; + } + _header_elements.clear(); +} + +const HeaderStructElementVec& HeaderStruct::getElements() const +{ + return _header_elements; +} + +a_util::result::Result HeaderStruct::addElement( HeaderStructElement* element ) +{ + _header_elements.push_back(element); + recalculatePacking(); + return ERR_NOERROR; +} + +a_util::result::Result HeaderStruct::removeElement( const std::string &name ) +{ + for (HeaderStructElementVec::iterator iter = _header_elements.begin(); iter != _header_elements.end(); iter++) + { + if ((*iter)->getName() == name) + { + delete *iter; + _header_elements.erase(iter); + return ERR_NOERROR; + } + } + return (ERR_NOT_FOUND); +} + +a_util::result::Result HeaderStruct::accept(IHeaderVisitor *visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} + +a_util::result::Result HeaderStruct::recalculatePacking() +{ + size_t packing = 0; + for (HeaderStructElementVec::const_iterator iter = _header_elements.begin(); iter != _header_elements.end(); iter++) + { + if (NULL != (*iter)->getType() && packing < (*iter)->getType()->getPacking()) + { + packing = (*iter)->getType()->getPacking(); + } + } + setPacking(packing); + return ERR_NOERROR; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_struct.h b/ddlgenerators/generator_library/headerrepresentation/header_struct.h new file mode 100644 index 0000000..40b193f --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_struct.h @@ -0,0 +1,112 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_STRUCT_H_INCLUDED +#define HEADER_STRUCT_H_INCLUDED +#include "header_struct_element.h" + +namespace ddl +{ + + /** + * Container type of HeaderStructElement objects. + */ + typedef std::vector HeaderStructElementVec; + + /** + * Representation of a struct in a header. + * The class calculates its own packing from its children + * every time one or more children have been added or removed. + * To override the calculated packing, set the packing value AFTER adding + * children. + */ + class HeaderStruct : public HeaderType + { + public: + /** + * Default CTOR + */ + HeaderStruct(); + + /** + * CTOR + * @param [in] name The name of the struct. + * @param [in] packing The packing of the struct. + * @param [in] header_elements The elements of the struct. + * The struct takes ownership of the passed elements. + */ + HeaderStruct(std::string name, + size_t packing = 4, + HeaderStructElementVec header_elements = HeaderStructElementVec()); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderStruct(HeaderStruct& other); + + /** + * DTOR + */ + virtual ~HeaderStruct(); + + /** + * This method gives access to the elements of the struct. + * @return The packing size of the element. + */ + const HeaderStructElementVec& getElements() const; + + /** + * This method adds an element to the internal list of elements of the struct. + * @param [in] element The element to be added. The struct takes ownership of the object. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result addElement(HeaderStructElement* element); + + /** + * This method removes an element from the internal list of elements of the struct. + * @param [in] name The name of the element to be removed. + * @return Standard result code. + * @retval ERR_NOERROR Everything is ok. + * @retval ERR_NOT_FOUND No element with this name was found. + */ + a_util::result::Result removeElement(const std::string &name); + + public: // implements cHeaderBaseType + + a_util::result::Result accept(IHeaderVisitor *visitor) const; + + private: + + /** + * The method recalculatePacking calculates the pack value according to its child element. + * The biggest pack value of any child is the pack value of this struct. + * This represents the mechanism of a C compiler to calculate the packing of a struct. + * + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result recalculatePacking(); + + /// The elements of the struct. + HeaderStructElementVec _header_elements; + }; +} // namespace ddl + +#endif // HEADER_STRUCT_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_struct_element.cpp b/ddlgenerators/generator_library/headerrepresentation/header_struct_element.cpp new file mode 100644 index 0000000..2e9b7e9 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_struct_element.cpp @@ -0,0 +1,172 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_struct_element.h" +#include "header_visitor_intf.h" +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + +namespace ddl +{ + +HeaderStructElement::HeaderStructElement() +{ + _type = NULL; + _array_size = 0; + _is_pointer = false; + _is_static = false; + _is_const = false; +} + +HeaderStructElement::HeaderStructElement(const std::string &name, + const HeaderType* type, + size_t array_size, + bool is_pointer, + bool is_static, + bool is_const) +{ + _name = name; + _type = type; + _array_size = array_size; + _is_pointer = is_pointer; + _is_static = is_static; + _is_const = is_const; +} + +HeaderStructElement::HeaderStructElement( HeaderStructElement& other ) +{ + _type = other._type; + _array_size = other._array_size; + _is_pointer = other._is_pointer; + _is_static = other._is_static; + _is_const = other._is_const; +} + +HeaderStructElement::~HeaderStructElement() +{ } + +const HeaderType* HeaderStructElement::getType() const +{ + return _type; +} + +a_util::result::Result HeaderStructElement::setType( const HeaderType* type ) +{ + _type = type; + return ERR_NOERROR; +} + +const std::string& HeaderStructElement::getName() const +{ + return _name; +} + +a_util::result::Result HeaderStructElement::setName( const std::string& name ) +{ + _name = name; + return ERR_NOERROR; +} + +size_t HeaderStructElement::getArraySize() const +{ + return _array_size; +} + +a_util::result::Result HeaderStructElement::setArraySize( size_t array_size ) +{ + _array_size = array_size; + return ERR_NOERROR; +} + +bool HeaderStructElement::isPointer() const +{ + return _is_pointer; +} + +a_util::result::Result HeaderStructElement::setIsPointer( bool is_pointer ) +{ + _is_pointer = is_pointer; + return ERR_NOERROR; +} + +bool HeaderStructElement::isStatic() const +{ + return _is_static; +} + +a_util::result::Result HeaderStructElement::setIsStatic( bool is_static ) +{ + _is_static = is_static; + return ERR_NOERROR; +} + +bool HeaderStructElement::isConst() const +{ + return _is_const; +} + +a_util::result::Result HeaderStructElement::setIsConst(bool is_constant) +{ + _is_const = is_constant; + return ERR_NOERROR; +} + +a_util::result::Result HeaderStructElement::accept(IHeaderVisitor *visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} + +const std::string &HeaderStructElement::getDescription() const +{ + return _description; +} + +a_util::result::Result HeaderStructElement::setDescription(const std::string& description) +{ + _description = description; + return ERR_NOERROR; +} + +const std::string &HeaderStructElement::getComment() const +{ + return _comment; +} + +a_util::result::Result HeaderStructElement::setComment(const std::string& comment) +{ + _comment = comment; + return ERR_NOERROR; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_struct_element.h b/ddlgenerators/generator_library/headerrepresentation/header_struct_element.h new file mode 100644 index 0000000..cb1706f --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_struct_element.h @@ -0,0 +1,198 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_STRUCT_ELEMENT_H_INCLUDED +#define HEADER_STRUCT_ELEMENT_H_INCLUDED +#include "header_base_intf.h" +#include "header_type.h" +#include "header_struct_element.h" + +namespace ddl +{ + + /** + * Representation of in a struct element. + */ + class HeaderStructElement : public IHeaderBase + { + public: + /** + * Default CTOR + */ + HeaderStructElement(); + + /** + * CTOR + * + * @param [in] name The name of the element. + * @param [in] type A pointer to the type this element is of. An instance of this class will not own the type. + * @param [in] array_size The array size of the element + * @param [in] is_pointer Set true, if the element is an pointer, false otherwise. + * @param [in] is_static Set true, if the element is static, false otherwise. + * @param [in] is_const Set true, if the element is constant, false otherwise. + */ + HeaderStructElement(const std::string &name, const HeaderType* type, + size_t array_size, + bool is_pointer, + bool is_static, + bool is_const); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderStructElement(HeaderStructElement& other); + + /** + * DTOR + */ + virtual ~HeaderStructElement(); + + // Setter and getter for member access + + /** + * This method gives access to the type of the element. + * @return The type of the element. + */ + const HeaderType* getType() const; + + /** + * This method sets the type of the element. + * @param [in] type The type of the element. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setType(const HeaderType* type); + + /** + * This method gives access to the name of the element. + * @return The name of the element. + */ + const std::string& getName() const; + + /** + * This method gives access to the name of the element. + * @param [in] name The name of the element. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setName(const std::string& name); + + /** + * This method gives access to the array size of the element. + * @return The array size of the element. + */ + size_t getArraySize() const; + + /** + * This method sets the array size of the element. + * @param [in] array_size The array size of the element. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setArraySize(size_t array_size); + + /** + * This method returns whether the element is a pointer or not. + * @return True if the element is a pointer, false otherwise. + */ + bool isPointer() const; + + /** + * This method sets whether the element is a pointer or not. + * @param [in] is_pointer Set true if the element is a pointer, false otherwise. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setIsPointer(bool is_pointer); + + /** + * This method returns whether the element is static or not. + * @return True if the element is static, false otherwise. + */ + bool isStatic() const; + + /** + * This method sets whether the element is static or not. + * @param [in] is_static Set true if the element is static, false otherwise. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setIsStatic(bool is_static); + + /** + * This method returns whether the element is a const. + * @return True if the element is a const, false otherwise. + */ + bool isConst() const; + + /** + * This method sets whether the element is a const or not. + * @param [in] is_constant Set true if the element is a const, false otherwise. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setIsConst(bool is_constant); + + /** + * This method gives access to the description of the type. + * @return The description of the element. + */ + const std::string& getDescription() const; + + /** + * This method gives access to the description of the type. + * @param [in] description The description of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setDescription(const std::string& description); + + /** + * This method gives access to the comment of the type. + * @return The comment of the element. + */ + const std::string& getComment() const; + + /** + * This method gives access to the comment of the type. + * @param [in] comment The comment of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setComment(const std::string& comment); + + public: //implements IHeaderBase + + virtual a_util::result::Result accept(IHeaderVisitor *visitor) const; + + private: + /// The type of the element. + const HeaderType* _type; + /// The name of the element. + std::string _name; + /// The array size of the element. + size_t _array_size; + // Flags for the element + /// The element is a pointer. + bool _is_pointer; + /// The element is static. + bool _is_static; + /// The element is const. + bool _is_const; + /// The description of the type. + std::string _description; + /// The comment of the type. + std::string _comment; + }; +} // namespace ddl + +#endif // HEADER_STRUCT_ELEMENT_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.cpp b/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.cpp new file mode 100644 index 0000000..1630045 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.cpp @@ -0,0 +1,441 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_to_ddl_converter.h" +#include "header_header.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-19, ERR_NOT_SUPPORTED) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-38, ERR_FAILED) + } +} + +using namespace ddl_generator::oo; + +using namespace ddl; + +namespace ddl +{ + + /** + * This class tries to resolve a typedef down to its original type, following all consecutive typedefs. + * start the process by visiting a typedef and if successfull, either the getStruct() or the getBasicType() + * method will not return a NULL pointer, meaning that this is the found type the typedef is pointing to + * in the end. + * The class will not take ownership of anything. Well thats kinda obvious since it only accepts pointers + * to const types. + */ + class TypeResolver : public IHeaderVisitor { + public: + /** + * CTOR + */ + TypeResolver() + { + reset(); + } + + /** + * The method Reset resets all internal states so that the class is fresh and shiny as new. + * + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine + */ + a_util::result::Result reset() + { + _basic_type = NULL; + _struct = NULL; + _enum = NULL; + _visited_typedefs.clear(); + return ERR_NOERROR; + } + + /** + * The method getStruct returns the found struct. + * + * @returns A pointer to the found struct if found, NULL otherwise. + */ + const HeaderStruct* getStruct() + { + return _struct; + } + + /** + * The method getBasicType returns the found basic type. + * + * @returns A pointer to the found basic tyoe if found, NULL otherwise. + */ + const HeaderBasicType* getBasicType() + { + return _basic_type; + } + + /** + * The method getEnum returns the found enum. + * + * @returns A pointer to the found Enum if found, NULL otherwise. + */ + const HeaderEnum* getEnum() + { + return _enum; + } + + public: // Implements IHeaderVisitor + virtual a_util::result::Result visit(const Header* header) + { + return ERR_NOT_IMPL; + } + virtual a_util::result::Result visit(const HeaderBasicType* basic_type) + { + _basic_type = basic_type; + return ERR_NOERROR; + } + virtual a_util::result::Result visit(const HeaderTypedef* type_def) + { + // Check if we have visited that typedef before + if (std::find(_visited_typedefs.begin(), _visited_typedefs.end(), type_def) == _visited_typedefs.end()) + { + // Store typedef, so we wont visit it again, in case of a circular connection + _visited_typedefs.push_back(type_def); + + return type_def->getOriginalType()->accept(this); + } + return ERR_NOT_SUPPORTED; + } + virtual a_util::result::Result visit(const HeaderConstant* constant) + { + return ERR_NOT_IMPL; + } + + virtual a_util::result::Result visit(const HeaderStruct* header_struct) + { + _struct = header_struct; + return ERR_NOERROR; + } + virtual a_util::result::Result visit(const HeaderStructElement* struct_element) + { + return ERR_NOT_IMPL; + } + + virtual a_util::result::Result visit(const HeaderEnum* header_enum) + { + _enum = header_enum; + return ERR_NOERROR; + } + private: + const HeaderBasicType *_basic_type; + const HeaderStruct *_struct; + const HeaderEnum *_enum; + HeaderConstTypedefs _visited_typedefs; + }; + + HeaderToDDLConverter::HeaderToDDLConverter() : _description(NULL), _header(NULL) + { } + + HeaderToDDLConverter::~HeaderToDDLConverter() + { } + + + a_util::result::Result HeaderToDDLConverter::visit(const Header* header) + { + _header = header; + for (HeaderTypedefs::const_iterator iter = header->getTypedefs().begin(); iter != header->getTypedefs().end(); iter++) + { + (*iter)->accept(this); + } + for (HeaderStructs::const_iterator iter = header->getStructs().begin(); iter != header->getStructs().end(); iter++) + { + (*iter)->accept(this); + } + for (HeaderConstants::const_iterator iter = header->getConstants().begin(); iter != header->getConstants().end(); iter++) + { + (*iter)->accept(this); + } + for (auto iter = header->getEnums().begin(); iter != header->getEnums().end(); iter++) + { + (*iter)->accept(this); + } + return ERR_NOERROR; + } + + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderBasicType* basic_type) + { + _basic_types.insert(basic_type); + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderTypedef* type_def) + { + if (std::find(_typedefs.begin(), _typedefs.end(), type_def) == _typedefs.end()) + { + _typedefs.push_back(type_def); + type_def->getOriginalType()->accept(this); + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderConstant* constant) + { + if (std::find(_constants.begin(), _constants.end(), constant) == _constants.end()) + { + _constants.push_back(constant); + // Also add the type of the constant + constant->getType()->accept(this); + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderStruct* header_struct) + { + if (std::find(_structs.begin(), _structs.end(), header_struct) == _structs.end()) + { + // Add struct to vector, so if its referenced within other types used in the struct, there wont be an infinite loop. + _structs.push_back(header_struct); + // Take care of the struct elements + for (HeaderStructElementVec::const_iterator iter = header_struct->getElements().begin(); iter != header_struct->getElements().end(); iter++) + { + (*iter)->accept(this); + } + // Now move the struct to the end, so all needed types will be defined before the struct + _structs.erase(std::find(_structs.begin(), _structs.end(), header_struct)); + _structs.push_back(header_struct); + + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderStructElement* struct_element) + { + struct_element->getType()->accept(this); + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::visit(const HeaderEnum* header_enum) + { + if (std::find(_enums.begin(), _enums.end(), header_enum) == _enums.end()) + { + _enums.push_back(header_enum); + } + + return ERR_NOERROR; + } + + DDLDescription * HeaderToDDLConverter::getDDL() const + { + return _description; + } + + a_util::result::Result HeaderToDDLConverter::createNew(const ddl::DDLVersion& version /*= 0*/) + { + _description = DDLDescription::createDefault(version, 4, false); + buildHeader(); + buildUnits(); + buildDatatypes(); + buildEnums(); + buildStructs(); + buildStreams(); + + + ddl::DDLInspector inspector(true); + if (isFailed((inspector.visitDDL(_description)))) + { + LOG_ERROR(inspector.getLastErrorDesc().c_str()); + return ERR_FAILED; + } + + return ERR_NOERROR; + } + + + void HeaderToDDLConverter::destroyDDL() + { + if (_description != NULL) + { + delete _description; + _description = NULL; + } + } + + a_util::result::Result HeaderToDDLConverter::buildHeader() + { + DDLHeader* header = _description->getHeader(); + a_util::datetime::Date now = a_util::datetime::getCurrentLocalDate(); + header->setAuthor(a_util::system::getCurrentUserName()); + header->setDateCreation(now); + header->setDateChange(now); + header->setDescription(std::string("Generated by DDL_Editor ")); + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildUnits() + { + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildDatatypes() + { + for (HeaderConstBasicTypes::iterator iter = _basic_types.begin(); iter != _basic_types.end(); iter++) + { + if (_description->getDataTypeByName((*iter)->getName()) == NULL) + { + _description->addDatatype(new DDLDataType((*iter)->getName(), static_cast((*iter)->getBitsize_t()))); + } + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildStructs() + { + // First all structs will be created but without any members. + // This way, all types are already defined. + // This approach is comparable to a forward declaration known from C++ + for (HeaderConstStructs::iterator struct_iter = _structs.begin(); struct_iter != _structs.end(); struct_iter++) + { + DDLComplex* complex = new DDLComplex((*struct_iter)->getName(), 0, "", toAlignment((*struct_iter)->getPacking())); + _description->addStruct(complex); + } + // Second all structs will be filled with elements. + for (HeaderConstStructs::iterator struct_iter = _structs.begin(); struct_iter != _structs.end(); struct_iter++) + { + DDLComplex* complex = _description->getStructByName((*struct_iter)->getName()); + for (HeaderStructElementVec::const_iterator element_iter = (*struct_iter)->getElements().begin(); + element_iter != (*struct_iter)->getElements().end(); element_iter++) + { + // Resolve the type of the element. Please refer to ticket #19830, comment 48 if you want to know why this is done. + TypeResolver resolver; + if (isFailed(((*element_iter)->getType()->accept(&resolver)))) + { + return ERR_FAILED; + } + IDDLDataType* ddl_data_type = NULL; + if (resolver.getBasicType() != NULL) + { + ddl_data_type = _description->getDataTypeByName(resolver.getBasicType()->getName()); + } + else if (resolver.getStruct() != NULL) + { + ddl_data_type = _description->getStructByName(resolver.getStruct()->getName()); + } + else if (resolver.getEnum() != NULL) + { + ddl_data_type = _description->getEnumByName(resolver.getEnum()->getName()); + } + else + { + // Something really went wrong here + return (ERR_FAILED); + } + DDLElement* element = new DDLElement(ddl_data_type, + (*element_iter)->getName(), + 0, // See bytepos related comment below + static_cast((*element_iter)->getArraySize()), + DDLByteorder::e_le, + DDLAlignment::e0); // Alignment will be determined later + + // Take the alignment of the whole struct into account. + if ((*element_iter)->getType()->getPacking() > (*struct_iter)->getPacking()) + { + element->setAlignment(toAlignment((*struct_iter)->getPacking())); + } + else + { + element->setAlignment(toAlignment((*element_iter)->getType()->getPacking())); + } + + // Bytepos will not be set here (to anything but zero), the byte position calculation + // method of the DDL Inspector will be used later. + complex->addElement(element); + } + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildStreams() + { + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildEnums() + { + for (auto iter = _enums.begin(); iter != _enums.end(); iter++) + { + const HeaderEnum* current_enum = *iter; + if (NULL != _description->getEnumByName(current_enum->getName())) + { + continue; + } + EnumNameValueVec enum_values; + for (auto value_iter = current_enum->getValues().begin(); value_iter != current_enum->getValues().end(); value_iter++) + { + std::pair pair(value_iter->second, a_util::strings::format("%d", value_iter->first)); + enum_values.push_back(pair); + } + DDLDataType* data_type = _description->getDataTypeByName("tInt32"); + DDLEnum* ddl_enum = new DDLEnum(data_type, current_enum->getName(), enum_values); + + _description->addEnum(ddl_enum); + } + return ERR_NOERROR; + } + + a_util::result::Result HeaderToDDLConverter::buildStreamMetaTypes() + { + return ERR_NOERROR; + } + + ddl::DDLAlignment::AlignmentType HeaderToDDLConverter::toAlignment(size_t packing) + { + DDLAlignment::AlignmentType result = DDLAlignment::e1; + switch (packing) + { + case 0: + case 1: + result = DDLAlignment::e1; + break; + case 2: + result = DDLAlignment::e2; + break; + case 4: + result = DDLAlignment::e4; + break; + case 8: + result = DDLAlignment::e8; + break; + case 16: + result = DDLAlignment::e16; + break; + case 32: + result = DDLAlignment::e32; + break; + case 64: + result = DDLAlignment::e64; + break; + } + return result; + } + +} diff --git a/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.h b/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.h new file mode 100644 index 0000000..99db0e4 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_to_ddl_converter.h @@ -0,0 +1,144 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_TO_DDL_CONVERTER_H_INCLUDED +#define HEADER_TO_DDL_CONVERTER_H_INCLUDED + +#include "header_basic_type.h" +#include "header_typedef.h" +#include "header_constant.h" +#include "header_struct.h" +#include "header_enum.h" +#include "header_visitor_intf.h" + +namespace ddl +{ +/** + * A Set of basic types + */ +typedef std::set HeaderConstBasicTypes; + +/** + * Container type of basic type objects + */ +typedef std::vector HeaderConstTypedefs; + +/** + * Container type of constants objects + */ +typedef std::vector HeaderConstConstants; + +/** + * Container type of struct objects + */ +typedef std::vector HeaderConstStructs; + +/** + * Container type of enum objects + */ +typedef std::vector HeaderConstEnums; + + +/** + * This class generates a DDL from a header. + * Use this class by first visiting the element(s) of the header you want to be part of your DDL, + * then call createNew() to create the DDL from the previously parsed header elements. + * The generator tries to extract all needed datatypes from the header and stores them in a local + * header as a copy (not the basic types). This copy then will then be converted to DDL. + */ +class HeaderToDDLConverter : public IHeaderVisitor, public IDDLFactoryMethod +{ +public: + + /** + * CTOR + */ + HeaderToDDLConverter(); + + /** + * DTOR + */ + virtual ~HeaderToDDLConverter(); + +public: // implements IHeaderVisitor + + virtual a_util::result::Result visit(const Header* header); + + virtual a_util::result::Result visit(const HeaderBasicType* basic_type); + + virtual a_util::result::Result visit(const HeaderTypedef* type_def); + + virtual a_util::result::Result visit(const HeaderConstant* constant); + + virtual a_util::result::Result visit(const HeaderStruct* header_struct); + + virtual a_util::result::Result visit(const HeaderStructElement* struct_element); + + virtual a_util::result::Result visit(const HeaderEnum* header_enum); + +public: // implements IDDLFactoryMethod + virtual DDLDescription * getDDL() const; + + virtual a_util::result::Result createNew(const DDLVersion& version = DDLVersion::ddl_version_invalid); + + virtual void destroyDDL(); + + virtual a_util::result::Result buildHeader(); + + virtual a_util::result::Result buildUnits(); + + virtual a_util::result::Result buildDatatypes(); + + virtual a_util::result::Result buildStructs(); + + virtual a_util::result::Result buildStreams(); + + virtual a_util::result::Result buildEnums(); + virtual a_util::result::Result buildStreamMetaTypes(); + +private: + + /** + * The method toAlignment calculates the alignment from an packing value. + * + * @param [in] packing The packing value + * @returns The alignment value, e0 if no matching packing or 0 was found. + */ + ddl::DDLAlignment::AlignmentType toAlignment(size_t packing); + + /// The header that was passed. + DDLDescription* _description; + + /// The header to be converted + const Header* _header; + + /// The basic types found during parsing + HeaderConstBasicTypes _basic_types; + /// The constants found during parsing + HeaderConstConstants _constants; + /// The structs found during parsing + HeaderConstStructs _structs; + /// The typedefs found during parsing + HeaderConstTypedefs _typedefs; + /// The enums found during parsing + HeaderConstEnums _enums; +}; +} + +#endif // HEADER_TO_DDL_CONVERTER_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_type.cpp b/ddlgenerators/generator_library/headerrepresentation/header_type.cpp new file mode 100644 index 0000000..48a4990 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_type.cpp @@ -0,0 +1,100 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_type.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + + + +namespace ddl +{ + +HeaderType::HeaderType() : _packing(0) +{ } + +HeaderType::HeaderType(const std::string &name, size_t packing) : + _packing(packing), + _name(name) +{ } + +HeaderType::HeaderType(const HeaderType& other) : + _packing(other._packing), + _name(other._name) +{ } + +HeaderType::~HeaderType() +{ } + +const std::string &HeaderType::getName() const +{ + return _name; +} + +a_util::result::Result HeaderType::setName(const std::string& name) +{ + _name = name; + return ERR_NOERROR; +} + +const std::string &HeaderType::getDescription() const +{ + return _description; +} + +a_util::result::Result HeaderType::setDescription(const std::string& description) +{ + _description = description; + return ERR_NOERROR; +} + +const std::string &HeaderType::getComment() const +{ + return _comment; +} + +a_util::result::Result HeaderType::setComment(const std::string& comment) +{ + _comment = comment; + return ERR_NOERROR; +} + +size_t HeaderType::getPacking() const +{ + return _packing; +} + +a_util::result::Result HeaderType::setPacking( size_t packing ) +{ + _packing = packing; + return ERR_NOERROR; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_type.h b/ddlgenerators/generator_library/headerrepresentation/header_type.h new file mode 100644 index 0000000..bba7a60 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_type.h @@ -0,0 +1,127 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_TYPE_H_INCLUDED +#define HEADER_TYPE_H_INCLUDED + +#include "header_base_intf.h" + +namespace ddl +{ + + /** + * Representation of a type in a header. + */ + class HeaderType : public IHeaderBase + { + public: + /** + * Default CTOR + */ + HeaderType(); + + /** + * CTOR + * + * @param [in] name The name of the type. + * @param [in] packing he packing of the type + */ + HeaderType(const std::string &name, size_t packing); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderType(const HeaderType& other); + + /** + * DTOR + */ + virtual ~HeaderType(); + + /** + * This method gives access to the name of the type. + * @return The name of the element. + */ + const std::string& getName() const; + + /** + * This method gives access to the name of the type. + * @param [in] name The name of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setName(const std::string& name); + + /** + * This method gives access to the packing size of the type. + * @return The packing size of the struct. + */ + virtual size_t getPacking() const; + + /** + * This method sets the packing size of the type. + * @param [in] packing The packing size of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setPacking(size_t packing); + + + /** + * This method gives access to the description of the type. + * @return The description of the element. + */ + const std::string& getDescription() const; + + /** + * This method gives access to the description of the type. + * @param [in] description The description of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setDescription(const std::string& description); + + /** + * This method gives access to the comment of the type. + * @return The comment of the element. + */ + const std::string& getComment() const; + + /** + * This method gives access to the comment of the type. + * @param [in] comment The comment of the type. + * @return Standard result code. Will always return ERR_NOERROR. + */ + a_util::result::Result setComment(const std::string& comment); + + public: //implements IHeaderBase + + virtual a_util::result::Result accept(IHeaderVisitor *visitor) const = 0; + + protected: + /// The packing of the type. + size_t _packing; + /// The name of the type. + std::string _name; + /// The description of the type. + std::string _description; + /// The comment of the type. + std::string _comment; + }; +} // namespace ddl + +#endif // HEADER_TYPE_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_typedef.cpp b/ddlgenerators/generator_library/headerrepresentation/header_typedef.cpp new file mode 100644 index 0000000..e2f1c54 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_typedef.cpp @@ -0,0 +1,85 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#include +#include "header_typedef.h" +#include "header_visitor_intf.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} + +using namespace ddl_generator::oo; +using namespace ddl; + + +namespace ddl +{ + +HeaderTypedef::HeaderTypedef() : HeaderType() +{ + _type = NULL; +} + +HeaderTypedef::HeaderTypedef(const std::string &name, const HeaderType* type) + : HeaderType(name, 0), _type(type) +{ } + +HeaderTypedef::HeaderTypedef(const HeaderTypedef& other) + : HeaderType(other), _type(other._type) +{ } + +HeaderTypedef::~HeaderTypedef() +{ + _type = NULL; +} + +a_util::result::Result HeaderTypedef::accept(IHeaderVisitor *visitor) const +{ + if (!visitor) + { + return ERR_INVALID_ARG; + } + return (visitor->visit(this)); +} + + +const HeaderType* HeaderTypedef::getOriginalType() const +{ + return _type; +} + +a_util::result::Result HeaderTypedef::setOriginalType(const HeaderType *type) +{ + _type = type; + return ERR_NOERROR; +} + +size_t HeaderTypedef::getPacking() const +{ + return _type != NULL ? _type->getPacking() : 0; +} + +} // namespace ddl diff --git a/ddlgenerators/generator_library/headerrepresentation/header_typedef.h b/ddlgenerators/generator_library/headerrepresentation/header_typedef.h new file mode 100644 index 0000000..7970958 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_typedef.h @@ -0,0 +1,93 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_TYPEDEF_H_INCLUDED +#define HEADER_TYPEDEF_H_INCLUDED + +#include "header_type.h" + +namespace ddl +{ + + /** + * Representation of a typedef in a header. + * + * @remark This class does not support unnamed structs/unions or anonymous unions. + */ + class HeaderTypedef : public HeaderType + { + public: + /** + * Default CTOR + */ + HeaderTypedef(); + + /** + * CTOR + * @param[in] name The name of the type. + * @param[in] type The original type this type represents. This class is not taking ownership of the type. + */ + HeaderTypedef(const std::string &name, const HeaderType* type); + + /** + * Copy CTOR + * @param [in] other The other type this instance will be a copy of. + */ + HeaderTypedef(const HeaderTypedef& other); + + /** + * DTOR + */ + virtual ~HeaderTypedef(); + + /** + * The method getOriginalType gives access to the original type this type is representing. + * + * @returns The original type. + */ + const HeaderType* getOriginalType() const; + + /** + * The method setOriginalType sets the original type this type represents. + * + * @param [in] type The original type. This class is not taking ownership of the type. + * @returns Standard result code. + * @retval ERR_NOERROR Everything went fine. + */ + a_util::result::Result setOriginalType(const HeaderType *type); + + public: //implements HeaderType + + virtual a_util::result::Result accept(IHeaderVisitor *visitor) const; + + public: //overrides HeaderType + /** + * @copydoc HeaderType::getPacking() + * @remark The packing information of the mapped type will be inherited. + * If no mapped type is defined, 0 will be returned. + */ + size_t getPacking() const; + + private: + /// The original type of this typedef + const HeaderType* _type; + }; +} // namespace ddl + +#endif // HEADER_TYPEDEF_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/header_visitor_intf.h b/ddlgenerators/generator_library/headerrepresentation/header_visitor_intf.h new file mode 100644 index 0000000..466fb9b --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/header_visitor_intf.h @@ -0,0 +1,105 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + */ + +#ifndef HEADER_VISITOR_H_INCLUDED +#define HEADER_VISITOR_H_INCLUDED + +namespace ddl +{ + class Header; + class HeaderBasicType; + class HeaderTypedef; + class HeaderConstant; + class HeaderStruct; + class HeaderStructElement; + class HeaderEnum; + + /** + * Abstract base class/interface for Visitor design-pattern. + */ + class IHeaderVisitor + { + public: + /** + * Visitor for a whole header. + * @param [in] header pointer to the header object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const Header* header) = 0; + + /** + * Visitor for a basic type. + * @param [in] basic_type pointer to the basic type object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderBasicType* basic_type) = 0; + + /** + * Visitor for a typedef. + * @param [in] type_def pointer to the basic type object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderTypedef* type_def) = 0; + + /** + * Visitor for a constant. + * @param [in] constant pointer to the constant object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderConstant* constant) = 0; + + /** + * Visitor for a struct. + * @param [in] header_struct pointer to the struct object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderStruct* header_struct) = 0; + + /** + * Visitor for a struct element. + * @param [in] struct_element pointer to the struct element object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderStructElement* struct_element) = 0; + + /** + * Visitor for a enum element. + * @param [in] header_enum pointer to the enum object. + * @return Standard result code. + * @retval ERR_NOERROR Everything went fine. + * @retval ERR_POINTER Null-pointer passed. + */ + virtual a_util::result::Result visit(const HeaderEnum* header_enum) = 0; + }; + +} // namespace ddl + +#endif // HEADER_VISITOR_H_INCLUDED diff --git a/ddlgenerators/generator_library/headerrepresentation/parserhelper.cpp b/ddlgenerators/generator_library/headerrepresentation/parserhelper.cpp new file mode 100644 index 0000000..7ee4e9d --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/parserhelper.cpp @@ -0,0 +1,253 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include "parserhelper.h" + + +namespace ddl_generator +{ + +void skipWhitespace(const char*& p, const char* additional_whitechars) +{ + if (nullptr == p) + { + return; + } + if (additional_whitechars != nullptr) + { + while (a_util::strings::white_space.find(*p) != std::string::npos || (*p != '\0' && strchr(additional_whitechars, *p) != nullptr)) + { + p++; + } + } + else + { + while (a_util::strings::white_space.find(*p) != std::string::npos) + { + p++; + } + } +} + + +bool getNextWord(const char*& src, std::string& dest, const char* additional_separator, bool use_escape) +{ + if (nullptr == src) + { + return false; + } + dest.clear(); + + skipWhitespace(src); + + if (*src == '\0') + { + return false; + } + + char escape_active = false; + char last_char = '\0'; + char quote = '\0'; + + if (*src == '\"' || *src == '\'') + { + quote = *(src++); + const char* strc_start = src; + + while (*src != '\0' && (escape_active || *src != quote)) + { + escape_active = use_escape && (*src == '\\' && last_char != '\\'); // escape next char? + last_char = *src; + src++; + } + dest.assign(strc_start, src - strc_start); + //dest.set(strc_start, src-strc_start); + + if (*src == quote) + { + src++; + } + } + else + { + const char* src_start = src; + + if (additional_separator == nullptr) + { + while (*src != '\0' && a_util::strings::white_space.find(*src) == std::string::npos) + { + src++; + size_t n = a_util::strings::white_space.find(*src); + size_t n_m = std::string::npos; + if (*src == '\"' || *src == '\'') + { + quote = *(src); + + do + { + escape_active = use_escape && (*src == '\\' && last_char != '\\'); + last_char = *src; + src++; + } while (*src != '\0' && (escape_active || *src != quote)); + } + } + + dest.assign(src_start, src-src_start); + } + else + { + while (*src != '\0' && (a_util::strings::white_space.find(*src) == std::string::npos + && strchr(additional_separator, *src) == nullptr)) + { + src++; + } + + dest.assign(src_start, src-src_start); + } + } + + return true; +} + +void seekChars(const char*& p, const char* chars, bool ignore_quotes) +{ + + if ((nullptr == p) || + (nullptr == chars)) + { + return; + } + + char escape_active = false; + char last_char = '\0'; + bool inside_quotes = false; + char quote = '\0'; + + while (*p != '\0' && (escape_active || inside_quotes || (strchr(chars, *p) == nullptr))) + { + if (!ignore_quotes) + { + if (!escape_active && (*p == '\"' || *p == '\'')) + { + if (inside_quotes && quote == *p) + { + quote = '\0'; + inside_quotes = false; + } + else + { + quote = *p; + inside_quotes = true; + } + } + } + else + { + if (!escape_active && (*p == '\"' || *p == '\'')) + { + quote = '\0'; + } + } + + escape_active = (*p == '\\' && last_char != '\\'); // escape next char? + last_char = *p; + p++; + } +} + +void seekString(const char*& p, const char* seek_string, char* comment, bool ignore_quotes) +{ + if ((nullptr == p) || + (nullptr == seek_string)) + { + return; + } + bool escape_active = false; + char last_char = '\0'; + bool inside_quotes = false; + char quote = '\0'; + size_t str_len = a_util::strings::getLength(seek_string); + int n_char = 0; + + if (comment) + { + comment[n_char] = '\0'; + } + while (*p != '\0') + { + if (!ignore_quotes) + { + if (!escape_active && !inside_quotes && *p == *seek_string) + { + if (a_util::strings::compare(p, seek_string, str_len) == 0) + { + if (comment) + { + comment[n_char] = '\0'; + } + return; + } + } + + if (!escape_active && (*p == '\"' || *p == '\'')) + { + if (inside_quotes && quote == *p) + { + quote = '\0'; + inside_quotes = false; + } + else + { + quote = *p; + inside_quotes = true; + } + } + } + else + { + if (!escape_active && *p == *seek_string) + { + if (a_util::strings::compare(p, seek_string, str_len) == 0) + { + if (comment) + { + comment[n_char] = '\0'; + } + return; + } + } + + } + escape_active = (*p == '\\' && last_char != '\\'); // escape next char? + last_char = *p; + if (comment) + { + comment[n_char] = *p; + } + ++p; + n_char++; + } + if (comment) + { + comment[n_char] = '\0'; + } +} + +} // namespace A_UTILS_NS diff --git a/ddlgenerators/generator_library/headerrepresentation/parserhelper.h b/ddlgenerators/generator_library/headerrepresentation/parserhelper.h new file mode 100644 index 0000000..07eaea4 --- /dev/null +++ b/ddlgenerators/generator_library/headerrepresentation/parserhelper.h @@ -0,0 +1,79 @@ +/** + * @file + * + * Parser helper functions. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ +#include + + +#ifndef DDL_GEN_PARSER_HELPER_CLASS_HEADER +#define DDL_GEN_PARSER_HELPER_CLASS_HEADER + +namespace ddl_generator +{ + + +/** + * Advances the pointer to point at a position after the next whitespace sequence. + * + * @param p [inout] The current position. + * @param additional_whitechars [in] Additional characters which are to be skipped. + * @return void + * @rtsafe + */ +void skipWhitespace(const char*& p, const char* additional_whitechars=nullptr); + +/** + * Copies the next word in a string into a string object. + * + * @param src [in] The source string. + * @param dest [out] The destination string. + * @param additional_separator [in] Additional separator characters. + * @param use_escape [in] Uses the \\ character to detect a word too + * + * @return tTrue if successful, otherwise tFalse. + */ +bool getNextWord(const char*& src, + std::string &dest, + const char* additional_separator=nullptr, + bool use_escape = true); + +/** + * Advances a pointer in a string to the next occurance of specified characters. + * @param p [inout] The current position. + * @param chars [in] The characters to look for. + * @param ignore_quotes [in] Whether or not to ignore occurences which occur between quotes. + * @return void + * @rtsafe + */ +void seekChars(const char*& p, const char* chars, bool ignore_quotes=false); + +/** + * Advances a pointer in a string to the next occurcance of a string. + * @param p [inout] The current position. + * @param seek_string [in] The string to look for. + * @param comment [out] Optional buffer that will be filled with the skipped characters. + * @param ignore_quotes [in] Whether or not to ignore occurences which occur between quotes. + * @return void + * @rtsafe + */ +void seekString(const char*& p, const char* seek_string, char* comment = nullptr, bool ignore_quotes=false); + +} // namespace A_UTILS_NS + +#endif // DDL_GEN_PARSER_HELPER_CLASS_HEADER diff --git a/ddlgenerators/header2ddl/CMakeLists.txt b/ddlgenerators/header2ddl/CMakeLists.txt new file mode 100644 index 0000000..61275e5 --- /dev/null +++ b/ddlgenerators/header2ddl/CMakeLists.txt @@ -0,0 +1,30 @@ +set(PROJECT_NAME header2ddl) + +set(SOURCES + main.cpp + header2ddl_commandline.h + header2ddl_commandline.cpp + ${DDL_GENERATOR_COMMON} + ${HEADER_PRESENTATION_H} + ${HEADER_PRESENTATION_CPP} +) + +if (WIN32) + #list(APPEND SOURCES native_resource.rc) +endif (WIN32) + +add_executable(${PROJECT_NAME} WIN32 ${SOURCES}) + +target_link_libraries(${PROJECT_NAME} + ddl + ddl_generator +) + +if(MSVC) + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/SUBSYSTEM:console") +endif(MSVC) + +install(TARGETS ${PROJECT_NAME} DESTINATION ./bin/debug CONFIGURATIONS Debug) +install(TARGETS ${PROJECT_NAME} DESTINATION ./bin CONFIGURATIONS Release RelWithDebInfo) + +set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER ddl/utils) diff --git a/ddlgenerators/header2ddl/header2ddl_commandline.cpp b/ddlgenerators/header2ddl/header2ddl_commandline.cpp new file mode 100644 index 0000000..7a0b657 --- /dev/null +++ b/ddlgenerators/header2ddl/header2ddl_commandline.cpp @@ -0,0 +1,82 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include "header2ddl_commandline.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} +using namespace ddl_generator::oo; + +namespace ddl +{ + Header2DDLCommandLine::Header2DDLCommandLine() : CommandLine() + { + _cli |= getDDLVersionOpt(); + _cli |= getHeaderFileSetOpt(); + } + + ddl::DDLVersion Header2DDLCommandLine::getDDLVersion() + { + return DDLVersion::fromString(_opt_DDL_version); + } + std::string Header2DDLCommandLine::getHeaderFileSet() + { + return _opt_header_file_set; + } + + void Header2DDLCommandLine::setHeaderFile(std::string header_file) + { + _opt_header_file = header_file; + } + + void Header2DDLCommandLine::printExamples() + { + std::cout << "examples: " << std::endl; + std::cout << " --headerfile=c:/myHeaderFile.h " << + "--descriptionfile=c:/myDescriptionFile.description"; + std::cout << std::endl << " or" << std::endl; + std::cout << " --headerfile=c:/myHeaderFile.h " << + "--descriptionfile=c:/myDescriptionFile.description "; + std::cout << "-struct=tMyStruct" << std::endl; + } + + clara::Opt Header2DDLCommandLine::getDDLVersionOpt() + { + return clara::Opt(_opt_DDL_version, "version") + ["-v"]["--ddlversion"] + ("[Optional] Default value is 4.0. Supported formats are 3.0 and 4.0"); + } + + clara::Opt Header2DDLCommandLine::getHeaderFileSetOpt() + { + return clara::Opt(_opt_header_file_set, "list,of,files") + ["--headerfileset"] + ("Can be used instead of the headerfile option. List of comma separated " + "headerfiles (no spaces!) to be merged into a single descriptionfile."); + } + +} diff --git a/ddlgenerators/header2ddl/header2ddl_commandline.h b/ddlgenerators/header2ddl/header2ddl_commandline.h new file mode 100644 index 0000000..68e0203 --- /dev/null +++ b/ddlgenerators/header2ddl/header2ddl_commandline.h @@ -0,0 +1,49 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _HEADER2DDL_COMMAND_LINE_H_ +#define _HEADER2DDL_COMMAND_LINE_H_ + +#include +#include "commandline.h" + +namespace ddl +{ + class Header2DDLCommandLine : public ddl::CommandLine + { + public: + Header2DDLCommandLine(); + + DDLVersion getDDLVersion(); + std::string getHeaderFileSet(); + + void setHeaderFile(std::string headerFile); + + protected: + void printExamples() override; + + clara::Opt getDDLVersionOpt(); + clara::Opt getHeaderFileSetOpt(); + + std::string _opt_DDL_version = "4.0"; + std::string _opt_header_file_set; + }; +} +#endif + diff --git a/ddlgenerators/header2ddl/main.cpp b/ddlgenerators/header2ddl/main.cpp new file mode 100644 index 0000000..5acb849 --- /dev/null +++ b/ddlgenerators/header2ddl/main.cpp @@ -0,0 +1,110 @@ +/** + * @file + * Launcher + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include +#include "header2ddl_commandline.h" + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + } +} +using namespace ddl_generator::oo; + +a_util::result::Result HandleInputFileset(std::string strHeaderFileSet, std::string& strMergedHeaderFile) +{ + std::vector vecHeaderFiles = a_util::strings::split(strHeaderFileSet, ","); + if (vecHeaderFiles.size() == 0) + { + LOG_ERROR("ERROR: Empty header file list"); + return ERR_INVALID_ARG.getCode(); + } + + std::string strMergedHeaderContent; + for (std::string strHeaderpath : vecHeaderFiles) + { + std::string strHeaderContent; + if (!a_util::filesystem::exists(strHeaderpath) || a_util::result::isFailed(a_util::filesystem::readTextFile(strHeaderpath, strHeaderContent))) + { + LOG_ERROR(a_util::strings::format("ERROR: Could not read header file '%s'", strHeaderpath.c_str()).c_str()); + return ERR_INVALID_ARG.getCode(); + } + + strMergedHeaderContent.append(strHeaderContent); + } + + a_util::filesystem::Path mergedHeader = a_util::filesystem::getTempDirectory().append("MergedHeader.h"); + a_util::filesystem::writeTextFile(mergedHeader, strMergedHeaderContent); + strMergedHeaderFile = mergedHeader.toString(); + return ERR_NOERROR.getCode(); +} + + +int main(int argc, char* argv[]) +{ + ddl::Header2DDLCommandLine cmd_line; + if (a_util::result::isFailed(cmd_line.parseArgs(argc, argv))) + { + return ERR_INVALID_ARG.getCode(); + } + + if (cmd_line.isHelpRequested()) + { + cmd_line.printHelp(); + return ERR_NOERROR.getCode(); + } + + std::string strMergedHeader; + if (!cmd_line.getHeaderFileSet().empty()) + { + a_util::result::Result res = HandleInputFileset(cmd_line.getHeaderFileSet(), strMergedHeader); + if (a_util::result::isFailed(res)) + { + return res.getErrorCode(); + } + cmd_line.setHeaderFile(strMergedHeader); + } + if (a_util::result::isFailed(cmd_line.checkMandatoryArguments())) + { + return ERR_INVALID_ARG.getCode(); + } + + DDLUtilsCore core; + a_util::result::Result res = core.generateDescriptionFile(cmd_line.getHeaderFile(), + cmd_line.getDescriptionFile(), cmd_line.getDDLVersion(), cmd_line.getStruct()); + if (a_util::result::isFailed(res)) + { + std::cerr << "Error: An error occured during generating of the description file."; + } + + // delete temp file + if (!strMergedHeader.empty()) + { + a_util::filesystem::remove(strMergedHeader); + } + + return res.getErrorCode(); + +} diff --git a/ddlrepresentation/ddl_common.h b/ddlrepresentation/ddl_common.h new file mode 100644 index 0000000..9d2cf3e --- /dev/null +++ b/ddlrepresentation/ddl_common.h @@ -0,0 +1,70 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_COMMON_HEADER +#define DDL_COMMON_HEADER + + + // Disables VS warnings about unsafe C functions +#ifdef WIN32 +#define _SCL_SECURE_NO_WARNINGS // NOLINT +#endif + + // Determine whether move semantics are available +#ifdef _MSC_VER + // On Windows, make the decision using the VS version +#if _MSC_VER >= 1800 // VS 2013 (needs default-generation) +#define DDL_HAS_MOVE 1 +#else +#define DDL_HAS_MOVE 0 +#endif +#else + // Otherwise use the standard version macro +#if __cplusplus >= 201103L +#define DDL_HAS_MOVE 1 +#else +#define DDL_HAS_MOVE 0 +#endif +#endif + + // Include utils +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + // Include standard headers +#include +#include +#include +#include +#include +#include + + +#endif // DDL_COMMON_HEADER + diff --git a/ddlrepresentation/ddl_error.cpp b/ddlrepresentation/ddl_error.cpp new file mode 100644 index 0000000..48284f2 --- /dev/null +++ b/ddlrepresentation/ddl_error.cpp @@ -0,0 +1,50 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddl_error.h" + +namespace ddl +{ + static DDLError s_last_error; + + a_util::result::Result DDLError::setLastDDLError(a_util::result::Result result, + const std::string& error) + { + s_last_error._last_error_code = result; + if (!error.empty()) + { + s_last_error._last_error_description = error; + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLError::getLastDDLErrorCode() + { + return s_last_error._last_error_code; + } + + const char* DDLError::getLastDDLErrorDescription() + { + return s_last_error._last_error_description.c_str(); + } + + +} // namespace ddl + + diff --git a/ddlrepresentation/ddl_error.h b/ddlrepresentation/ddl_error.h new file mode 100644 index 0000000..c07bfb8 --- /dev/null +++ b/ddlrepresentation/ddl_error.h @@ -0,0 +1,77 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLERROR_H_INCLUDED +#define DDLERROR_H_INCLUDED + +#include "ddl_common.h" + +namespace ddl +{ + /** + * Static DDL Error Handling class. + * + * The parser will use this static Error handling to inform about validation errors. + */ + class DDLError + { + std::string _last_error_description; + a_util::result::Result _last_error_code; + + public: + /** + * Gets the last DDL Error Code occured. + * @return the DDL Error. + */ + static a_util::result::Result getLastDDLErrorCode(); + /** + * Gets the last DDL Error description occured. + * @return the last DDL Error description. + * @remark not thread safe! + */ + static const char* getLastDDLErrorDescription(); + /** + * Sets the last DDL Error and error description. + * @return the last DDL Error description. + * @remark not thread safe! + */ + static a_util::result::Result setLastDDLError(a_util::result::Result result, + const std::string& error); + }; + +/** + * Helper to set an error description to the DDL error handling and return a DDL Error. + * @param [in] \_\_errCode\_\_ the error code to return + * @param [in] \_\_desc\_\_ the description to set + */ +#define RETURN_DDLERROR_DESC(__errCode__, __desc__) { ddl::DDLError::setLastDDLError(__errCode__, __desc__); return __errCode__; } +/** + * Helper to set an error description to the DDL error handling and return a DDL Error if failed. + * @param [in] \_\_callterm\_\_ statement to execute to. + */ +#define RETURN_DDLERROR_IF_FAILED(__callterm__) { a_util::result::Result ntmpRes = __callterm__; if (isFailed(ntmpRes)) { RETURN_DDLERROR_DESC(ntmpRes, ""); } } +/** + * Helper to set an error description to the DDL error handling and return a DDL Error if failed. + * @param [in] \_\_callterm\_\_ statement to execute to. + * @param [in] \_\_desc\_\_ additional error description to set. + */ +#define RETURN_DDLERROR_IF_FAILED_DESC(__callterm__, __desc__) { a_util::result::Result ntmpRes = __callterm__; if (isFailed(ntmpRes)) { RETURN_DDLERROR_DESC(ntmpRes, __desc__); } } +} // namespace ddl + +#endif // DDLERROR_H_INCLUDED diff --git a/ddlrepresentation/ddl_intf.h b/ddlrepresentation/ddl_intf.h new file mode 100644 index 0000000..cbb002d --- /dev/null +++ b/ddlrepresentation/ddl_intf.h @@ -0,0 +1,118 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_INTF_H_INCLUDED +#define DDL_INTF_H_INCLUDED + +#include "ddl_common.h" + +namespace ddl +{ + + class IDDLVisitor; + class IDDLChangeVisitor; + + /** + * Interface class for object representation of DDL descriptions. + * E.g. it provides the accept() method for the Visitor design-pattern. + */ + class IDDL + { + public: + /** + * Virtual DTOR + */ + virtual ~IDDL(){} + + /** + * Acceptance method for Visitor design-pattern. + * @param[in] visitor - Pointer to Visitor instance + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_INITIALIZED The object was not or not correctly + * initialized + */ + virtual a_util::result::Result accept (IDDLVisitor * visitor) const = 0; + + /** + * Acceptance method for Visitor and Change design-pattern. + * @param[in] visitor - Pointer to Visitor instance + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_INITIALIZED The object was not or not correctly + * initialized + */ + virtual a_util::result::Result accept(IDDLChangeVisitor * visitor) = 0; + + /** + * Getter for the initialization flag. + * @retval true The object was initialized correctly + * @retval false The object was not or not correctly initialized + */ + virtual bool isInitialized() const = 0; + + /** + * Getter for the name of the representation object. + * @return the name + */ + virtual const std::string& getName() const = 0; + + /** + * Getter for the predefinition flag. + * @retval true The object was predefined + * @retval false The object was defined later + */ + virtual bool isPredefined() const = 0; + + /** + * Getter for the predefinition flag. + * @retval true The object was predefined + * @retval false The object was defined later + */ + virtual bool isOverwriteable() const = 0; + + /** + * Getter for the creation level. + * @return the level at creation time of this representation object + */ + virtual int getCreationLevel() const = 0; + + /** + * Getter for complex data type flag. + * @retval true This is a complex data type + */ + virtual bool isComplex() const + { + // default is not complex + return false; + } + + /** + * Flags for Merging + * + */ + enum TagMergeFlags + { + ddl_merge_force_overwrite = 0x01 + }; + }; + +} // namespace ddl + +#endif // DDL_INTF_H_INCLUDED diff --git a/ddlrepresentation/ddl_type.cpp b/ddlrepresentation/ddl_type.cpp new file mode 100644 index 0000000..38e5d73 --- /dev/null +++ b/ddlrepresentation/ddl_type.cpp @@ -0,0 +1,72 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddl_type.h" + +namespace ddl +{ + + bool DDL::isEqual(IDDL *lhs, IDDL *rhs) + { + if (NULL == lhs || + NULL == rhs) + { + return false; + } + return a_util::strings::isEqualNoCase(lhs->getName().c_str(), rhs->getName().c_str()); + } + + bool DDL::isSorted(IDDL *lhs, IDDL *rhs) + { + if (NULL == lhs) + { + return false; + } + if (NULL == rhs) + { + return true; + } + return lhs->getName() < rhs->getName(); + } + + bool DDL::isInitialized() const + { + // default case + return true; + } + + bool DDL::isPredefined() const + { + // default case + return false; + } + + bool DDL::isOverwriteable() const + { + return getCreationLevel() > 0; // cMediaManager::DL_AlwaysThere + } + + int DDL::getCreationLevel() const + { + // default case + // cMediaManager::DL_AlwaysThere + return 0; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddl_type.h b/ddlrepresentation/ddl_type.h new file mode 100644 index 0000000..b11c82b --- /dev/null +++ b/ddlrepresentation/ddl_type.h @@ -0,0 +1,203 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_TYPE_H_INCLUDED +#define DDL_TYPE_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_intf.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-49, ERR_OUT_OF_RANGE) + + /** + * The abstract helper class for representation classes for DDL descriptions. + */ + class DDL : public IDDL + { + public: + + virtual bool isInitialized() const; + + virtual bool isPredefined() const; + + virtual bool isOverwriteable() const; + + virtual int getCreationLevel() const; + + /** + * Functor for use with \c std::transform() to delete all objects + * where the elements of a vector point at. + * @param[in] obj - Pointer to the object to delete + * @return Pointer to the predefined object that was not deleted (see remarks). + * @remarks Objects which are declarated as predefined are not deleted. + */ + template + static T* deleteChild(T *obj) + { + if (NULL != obj) + { + if (obj->isPredefined()) + { + return obj; + } + else + { + delete obj; + } + } + return NULL; + } + + /** + * Method moves element within the list. + * @param[in] obj - Pointer to the list object + * @param[in] from - Position of element in the list + * @param[in] to - New position of element in the list + * @return ERR_OUT_OF_RANGE - from and to parameters are out of range. + * @return a_util::result::SUCCESS + */ + template + static a_util::result::Result moveChild(T *obj, const int from, const int to) + { + if (NULL == obj) { return a_util::result::Result(-4); } //ERR_POINTER for hackers... + + if (-1 == from || -1 == to || + (int)obj->size() < from || (int)obj->size() < to) + { + return ERR_OUT_OF_RANGE; + } + + if (from != to) + { + if (from < to) + { + std::rotate(obj->begin() + from, + obj->begin() + from + 1, + obj->begin() + to + 1); + } + else + { + std::rotate(obj->begin() + to, + obj->begin() + from, + obj->begin() + from + 1); + } + } + return a_util::result::SUCCESS; + } + + /** + * Functor for use with \c std::transform() to clone the objects + * where the elements of a vector point at. + * @tparam T - Representation object type (e.g. \c Prefix) + * @param[in] obj - Pointer to the object to clone + * @return Pointer to cloned instance of T or \c NULL if there was + * no original instance (obj == NULL). + */ + template + static T* clone(T* obj) + { + if (NULL != obj) + { + if (obj->isPredefined()) + { + return ref(obj); + } + return new T(*obj); + } + return NULL; + } + + /** + * Functor for use with \c std::transform() to ref the objects + * where the elements of a vector point at, this is for the Always_there. + * @tparam T - Representation object type (e.g. \c Prefix) + * @param[in] obj - Pointer to the object to clone + * @return Pointer to ref instance of T or \c NULL if there was + * no original instance (obj == NULL). + */ + template + static T* ref(T* obj) + { + if (NULL != obj) + { + return obj; + } + return NULL; + } + + /** + * Predicate to compare 2 DDL representation objects (for use with + * \c std::unique()). + * @param[in] lhs - Pointer to the object on left-hand side + * @param[in] rhs - Pointer to the object on right-hand side + * @retval true if the objects have the same name + * @retval false else + */ + static bool isEqual(IDDL* lhs, IDDL* rhs); + + /** + * sort predicate to compare to 2 DDL representation objects (for use + * with \c std::sort()). + * @param[in] lhs - Pointer to the object on left-hand side + * @param[in] rhs - Pointer to the object on right-hand side + * @retval true if the left argument goes before the right one. + * @retval false else + */ + static bool isSorted(IDDL* lhs, IDDL* rhs); + }; + + /// functional pattern to use std find algorithms + template + struct DDLCompareFunctor + { + /// the name of the pattern + const std::string& pattern; + + /** + * CTR + * + * @param [in] pattern the name of the pattern + */ + DDLCompareFunctor(const std::string& pattern): pattern(pattern) + { + } + + /** + * compare function for pattern + * + * @param [in] entry pointer to the DDL object + * + * @return true if equal, false otherwise + */ + bool operator()(const T* entry) + { + if (NULL == entry) + { + return false; + } + return pattern == entry->getName(); + } + }; + +} // namespace ddl + +#endif // DDL_TYPE_H_INCLUDED diff --git a/ddlrepresentation/ddlalignment.cpp b/ddlrepresentation/ddlalignment.cpp new file mode 100644 index 0000000..937603e --- /dev/null +++ b/ddlrepresentation/ddlalignment.cpp @@ -0,0 +1,87 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlalignment.h" + +namespace ddl +{ + std::string DDLAlignment::toString(AlignmentType const alignment) + { + if (alignment != e_invalid) + { + return a_util::strings::toString((int32_t)alignment); + } + + return ""; + } + + DDLAlignment::AlignmentType DDLAlignment::fromString(const std::string &alignment) + { + if (!a_util::strings::isInt32(alignment)) + { + // fallback to default + return e_invalid; + } + int alignment_int = a_util::strings::toInt32(alignment); + if (alignment_int <= 0) + { + return e1; + } + else + { + switch(alignment_int) + { + case 1: + { + return e1; + } + case 2: + { + return e2; + } + case 4: + { + return e4; + } + case 8: + { + return e8; + } + case 16: + { + return e16; + } + case 32: + { + return e32; + } + case 64: + { + return e64; + } + default: + { + break; + } + } + } + + return e_invalid; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlalignment.h b/ddlrepresentation/ddlalignment.h new file mode 100644 index 0000000..e22bfa3 --- /dev/null +++ b/ddlrepresentation/ddlalignment.h @@ -0,0 +1,69 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLALIGNMENT_H_INCLUDED +#define DDLALIGNMENT_H_INCLUDED + +#include "ddl_common.h" + + + +namespace ddl +{ + /** + * Abstract wrapper class for the alignment enumeration + */ + class DDLAlignment + { + public: + /** + * Representation of the alignment enumeration + */ + typedef enum + { + e0 = 1, /**< for backward compatibility */ + e1 = 1, /**< Default alignment */ + e2 = 2, + e4 = 4, + e8 = 8, + e16 = 16, + e32 = 32, + e64 = 64, + e_invalid = 255 + } AlignmentType; + + /** + * Converts the given alignment to a string. + * @param[in] alignment - The alignment to convert + * @return the alignment as string + */ + static std::string toString(AlignmentType const alignment); + + /** + * Extracts the alignment out of a given string. + * @param[in] alignment - String containing the alignment + * @return the extracted alignment + */ + static AlignmentType fromString(const std::string& alignment); + + }; + +} // namespace ddl + +#endif // DDLALIGNMENT_H_INCLUDED diff --git a/ddlrepresentation/ddlbaseunit.cpp b/ddlrepresentation/ddlbaseunit.cpp new file mode 100644 index 0000000..b7875d4 --- /dev/null +++ b/ddlrepresentation/ddlbaseunit.cpp @@ -0,0 +1,136 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlbaseunit.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLBaseunit::DDLBaseunit() : + _name{}, + _symbol{}, + _description{}, + _init_flag{}, + _level{1} + { + } + + DDLBaseunit::DDLBaseunit(const std::string& name, + const std::string& symbol, + const std::string& description, + int const creation_level) : + _name(name), + _symbol(symbol), + _description(description), + _init_flag(true), + _level(creation_level) + { + } + + a_util::result::Result DDLBaseunit::create(const std::string& name, + const std::string& symbol, + const std::string& description, + int const creation_level) + { + if (name.empty()) + { + return ERR_INVALID_ARG; + } + _name = name; + _symbol = symbol; + _description = description; + _init_flag = true; + _level = creation_level; + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLBaseunit::accept(IDDLVisitor *visitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return visitor->visit(this); + } + + a_util::result::Result DDLBaseunit::accept(IDDLChangeVisitor *visitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return visitor->visit(this); + } + + bool DDLBaseunit::isInitialized() const + { + return _init_flag; + } + + const std::string& DDLBaseunit::getName() const + { + return _name; + } + + void DDLBaseunit::setName(const std::string& name) + { + _name = name; + } + + const std::string& DDLBaseunit::getSymbol() const + { + return _symbol; + } + + void DDLBaseunit::setSymbol(const std::string& symbol) + { + _symbol = symbol; + } + + + const std::string& DDLBaseunit::getDescription() const + { + return _description; + } + + void DDLBaseunit::setDescription(const std::string& description) + { + _description = description; + } + + + bool DDLBaseunit::isPredefined() const + { + return _level == -1; // cMediaManager::DL_AlwaysThere + } + + bool DDLBaseunit::isOverwriteable() const + { + return _level> 0; + } + + int DDLBaseunit::getCreationLevel() const + { + return _level; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlbaseunit.h b/ddlrepresentation/ddlbaseunit.h new file mode 100644 index 0000000..30ab224 --- /dev/null +++ b/ddlrepresentation/ddlbaseunit.h @@ -0,0 +1,118 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLBASE_UNIT_H_INCLUDED +#define DDLBASE_UNIT_H_INCLUDED + +#include "ddl_common.h" +#include "ddlunit_intf.h" + +namespace ddl +{ + /** + * Representation of a base unit inside a DDL description. + */ + class DDLBaseunit : public IDDLUnit + { + public: + /** + * Default CTOR + */ + DDLBaseunit(); + + /** + * CTOR + * @param[in] name - Name of the base unit (e.g. "metre") + * @param[in] symbol - Symbol of the base unit (e.g. "m") + * @param[in] description - Description of the represented base unit + * @param[in] creation_level - Level at creation time (optional) + */ + DDLBaseunit(const std::string& name, + const std::string& symbol, + const std::string& description, + int const creation_level = 1); + + /** + * Creation method to fill the object with data. + * @param[in] name - Name of the base unit (e.g. "metre") + * @param[in] symbol - Symbol of the base unit (e.g. "m") + * @param[in] description - Description of the represented base unit + * @param[in] creation_level - Level at creation time (optional) + * @retval ERR_INVALID_ARG Empty name committed + */ + a_util::result::Result create(const std::string& name, + const std::string& symbol, + const std::string& description, + int const creation_level = 1); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isPredefined() const; + bool isOverwriteable() const; + + bool isInitialized() const; + + int getCreationLevel() const; + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the name. + */ + void setName(const std::string& name); + + /** + * Getter for the symbol. + * @return the symbol + */ + const std::string& getSymbol() const; + /** + * Setter for the description. + */ + void setSymbol(const std::string& symbol); + + + /** + * Getter for the description. + * @return the description + */ + const std::string& getDescription() const; + + /** + * Setter for the description. + */ + void setDescription(const std::string& desc); + + private: + std::string _name; + std::string _symbol; + std::string _description; + + bool _init_flag; + int _level; + }; + +} // namespace ddl + +#endif // DDLBASE_UNIT_H_INCLUDED diff --git a/ddlrepresentation/ddlbyteorder.cpp b/ddlrepresentation/ddlbyteorder.cpp new file mode 100644 index 0000000..7bc880a --- /dev/null +++ b/ddlrepresentation/ddlbyteorder.cpp @@ -0,0 +1,65 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlbyteorder.h" + +namespace ddl +{ + std::string DDLByteorder::toString(DDLByteorder::Byteorder const byteorder) + { + switch(byteorder) + { + case e_le: + { + return std::string("LE"); + } + case e_be: + { + return std::string("BE"); + } + default: + { + // error case + return a_util::strings::empty_string; + } + } + } + + DDLByteorder::Byteorder DDLByteorder::fromString(const std::string& byteorder) + { + if (byteorder == "LE") + { + return e_le; + } + if (byteorder == "BE") + { + return e_be; + } + if (byteorder == "Motorola") + { + return e_be; + } + if (byteorder == "Intel") + { + return e_le; + } + // fallback to default + return e_le; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlbyteorder.h b/ddlrepresentation/ddlbyteorder.h new file mode 100644 index 0000000..2eb1f51 --- /dev/null +++ b/ddlrepresentation/ddlbyteorder.h @@ -0,0 +1,64 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef BYTEORDER_H_INCLUDED +#define BYTEORDER_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" + +namespace ddl +{ + /** + * Abstract wrapper class for the byteorder enumeration. + */ + class DDLByteorder : public DDL + { + public: + /** + * Representation of the byteorder enumeration + */ + typedef enum + { + platform_not_supported = 0x00, + plattform_little_endian_8 = 0x01, + platform_big_endian_8 = 0x02, + e_noe = platform_not_supported, + e_le = plattform_little_endian_8, + e_be = platform_big_endian_8 + } Byteorder; + + /** + * Converts the given byteorder enumeration to a string. + * @param[in] byteorder - Byteorder value to convert + * @return the byteorder as string + */ + static std::string toString(Byteorder const byteorder); + + /** + * Extracts the byteorder out of the given string. + * @param[in] byteorder - String containing the byteorder + * @return the extracted byteorder + */ + static Byteorder fromString(const std::string& byteorder); + }; + +} // namespace ddl + +#endif // BYTEORDER_H_INCLUDED diff --git a/ddlrepresentation/ddlcloner.cpp b/ddlrepresentation/ddlcloner.cpp new file mode 100644 index 0000000..e220686 --- /dev/null +++ b/ddlrepresentation/ddlcloner.cpp @@ -0,0 +1,625 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlcloner.h" +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + +#include "ddlimporter.h" + + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-18, ERR_NO_CLASS) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLDescription * DDLCloner::getDDL() const + { + return _ddl_desc; + } + + void DDLCloner::destroyDDL() + { + DDLImporter::destroyDDL(_ddl_desc); + _ddl_desc = NULL; + } + + a_util::result::Result DDLCloner::createNew(const DDLVersion& version /* = 0 */) + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + // The DDL object does not get deleted because the caller/user of this + // object is responsible for it. + _ddl_desc = NULL; + // clone original DDL + RETURN_IF_FAILED(buildHeader()); + RETURN_IF_FAILED(buildUnits()); + RETURN_IF_FAILED(buildDatatypes()); + RETURN_IF_FAILED(buildEnums()); + RETURN_IF_FAILED(buildStructs()); + RETURN_IF_FAILED(buildStreams()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildHeader() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + // copy header object + DDLHeader *header = new DDLHeader(*_original_desc->getHeader()); + // external declarations have to be cloned separately + DDLExtDeclarationVec ext_declarations = header->getExtDeclarations(); + std::transform(ext_declarations.begin(), ext_declarations.end(), + ext_declarations.begin(), DDL::clone); + _ddl_desc = new DDLDescription(header); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildUnits() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + + // clone baseunit objects + DDLBaseunitVec baseunits = _original_desc->getBaseunits(); + std::transform(baseunits.begin(), baseunits.end(), baseunits.begin(), + DDL::clone); + _ddl_desc->refBaseunits(baseunits); + + // clone prefix objects + DDLPrefixVec ddlprefixes = _original_desc->getPrefixes(); + std::transform(ddlprefixes.begin(), ddlprefixes.end(), + ddlprefixes.begin(), DDL::clone); + _ddl_desc->refPrefixes(ddlprefixes); + + // clone unit objects + DDLUnitVec units = _original_desc->getUnits(); + std::transform(units.begin(), units.end(), + units.begin(), DDL::clone); + // refunit objects have to be cloned separately + for (DDLUnitIt it_unit = units.begin(); units.end() != it_unit; + ++it_unit) + { + DDLRefUnitVec refunits = (*it_unit)->getRefUnits(); + for (DDLRefUnitIt it_ru = refunits.begin(); refunits.end() != it_ru; + ++it_ru) + { + // find prefix object + DDLPrefixIt it_prefix = std::find_if(ddlprefixes.begin(), + ddlprefixes.end(), DDLCompareFunctor((*it_ru)->getPrefix())); + if (ddlprefixes.end() == it_prefix) + { + return ERR_NO_CLASS; + } + // find unit and create refunit object with appropriate CTOR + DDLBaseunitIt it_bu_found = std::find_if(baseunits.begin(), + baseunits.end(), DDLCompareFunctor((*it_ru)->getName())); + if (baseunits.end() == it_bu_found) + { + // not found in baseunit vector + DDLUnitIt it_u_found = std::find_if(units.begin(), + units.end(), DDLCompareFunctor((*it_ru)->getName())); + if (units.end() == it_u_found) + { + // not found in unit vector + // => not defined at all + return ERR_NO_CLASS; + } + *it_ru = new DDLRefUnit(*it_u_found, (*it_ru)->getPower(), + *it_prefix); + } + else + { + *it_ru = new DDLRefUnit(*it_bu_found, (*it_ru)->getPower(), + *it_prefix); + } + } + (*it_unit)->setRefUnits(refunits); + } + _ddl_desc->refUnits(units); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildDatatypes() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + DDLDTVec datatypes = _original_desc->getDatatypes(); + for (DDLDTIt it_dt = datatypes.begin(); datatypes.end() != it_dt; ++it_dt) + { + DDLVersion version = (*it_dt)->getDDLVersion(); + if ((*it_dt)->getUnit().empty()) + { + // datatype without defined unit + (*it_dt) = new DDLDataType((*it_dt)->getName(), + (*it_dt)->getNumBits(), + NULL, + (*it_dt)->getDescription(), + (*it_dt)->getAlignment(), + (*it_dt)->getArraysize(), + (*it_dt)->getCreationLevel(), + (*it_dt)->getArraySizeSource(), + (*it_dt)->isMinValid(), + (*it_dt)->getMinValue(), + (*it_dt)->isMaxValid(), + (*it_dt)->getMaxValue()); + } + else + { + // find unit and clone datatype object with appropriate CTOR + DDLBaseunitVec baseunits = _ddl_desc->getBaseunits(); + DDLBaseunitIt it_bu_found = std::find_if(baseunits.begin(), + baseunits.end(), DDLCompareFunctor((*it_dt)->getUnit())); + if (baseunits.end() == it_bu_found) + { + // not found in baseunit vector + DDLUnitVec units = _ddl_desc->getUnits(); + DDLUnitIt it_u_found = std::find_if(units.begin(), + units.end(), DDLCompareFunctor((*it_dt)->getUnit())); + if (units.end() == it_u_found) + { + // not found in unit vector + // => not defined at all + return ERR_NO_CLASS; + } + (*it_dt) = new DDLDataType((*it_dt)->getName(), + (*it_dt)->getNumBits(), + *it_u_found, + (*it_dt)->getDescription(), + (*it_dt)->getAlignment(), + (*it_dt)->getArraysize(), + (*it_dt)->getCreationLevel(), + (*it_dt)->getArraySizeSource(), + (*it_dt)->isMinValid(), + (*it_dt)->getMinValue(), + (*it_dt)->isMaxValid(), + (*it_dt)->getMaxValue()); + } + else + { + (*it_dt) = new DDLDataType((*it_dt)->getName(), + (*it_dt)->getNumBits(), + *it_bu_found, + (*it_dt)->getDescription(), + (*it_dt)->getAlignment(), + (*it_dt)->getArraysize(), + (*it_dt)->getCreationLevel(), + (*it_dt)->getArraySizeSource(), + (*it_dt)->isMinValid(), + (*it_dt)->getMinValue(), + (*it_dt)->isMaxValid(), + (*it_dt)->getMaxValue()); + } + } + (*it_dt)->setDDLVersion(version); + } + _ddl_desc->refDatatypes(datatypes); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildEnums() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + DDLEnumVec enums = _original_desc->getEnums(); + // clone enums + std::transform(enums.begin(), enums.end(), + enums.begin(), DDL::clone); + _ddl_desc->refEnums(enums); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildStructs() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + // clone structs + DDLComplexVec structs; + structs.cloneFrom(_original_desc->getStructs()); + + // elements have to be cloned seperately + DDLDTVec datatypes = _ddl_desc->getDatatypes(); + DDLUnitVec units = _ddl_desc->getUnits(); + DDLBaseunitVec baseunits = _ddl_desc->getBaseunits(); + DDLEnumVec ddl_enums = _ddl_desc->getEnums(); + for (DDLComplexVec::iterator it_struct = structs.begin(); + structs.end() != it_struct; ++it_struct) + { + DDLElementVec elements = (*it_struct)->getElements(); + for (DDLElementIt it_element = elements.begin(); + elements.end() != it_element; ++it_element) + { + DDLComplex* ddl_struct = NULL; + DDLEnum* ddl_enum = NULL; + DDLDataType* type = datatypes.find((*it_element)->getType()); + if (!type) + { + // not found in datatypes vector + ddl_struct = structs.find((*it_element)->getType()); + if (!ddl_struct) + { + // not found in structs vector + ddl_enum = ddl_enums.find((*it_element)->getType()); + if (!ddl_enum) + { + // not found in enums vector + // => not defined at all + return ERR_NO_CLASS; + } + } + } + + if ((*it_element)->getUnit().empty()) + { + // no unit defined + if (ddl_enum) + { + *it_element = new DDLElement(ddl_enum, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + NULL, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else if(ddl_struct) + { + *it_element = new DDLElement(ddl_struct, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + NULL, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else + { + *it_element = new DDLElement(type, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + NULL, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + } + else + { + // find unit + DDLBaseunitIt it_bu_found = std::find_if(baseunits.begin(), + baseunits.end(), DDLCompareFunctor((*it_element)->getUnit())); + if (baseunits.end() == it_bu_found) + { + // not found in baseunit vector + DDLUnitIt it_u_found = std::find_if(units.begin(), + units.end(), DDLCompareFunctor((*it_element)->getUnit())); + if (units.end() == it_u_found) + { + // not found in units vector + // => not defined at all + return ERR_NO_CLASS; + } + if (ddl_enum) + { + *it_element = new DDLElement(ddl_enum, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_u_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else if (ddl_struct) + { + *it_element = new DDLElement(ddl_struct, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_u_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else + { + *it_element = new DDLElement(type, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_u_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + } + else + { + if (ddl_enum) + { + *it_element = new DDLElement(ddl_enum, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_bu_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else if (ddl_struct) + { + *it_element = new DDLElement(ddl_struct, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_bu_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + else + { + *it_element = new DDLElement(type, + (*it_element)->getName(), + (*it_element)->getBytepos(), + (*it_element)->getArraysize(), + (*it_element)->getByteorder(), + (*it_element)->getAlignment(), + *it_bu_found, + (*it_element)->getBitpos(), + (*it_element)->getNumBits(), + (*it_element)->getDescription(), + (*it_element)->getComment(), + (*it_element)->getArraySizeSource(), + (*it_element)->getConstantValue(), + (*it_element)->isMinValid(), + (*it_element)->getMinValue(), + (*it_element)->isMaxValid(), + (*it_element)->getMaxValue(), + (*it_element)->isDefaultValid(), + (*it_element)->getDefaultValue(), + (*it_element)->isScaleValid(), + (*it_element)->getScaleValue(), + (*it_element)->isOffsetValid(), + (*it_element)->getOffsetValue()); + } + } + } + } + (*it_struct)->setElements(elements); + } + _ddl_desc->refStructs(structs); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::buildStreams() + { + if (NULL == _original_desc) + { + return ERR_NOT_INITIALIZED; + } + // clone the streams + DDLStreamVec streams = _original_desc->getStreams(); + DDLComplexVec structs = _ddl_desc->getStructs(); + for (DDLStreamIt it_stream = streams.begin(); + streams.end() != it_stream; ++it_stream) + { + // find type + DDLComplexIt it_found = std::find_if(structs.begin(), + structs.end(), DDLCompareFunctor((*it_stream)->getType())); + if (structs.end() == it_found) + { + // type not found + return ERR_NO_CLASS; + } + + // clone the contained stream structs + DDLStreamStructVec strm_structs = (*it_stream)->getStructs(); + DDLVersion version = (*it_stream)->getDDLVersion(); + *it_stream = new DDLStream(*it_found, (*it_stream)->getName(), + (*it_stream)->getDescription(), strm_structs, + (*it_stream)->getCreationLevel()); + (*it_stream)->setDDLVersion(version); + + for (DDLStreamStructIt it_struct = strm_structs.begin(); + strm_structs.end() != it_struct; ++it_struct) + { + // find type + it_found = std::find_if(structs.begin(), structs.end(), + DDLCompareFunctor((*it_struct)->getType())); + if (structs.end() == it_found) + { + // type not found + return ERR_NO_CLASS; + } + *it_struct = new DDLStreamStruct(*it_found, + (*it_struct)->getBytepos(), (*it_struct)->getName()); + } + (*it_stream)->refStructs(strm_structs); + } + _ddl_desc->refStreams(streams); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLCloner::setOriginal(const DDLDescription* original) + { + if (!original) { return ERR_POINTER; } + _original_desc = original; + return a_util::result::SUCCESS; + } + + a_util::result::Result ddl::DDLCloner::buildStreamMetaTypes() + { + return ERR_NOT_IMPL; ///@todo + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlcloner.h b/ddlrepresentation/ddlcloner.h new file mode 100644 index 0000000..9dfc012 --- /dev/null +++ b/ddlrepresentation/ddlcloner.h @@ -0,0 +1,69 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_CLONER_H_INCLUDED +#define DDL_CLONER_H_INCLUDED + +#include "ddl_common.h" +#include "ddlfactorymethod_intf.h" +#include "ddldescription.h" + +namespace ddl +{ + /** + * Implementation of IDDLFactorMethod for cloning of DDL representations. + */ + class DDLCloner : public IDDLFactoryMethod + { + public: // implements IDDLFactoryMethod + + DDLDescription * getDDL() const; + + a_util::result::Result createNew(const DDLVersion& version = DDLVersion::ddl_version_invalid); + + void destroyDDL(); + + a_util::result::Result buildHeader(); + + a_util::result::Result buildUnits(); + + a_util::result::Result buildDatatypes(); + + a_util::result::Result buildEnums(); + + a_util::result::Result buildStructs(); + + a_util::result::Result buildStreams(); + + a_util::result::Result buildStreamMetaTypes(); + public: + /** + * Setter method for the original DDL object. + * @param[in] original - Pointer to the DDL object + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result setOriginal(const DDLDescription* original); + + private: // members + DDLDescription* _ddl_desc; + const DDLDescription* _original_desc; + }; +} // namespace ddl + +#endif // DDL_CLONER_H_INCLUDED diff --git a/ddlrepresentation/ddlcompare.cpp b/ddlrepresentation/ddlcompare.cpp new file mode 100644 index 0000000..bedef32 --- /dev/null +++ b/ddlrepresentation/ddlcompare.cpp @@ -0,0 +1,1263 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlcompare.h" +#include //std::unique_ptr<> +#include "../codec/struct_layout.h" +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" +#include "ddl_error.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + +#include "ddlimporter.h" + + + +namespace ddl +{ + +//define all needed error types and values locally +_MAKE_RESULT(-3, ERR_UNEXPECTED) +_MAKE_RESULT(-5, ERR_INVALID_ARG) +_MAKE_RESULT(-20, ERR_NOT_FOUND) +_MAKE_RESULT(-38, ERR_FAILED) + +#define COMPARE(__name, __method) __name##1->__method() != __name##2->__method() +#define COMPARE_VERSION(__name, __method, __flag_prefix) ((flags & DDLCompare::__flag_prefix ## _versions) && (__name##1->__method() != __name##2->__method())) +#define COMPARE_DESCRIPTION(__name, __flag_prefix) ((flags & DDLCompare::__flag_prefix ## _descriptions) && (__name##1->getDescription() != __name##2->getDescription())) +#define COMPARE_COMMENT(__name, __flag_prefix) ((flags & DDLCompare::__flag_prefix ## _comments) && (__name##1->getComment() != __name##2->getComment())) +#define CHECK_NAMES(__var, __kind) \ +if (flags & DDLCompare::icf_names && \ + __var##1->getName() != __var##2->getName()) \ +{ \ + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The " __kind " '%s' has a different name than '%s'.", __var##1->getName().c_str(), __var##2->getName().c_str())); \ +} \ + +#define CHECK_OPTIONAL(__name, __attr) \ +(COMPARE(__name, is##__attr##Valid) || \ + (__name##1->is##__attr##Valid() && COMPARE(__name, get##__attr##Value))) + +class DDLImporterWrapper +{ + private: + DDLImporter _importer; + + public: + + ~DDLImporterWrapper() + { + _importer.destroyDDL(); + } + + a_util::result::Result create(const std::string& desc, const DDLDescription* ref_desc) + { + _importer.setMergeDefaults(false); + _importer.setPreferReferenceEntities(false); + RETURN_DDLERROR_IF_FAILED_DESC(_importer.setXML(desc), _importer.getErrorDesc()); + if (ref_desc) + { + RETURN_DDLERROR_IF_FAILED_DESC(_importer.createPartial(ref_desc, DDLVersion::ddl_version_invalid), _importer.getErrorDesc()); + } + else + { + RETURN_DDLERROR_IF_FAILED_DESC(_importer.createNew(DDLVersion::ddl_version_invalid), _importer.getErrorDesc()); + } + + return a_util::result::SUCCESS; + } + + const DDLDescription* getDDL() + { + return _importer.getDDL(); + } + +}; + +template +static a_util::result::Result CompareSizes(const T& vec1, const T& vec2, uint32_t flags, const std::string& name, uint32_t subset_flags) +{ + if (flags & subset_flags) + { + if (vec1.size() > vec2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, "The first description has more " + name + " then the second."); + } + } + else + { + if (vec1.size() != vec2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, "The descriptions have different amounts of " + name + "."); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isBinaryEqual(const std::string& type1, const std::string& desc1, const std::string& type2, const std::string& desc2, bool is_subset) +{ + std::unique_ptr ref_desc(DDLDescription::createDefault()); + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, ref_desc.get())); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, ref_desc.get())); + + return isBinaryEqual(type1, importer1.getDDL(), type2, importer2.getDDL(), is_subset); +} + +static a_util::result::Result CompareStaticElements(const std::vector& elements1, + const std::vector& elements2) +{ + for (size_t n_element = 0; n_element < elements1.size(); ++n_element) + { + const StructLayoutElement& element1 = elements1[n_element]; + const StructLayoutElement& element2 = elements2[n_element]; + if (element1.deserialized.bit_offset != element2.deserialized.bit_offset || + element1.deserialized.bit_size != element2.deserialized.bit_size) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The elements '%s' and '%s' differ in size or address.", + element1.name.c_str(), element2.name.c_str()); + } + if (element1.type != element2.type) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The elements '%s' and '%s' have different types.", + element1.name.c_str(), element2.name.c_str()); + } + } + + return a_util::result::SUCCESS; +} + +static a_util::result::Result CompareDynamicElements(const std::vector& elements1, + const std::vector& elements2) +{ + for (size_t n_element = 0; n_element < elements1.size(); ++n_element) + { + const DynamicStructLayoutElement& element1 = elements1[n_element]; + const DynamicStructLayoutElement& element2 = elements2[n_element]; + + if (element1.alignment != element2.alignment) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The elements '%s' and '%s' have different alignment.", + element1.name.c_str(), element2.name.c_str()); + } + + if (element1.static_elements.size() != element2.static_elements.size()) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The elements '%s' and '%s' have different amounts of child elements.", + element1.name.c_str(), element2.name.c_str()); + } + + RETURN_IF_FAILED(CompareStaticElements(element1.static_elements, + element2.static_elements)); + + if (element1.dynamic_elements.size() != element2.dynamic_elements.size()) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The elements '%s' and '%s' have different amounts of dynamic elements.", + element1.name.c_str(), element2.name.c_str()); + } + + RETURN_IF_FAILED(CompareDynamicElements(element1.dynamic_elements, + element2.dynamic_elements)); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isBinaryEqual(const std::string& type1, const DDLDescription* desc1, const std::string& type2, const DDLDescription* des2, bool is_subset) +{ + const DDLComplex* struct1 = desc1->getStructByName(type1); + if (!struct1) + { + RETURN_ERROR_DESCRIPTION(ERR_NOT_FOUND, ("Unable to find definitions for struct " + type1).c_str()); + } + const DDLComplex* struct2 = des2->getStructByName(type2); + if (!struct2) + { + RETURN_ERROR_DESCRIPTION(ERR_NOT_FOUND, ("Unable to find definitions for struct " + type2).c_str()); + } + + StructLayout layout1(struct1); + StructLayout layout2(struct2); + + RETURN_IF_FAILED(layout1.isValid()); + RETURN_IF_FAILED(layout2.isValid()); + + if (is_subset) + { + if (layout1.getStaticElements().size() > layout2.getStaticElements().size()) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The struct '%s' has more elements than '%s'.", type1.c_str(), type2.c_str()); + } + } + else + { + if (layout1.getStaticElements().size() != layout2.getStaticElements().size()) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The structs '%s' and '%s' have different amounts of elements.", type1.c_str(), type2.c_str()); + } + } + + RETURN_IF_FAILED(CompareStaticElements(layout1.getStaticElements(), layout2.getStaticElements())); + + + // check dynamic stuff + if (layout1.getDynamicElements().size() != layout2.getDynamicElements().size()) + { + RETURN_ERROR_DESCRIPTION(ERR_FAILED, "The structs '%s' and '%s' have different amounts of dynamic elements.", type1.c_str(), type2.c_str()); + } + + if (layout1.hasDynamicElements()) + { + RETURN_IF_FAILED(CompareDynamicElements(layout1.getDynamicElements(), layout2.getDynamicElements())); + } + + return a_util::result::SUCCESS; +} + +static a_util::result::Result CompareDataTypes(const DDLDataType* dt1, + const DDLDataType* dt2, + uint32_t flags) +{ + // Data types have to have the same name + if (COMPARE(dt, getName)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The datatypes '%s' and '%s' do not match.", dt1->getName().c_str(), dt2->getName().c_str())); + } + + if (COMPARE_DESCRIPTION(dt, icf) || + COMPARE(dt, getArraysize) || + COMPARE(dt, getUnit) || + COMPARE(dt, getAlignment) || + COMPARE(dt, getNumBits) || + COMPARE(dt, getArraySizeSource)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The datatype '%s' is different in the second description.", dt1->getName().c_str())); + } + + if (flags & DDLCompare::icf_visualizations_attributes) + { + if (CHECK_OPTIONAL(dt, Min) || + CHECK_OPTIONAL(dt, Max)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The datatype min/max attributes of '%s' are different in the second description.", dt1->getName().c_str())); + } + } + + return a_util::result::SUCCESS; +} + +static a_util::result::Result CompareEnums(const DDLEnum* p_enum1, + const DDLEnum* p_enum2, + uint32_t flags) +{ + CHECK_NAMES(p_enum, "enum") + + if (COMPARE(p_enum, getType)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The enum '%s' has a different type in the second description.", p_enum1->getName().c_str())); + } + + if (!(flags & DDLCompare::icf_no_enum_values_check)) + { + if (COMPARE(p_enum, getValues)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The values of enum '%s' are different in the second description.", p_enum1->getName().c_str())); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLPrefix* prefix1, const DDLPrefix* prefix2, + uint32_t flags) +{ + CHECK_NAMES(prefix, "prefix") + + if (COMPARE(prefix, getPower) || + COMPARE(prefix, getSymbol)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The prefixes '%s' and '%s' do not match.", + prefix1->getName().c_str(), prefix2->getName().c_str())); + } + + return a_util::result::SUCCESS; +} + +static a_util::result::Result CompareBaseUnits(const DDLBaseunit* baseunit1, + const DDLBaseunit* baseunit2, + uint32_t flags) +{ + CHECK_NAMES(baseunit, "base unit") + + if (COMPARE_DESCRIPTION(baseunit, icf) || + COMPARE(baseunit, getSymbol)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The baseunits '%s' and '%s' do not match.", + baseunit1->getName().c_str(), baseunit2->getName().c_str())); + } + + return a_util::result::SUCCESS; +} + +static a_util::result::Result CompareUnits(const DDLUnit* unit1, const DDLUnit* unit2, + uint32_t flags) +{ + CHECK_NAMES(unit, "unit") + + if (COMPARE(unit, getDenominator) || + COMPARE(unit, getNumerator) || + COMPARE(unit, getOffset)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The units '%s' and '%s' do not match.", + unit1->getName().c_str(), unit2->getName().c_str())); + } + + if (!(flags & DDLCompare::icf_no_recursion)) + { + const DDLRefUnitVec& ref_units1 = unit1->getRefUnits(); + const DDLRefUnitVec& ref_units2 = unit2->getRefUnits(); + + RETURN_IF_FAILED(CompareSizes(ref_units1, ref_units2, flags, "refunits", DDLCompare::icf_subset)); + + for (DDLRefUnitVec::const_iterator it1 = ref_units1.begin(); it1 != ref_units1.end(); ++it1) + { + DDLRefUnit* ref_unit1 = *it1; + + DDLRefUnitVec::const_iterator it2 = std::find_if(ref_units2.begin(), ref_units2.end(), DDLCompareFunctor(ref_unit1->getName())); + if (it2 == ref_units2.end()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The reference unit '%s' of unit '%s' is not available in the second description.", + ref_unit1->getName().c_str(), unit1->getName().c_str())); + } + + DDLRefUnit* ref_unit2 = *it2; + + RETURN_IF_FAILED(DDLCompare::isEqual(ref_unit1, ref_unit2, flags)); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const IDDLUnit* i_unit1, const IDDLUnit* i_unit2, + uint32_t flags) +{ + const DDLBaseunit* baseunit1 = dynamic_cast(i_unit1); + const DDLBaseunit* baseunit2 = dynamic_cast(i_unit2); + const DDLUnit* unit1 = dynamic_cast(i_unit1); + const DDLUnit* unit2 = dynamic_cast(i_unit2); + if (baseunit1 && baseunit2) + { + return CompareBaseUnits(baseunit1, baseunit2, flags); + } + else if (unit1 && unit2) + { + return CompareUnits(unit1, unit2, flags); + } + else + { + if (baseunit1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The first unit '%s' is a base unit and the second '%s' is a unit", + i_unit1->getName().c_str(), i_unit2->getName().c_str())); + } + else + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The first unit '%s' is a unit and the second '%s' is a base unit", + i_unit1->getName().c_str(), i_unit2->getName().c_str())); + } + return a_util::result::SUCCESS; + } +} + + +a_util::result::Result CompareStructs(const DDLComplex* ddl_struct1, const DDLComplex* ddl_struct2, uint32_t flags) +{ + CHECK_NAMES(ddl_struct, "struct") + + if ((flags & DDLCompare::icf_versions) && + ddl_struct1->getVersion() != ddl_struct2->getVersion()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The versions of '%s' and '%s' do not match.", ddl_struct1->getName().c_str(), ddl_struct2->getName().c_str())); + } + + if ((flags & DDLCompare::icf_comments) && + ddl_struct1->getComment() != ddl_struct2->getComment()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The comments of '%s' and '%s' do not match.", ddl_struct1->getName().c_str(), ddl_struct2->getName().c_str())); + } + + if (flags & DDLCompare::icf_memory) + { + if (ddl_struct1->getAlignment() != ddl_struct2->getAlignment()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The alignments of '%s' and '%s' do not match.", ddl_struct1->getName().c_str(), ddl_struct2->getName().c_str())); + } + } + + if (!(flags & DDLCompare::icf_no_recursion)) + { + const DDLElementVec& elements1 = ddl_struct1->getElements(); + const DDLElementVec& elements2 = ddl_struct2->getElements(); + + if (flags & DDLCompare::icf_subset) + { + if (elements1.size() > elements2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The there are more elements in '%s' than in '%s'.", ddl_struct1->getName().c_str(), ddl_struct2->getName().c_str())); + } + } + else + { + if (elements1.size() != elements2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The amount of elements in '%s' and '%s' is not equal.", ddl_struct1->getName().c_str(), ddl_struct2->getName().c_str())); + } + } + + DDLElementVec::const_iterator it_element1 = elements1.begin(); + DDLElementVec::const_iterator it_element2 = elements2.begin(); + for (; it_element1 != elements1.end(); ++it_element1, ++it_element2) + { + const DDLElement* element1 = *it_element1; + const DDLElement* element2 = *it_element2; + + // we do this special checks here, sinc the specialized isEqual method does nto have access to the other elements. + + if (element1->isDynamic() != element2->isDynamic()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("One of the elements '%s.%s' and '%s.%s' is dynamic the other not.", + ddl_struct1->getName().c_str(), element1->getName().c_str(), ddl_struct2->getName().c_str(), element2->getName().c_str())); + } + + if (element1->isDynamic()) + { + // find element positions + DDLElementVec::const_iterator it_size_element1 = std::find_if(elements1.begin(), it_element1, + DDLCompareFunctor(element1->getArraySizeSource())); + if (it_size_element1 == elements1.end()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_INVALID_ARG, a_util::strings::format("The array size element specified in '%s.%s' could not be found", + ddl_struct1->getName().c_str(), element1->getName().c_str())); + } + + DDLElementVec::const_iterator it_size_element2 = std::find_if(elements2.begin(), it_element2, + DDLCompareFunctor(element2->getArraySizeSource())); + if (it_size_element2 == elements2.end()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_INVALID_ARG, a_util::strings::format("The array size element specified in '%s.%s' could not be found", + ddl_struct2->getName().c_str(), element2->getName().c_str())); + } + + if (it_size_element1 - elements1.begin() != it_size_element2 - elements2.begin()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The referenced dynamic array size element of the elements '%s.%s' and '%s.%s' do not match.", + ddl_struct1->getName().c_str(), element1->getName().c_str(), ddl_struct2->getName().c_str(), element2->getName().c_str())); + } + } + + // only the last element is allowed to be a subset + uint32_t sub_flags = flags; + if ((flags & DDLCompare::icf_subset) && + (it_element1 + 1 != elements1.end())) + { + sub_flags = flags & !DDLCompare::icf_subset; + } + + RETURN_IF_FAILED(DDLCompare::isEqual(element1, element2, sub_flags)); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const IDDLDataType* type1, const IDDLDataType* type2, + uint32_t flags) +{ + const DDLDataType* dt1 = dynamic_cast(type1); + const DDLDataType* dt2 = dynamic_cast(type2); + const DDLComplex* ddl_struct1 = dynamic_cast(type1); + const DDLComplex* ddl_struct2 = dynamic_cast(type2); + const DDLEnum* enum1 = dynamic_cast(type1); + const DDLEnum* enum2 = dynamic_cast(type2); + + if (dt1 && dt2) + { + return CompareDataTypes(dt1, dt2, flags); + } + else if (ddl_struct1 && ddl_struct2) + { + return CompareStructs(ddl_struct1, ddl_struct2, flags); + } + else if (enum1 && enum2) + { + return CompareEnums(enum1, enum2, flags); + } + else + { + std::string kind1 = "basic data type"; + if (ddl_struct1) + { + kind1 = "struct"; + } + else if (enum1) + { + kind1 = "enum"; + } + + std::string kind2 = "basic data type"; + if (ddl_struct2) + { + kind2 = "struct"; + } + else if (enum2) + { + kind2 = "enum"; + } + + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The first type '%s' is a %s and the second '%s' is a %s.", + type1->getName().c_str(), kind1.c_str(), type2->getName().c_str(), kind2.c_str())); + + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLStream* stream1, const DDLStream* stream2, + uint32_t flags) +{ + CHECK_NAMES(stream, "stream") + + if (COMPARE_VERSION(stream, getDDLVersion, icf) || + COMPARE_DESCRIPTION(stream, icf)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The stream '%s' is different in the second description", stream1->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(stream1->getTypeObject(), stream2->getTypeObject(), flags)); + + if (!(flags & icf_no_recursion)) + { + const DDLStreamStructVec& structs1 = stream1->getStructs(); + const DDLStreamStructVec& structs2 = stream2->getStructs(); + + if (flags & DDLCompare::icf_subset) + { + if (structs1.size() > structs2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The there are more structs in '%s' in the second description", stream1->getName().c_str())); + } + } + else + { + if (structs1.size() != structs2.size()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The stream '%s' has a different amount of structs in the second description.", stream1->getName().c_str())); + } + } + + DDLStreamStructVec::const_iterator it_struct1 = structs1.begin(); + DDLStreamStructVec::const_iterator it_struct2 = structs2.begin(); + + for (; it_struct1 != structs1.end(); ++it_struct1, ++it_struct2) + { + const DDLStreamStruct* ddl_struct1 = *it_struct1; + const DDLStreamStruct* ddl_struct2 = *it_struct2; + + // only the last element is allowed to be a subset + uint32_t sub_flags = flags; + if ((flags & DDLCompare::icf_subset) && + (it_struct1 + 1 != structs1.end())) + { + sub_flags = flags & !DDLCompare::icf_subset; + } + + RETURN_IF_FAILED(DDLCompare::isEqual(ddl_struct1, ddl_struct2, sub_flags)); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLExtDeclaration* ext1, const DDLExtDeclaration* ext2, + uint32_t flags) +{ + CHECK_NAMES(ext, "ext declaration") // name == key + + if (COMPARE(ext, getValue)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The external declaration '%s' is different in the second description.", + ext1->getName().c_str())); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLRefUnit* ref_unit1, const DDLRefUnit* ref_unit2, + uint32_t flags) +{ + CHECK_NAMES(ref_unit, "ref unit") + + if (COMPARE(ref_unit, getPower)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The reference unit '%s' is different in the second description.", + ref_unit1->getName().c_str())); + } + + if (!(flags & icf_no_recursion)) + { + RETURN_IF_FAILED(DDLCompare::isEqual(ref_unit1->getUnitObject(), ref_unit2->getUnitObject(), flags)); + RETURN_IF_FAILED(DDLCompare::isEqual(ref_unit1->getPrefixObject(), ref_unit2->getPrefixObject(), flags)); + } + else if (flags & icf_names) + { + if (COMPARE(ref_unit, getPrefix)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The prefix of the reference unit '%s' is different in the second description.", + ref_unit1->getName().c_str())); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLElement* element1, const DDLElement* element2, + uint32_t flags) +{ + if (flags & DDLCompare::icf_memory) + { + if (COMPARE(element, getAlignment)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The alignments of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + } + + if (COMPARE(element, getArraysize)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The arraysizes of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (COMPARE(element, getConstantValue)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The constant values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (flags & icf_visualizations_attributes) + { + if (CHECK_OPTIONAL(element, Default)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The default values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (CHECK_OPTIONAL(element, Scale)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The scale values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (CHECK_OPTIONAL(element, Offset)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The scale values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (CHECK_OPTIONAL(element, Min)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The min values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (CHECK_OPTIONAL(element, Max)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The max values of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + } + + if (COMPARE(element, isDynamic)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("One of the elements '%s' and '%s' is dynamic the other not.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (element1->isDynamic()) + { + // here all we can do is compare the names + if (flags & DDLCompare::icf_names && + COMPARE(element, getArraySizeSource)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The element '%s' has a different arraysize specifier than '%s'.", + element1->getName().c_str(), element2->getName().c_str())); + } + } + + if (flags & DDLCompare::icf_serialized) + { + if (COMPARE(element, getBitpos)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The bitpos of the elements '%s' and '%s' does not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + if (COMPARE(element, getBytepos)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The bitpos of the elements '%s' and '%s' does not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + if (COMPARE(element, getByteorder)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The bitpos of the elements '%s' and '%s' does not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + } + + CHECK_NAMES(element, "element") + + if (!(flags & icf_no_recursion)) + { + if (flags & DDLCompare::icf_units) + { + IDDLUnit* unit1 = element1->getUnitObject(); + IDDLUnit* unit2 = element2->getUnitObject(); + + if ((unit1 == NULL) != (unit2 == NULL)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The units of the elements '%s' and '%s' do not match.", + element1->getName().c_str(), element2->getName().c_str())); + } + + if (unit1) + { + RETURN_IF_FAILED(DDLCompare::isEqual(unit1, unit2, flags)); + } + } + + // we handle the special case of basic data types in order to provide a meaningfull errror message + DDLDataType* dt1 = dynamic_cast(element1->getTypeObject()); + DDLDataType* dt2 = dynamic_cast(element2->getTypeObject()); + if (dt1 && dt2) + { + if (COMPARE(dt, getName)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The data types of the elements '%s(%s)' and '%s(%s)' do not match.", + element1->getName().c_str(), dt1->getName().c_str(), + element2->getName().c_str(), dt2->getName().c_str())); + } + } + + RETURN_IF_FAILED(DDLCompare::isEqual(element1->getTypeObject(), element2->getTypeObject(), flags)); + } + else if (flags & icf_names) + { + // compare the names of the types only. + if (COMPARE(element, getType)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The data types of the elements '%s(%s)' and '%s(%s)' do not match.", + element1->getName().c_str(), element1->getType().c_str(), + element2->getName().c_str(), element2->getType().c_str())); + } + + if (flags & DDLCompare::icf_units) + { + if (COMPARE(element, getUnit)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The units of the elements '%s(%s)' and '%s(%s)' do not match.", + element1->getName().c_str(), element1->getUnit().c_str(), + element2->getName().c_str(), element2->getUnit().c_str())); + } + } + } + + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLStreamStruct* ddl_struct1, const DDLStreamStruct* ddl_struct2, + uint32_t flags) +{ + if (((flags & DDLCompare::icf_serialized) && COMPARE(ddl_struct, getBytepos)) || + ((flags & DDLCompare::icf_names) && COMPARE(ddl_struct, getName))) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The stream structs '%s' and '%s' are not equal", + ddl_struct1->getName().c_str(), + ddl_struct2->getName().c_str())); + } + + if (!(flags & icf_no_recursion)) + { + RETURN_IF_FAILED(DDLCompare::isEqual(ddl_struct1->getTypeObject(), ddl_struct2->getTypeObject(), flags)); + } + else if (flags & icf_names) + { + // compare the names of the types only. + if (COMPARE(ddl_struct, getType)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The types of the stream structs '%s(%s)' and '%s(%s)' do not match.", + ddl_struct1->getName().c_str(), ddl_struct1->getType().c_str(), + ddl_struct2->getName().c_str(), ddl_struct2->getType().c_str())); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqual(const DDLDescription* desc1, + const DDLDescription* des2, + uint32_t flags) +{ + // build flags for the item based comparisions + uint32_t item_flags = icf_memory | icf_serialized | icf_names; + if (flags & dcf_versions) + { + item_flags |= icf_versions; + } + if (flags & dcf_descriptions) + { + item_flags |= icf_descriptions; + } + if (flags & dcf_comments) + { + item_flags |= icf_comments; + } + if (flags & dcf_units || flags & dcf_base_units) + { + item_flags |= icf_units; + } + if (flags & dcf_visualization_attributes) + { + item_flags |= icf_visualizations_attributes; + } + if (flags & dcf_no_enum_values_check) + { + item_flags |= icf_no_enum_values_check; + } + if (flags & dcf_no_recursion) + { + item_flags |= icf_no_recursion; + } + + if (flags & dcf_header) + { + const DDLHeader* pHeader1 = desc1->getHeader(); + const DDLHeader* pHeader2 = des2->getHeader(); + + if (COMPARE(pHeader, getAuthor) || + COMPARE_DESCRIPTION(pHeader, dcf) || + COMPARE_VERSION(pHeader, getLanguageVersion, dcf) || + COMPARE(pHeader, getName)) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, "The headers are different."); + } + + // only check dates if dcf_no_header_dates is not set + if ((flags & dcf_no_header_dates) == 0 && + (COMPARE(pHeader, getDateChange) || COMPARE(pHeader, getDateCreation))) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, "The headers are different."); + } + + const DDLExtDeclarationVec& exts1 = pHeader1->getExtDeclarations(); + const DDLExtDeclarationVec& exts2 = pHeader2->getExtDeclarations(); + + RETURN_IF_FAILED(CompareSizes(exts1, exts2, flags, "external declarations", dcf_subset)); + + for (DDLExtDeclarationVec::const_iterator it_ext1 = exts1.begin(); it_ext1 != exts1.end(); ++it_ext1) + { + const DDLExtDeclaration* ext1 = *it_ext1; + DDLExtDeclarationVec::const_iterator it_ext2 = std::find_if(exts2.begin(), exts2.end(), + DDLCompareFunctor(ext1->getName())); // key = name + if (it_ext2 == exts2.end()) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The external declaration '%s' is not available in the second description.", + ext1->getName().c_str())); + } + + const DDLExtDeclaration* ext2 = *it_ext2; + + RETURN_IF_FAILED(isEqual(ext1, ext2, flags)); + } + + } + + if (flags & dcf_data_types) + { + const DDLDTVec& dts1 = desc1->getDatatypes(); + const DDLDTVec& dts2 = des2->getDatatypes(); + + RETURN_IF_FAILED(CompareSizes(dts1, dts2, flags, "datatypes", dcf_subset)); + + for (DDLDTVec::const_iterator it = dts1.begin(); it != dts1.end(); ++it) + { + const DDLDataType* dt1 = *it; + const DDLDataType* dt2 = des2->getDataTypeByName(dt1->getName()); + if (!dt2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The data type '%s' is not available in the second description.", (*it)->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(dt1, dt2, item_flags)); + } + } + + if (flags & dcf_enums) + { + const DDLEnumVec& enums1 = desc1->getEnums(); + const DDLEnumVec& enums2 = des2->getEnums(); + + RETURN_IF_FAILED(CompareSizes(enums1, enums2, flags, "enums", dcf_subset)); + + for (DDLEnumVec::const_iterator it = enums1.begin(); it != enums1.end(); ++it) + { + const DDLEnum* enum1 = *it; + const DDLEnum* enum2 = des2->getEnumByName(enum1->getName()); + if (!enum2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The enum '%s' is not available in the second description.", enum1->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(enum1, enum2, item_flags)); + } + } + + if (flags & dcf_base_units) + { + const DDLBaseunitVec& units1 = desc1->getBaseunits(); + const DDLBaseunitVec& units2 = des2->getBaseunits(); + + RETURN_IF_FAILED(CompareSizes(units1, units2, flags, "baseunits", dcf_subset)); + + for (DDLBaseunitVec::const_iterator it_unit = units1.begin(); it_unit != units1.end(); ++it_unit) + { + const DDLBaseunit* unit1 = *it_unit; + const DDLBaseunit* unit2 = des2->getBaseunitByName(unit1->getName()); + if (!unit2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The baseunit '%s' is not available in the second description.", unit1->getName().c_str())); + } + + RETURN_IF_FAILED(CompareBaseUnits(unit1, unit2, item_flags)); + } + } + + if (flags & dcf_units) + { + const DDLUnitVec& units1 = desc1->getUnits(); + const DDLUnitVec& units2 = des2->getUnits(); + + RETURN_IF_FAILED(CompareSizes(units1, units2, flags, "units", dcf_subset)); + + for (DDLUnitVec::const_iterator it_unit = units1.begin(); it_unit != units1.end(); ++it_unit) + { + const DDLUnit* unit1 = *it_unit; + const DDLUnit* unit2 = des2->getUnitByName(unit1->getName()); + if (!unit2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The unit '%s' is not available in the second description.", unit1->getName().c_str())); + } + + uint32_t unit_flags = item_flags; + if (flags & dcf_subset) + { + unit_flags |= icf_subset; + } + RETURN_IF_FAILED(isEqual(unit1, unit2, unit_flags)); + } + } + + if (flags & dcf_prefixes) + { + const DDLPrefixVec& prefixes1 = desc1->getPrefixes(); + const DDLPrefixVec& prefixes2 = des2->getPrefixes(); + + RETURN_IF_FAILED(CompareSizes(prefixes1, prefixes2, flags, "prefixes", dcf_subset)); + + for (DDLPrefixVec::const_iterator it = prefixes1.begin(); it != prefixes1.end(); ++it) + { + const DDLPrefix* prefix1 = *it; + const DDLPrefix* prefix2 = des2->getPrefixByName(prefix1->getName()); + if (!prefix2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The prefix '%s' is not available in the second description.", prefix1->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(prefix1, prefix2, item_flags)); + } + } + + if (flags & dcf_structs) + { + const DDLComplexVec& structs1 = desc1->getStructs(); + const DDLComplexVec& structs2 = des2->getStructs(); + + RETURN_IF_FAILED(CompareSizes(structs1, structs2, flags, "structs", dcf_subset)); + + for (DDLComplexVec::const_iterator it_struct1 = structs1.begin(); + it_struct1 != structs1.end(); ++it_struct1) + { + const DDLComplex* ddl_struct1 = *it_struct1; + const DDLComplex* ddl_struct2 = des2->getStructByName(ddl_struct1->getName()); + if (!ddl_struct2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The struct '%s' is not available in the second description.", ddl_struct1->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(ddl_struct1, ddl_struct2, item_flags)); + } + } + + if (flags & dcf_streams) + { + const DDLStreamVec& streams1= desc1->getStreams(); + const DDLStreamVec& streams2= des2->getStreams(); + + RETURN_IF_FAILED(CompareSizes(streams1, streams2, flags, "streams", dcf_subset)); + + DDLStreamVec::const_iterator it_stream1 = streams1.begin(); + DDLStreamVec::const_iterator it_stream2 = streams2.begin(); + for (; it_stream1 != streams1.end(); ++it_stream1, ++it_stream2) + { + const DDLStream* stream1 = *it_stream1; + const DDLStream* stream2 = des2->getStreamByName(stream1->getName()); + if (!stream2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The stream '%s' is not available in the second description.", stream1->getName().c_str())); + } + + RETURN_IF_FAILED(isEqual(stream1, stream2, item_flags)); + } + } + + return a_util::result::SUCCESS; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// string based methods +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +a_util::result::Result DDLCompare::isEqualPrefix(const std::string& prefix_str1, const std::string& desc1, + const std::string& prefix_str2, const std::string& desc2, + uint32_t flags) +{ + a_util::memory::unique_ptr ref_desc(DDLDescription::createDefault()); + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, ref_desc.get())); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, ref_desc.get())); + + const DDLPrefix* prefix1 = importer1.getDDL()->getPrefixByName(prefix_str1); + if (!prefix1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The prefix '%s' is not definied within the first DDL.", prefix_str1.c_str())); + } + + const DDLPrefix* prefix2 = importer2.getDDL()->getPrefixByName(prefix_str2); + if (!prefix2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The prefix '%s' is not definied within the second DDL.", prefix_str2.c_str())); + } + + return isEqual(prefix1, prefix2, flags); +} + +a_util::result::Result DDLCompare::isEqualUnit(const std::string& unit_str1, const std::string& desc1, + const std::string& unit_str2, const std::string& desc2, + uint32_t flags) +{ + if (unit_str1 != unit_str2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_FAILED, a_util::strings::format("The units '%s' and '%s' do not match.", + unit_str1.c_str(), unit_str1.c_str())); + } + + a_util::memory::unique_ptr ref_desc(DDLDescription::createDefault()); + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, ref_desc.get())); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, ref_desc.get())); + + const DDLBaseunit* baseunit1 = importer1.getDDL()->getBaseunitByName(unit_str1); + const DDLBaseunit* baseunit2 = importer2.getDDL()->getBaseunitByName(unit_str2); + const DDLUnit* unit1 = importer1.getDDL()->getUnitByName(unit_str1); + const DDLUnit* unit2 = importer2.getDDL()->getUnitByName(unit_str2); + + if (!baseunit1 && !unit1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The units '%s' is not defined in the first description.", + unit_str1.c_str())); + } + if (!baseunit2 && !unit2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The units '%s' is not defined in the second description.", + unit_str2.c_str())); + } + + if (baseunit1 && baseunit2) + { + return CompareBaseUnits(baseunit1, baseunit2, flags); + } + else if (unit1 && unit2) + { + return CompareUnits(unit1, unit2, flags); + } + else + { + if (baseunit1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The units '%s' is a base unit in the first description and the unit '%s' is a unit in the second.", + unit_str1.c_str(), unit_str2.c_str())); + } + else + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The units '%s' is a unit in the first description and the unit '%s' is a base unit in the second.", + unit_str1.c_str(), unit_str2.c_str())); + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqualType(const std::string& type1, const std::string& desc1, + const std::string& type2, const std::string& desc2, + uint32_t flags) +{ + a_util::memory::unique_ptr ref_desc(DDLDescription::createDefault()); + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, ref_desc.get())); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, ref_desc.get())); + + const DDLDataType* dt1 = importer1.getDDL()->getDataTypeByName(type1); + const DDLDataType* dt2 = importer2.getDDL()->getDataTypeByName(type2); + const DDLComplex* ddl_struct1 = importer1.getDDL()->getStructByName(type1); + const DDLComplex* ddl_struct2 = importer2.getDDL()->getStructByName(type2); + const DDLEnum* enum1 = importer1.getDDL()->getEnumByName(type1); + const DDLEnum* enum2 = importer2.getDDL()->getEnumByName(type2); + + if (!dt1 && !ddl_struct1 && !enum1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The type '%s' is not defined in the first description.", + type1.c_str())); + } + if (!dt2 && !ddl_struct2 && !enum2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The type '%s' is not defined in the second description.", + type2.c_str())); + } + + if (dt1 && dt2) + { + return CompareDataTypes(dt1, dt2, flags); + } + else if (ddl_struct1 && ddl_struct2) + { + return CompareStructs(ddl_struct1, ddl_struct2, flags); + } + else if (enum1 && enum2) + { + return CompareEnums(enum1, enum2, flags); + } + else + { + std::string kind1 = "basic data type"; + if (ddl_struct1) + { + kind1 = "struct"; + } + else if (enum1) + { + kind1 = "enum"; + } + + std::string kind2 = "basic data type"; + if (ddl_struct2) + { + kind2 = "struct"; + } + else if (enum2) + { + kind2 = "enum"; + } + + RETURN_DDLERROR_IF_FAILED_DESC(ERR_UNEXPECTED, a_util::strings::format("The first type '%s' is a %s and the second '%s' is a %s.", + type1.c_str(), kind1.c_str(), type2.c_str(), kind2.c_str())); + + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result DDLCompare::isEqualStream(const std::string& stream_str1, const std::string& desc1, + const std::string& stream_str2, const std::string& desc2, + uint32_t flags) +{ + a_util::memory::unique_ptr ref_desc(DDLDescription::createDefault()); + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, ref_desc.get())); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, ref_desc.get())); + + const DDLStream* stream1 = importer1.getDDL()->getStreamByName(stream_str1); + if (!stream1) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The stream '%s' is not definied within the first DDL.", stream_str1.c_str())); + } + + const DDLStream* stream2 = importer2.getDDL()->getStreamByName(stream_str2); + if (!stream2) + { + RETURN_DDLERROR_IF_FAILED_DESC(ERR_NOT_FOUND, a_util::strings::format("The stream '%s' is not definied within the second DDL.", stream_str2.c_str())); + } + + return isEqual(stream1, stream2, flags); +} + +a_util::result::Result DDLCompare::isEqual(const std::string& desc1, + const std::string& desc2, + uint32_t flags) +{ + DDLImporterWrapper importer1; + RETURN_IF_FAILED(importer1.create(desc1, NULL)); + DDLImporterWrapper importer2; + RETURN_IF_FAILED(importer2.create(desc2, NULL)); + + return isEqual(importer1.getDDL(), importer2.getDDL(), flags); +} + + +} + + diff --git a/ddlrepresentation/ddlcompare.h b/ddlrepresentation/ddlcompare.h new file mode 100644 index 0000000..e799af3 --- /dev/null +++ b/ddlrepresentation/ddlcompare.h @@ -0,0 +1,309 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLCOMPARE_H_INCLUDED +#define DDLCOMPARE_H_INCLUDED + +#include "ddl_common.h" +#include "ddldescription.h" +#include "ddlunit_intf.h" +#include "ddlelement.h" + +namespace ddl +{ + +/** + * Utility class to compare media descriptions + */ +class DDLCompare +{ + public: + /** + * Flags for the description based isEqual methods + */ + enum DescriptionCheckFlags + { + dcf_data_types = 0x01, ///< Compare datatypes + dcf_units = 0x02, ///< Compare units + dcf_enums = 0x04, ///< Compare enums + dcf_structs = 0x08, ///< Compare structs + dcf_streams = 0x10, ///< Compare streams + dcf_base_units = 0x20, ///< Compare baseunits + dcf_prefixes = 0x40, ///< Compare prefixes + dcf_all = 0xFF, ///< Compare all elements (see above) + dcf_subset = 0x0100, ///< Checks whether the first description is a subset of the second + dcf_versions = 0x0200, ///< Compares the version attributes as well + dcf_comments = 0x0400, ///< Compares the comment attributes as well + dcf_descriptions = 0x0800, ///< Compares the description attributes as well + dcf_header = 0x1000, ///< Compare the header as well + dcf_visualization_attributes = 0x2000, ///< Check attributes relevant for visualization (min/max/default/scale/offset) + dcf_no_enum_values_check = 0x010000, ///< Do not compare enum values. + dcf_no_recursion = 0x020000, ///< Do not compare sub-entities (elements, ref units, stream structs, ...) + dcf_no_header_dates = 0x040000, ///< Do not compare header dates (date_creation, date_change) + + dcf_everything = 0xFFFF ///< Check everything (all flags except the "No" variants) + }; + + /** + * Flags for the item based isEqual methods + */ + enum ItemCheckFlags + { + icf_none = 0x00, + icf_memory = 0x01, ///< Compare the in-memory representation + icf_serialized = 0x02, ///< Compare the serialized representation + icf_names = 0x04, ///< Compare the names of structs and their elements + icf_versions = 0x08, ///< Compare the versions of all elements and structs + icf_units = 0x10, ///< Compare the units as well + icf_comments = 0x20, ///< Compare the comments as well + icf_descriptions = 0x40, ///< Compare the comments as well + icf_subset = 0x80, ///< Check if the first item is a subset of the second. + icf_visualizations_attributes = 0x0100, ///< Check attributes relevant for visualization (min/max/default/scale/offset) + icf_no_enum_values_check = 0x0200, ///< Do not compare enum values. + icf_no_recursion = 0x0400 ///< Do not compare sub-entities (elements, ref units, stream structs, ...) + }; + + public: + + /** + * @brief isBinaryEqual checks whether two type descriptions describe the same binary data layout + * @param [in] type1 The name of the first type. + * @param [in] desc1 The description that has type1. + * @param [in] type2 The name of the second type. + * @param [in] desc2 The description that has type2. + * @param [in] is_subset If true then the method checks if the first type is a subset of the second (starting at offset 0, possibly with smaller size). + * @retval a_util::result::SUCCESS The description describe the same layout + * @retval ERR_FAILED The description do NOT describe the same layout + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isBinaryEqual(const std::string& type1, const std::string& desc1, + const std::string& type2, const std::string& desc2, + bool is_subset = true); + + /** + * @brief isBinaryEqual checks whether two type descriptions describe the same binary data layout + * @param [in] type1 The name of the first type. + * @param [in] desc1 The description that has type1. + * @param [in] type2 The name of the second type. + * @param [in] desc2 The description that has type2. + * @param [in] is_subset If true then the method checks if the first type is a subset of the second (starting at offset 0, possibly with smaller size). + * @retval a_util::result::SUCCESS The description describe the same layout + * @retval ERR_FAILED The description do NOT describe the same layout + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isBinaryEqual(const std::string& type1, const DDLDescription* desc1, + const std::string& type2, const DDLDescription* desc2, + bool is_subset = true); + + // main ddl entities comparisons + + /** + * @brief isEqualPrefix checks whether two prefix descriptions are equal. + * @param [in] prefix1 The name of the first prefix. + * @param [in] desc1 The description that has prefix1. + * @param [in] prefix2 The name of the second prefix. + * @param [in] desc2 The description that has prefix2. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqualPrefix(const std::string& prefix1, const std::string& desc1, + const std::string& prefix2, const std::string& desc2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two prefix descriptions are equal. + * @param [in] prefix1 The first prefix. + * @param [in] prefix2 The second prefix. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLPrefix* prefix1, const DDLPrefix* prefix2, + uint32_t flags = icf_none); + + /** + * @brief isEqualUnit checks whether two unit descriptions are equal. + * @param [in] unit1 The name of the first type. + * @param [in] desc1 The description that has unit1. + * @param [in] unit2 The name of the second type. + * @param [in] desc2 The description that has unit2. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqualUnit(const std::string& unit1, const std::string& desc1, + const std::string& unit2, const std::string& desc2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two unit descriptions are equal. + * @param [in] unit1 The first unit. + * @param [in] unit2 The second unit. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const IDDLUnit* unit1, const IDDLUnit* unit2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two type (POD/enum/struct) descriptions are equal. + * When this is true for a struct then it also implies @ref isBinaryEqual is true + * @param [in] type1 The name of the first type. + * @param [in] desc1 The description that has type1. + * @param [in] type2 The name of the second type. + * @param [in] desc2 The description that has type2. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqualType(const std::string& type1, const std::string& desc1, + const std::string& type2, const std::string& desc2, + uint32_t flags = icf_memory); + + /** + * @brief isEqual checks whether two type (POD/enum/struct) descriptions are equal + * When this is true for a struct then it also implies @ref isBinaryEqual is true + * @param [in] type1 The first type. + * @param [in] type2 The second type. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const IDDLDataType* type1, const IDDLDataType* type2, + uint32_t flags = icf_memory); + + /** + * @brief isEqual checks whether two stream descriptions are equal. + * @param [in] stream1 The name of the first stream. + * @param [in] desc1 The description that has stream1. + * @param [in] stream2 The name of the second stream. + * @param [in] desc2 The description that has stream2. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqualStream(const std::string& stream1, const std::string& desc1, + const std::string& stream2, const std::string& desc2, + uint32_t flags = icf_memory); + + /** + * @brief isEqual checks whether two stream descriptions are equal. + * @param [in] stream1 The first stream. + * @param [in] stream2 The second stream. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLStream* stream1, const DDLStream* stream2, + uint32_t flags = icf_memory); + + // sub-item comparison + + /** + * @brief isEqual checks whether two external declarations are equal. + * @param [in] ext1 The first declaration. + * @param [in] ext2 The second declaration. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLExtDeclaration* ext1, const DDLExtDeclaration* ext2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two reference units are equal. + * @param [in] ref_unit1 The first unit. + * @param [in] ref_unit2 The second unit. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLRefUnit* ref_unit1, const DDLRefUnit* ref_unit2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two struct elements are equal. + * Note that in case of dynamic elements only the name of the array size specifier can be checked. + * Compare the whole struct if you need a more tourough comparison. + * @param [in] elem1 The first element. + * @param [in] elem2 The second element. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLElement* elem1, const DDLElement* elem2, + uint32_t flags = icf_none); + + /** + * @brief isEqual checks whether two stream structs equal. + * @param [in] stream_struct1 The first struct. + * @param [in] stream_struct2 The second struct. + * @param [in] flags Flags that specifiy what should be checked, see @ref ItemCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLStreamStruct* stream_struct1, const DDLStreamStruct* stream_struct2, + uint32_t flags = icf_none); + + // description based methods + + /** + * @brief isEqual checks whether two descriptions are equal. + * @param [in] desc1 The first description. + * @param [in] desc2 The second description. + * @param [in] flags Flags that specifiy what should be checked, see @ref DescriptionCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const std::string& desc1, + const std::string& desc2, + uint32_t flags = dcf_all | dcf_subset); + + /** + * @brief isEqual checks whether two descriptions are equal. + * @param [in] desc1 The first description. + * @param [in] desc2 The second description. + * @param [in] flags Flags that specifiy what should be checked, see @ref DescriptionCheckFlags. + * @retval a_util::result::SUCCESS The descriptions are equal. + * @retval ERR_FAILED The description are not equal. + * @retval Standard result (other DDL parsing errors etc.) + */ + static a_util::result::Result isEqual(const DDLDescription* desc1, + const DDLDescription* desc2, + uint32_t flags = dcf_all | dcf_subset); +}; + +} + +#endif diff --git a/ddlrepresentation/ddlcomplex.cpp b/ddlrepresentation/ddlcomplex.cpp new file mode 100644 index 0000000..db42df3 --- /dev/null +++ b/ddlrepresentation/ddlcomplex.cpp @@ -0,0 +1,303 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include //std::swap + +#include "ddlcomplex.h" +#include "ddlalignment.h" +#include "ddldescription.h" +#include "ddlelement.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG); + _MAKE_RESULT(-20, ERR_NOT_FOUND); + + DDLComplex::DDLComplex() : + _language_version(DDLVersion::getDefaultVersion()), _init_flag(false), _level(1), _dynamic_elements(false) + { + } + + DDLComplex::DDLComplex(const std::string& name, + unsigned int const version, + const std::string& comment, + DDLAlignment::AlignmentType const alignment, + DDLElementVec ddl_elements, + int const creation_level, + DDLVersion language_version) : + _language_version(language_version), + _name(name), + _version(version), + _comment(comment), + _alignment(alignment), + _ddl_elements(), + _init_flag(true), + _level(creation_level), + _dynamic_elements(false) + { + cloneElements(ddl_elements); + } + + DDLComplex::DDLComplex(const DDLComplex &other) : + _language_version(other.getDDLVersion()), + _name(other.getName()), + _version(other.getVersion()), + _comment(other.getComment()), + _alignment(other.getAlignment()), + _init_flag(true), + _level(other.getCreationLevel()) + { + cloneElements(other.getElements()); + } + + DDLComplex& DDLComplex::operator=(DDLComplex other) + { + swap(*this, other); + return *this; + } + + DDLComplex::DDLComplex(DDLComplex&& other) : DDLComplex() + { + swap(*this, other); + } + + DDLComplex::~DDLComplex() + { + std::transform(_ddl_elements.begin(), _ddl_elements.end(), + _ddl_elements.begin(), DDL::deleteChild); + _ddl_elements.clear(); + } + + a_util::result::Result DDLComplex::create(const std::string& name, + unsigned int const version, + const std::string& comment, + DDLAlignment::AlignmentType const alignment, + DDLElementVec ddl_elements, + int const creation_level) + { + if (name.empty()) + { + return ERR_INVALID_ARG; + } + _name = name; + _version = version; + _comment = comment; + _alignment = alignment; + cloneElements(ddl_elements); + _init_flag = true; + _level = creation_level; + _language_version = DDLVersion::getDefaultVersion(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLComplex::accept(IDDLVisitor *visitor) const + { + return visitor->visit(this); + } + a_util::result::Result DDLComplex::accept(IDDLChangeVisitor *visitor) + { + return visitor->visit(this); + } + + const std::string& DDLComplex::getName() const + { + return _name; + } + + void DDLComplex::setName(const std::string& name ) + { + _name = name; + } + + bool DDLComplex::isInitialized() const + { + return _init_flag; + } + + bool DDLComplex::isPredefined() const + { + return _level == -1; // cMediaManager::DL_Internal + } + + bool DDLComplex::isOverwriteable() const + { + return _level > 0; // cMediaManager::DL_AlwaysThere + } + + int DDLComplex::getCreationLevel() const + { + return _level; + } + + unsigned int DDLComplex::getVersion() const + { + return _version; + } + + void DDLComplex::setVersion(unsigned int const version) + { + _version = version; + } + + DDLVersion DDLComplex::getDDLVersion() const + { + return _language_version; + } + + a_util::result::Result DDLComplex::setDDLVersion(const DDLVersion& language_version) + { + _language_version = language_version; + return a_util::result::SUCCESS; + } + + void DDLComplex::setComment(const std::string& comment) + { + _comment = comment; + } + + std::string DDLComplex::getComment() const + { + return _comment; + } + + void DDLComplex::setAlignment(DDLAlignment::AlignmentType const alignment) + { + _alignment = alignment; + } + + DDLAlignment::AlignmentType DDLComplex::getAlignment() const + { + return _alignment; + } + + void DDLComplex::cloneElements(DDLElementVec ddl_elements) + { + std::transform(_ddl_elements.begin(), _ddl_elements.end(), _ddl_elements.begin(), DDLDescription::deleteChild); + _ddl_elements.clear(); + + _ddl_elements = ddl_elements; + std::transform(_ddl_elements.begin(), _ddl_elements.end(), _ddl_elements.begin(), DDLDescription::clone); + _dynamic_elements = false; + for (DDLElementIt itEl = _ddl_elements.begin(); itEl != _ddl_elements.end(); itEl++) + { + if ((*itEl)->isDynamic()) + { + _dynamic_elements = true; + break; + } + } + } + + void DDLComplex::setElements(DDLElementVec ddl_elements) + { + std::transform(_ddl_elements.begin(), _ddl_elements.end(), _ddl_elements.begin(), DDLDescription::deleteChild); + _ddl_elements.clear(); + + _ddl_elements = ddl_elements; + _dynamic_elements = false; + for (DDLElementIt itEl = _ddl_elements.begin(); itEl != _ddl_elements.end(); itEl++) + { + if ((*itEl)->isDynamic()) + { + _dynamic_elements = true; + break; + } + } + } + + void DDLComplex::addElement(DDLElement* element, int pos) + { + if (NULL != element) + { + const DDLElementVec::size_type size_pos = static_cast(pos); + if (0 <= size_pos && size_pos < _ddl_elements.size()) + { + _ddl_elements.insert(_ddl_elements.begin() + size_pos, element); + } + else + { + _ddl_elements.push_back(element); + } + if (!_dynamic_elements) + { + _dynamic_elements = element->isDynamic(); + } + } + } + + a_util::result::Result DDLComplex::removeElement(const std::string& element_name) + { + DDLElementIt it = _ddl_elements.begin(); + while (_ddl_elements.end() != it) + { + if ((*it)->getName() == element_name) + { + bool itHasDynArr = (*it)->isDynamic(); + DDLDescription::deleteChild(*it); + _ddl_elements.erase(it); + if (_dynamic_elements && itHasDynArr) + { + // We have to verify if the structure was dynamic only because of this element + _dynamic_elements = false; + for (DDLElementIt itEl = _ddl_elements.begin(); itEl != _ddl_elements.end(); itEl++) + { + if ((*itEl)->isDynamic()) + { + _dynamic_elements = true; + break; + } + } + } + return a_util::result::SUCCESS; + } + it++; + } + return ERR_NOT_FOUND; + } + + const DDLElementVec& DDLComplex::getElements() const + { + return _ddl_elements; + } + + DDLElementVec& DDLComplex::getElements() + { + return _ddl_elements; + } + + bool DDLComplex::hasDynamicElements() + { + return _dynamic_elements; + } + + void swap(DDLComplex& lhs, DDLComplex& rhs) noexcept + { + using std::swap; // ADL + swap(lhs._language_version, rhs._language_version); + swap(lhs._name, rhs._name); + swap(lhs._version, rhs._version); + swap(lhs._comment, rhs._comment); + swap(lhs._alignment, rhs._alignment); + swap(lhs._ddl_elements, rhs._ddl_elements); + swap(lhs._init_flag, rhs._init_flag); + swap(lhs._level, rhs._level); + swap(lhs._dynamic_elements, rhs._dynamic_elements); + } +} // namespace ddl diff --git a/ddlrepresentation/ddlcomplex.h b/ddlrepresentation/ddlcomplex.h new file mode 100644 index 0000000..5b9cef6 --- /dev/null +++ b/ddlrepresentation/ddlcomplex.h @@ -0,0 +1,275 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLCOMPLEX_H_INCLUDED +#define DDLCOMPLEX_H_INCLUDED + +#include "ddl_common.h" +#include "ddldatatype_intf.h" +#include "ddlvisitor_intf.h" +#include "ddl_type.h" +#include "ddlalignment.h" +#include "ddlversion.h" + +namespace ddl +{ + + class DDLElement; + class DDLAlignment; + + /** + * Container type of DDLElement objects + */ + typedef std::vector DDLElementVec; + /** + * Iterator type for DDLElementVec + */ + typedef DDLElementVec::iterator DDLElementIt; + /** + * Constant-iterator type for DDLElementVec + */ + typedef DDLElementVec::const_iterator DDLElementItConst; + + /** + * Representation for a complex datatype inside a DDL specification. + */ + class DDLComplex : public IDDLDataType + { + public: + /** + * Default CTOR + */ + DDLComplex(); + + /** + * CTOR + * @param[in] name - Name of the data type + * @param[in] version - Version number of the specified data type + * @param[in] comment - Additional comments (optional) + * @param[in] alignment - Alignment value (optional) + * @param[in] ddl_elements - Vector of sub elements (optional) + * @param[in] creation_level - Level at creation time (optional) + */ + DDLComplex(const std::string& name, + unsigned int const version, + const std::string& comment = a_util::strings::empty_string, + DDLAlignment::AlignmentType const alignment = DDLAlignment::e1, + DDLElementVec ddl_elements = DDLElementVec(), + int const creation_level = 1, + DDLVersion language_version = DDLVersion::getDefaultVersion()); + + /** + * Copy CTOR + * @param[in] other - Reference to complex datatype object to copy + */ + DDLComplex(const DDLComplex &other); + + /** + * Assignment operator (either copies or moves) + * @param[in] other Complex DDL type to copy from + * @return @c *this + */ + DDLComplex& operator=(DDLComplex other); + + /** + * Move CTOR + * @param[in,out] other Complex DDL type to move from - empty but valid when finished + */ + DDLComplex(DDLComplex&& other); + + /** + * DTOR + */ + virtual ~DDLComplex(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + const std::string& getName() const; + + /** + * Setter for the name of the complex datatype. + * @param [in] name - Name of the complex datatype + * + * @return void + */ + void setName(const std::string& name ); + + + bool isInitialized() const; + + bool isPredefined() const; + bool isOverwriteable() const; + + int getCreationLevel() const; + + /** + * Creation method to fill the object with data. + * @param[in] name - Name of the data type + * @param[in] version - Version number of the specified data type + * @param[in] comment - Additional comments (optional) + * @param[in] alignment - Alignment value (optional) + * @param[in] ddl_elements - Vector of sub elements (optional) + * @param[in] creation_level - Level at creation time (optional) + * @retval ERR_INVALID_ARG Empty name committed + */ + a_util::result::Result create(const std::string& name, + unsigned int const version, + const std::string& comment = a_util::strings::empty_string, + DDLAlignment::AlignmentType const alignment = DDLAlignment::e1, + DDLElementVec ddl_elements = DDLElementVec(), + int const creation_level = 1); + + /** + * Getter for the version. + * @return the version + */ + unsigned int getVersion() const; + + /** + * Setter for the version. + * @param version the version to set + * + * @return void + */ + void setVersion(unsigned int const version); + + /** + * Getter for the DDL version. + * @return the DDL version + */ + DDLVersion getDDLVersion() const; + + /** + * Setter for the DDL version. + * @param language_version the DDL version to set + * @return Standard result code. + * @retval a_util::result::SUCCESS + */ + a_util::result::Result setDDLVersion(const DDLVersion& language_version); + + /** + * Setter for the comment. + * @param[in] comment - Additional comments + * + * @return void + */ + void setComment(const std::string& comment); + + /** + * Getter for the comment. + * @return the comment + */ + std::string getComment() const; + + /** + * Setter for the alignment. + * @param[in] alignment - Alignment value + * + * @return void + */ + void setAlignment(DDLAlignment::AlignmentType const alignment); + + /** + * Setter for the element vector. + * @param[in] ddl_elements - Vector of elements + * + * @return void + */ + void cloneElements(DDLElementVec ddl_elements); + + /** + * Setter for the element vector. + * @param[in] ddl_elements - Vector of elements + * + * @return void + */ + void setElements(DDLElementVec ddl_elements); + + /** + * Adder for an element. + * @param[in] element - Pointer to the element to add + * @param[in] pos - Position to add the element + * + * @return void + */ + void addElement(DDLElement* element, int pos = -1); + + /** + * removal for an element. + * @param[in] element_name - name of the element to remove + * @retval ERR_NOT_FOUND if not found + */ + a_util::result::Result removeElement(const std::string& element_name); + + /** + * Getter for the elements. + * @return vector of the elements + */ + const DDLElementVec& getElements() const; + + /** + * Getter for the elements. + * @return vector of the elements + */ + DDLElementVec& getElements(); + + /** + * Getter for the boolean identifying dynamic elements. + * *Note*: this function is not recursive, so to identify structures containing + * structures with dynamic elements, you have to do the recursion yourself. + * @return true if dynamic elements were found + */ + bool hasDynamicElements(); + + /** + * Getter for the alignment of the complex datatype. + * @return the alignment + */ + DDLAlignment::AlignmentType getAlignment() const; + + bool isComplex() const + { + return true; + } + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLComplex& lhs, DDLComplex& rhs) noexcept; + + private: + /// The DDL Version this structure was created in + DDLVersion _language_version; + std::string _name; + unsigned int _version; + std::string _comment; + DDLAlignment::AlignmentType _alignment; + DDLElementVec _ddl_elements; + + bool _init_flag; + int _level; + bool _dynamic_elements; + }; + +} // namespace ddl + +#endif // _COMPLEX_H_INCLUDED_ diff --git a/ddlrepresentation/ddlcontainer.cpp b/ddlrepresentation/ddlcontainer.cpp new file mode 100644 index 0000000..4fc4d74 --- /dev/null +++ b/ddlrepresentation/ddlcontainer.cpp @@ -0,0 +1,445 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlcontainer.h" +#include "ddl_type.h" + +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" + +namespace ddl +{ + +template +struct LessCompare +{ + bool operator()(const T* obj1, const T* obj2) + { + return obj1->getName() < obj2->getName(); + } + + bool operator()(const T* obj, const std::string& name) + { + return obj->getName() < name; + } + + bool operator()(const std::string& name, const T* obj) + { + return name < obj->getName(); + } +}; + +template +DDLContainerNoClone::DDLContainerNoClone(bool sorted): _sorted(sorted) +{ +} + +template +void DDLContainerNoClone::insert(T* elem, int pos) +{ + if (_sorted) + { + _pointers.insert(std::lower_bound(_pointers.begin(), _pointers.end(), elem, LessCompare()), elem); + } + else + { + const typename std::vector::size_type sz_pos = + static_cast::size_type>(pos); + if (0 <= sz_pos && sz_pos < _pointers.size()) + { + _pointers.insert(_pointers.begin() + sz_pos, elem); + } + else + { + _pointers.push_back(elem); + } + } +} + +template +typename DDLContainerNoClone::iterator DDLContainerNoClone::findIt(const std::string& name) +{ + if (_sorted) + { + iterator it = std::lower_bound(this->begin(), this->end(), name, LessCompare()); + if (this->end() == it || name != (*it)->getName()) + { + // not found + return this->end(); + } + return it; + } + else + { + iterator it = std::find_if(this->begin(), this->end(), DDLCompareFunctor<>(name)); + if (this->end() == it) + { + // not found + return this->end(); + } + return it; + } +} + +template +const T* DDLContainerNoClone::find(const std::string& name) const +{ + if (_sorted) + { + return find_sorted(name); + } + return find_unsorted(name); +} + +template +T* DDLContainerNoClone::find(const std::string& name) +{ + if (_sorted) + { + return find_sorted(name); + } + return find_unsorted(name); +} + +template +const T* DDLContainerNoClone::find_unsorted(const std::string& name) const +{ + + const_iterator it = std::find_if(this->begin(), this->end(), DDLCompareFunctor<>(name)); + if (this->end() == it) + { + // not found + return NULL; + } + return *it; +} + +template +const T* DDLContainerNoClone::find_sorted(const std::string& name) const +{ + + const_iterator it = std::lower_bound(this->begin(), this->end(), name, LessCompare()); + if (this->end() == it || name != (*it)->getName()) + { + // not found + return find_unsorted(name); + } + return *it; +} + +template +T* DDLContainerNoClone::find_unsorted(const std::string& name) +{ + + iterator it = std::find_if(this->begin(), this->end(), DDLCompareFunctor<>(name)); + if (end() == it) + { + // not found + return NULL; + } + return *it; +} + +template +T* DDLContainerNoClone::find_sorted(const std::string& name) +{ + iterator it = std::lower_bound(this->begin(), this->end(), name, LessCompare()); + if (end() == it || name != (*it)->getName()) + { + // not found + auto obj = find_unsorted(name); + if (obj != nullptr) + { + sort(); + } + return obj; + } + return *it; +} + +template +void DDLContainerNoClone::copyFromRef(DDLContainerNoClone& other) +{ + _pointers.resize(other.size()); + std::copy(other.begin(), other.end(), _pointers.begin()); + if (_sorted && !other._sorted) + { + sort(); + } +} + + + +template +void DDLContainerNoClone::deleteAll() +{ + for (iterator it = begin(); it != end(); ++it) + { + DDL::deleteChild(*it); + } + clear(); +} + + template +void DDLContainerNoClone::sort() +{ + std::sort(_pointers.begin(), _pointers.end(), LessCompare()); +} + +template +bool DDLContainerNoClone::isSorted() const +{ + return _sorted; +} + +// Note on our iterators: +// we do not want to expose the std::vector and std::vector::iterator implementation to the user +// so we use the simplest kind of iterator, a pointer. +template +typename DDLContainerNoClone::iterator DDLContainerNoClone::begin() +{ +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + if (_pointers.empty()) + { + return &_empty_dummy; + } + else + { + return &*_pointers.begin(); + } +#else + return &*_pointers.begin(); +#endif +} + +template +typename DDLContainerNoClone::const_iterator DDLContainerNoClone::begin() const +{ +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + if (_pointers.empty()) + { + return &_empty_dummy; + } + else + { + return &*_pointers.begin(); + } +#else + return &*_pointers.begin(); +#endif +} + +template +typename DDLContainerNoClone::iterator DDLContainerNoClone::end() +{ +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + if (_pointers.empty()) + { + return &_empty_dummy; + } + else + { + return &*_pointers.begin() + _pointers.size(); + } +#else + return &*_pointers.end(); +#endif +} + +template +typename DDLContainerNoClone::const_iterator DDLContainerNoClone::end() const +{ +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + if (_pointers.empty()) + { + return &_empty_dummy; + } + else + { + return &*_pointers.begin() + _pointers.size(); + } +#else + return &*_pointers.end(); +#endif +} + +template +void DDLContainerNoClone::clear() +{ + _pointers.clear(); +} + +template +typename DDLContainerNoClone::iterator DDLContainerNoClone::erase(iterator it) +{ + typename std::vector::iterator it_helper = _pointers.erase(_pointers.begin() + (it - begin())); +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + if (it_helper == _pointers.end()) + { + return &_empty_dummy; + } + else + { + return &*it_helper; + } +#else + return &*it_helper; +#endif +} + +template +typename DDLContainerNoClone::iterator DDLContainerNoClone::erase(iterator pos_first, iterator pos_last) +{ + if (pos_first == pos_last) + { + return end(); + } + +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + // have a look at http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#464 and + // http://stackoverflow.com/questions/3829788/using-operator-on-empty-stdvector + // to find out the reason for this special implementation (VS2008 and lower) + + // another bug in MSVS Debug http://connect.microsoft.com/VisualStudio/feedback/details/557029/visual-c-iterator-debugging-incorrectly-raises-assertion-on-correct-use-of-return-value-of-std-vector-erase + // prevents us from using the erase(start, end) version. + typename std::vector::iterator it_helper = _pointers.begin() + (pos_first - begin()); + for (uint64_t nCount = pos_last - pos_first; nCount > 0; --nCount) + { + it_helper = _pointers.erase(it_helper); + } + + if (it_helper == _pointers.end()) + { + return &_empty_dummy; + } + else + { + return &*it_helper; + } +#else + typename std::vector::iterator it_helper = _pointers.erase(_pointers.begin() + (pos_first - begin()), + _pointers.begin() + (pos_last - begin())); + return &*it_helper; +#endif +} + +template +bool DDLContainerNoClone::empty() const +{ + return _pointers.empty(); +} + +template +unsigned int DDLContainerNoClone::size() const +{ + return static_cast(_pointers.size()); +} + +template +T*& DDLContainerNoClone::operator[] (unsigned int pos) +{ + return _pointers[pos]; +} + +template +T* const& DDLContainerNoClone::operator[] (unsigned int pos) const +{ + return _pointers[pos]; +} + +template +T*& DDLContainerNoClone::at(unsigned int pos) +{ + return _pointers.at(pos); +} + +template +T* const& DDLContainerNoClone::at(unsigned int pos) const +{ + return _pointers.at(pos); +} + +template +DDLContainer::DDLContainer(bool sorted): DDLContainerNoClone(sorted) +{ +} + +template +void DDLContainer::cloneFrom(const DDLContainer& other) +{ + this->clear(); + for (typename DDLContainer::const_iterator it = other.begin(); it != other.end(); ++it) + { + this->insert(DDL::clone(*it)); + } +} + +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; +template class DDLContainerNoClone; + +#if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) +IDDL* DDLContainerNoClone::_empty_dummy = NULL; +DDLUnit* DDLContainerNoClone::_empty_dummy = NULL; +DDLBaseunit* DDLContainerNoClone::_empty_dummy = NULL; +DDLPrefix* DDLContainerNoClone::_empty_dummy = NULL; +DDLDataType* DDLContainerNoClone::_empty_dummy = NULL; +DDLEnum* DDLContainerNoClone::_empty_dummy = NULL; +DDLComplex* DDLContainerNoClone::_empty_dummy = NULL; +DDLStream* DDLContainerNoClone::_empty_dummy = NULL; +DDLStreamMetaType* DDLContainerNoClone::_empty_dummy = NULL; +#endif + +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; +template class DDLContainer; + +} diff --git a/ddlrepresentation/ddlcontainer.h b/ddlrepresentation/ddlcontainer.h new file mode 100644 index 0000000..cb7123c --- /dev/null +++ b/ddlrepresentation/ddlcontainer.h @@ -0,0 +1,335 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_CONTAINER_H_INCLUDED +#define DDL_CONTAINER_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_intf.h" + +namespace ddl +{ + class DDLUnit; + class DDLBaseunit; + class DDLPrefix; + class DDLDataType; + class DDLEnum; + class DDLComplex; + class DDLStream; + class DDLStreamMetaType; + +/** + * Utility class that stores DDL entities + */ +template +class DDLContainerNoClone +{ + private: + std::vector _pointers; + bool _sorted; + + #if defined(WIN32) && ((_MSC_VER < 1600) || defined(_DEBUG)) + static T* _empty_dummy; + #endif + + public: + + ///iterator for DDL container + typedef T** iterator; // NOLINT + + ///const iterator for DDL container + typedef T* const * const_iterator; // NOLINT + + public: + + /** + * Constructor + * @param [in] sorted whether the items should be sorted by name (this improves access times) + */ + DDLContainerNoClone(bool sorted = true); + + /** + * @brief insert + * @param [in] elem The element to insert. + * @param [in] pos Position to add the element + * @return void + */ + void insert(T* elem, int pos = -1); + + /** + * Finds an element by name + * @param [in] name + * @return pointer to the element or NULL + */ + T* find(const std::string& name); + + /** + * Finds an element by name + * @param [in] name + * @return iterator to the element or end() + */ + iterator findIt(const std::string& name); + + /** + * Finds an element by name + * @param [in] name + * @return pointer to the element or NULL + */ + const T* find(const std::string& name) const; + + /** + * Copies the pointers from the other container. + * @param [in] other Thge other container + * @return void + */ + void copyFromRef(DDLContainerNoClone &other); + + /** + * Deletes all stored items (by calling delete on the pointers) + */ + void deleteAll(); + + /** + * sort the items by name. + */ + void sort(); + + /** + * Returns Whether or not the container is sorted by name or not. + * @return whether or not the container is sorted by name or not. + */ + bool isSorted() const; + + /** + * Returns an iterator to the first element. + * @return an iterator to the first element. + */ + iterator begin(); + + /** + * Returns an iterator to the first element. + * @return an iterator to the first element. + */ + const_iterator begin() const; + + /** + * Returns an iterator to the element after the last element. + * @return an iterator to the element after the last element. + */ + iterator end(); + + /** + * Returns an iterator to the element after the last element. + * @return an iterator to the element after the last element. + */ + const_iterator end() const; + + /** + * clears the container (does not destroy the elements) + */ + void clear(); + + /** + * removes an element from the container + * @param [in] pos The element which should be removed. + * @return iterator to the element after the erased element. + */ + iterator erase(iterator pos); + + /** + * @brief removes a sequence of elements from the container + * @param pos_first the first element to erase. + * @param pos_last the first one that should not be erased. + * @return iterator to the element after the erased elements. + */ + iterator erase(iterator pos_first, iterator pos_last); + + /** + * Returns whether the container is empty or not. + * @return whether the container is empty or not. + */ + bool empty() const; + + /** + * Returns the size of the container. + * @return the size of the container. + */ + unsigned int size() const; // for compatibility reasons + + /** + * random access operator. + * @param [in] pos The index of the element. + * @return The element. + */ + T*& operator[] (unsigned int pos); + + /** + * random access operator. + * @param [in] pos The index of the element. + * @return The element. + */ + T* const& operator[] (unsigned int pos) const; + + /** + * random access method. + * @param [in] pos The index of the element. + * @return The element. + */ + T*& at(unsigned int pos); + + /** + * random access method. + * @param [in] pos The index of the element. + * @return The element. + */ + T* const& at(unsigned int pos) const; + + private: + /** + * Finds an sorted element by name + * @param [in] name + * @return pointer to the element or NULL + */ + T* find_sorted(const std::string& name); + + /** + * Finds an sorted element by name + * @param [in] name + * @return pointer to the element or NULL + */ + const T* find_sorted(const std::string& name) const; + + + /** + * Finds an unsorted element by name + * @param [in] name + * @return pointer to the element or NULL + */ + T* find_unsorted(const std::string& name); + + /** + * Finds an unsorted element by name + * @param [in] name + * @return pointer to the element or NULL + */ + const T* find_unsorted(const std::string& name) const; +}; + +/** + * Utility class to store DDL elements that can be cloned. + */ +template +class DDLContainer: public DDLContainerNoClone +{ + public: + /** + * Constructor + * @param [in] sorted Whether the container shall be sorted by name or not. + */ + DDLContainer(bool sorted = true); + + /** + * Clones all elements of a given container. + * @param [in] other the container that should be cloned. + * @return void + */ + void cloneFrom(const DDLContainer& other); +}; + +/** + * Container type of basic DDL objects + */ +typedef DDLContainerNoClone DDLVec; + +/** + * Container type of DDLUnit objects + */ +typedef DDLContainer DDLUnitVec; +/** + * Container type of DDLBaseunit objects + */ +typedef DDLContainer DDLBaseunitVec; +/** + * Container type of DDLPrefix objects + */ +typedef DDLContainer DDLPrefixVec; +/** + * Container type of DDLDataType objects + */ +typedef DDLContainer DDLDTVec; +/** + * Container type of DDLEnum objects + */ +typedef DDLContainer DDLEnumVec; +/** + * Container type of DDLComplex objects + */ +typedef DDLContainer DDLComplexVec; +/** + * Container type of DDLStream objects + */ +typedef DDLContainer DDLStreamVec; +/** + * Container type of DDLStreamMetaType objects + */ +typedef DDLContainer DDLStreamMetaTypeVec; + +/** + * Iterator type for DDLUnitVec + */ +typedef DDLUnitVec::iterator DDLUnitIt; +/** + * Iterator type for DDLBaseunitVec + */ +typedef DDLBaseunitVec::iterator DDLBaseunitIt; +/** + * Iterator type for DDLPrefixVec + */ +typedef DDLPrefixVec::iterator DDLPrefixIt; +/** + * Iterator type for DDLDTVec + */ +typedef DDLDTVec::iterator DDLDTIt; +/** + * Iterator type for tDDLConstVec + */ +typedef DDLEnumVec::iterator DDLEnumIt; +/** + * Iterator type for DDLComplexVec + */ +typedef DDLComplexVec::iterator DDLComplexIt; +/** + * Iterator type for DDLStreamVec + */ +typedef DDLStreamVec::iterator DDLStreamIt; + +/** + * Associative container type for DDLStream objects + */ +typedef std::map DDLStreamMap; + +/** + * Iterator type for DDLStreamMap + */ +typedef DDLStreamMap::iterator DDLStreamMapIt; + +} + +#endif + diff --git a/ddlrepresentation/ddldatatype.cpp b/ddlrepresentation/ddldatatype.cpp new file mode 100644 index 0000000..6fb826b --- /dev/null +++ b/ddlrepresentation/ddldatatype.cpp @@ -0,0 +1,300 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddldatatype.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + + DDLDataType::DDLDataType() : + _language_version{DDLVersion::ddl_version_invalid}, + _name{}, + _num_bits{}, + _byte_size{}, + _aligned_size{}, + _unit{}, + _description{}, + _array_size{}, + _array_size_source{}, + _alignment{}, + _init_flag{}, + _level{1}, + _min_valid{}, + _min_val{}, + _max_valid{}, + _max_val{}, + _default_valid{}, + _default_val{} + { + } + + DDLDataType::DDLDataType(const std::string& name, + unsigned int const num_bits, + IDDLUnit* unit, + const std::string& description, + DDLAlignment::AlignmentType const alignment, + unsigned int const array_size, + int const creation_level, + const std::string& array_size_source, + bool const min_valid, + const std::string& min_value, + bool const max_valid, + const std::string& max_value) : + _language_version(DDLVersion::ddl_version_invalid), + _name(name), + _num_bits(num_bits), + _unit(unit), + _description(description), + _array_size(array_size), + _array_size_source(array_size_source), + _alignment(alignment), + _init_flag(true), + _level(creation_level), + _min_valid(min_valid), + _min_val(min_value), + _max_valid(max_valid), + _max_val(max_value) + { + } + + a_util::result::Result DDLDataType::accept(IDDLVisitor *visitor) const + { + return visitor->visit(this); + } + + a_util::result::Result DDLDataType::accept(IDDLChangeVisitor *visitor) + { + return visitor->visit(this); + } + + const std::string& DDLDataType::getName() const + { + return _name; + } + + void DDLDataType::setName(const std::string& name) + { + _name = name; + } + + bool DDLDataType::isInitialized() const + { + return _init_flag; + } + + int DDLDataType::getCreationLevel() const + { + return _level; + } + + a_util::result::Result DDLDataType::create(const std::string& name, + unsigned int const num_bits, + IDDLUnit* unit, + const std::string& description, + DDLAlignment::AlignmentType const alignment, + unsigned int const array_size, + int const creation_level, + const std::string& array_size_source, + bool const min_valid, + const std::string& min_value, + bool const max_valid, + const std::string& max_value) + { + if (!unit) { return ERR_POINTER; } + _name = name; + _num_bits = num_bits; + _unit = unit; + _description = description; + _array_size = array_size; + _init_flag = true; + _level = creation_level; + _alignment = alignment; + _array_size_source = array_size_source; + _language_version = DDLVersion::ddl_version_invalid; + _min_valid = min_valid; + _min_val = min_value; + _max_valid = max_valid; + _max_val = max_value; + return a_util::result::SUCCESS; + } + + unsigned int DDLDataType::getNumBits() const + { + return _num_bits; + } + + void DDLDataType::setNumBits(unsigned int const num_bits) + { + _num_bits = num_bits; + } + + void DDLDataType::setDescription(const std::string& description) + { + _description = description; + } + + std::string DDLDataType::getDescription() const + { + return _description; + } + + void DDLDataType::setArraysize(unsigned int const array_size) + { + if (array_size > 0) + { + _array_size = array_size; + } + } + + unsigned int DDLDataType::getArraysize() const + { + return _array_size; + } + + void DDLDataType::setUnit(IDDLUnit* unit) + { + _unit = unit; + } + + std::string DDLDataType::getUnit() const + { + if (NULL == _unit) + { + return a_util::strings::empty_string; + } + return _unit->getName(); + } + + const IDDLUnit* DDLDataType::getUnitObject() const + { + if (!_init_flag) + { + return NULL; + } + return _unit; + } + + IDDLUnit* DDLDataType::getUnitObject() + { + if (!_init_flag) + { + return NULL; + } + return _unit; + } + + bool DDLDataType::isPredefined() const + { + return _level == -1; // cMediaManager::DL_AlwaysThere + } + + bool DDLDataType::isOverwriteable() const + { + return _level > 0; + } + + void DDLDataType::setAlignment(DDLAlignment::AlignmentType const alignment) + { + _alignment = alignment; + } + + DDLAlignment::AlignmentType DDLDataType::getAlignment() const + { + return _alignment; + } + + std::string DDLDataType::getArraySizeSource() const + { + return _array_size_source; + } + + void DDLDataType::setArraySizeSource( const std::string& array_size_source ) + { + _array_size_source = array_size_source; + } + + bool DDLDataType::isDynamic() const + { + if (getArraysize() == 0 || + (!getArraySizeSource().empty() && !a_util::strings::isInt64(getArraySizeSource()))) + { + return true; + } + + return false; + } + + DDLVersion DDLDataType::getDDLVersion() const + { + return _language_version; + } + + a_util::result::Result DDLDataType::setDDLVersion(DDLVersion& language_version) + { + _language_version = language_version; + return a_util::result::SUCCESS; + } + + const std::string & DDLDataType::getMinValue () const + { + return _min_val; + } + + a_util::result::Result DDLDataType::setMinValue (const std::string& min_value) + { + // TODO validate new min value + _min_val = min_value; + return a_util::result::SUCCESS; + } + + const std::string & DDLDataType::getMaxValue () const + { + return _max_val; + } + + a_util::result::Result DDLDataType::setMaxValue (const std::string& max_value) + { + // TODO validate new max value + _max_val = max_value; + return a_util::result::SUCCESS; + } + + void DDLDataType::setMinValidity (bool const min_valid) + { + _min_valid = min_valid; + } + + bool DDLDataType::isMinValid () const + { + return _min_valid; + } + + void DDLDataType::setMaxValidity (bool const max_valid) + { + _max_valid = max_valid; + } + + bool DDLDataType::isMaxValid () const + { + return _max_valid; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddldatatype.h b/ddlrepresentation/ddldatatype.h new file mode 100644 index 0000000..1a1e598 --- /dev/null +++ b/ddlrepresentation/ddldatatype.h @@ -0,0 +1,330 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLDATATYPE_H_INCLUDED +#define DDLDATATYPE_H_INCLUDED + +#include "ddl_common.h" +#include "ddldatatype_intf.h" +#include "ddlvisitor_intf.h" +#include "ddlunit_intf.h" +#include "ddlalignment.h" +#include "ddlversion.h" + +namespace ddl +{ + + /** + * Representation for a (simple) data type inside a DDL description. + */ + class DDLDataType : public IDDLDataType + { + public: + /** + * Default CTOR + */ + DDLDataType(); + + /** + * CTOR + * @param[in] name - Name of the primitive data type + * @param[in] size - Size in bit + * @param[in] unit - Pointer to the unit of the data type (optional) + * @param[in] description - Description of the primitive data type (optional) + * @param[in] alignment - Alignment of the primitive data type (optional) + * @param[in] array_size - Array size of the primitive data type (optional) + * @param[in] creation_level - Level at creation time (optional) + * @param[in] array_size_source - Name of the element that represents + * the arrays size (optional) + * @param [in] min_valid - Validity flag for the minimum value (optional) + * @param[in] min_val - Minimum value of the data type (optional) + * @param [in] max_valid - Validity flag for the maximum value (optional) + * @param[in] max_val - Maximum value of the data type (optional) + */ + DDLDataType(const std::string& name, + unsigned int const size, + IDDLUnit* unit = NULL, + const std::string& description = a_util::strings::empty_string, + DDLAlignment::AlignmentType const alignment = DDLAlignment::e1, + unsigned int const array_size = 1, + int const creation_level = 1, + const std::string& array_size_source = a_util::strings::empty_string, + bool const min_valid = false, + const std::string& min_val = a_util::strings::empty_string, + bool const max_valid = false, + const std::string& max_val = a_util::strings::empty_string); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isPredefined() const; + bool isOverwriteable() const; + + const std::string& getName() const; + + /** + * Setter for the name of the data type. + * @param [in] name Name of the data type + * + * @return void + */ + void setName(const std::string& name); + int getCreationLevel() const; + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] name - Name of the primitive data type + * @param[in] size - Size in bit + * @param[in] unit - Pointer to the unit of the data type + * @param[in] description - Description of the primitive data type (optional) + * @param[in] alignment - Alignment of the primitive data type (optional) + * @param[in] array_size - Array size of the primitive data type (optional) + * @param[in] creation_level - Level at creation time (optional) + * @param[in] array_size_source - Name of the element that represents the arrays size + * @param [in] min_valid - Validity flag for the minimum value (optional) + * @param[in] min_val - Minimum value of the data type (optional) + * @param [in] max_valid - Validity flag for the maximum value (optional) + * @param[in] max_val - Maximum value of the data type (optional) + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(const std::string& name, + unsigned int const size, + IDDLUnit* unit = NULL, + const std::string& description = a_util::strings::empty_string, + DDLAlignment::AlignmentType const alignment = DDLAlignment::e1, + unsigned int const array_size = 1, + int const creation_level = 1, + const std::string& array_size_source = a_util::strings::empty_string, + bool const min_valid = false, + const std::string& min_val = a_util::strings::empty_string, + bool const max_valid = false, + const std::string& max_val = a_util::strings::empty_string); + + + /** + * Setter for the description. + * @param[in] description - Description of the primitive data type + * + * @return void + */ + void setDescription(const std::string& description); + + /** + * Getter for the description. + * @return the description + */ + std::string getDescription() const; + + /** + * Setter for the array size. + * @param[in] array_size - Array size of the data type
+ * = 1 -> primitve presentation
\> 1 -> array with the amount of elements + * + * @return void + */ + void setArraysize(unsigned int const array_size); + + /** + * Getter for the array size. + * @return the array size + */ + unsigned int getArraysize() const; + + /** + * Setter for the unit. + * @param[in] unit - Pointer to the unit object of the data type + * + * @return void + */ + void setUnit(IDDLUnit* unit); + + /** + * Getter for the unit name. + * @return name of the referenced unit (\c a_util::strings::empty_string if there is none) + */ + std::string getUnit() const; + + /** + * Getter for the unit object. + * @return pointer to the unit object (\c NULL if there is none) + */ + const IDDLUnit * getUnitObject() const; + + /** + * Getter for the unit object. + * @return pointer to the unit object (\c NULL if there is none) + */ + IDDLUnit * getUnitObject(); + + /** + * Setter for the alignment. + * @param[in] alignment - Alignment value + * + * @return void + */ + void setAlignment(DDLAlignment::AlignmentType const alignment); + + /** + * Getter for the alignment of the primitive data type. + * @return the alignment + */ + DDLAlignment::AlignmentType getAlignment() const; + + /** + * Getter for the size of the primitive data type. + * @return the size in [bit] + */ + unsigned int getNumBits() const; + + /** + * Setter for the size of the primitive data type. + * @param [in] num_bits - Size in [bit] + * + * @return void + */ + void setNumBits(unsigned int const num_bits); + + /** + * Getter for the array size source. + * @return the array size source + */ + std::string getArraySizeSource() const; + + /** + * Setter for the array size source. + * @param[in] array_size_source - the array size source element + * + * @return void + */ + void setArraySizeSource(const std::string& array_size_source); + + /** + * Checks if element is dynamic + * @return true if it is a dynamic array + */ + bool isDynamic() const; + + /** + * Getter for the DDL version. + * @return the DDL version + */ + DDLVersion getDDLVersion() const; + + /** + * Setter for the DDL version. + * @param language_version the DDL version to set + * @return Standard result code. + * @retval a_util::result::SUCCESS Everything is fine. + */ + a_util::result::Result setDDLVersion(DDLVersion& language_version); + + /** + * Setter for the validity flag for the minimum value. + * + * @param [in] min_valid Validity flag for the minimum value. + * + * @return void + */ + void setMinValidity (bool const min_valid); + + /** + * Getter for the validity flag for the minimum value. + * + * @return the validity flag for the minimum value + */ + bool isMinValid () const; + + /** + * Getter for the minimum value of the data type. + * + * @return the minimum value + */ + const std::string &getMinValue () const; + + /** + * Setter for the minimum value of the data type. + * + * @param [in] min_val The new minimum value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setMinValue (const std::string& min_val); + + /** + * Setter for the validity flag for the maximum value. + * + * @param [in] max_valid Validity flag for the maximum value. + * + * @return void + */ + void setMaxValidity (bool const max_valid); + + /** + * Getter for the validity flag for the maximum value. + * + * @return the validity flag for the maximum value + */ + bool isMaxValid () const; + + /** + * Getter for the maximum value of the data type. + * + * @return the maximum value + */ + const std::string &getMaxValue () const; + + /** + * Setter for the maximum value of the data type. + * + * @param [in] max_val The new maximum value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setMaxValue (const std::string& max_val); + + + private: // members + /// The DDL Version this structure was created in + DDLVersion _language_version; + std::string _name; + unsigned int _num_bits; + size_t _byte_size; + size_t _aligned_size; + IDDLUnit* _unit; + std::string _description; + unsigned int _array_size; + std::string _array_size_source; + DDLAlignment::AlignmentType _alignment; + + bool _init_flag; + int _level; + + bool _min_valid; + std::string _min_val; + bool _max_valid; + std::string _max_val; + bool _default_valid; + std::string _default_val; + }; + +} // namespace ddl + +#endif // DDLDATATYPE_H_INCLUDED diff --git a/ddlrepresentation/ddldatatype_intf.h b/ddlrepresentation/ddldatatype_intf.h new file mode 100644 index 0000000..890f9af --- /dev/null +++ b/ddlrepresentation/ddldatatype_intf.h @@ -0,0 +1,45 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLDATATYPE_INTF_H_INCLUDED +#define DDLDATATYPE_INTF_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_intf.h" + +namespace ddl +{ + class DDLAlignment; + + /** + * Common interface for DDL datatypes. + */ + class IDDLDataType : public IDDL + { + public: + + /** + * Virtual DTOR + */ + virtual ~IDDLDataType(){} + }; + +} // namespace ddl + +#endif // _DATATYPE_INTF_H_INCLUDED_ diff --git a/ddlrepresentation/ddldescription.cpp b/ddlrepresentation/ddldescription.cpp new file mode 100644 index 0000000..788d360 --- /dev/null +++ b/ddlrepresentation/ddldescription.cpp @@ -0,0 +1,1613 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include // std::swap +#include +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" +#include "ddldescription.h" +#include "ddlversion.h" +#include "ddlalignment.h" +#include "ddldatatype.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddlenum.h" +#include "ddlheader.h" +#include "ddlrefunit.h" +#include "ddlstreammetatype.h" +#include "ddlunit.h" +#include "ddlcomplex.h" +#include "ddlrepair.h" +#include "ddlstream.h" +#include "ddlinspector.h" + + +#ifndef WIN32 +// only necessary on Linux platforms, on Windows defined inside MSVC +#include +#include +#endif + +/// XML header for the data definition language description file +#define DESCRPTIONFILE_HEADER_DDL1_DEFAULT_IMPORTER "\n \ + \n \ +
\ + 1.02\n \ + \n \ + \n \ + \n \ + ADTF generated\n \ +
\n \ + \n\ + \n\ + \n\ + \n\ +
" + +#define DESCRPTIONFILE_HEADER_DDL2_DEFAULT_IMPORTER "\n \ + \n \ +
\ + 2.00\n \ + \n \ + \n \ + \n \ + ADTF generated\n \ +
\n \ + \n\ + \n\ + \n\ + \n\ + \n\ +
" + +#define DESCRPTIONFILE_HEADER_DDL3_DEFAULT_IMPORTER "\n \ + \n \ +
\ + 3.00\n \ + \n \ + \n \ + \n \ + ADTF generated\n \ +
\n \ + \n\ + \n\ + \n\ + \n\ + \n\ +
" + +#define DESCRPTIONFILE_HEADER_DDL4_DEFAULT_IMPORTER "\n \ + \n \ +
\ + 4.00\n \ + \n \ + \n \ + \n \ + ADTF generated\n \ +
\n \ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ +
" + +#define DESCRPTIONFILE_HEADER_DDLNEWST_DEFAULT_IMPORTER DESCRPTIONFILE_HEADER_DDL4_DEFAULT_IMPORTER + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + class DDLDefault + { + private: + explicit DDLDefault(DDLVersion version, bool bSorted): + m_aoPredefDTs(bSorted), + m_aoPredefBUs(bSorted), + m_aoPredefPrefixes(bSorted), + m_aoPredefEnums(bSorted), + _version(version) + { + initialize(); + }; + void initialize() + { + // Make sure this instance is only initialized once + +#if defined(WIN32) && _MSC_VER < 1900 + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif + m_aoPredefDTs.insert(new DDLDataType("tBool", 8, NULL, + "predefined ADTF tBool datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, "tFalse", true, "tTrue")); + m_aoPredefDTs.insert(new DDLDataType("tChar", 8, NULL, + "predefined ADTF tChar datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, + a_util::strings::toString((int8_t)std::numeric_limits::min()), true, + a_util::strings::toString((int8_t)std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tUInt8", 8, NULL, + "predefined ADTF tUInt8 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, "0", true, + a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tInt8", 8, NULL, + "predefined ADTF tInt8 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, + a_util::strings::toString(std::numeric_limits::min()), + true, a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tUInt16", 16, NULL, + "predefined ADTF tUInt16 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, "0", true, + a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tInt16", 16, NULL, + "predefined ADTF tInt16 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, + a_util::strings::toString(std::numeric_limits::min()), + true, a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tUInt32", 32, NULL, + "predefined ADTF tUInt32 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, "0", true, + a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tInt32", 32, NULL, + "predefined ADTF tInt32 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, + a_util::strings::toString(std::numeric_limits::min()), + true, a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tUInt64", 64, NULL, + "predefined ADTF tUInt64 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, "0", true, + a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tInt64", 64, NULL, + "predefined ADTF tInt64 datatype", DDLAlignment::e1, 1, + -1, a_util::strings::empty_string, true, + a_util::strings::toString(std::numeric_limits::min()), + true, a_util::strings::toString(std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tFloat32", 32, + NULL, "predefined ADTF tFloat32 datatype", + DDLAlignment::e1, 1, -1, a_util::strings::empty_string, true, + a_util::strings::format("%e", -std::numeric_limits::max()), true, + a_util::strings::format("%e", std::numeric_limits::max()))); + m_aoPredefDTs.insert(new DDLDataType("tFloat64", 64, + NULL, "predefined ADTF tFloat64 datatype", + DDLAlignment::e1, 1, -1, a_util::strings::empty_string, true, + a_util::strings::format("%e", -std::numeric_limits::max()), true, + a_util::strings::format("%e", std::numeric_limits::max()))); + + for (DDLDTVec::iterator pIter = m_aoPredefDTs.begin(); + pIter != m_aoPredefDTs.end(); pIter++) + { + (*pIter)->setDDLVersion(_version); + } + + m_aoPredefBUs.insert(new DDLBaseunit("Metre", "m", + "Fundamental unit for length", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Kilogram", "kg", + "Fundamental unit for mass", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Second", "s", + "Fundamental unit for time", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Ampere", "A", + "Fundamental unit for electric current", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Kelvin", "K", + "Fundamental unit for thermodynamic temperature", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Mole", "mol", + "Fundamental unit for amount of substance", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Candela", "cd", + "Fundamental unit for luminous intensity", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Degree", "deg", + "Non-SI standard unit for angle", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Radiant", "rad", + "Non-SI standard unit for angle", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("Unitless", "", + "No SI, but needed for own unit definitions", -1)); + m_aoPredefBUs.insert(new DDLBaseunit("nou", "", + "No SI, but needed for no unit definitions", -1)); + + m_aoPredefPrefixes.insert(new DDLPrefix("yotta", "Y", + 24, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("zetta", "Z", + 21, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("exa", "E", 18, + -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("peta", "P", + 15, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("tera", "T", + 12, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("giga", "G", 9, + -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("mega", "M", 6, + -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("kilo", "k", 3, + -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("hecto", "h", + 2, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("deca", "da", + 1, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("deci", "d", + -1, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("centi", "c", + -2, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("milli", "m", + -3, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("micro", "u", + -6, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("nano", "n", + -9, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("pico", "p", + -12, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("femto", "f", + -15, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("atto", "a", + -18, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("zepto", "z", + -21, -1)); + m_aoPredefPrefixes.insert(new DDLPrefix("yocto", "y", + -24, -1)); + + EnumNameValueVec vecEnumValuesBitmap; + vecEnumValuesBitmap.push_back(std::make_pair("PF_16BIT", "20")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_24BIT", "40")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_32BIT", "50")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_8BIT", "10")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_ABGR_4444", "29")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_ABGR_8888", "52")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_ARGB_8888", "51")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_BGRA_8888", "54")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_BGR_555", "34")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_BGR_565", "35")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_BGR_888", "46")); + + vecEnumValuesBitmap.push_back(std::make_pair("PF_CUSTOM", "1000")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_10", "21")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_12", "22")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_14", "23")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_16", "24")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_18", "41")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_20", "42")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_22", "43")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_24", "44")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_32", "55")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_8", "11")); + + vecEnumValuesBitmap.push_back(std::make_pair("PF_GREYSCALE_FLOAT32", "56")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGBA_4444", "28")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGBA_8888", "53")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGB_444", "25")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGB_555", "26")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGB_565", "27")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGB_8", "12")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RGB_888", "45")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RIII_10", "30")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RIII_12", "31")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_RIII_14", "32")); + + vecEnumValuesBitmap.push_back(std::make_pair("PF_RIII_16", "33")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_UNKNOWN", "0")); + vecEnumValuesBitmap.push_back(std::make_pair("PF_YUV420P_888", "60")); + + DDLEnum* pBitmapTypeEnum = new DDLEnum(m_aoPredefDTs.find("tInt16"), + "tPixelFormat", vecEnumValuesBitmap, NULL, -1); + m_aoPredefEnums.insert(pBitmapTypeEnum); + } + virtual ~DDLDefault() + { + + for (DDLEnumVec::iterator it = m_aoPredefEnums.begin(); + it != m_aoPredefEnums.end(); ++it) + { + delete (*it); + } + + m_aoPredefEnums.clear(); + + for (DDLDTIt oItDT = m_aoPredefDTs.begin(); + oItDT != m_aoPredefDTs.end(); + ++oItDT) + { + delete (*oItDT); + } + m_aoPredefDTs.clear(); + + for (DDLBaseunitIt oItBU = m_aoPredefBUs.begin(); + oItBU != m_aoPredefBUs.end(); + ++oItBU) + { + delete (*oItBU); + } + m_aoPredefBUs.clear(); + + for (DDLPrefixIt oItPref = m_aoPredefPrefixes.begin(); + oItPref != m_aoPredefPrefixes.end(); + ++oItPref) + { + delete (*oItPref); + } + m_aoPredefPrefixes.clear(); + }; + + public: + static const DDLDefault* getInstance(DDLVersion& language_version, bool bSorted) + { + static const DDLDefault m_gDefaultDDL_v10(DDLVersion::ddl_version_10, false); + static const DDLDefault m_gDefaultDDL_v20(DDLVersion::ddl_version_20, false); + static const DDLDefault m_gDefaultDDL_v30(DDLVersion::ddl_version_30, false); + static const DDLDefault m_gDefaultDDL_v40(DDLVersion::ddl_version_40, false); + + static const DDLDefault m_gDefaultDDL_v10_sorted(DDLVersion::ddl_version_10, true); + static const DDLDefault m_gDefaultDDL_v20_sorted(DDLVersion::ddl_version_20, true); + static const DDLDefault m_gDefaultDDL_v30_sorted(DDLVersion::ddl_version_30, true); + static const DDLDefault m_gDefaultDDL_v40_sorted(DDLVersion::ddl_version_40, true); + + if (bSorted) + { + if (DDLVersion::ddl_version_20 > language_version) + { + return &m_gDefaultDDL_v10_sorted; + } + else if (DDLVersion::ddl_version_20 <= language_version && DDLVersion::ddl_version_30 > language_version) + { + return &m_gDefaultDDL_v20_sorted; + } + else if (DDLVersion::ddl_version_30 <= language_version && DDLVersion::ddl_version_40 > language_version) + { + return &m_gDefaultDDL_v30_sorted; + } + else + { + return &m_gDefaultDDL_v40_sorted; + } + } + else + { + if (DDLVersion::ddl_version_20 > language_version) + { + return &m_gDefaultDDL_v10; + } + else if (DDLVersion::ddl_version_20 <= language_version && DDLVersion::ddl_version_30 > language_version) + { + return &m_gDefaultDDL_v20; + } + else if (DDLVersion::ddl_version_30 <= language_version && DDLVersion::ddl_version_40 > language_version) + { + return &m_gDefaultDDL_v30; + } + else + { + return &m_gDefaultDDL_v40; + } + } + } + + + + const DDLDTVec& GetDefaultDTs() const + { + return m_aoPredefDTs; + } + + const DDLBaseunitVec& GetDefaultBaseunits() const + { + return m_aoPredefBUs; + } + + const DDLPrefixVec& GetDefaultPrefixes() const + { + return m_aoPredefPrefixes; + } + + const DDLEnumVec& GetDefaultEnums() const + { + return m_aoPredefEnums; + } + + + public: + DDLDTVec m_aoPredefDTs; + DDLBaseunitVec m_aoPredefBUs; + DDLPrefixVec m_aoPredefPrefixes; + DDLEnumVec m_aoPredefEnums; + DDLVersion _version; + }; + + + DDLDescription::DDLDescription(DDLHeader* poHeader, + const DDLUnitVec &vecDDLUnits, + const DDLBaseunitVec &vecDDLBaseunits, + const DDLPrefixVec &vecDDLPrefixes, + const DDLDTVec &vecDTs, + const DDLComplexVec &vecStructs, + const DDLStreamVec &vecStreams, + const DDLEnumVec &vecEnums, + bool bMergeDefaults) : + _header(poHeader), + _units(vecDDLUnits.isSorted()), + _baseunits(vecDDLBaseunits.isSorted()), + _prefixes(vecDDLPrefixes.isSorted()), + _data_types(vecDTs.isSorted()), + _enums(vecEnums.isSorted()), + _structs(vecStructs.isSorted()), + _streams(vecStreams.isSorted()), + _merge_defaults(bMergeDefaults) + { + _init_flag = (NULL != poHeader); + cloneBaseunits(vecDDLBaseunits); + clonePrefixes(vecDDLPrefixes); + cloneUnits(vecDDLUnits); + cloneDatatypes(vecDTs); + cloneStructs(vecStructs); + cloneStreams(vecStreams); + cloneEnums(vecEnums); + } + + DDLDescription& DDLDescription::operator=(DDLDescription other) + { + swap(*this, other); + return *this; + } + + DDLDescription::DDLDescription(DDLDescription&& other) + { + swap(*this, other); + } + + DDLDescription::~DDLDescription() + { + delete _header; + _header = NULL; + + // delete child objects + _baseunits.deleteAll(); + _prefixes.deleteAll(); + _units.deleteAll(); + _data_types.deleteAll(); + _structs.deleteAll(); + _streams.deleteAll(); + _enums.deleteAll(); + } + + a_util::result::Result DDLDescription::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visitDDL(this); + } + + a_util::result::Result DDLDescription::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visitDDL(this); + } + + const std::string& DDLDescription::getName() const + { + static std::string s_Name("DDL"); + return s_Name; + } + + a_util::result::Result DDLDescription::create(DDLHeader* poHeader, + DDLUnitVec vecDDLUnits, + DDLBaseunitVec vecDDLBaseunits, + DDLPrefixVec vecDDLPrefixes, + DDLDTVec vecDTs, + DDLComplexVec vecStructs, + DDLStreamVec vecStreams, + DDLEnumVec vecEnums) + { + if (!poHeader) { return ERR_POINTER; } + _header = poHeader; + cloneBaseunits(vecDDLBaseunits); + clonePrefixes(vecDDLPrefixes); + cloneDatatypes(vecDTs); + cloneStructs(vecStructs); + cloneStreams(vecStreams); + cloneEnums(vecEnums); + _init_flag = true; + return a_util::result::SUCCESS; + } + + DDLHeader * DDLDescription::getHeader() const + { + return _header; + } + + void DDLDescription::cloneUnits(const DDLUnitVec& vecDDLUnits) + { + _units.deleteAll(); + mergeUnits(vecDDLUnits, IDDL::ddl_merge_force_overwrite, NULL); + } + + void DDLDescription::refUnits(DDLUnitVec& vecDDLUnits) + { + _units.deleteAll(); + mergePart(_units, vecDDLUnits, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + + void DDLDescription::mergeUnits(DDLUnitVec vecDDLUnits, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_units, vecDDLUnits, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addUnit(DDLUnit* poUnit, int nPos) + { + if (NULL != poUnit) + { + _units.insert(poUnit, nPos); + } + } + + DDLUnitVec& DDLDescription::getUnits() + { + return _units; + } + + const DDLUnitVec& DDLDescription::getUnits() const + { + return _units; + } + + const DDLUnit * DDLDescription::getUnitByName(const std::string& name) const + { + return _units.find(name); + } + + DDLUnit * DDLDescription::getUnitByName(const std::string& name) + { + return _units.find(name); + } + + void DDLDescription::cloneBaseunits(const DDLBaseunitVec& vecDDLBaseunits) + { + _baseunits.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _baseunits.cloneFrom(DDLDefault::getInstance(version, _baseunits.isSorted())->GetDefaultBaseunits()); + mergeBaseunits(vecDDLBaseunits, IDDL::ddl_merge_force_overwrite, NULL); + } + else + { + _baseunits.cloneFrom(vecDDLBaseunits); + } + } + + void DDLDescription::refBaseunits(DDLBaseunitVec& vecDDLBaseunits) + { + _baseunits.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _baseunits.cloneFrom(DDLDefault::getInstance(version, _baseunits.isSorted())->GetDefaultBaseunits()); + mergePart(_baseunits, vecDDLBaseunits, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + else + { + _baseunits.copyFromRef(vecDDLBaseunits); + } + } + + void DDLDescription::mergeBaseunits(DDLBaseunitVec vecDDLBaseunits, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_baseunits, vecDDLBaseunits, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addBaseunit(DDLBaseunit* poBaseunit, int nPos) + { + if (NULL != poBaseunit) + { + _baseunits.insert(poBaseunit, nPos); + } + } + + DDLBaseunitVec DDLDescription::getBaseunits() const + { + return _baseunits; + } + + DDLBaseunit * DDLDescription::getBaseunitByName(const std::string& name) + { + return _baseunits.find(name); + } + + const DDLBaseunit * DDLDescription::getBaseunitByName(const std::string& name) const + { + return _baseunits.find(name); + } + + void DDLDescription::clonePrefixes(const DDLPrefixVec& vecDDLPrefixes) + { + _prefixes.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _prefixes.cloneFrom(DDLDefault::getInstance(version, _prefixes.isSorted())->GetDefaultPrefixes()); + mergePrefixes(vecDDLPrefixes, IDDL::ddl_merge_force_overwrite, NULL); + } + else + { + _prefixes.cloneFrom(vecDDLPrefixes); + } + } + + void DDLDescription::refPrefixes(DDLPrefixVec& vecDDLPrefixes) + { + _prefixes.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _prefixes.cloneFrom(DDLDefault::getInstance(version, _prefixes.isSorted())->GetDefaultPrefixes()); + mergePart(_prefixes, vecDDLPrefixes, IDDL::ddl_merge_force_overwrite, NULL, NULL, true , true); + } + else + { + _prefixes.copyFromRef(vecDDLPrefixes); + } + } + + void DDLDescription::mergePrefixes(DDLPrefixVec vecDDLPrefixes, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_prefixes, vecDDLPrefixes, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addPrefix(DDLPrefix* poPrefix, int nPos) + { + if (NULL != poPrefix) + { + _prefixes.insert(poPrefix, nPos); + } + } + + DDLPrefixVec DDLDescription::getPrefixes() const + { + return _prefixes; + } + + const DDLPrefix * DDLDescription::getPrefixByName(const std::string& name) const + { + return _prefixes.find(name); + } + + DDLPrefix * DDLDescription::getPrefixByName(const std::string& name) + { + return _prefixes.find(name); + } + + void DDLDescription::cloneDatatypes(const DDLDTVec& vecDDLDataTypes) + { + _data_types.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _data_types.cloneFrom(DDLDefault::getInstance(version, _data_types.isSorted())->GetDefaultDTs()); + mergeDatatypes(vecDDLDataTypes, IDDL::ddl_merge_force_overwrite, NULL); + } + else + { + _data_types.cloneFrom(vecDDLDataTypes); + } + } + + void DDLDescription::refDatatypes(DDLDTVec& vecDDLDataTypes) + { + _data_types.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _data_types.cloneFrom(DDLDefault::getInstance(version, _data_types.isSorted())->GetDefaultDTs()); + mergePart(_data_types, vecDDLDataTypes, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + else + { + _data_types.copyFromRef(vecDDLDataTypes); + } + } + + void DDLDescription::mergeDatatypes(DDLDTVec vecDDLDataTypes, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_data_types, vecDDLDataTypes, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addDatatype(DDLDataType* poDatatype, int nPos) + { + if (NULL != poDatatype) + { + _data_types.insert(poDatatype, nPos); + } + } + + DDLDTVec& DDLDescription::getDatatypes() + { + return _data_types; + } + + const DDLDTVec& DDLDescription::getDatatypes() const + { + return _data_types; + } + + DDLDataType * DDLDescription::getDataTypeByName(const std::string& name) + { + return _data_types.find(name); + } + + const DDLDataType * DDLDescription::getDataTypeByName(const std::string& name) const + { + return _data_types.find(name); + } + + void DDLDescription::cloneStructs(const DDLComplexVec& vecStructs) + { + _structs.deleteAll(); + _structs.clear(); + //initdefault ... + mergeStructs(vecStructs, IDDL::ddl_merge_force_overwrite, NULL); + } + + + void DDLDescription::refStructs(DDLComplexVec& vecStructs) + { + _structs.deleteAll(); + _structs.clear(); + //initdefault ... + mergePart(_structs, vecStructs, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + + void DDLDescription::mergeStructs(DDLComplexVec vecStructs, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_structs, vecStructs, ui32JoinFlags, pvecDeleteData, this, false, false); + } + + void DDLDescription::addStruct(DDLComplex* poStruct, int nPos) + { + if (NULL != poStruct) + { + _structs.insert(poStruct, nPos); + } + } + + bool DDLDescription::hasDynamicStructs() + { + bool _dynamic_structs = false; + for (DDLComplexIt itEl = _structs.begin(); itEl != _structs.end(); itEl++) + { + if ((*itEl)->hasDynamicElements()) + { + _dynamic_structs = true; + break; + } + } + return _dynamic_structs; + } + + DDLComplexVec& DDLDescription::getStructs() + { + return _structs; + } + + const DDLComplexVec& DDLDescription::getStructs() const + { + return _structs; + } + + const DDLComplex * DDLDescription::getStructByName(const std::string& name) const + { + return _structs.find(name); + } + + DDLComplex* DDLDescription::getStructByName(const std::string& name) + { + return _structs.find(name); + } + + a_util::result::Result DDLDescription::removeType(const std::string& name) + { + DDLDTIt itDTFound = _data_types.findIt(name); + if (_data_types.end() == itDTFound) + { + DDLComplexIt itStructFound = _structs.findIt(name); + if (_structs.end() == itStructFound) + { + return ERR_NOT_FOUND; + } + DDLDescription::deleteChild(*itStructFound); + _structs.erase(itStructFound); + } + else + { + deleteChild(*itDTFound); + _data_types.erase(itDTFound); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removeDataType(const std::string& name) + { + DDLDTIt itDTFound = _data_types.findIt(name); + if (_data_types.end() == itDTFound) + { + return ERR_NOT_FOUND; + } + else + { + deleteChild(*itDTFound); + _data_types.erase(itDTFound); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removeComplexDataType(const std::string& name) + { + DDLComplexIt itStructFound = _structs.findIt(name); + if (_structs.end() == itStructFound) + { + return ERR_NOT_FOUND; + } + else + { + DDLDescription::deleteChild(*itStructFound); + _structs.erase(itStructFound); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::moveHeaderExcDec + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_header->getExtDeclarations(), nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveBaseunit + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_baseunits, nFrom, nTo); + } + + a_util::result::Result DDLDescription::movePrefix + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_prefixes, nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveUnit + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_units, nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveRefUnit + ( + const int nFrom, + const int nTo, + const std::string& strParent + ) + { + DDLUnitIt itUnitFound = _units.findIt(strParent); + if (_units.end() == itUnitFound) + { + return ERR_NOT_FOUND; + } + + return DDLDescription::moveChild(&((*itUnitFound)->getRefUnits()), nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveEnum + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_enums, nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveEnumElement + ( + const int nFrom, + const int nTo, + const std::string& strParent + ) + { + DDLEnumIt itEnumFound = _enums.findIt(strParent); + if (_enums.end() == itEnumFound) + { + return ERR_NOT_FOUND; + } + + EnumNameValueVec vecValue = (*itEnumFound)->getValues(); + RETURN_IF_FAILED(DDLDescription::moveChild(&vecValue, nFrom, nTo)); + + (*itEnumFound)->setValues(vecValue); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::moveDatatype + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_data_types, nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveComplexDataType + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_structs, nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveComplexDataTypeElement + ( + const int nFrom, + const int nTo, + const std::string& strParent + ) + { + DDLComplexIt itStructFound = _structs.findIt(strParent); + if (_structs.end() == itStructFound) + { + return ERR_NOT_FOUND; + } + + return DDLDescription::moveChild(&((*itStructFound)->getElements()), nFrom, nTo); + } + + a_util::result::Result DDLDescription::moveStream + ( + const int nFrom, + const int nTo + ) + { + return DDLDescription::moveChild(&_streams, nFrom, nTo); + } + + a_util::result::Result DDLDescription::removeEnum( const std::string& name ) + { + DDLEnumIt itEnum = _enums.findIt(name); + if (itEnum == _enums.end()) + { + return ERR_NOT_FOUND; + } + + deleteChild(*itEnum); + _enums.erase(itEnum); + + return a_util::result::SUCCESS; + } + + + void DDLDescription::cloneStreams(const DDLStreamVec& vecStreams) + { + _streams.deleteAll(); + _streams.clear(); + //initdefault ... + mergeStreams(vecStreams, IDDL::ddl_merge_force_overwrite, NULL); + } + + void DDLDescription::refStreams(DDLStreamVec& vecStreams) + { + _streams.deleteAll(); + _streams.clear(); + //initdefault ... + mergePart(_streams, vecStreams, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + + void DDLDescription::mergeStreams(DDLStreamVec vecStreams, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_streams, vecStreams, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addStream(DDLStream* poStream, int nPos) + { + if (NULL != poStream) + { + _streams.insert(poStream, nPos); + } + } + + DDLStreamVec& DDLDescription::getStreams() + { + return _streams; + } + + const DDLStreamVec& DDLDescription::getStreams() const + { + return _streams; + } + + DDLStream* DDLDescription::getStreamByName(const std::string& name) + { + return _streams.find(name); + } + + const DDLStream* DDLDescription::getStreamByName(const std::string& name) const + { + return _streams.find(name); + } + + a_util::result::Result DDLDescription::renameStream(const std::string& strOldName, const std::string& strNewName) + { + DDLStream * poStream = getStreamByName(strOldName); + if (NULL == poStream) + { + return ERR_NOT_FOUND; + } + poStream->setName(strNewName); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removeStream(const std::string& name) + { + DDLStreamIt itFound = _streams.findIt(name); + if (_streams.end() == itFound) + { + return ERR_NOT_FOUND; + } + deleteChild(*itFound); + _streams.erase(itFound); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removeBaseunit(const std::string& name) + { + DDLBaseunitIt itFound = _baseunits.findIt(name); + if (_baseunits.end() == itFound) + { + return ERR_NOT_FOUND; + } + deleteChild(*itFound); + _baseunits.erase(itFound); + return a_util::result::SUCCESS; + } + + + a_util::result::Result DDLDescription::removeUnit(const std::string& name) + { + DDLUnitIt itFound = _units.findIt(name); + if (_units.end() == itFound) + { + return ERR_NOT_FOUND; + } + deleteChild(*itFound); + _units.erase(itFound); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removePrefix(const std::string& name) + { + DDLPrefixIt itFound = _prefixes.findIt(name); + if (_prefixes.end() == itFound) + { + return ERR_NOT_FOUND; + } + deleteChild(*itFound); + _prefixes.erase(itFound); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::merge(DDLDescription &oDDL, uint32_t ui32JoinFlags) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + + if (oDDL.getHeader()->getLanguageVersion() > + _header->getLanguageVersion()) + { + LOG_INFO(a_util::strings::format("Merge of %s version to %s language version", + oDDL.getHeader()->getLanguageVersion().toString().c_str(), _header->getLanguageVersion().toString().c_str()).c_str()); + _header->setLanguageVersion(oDDL.getHeader()->getLanguageVersion()); + } + + DDLVec vecDeletionVector; //(this is the vector for all vector items that can be deleted after merge) + + mergeBaseunits(oDDL.getBaseunits(), ui32JoinFlags, &vecDeletionVector); + mergePrefixes(oDDL.getPrefixes(), ui32JoinFlags, &vecDeletionVector); + mergeUnits(oDDL.getUnits(), ui32JoinFlags, &vecDeletionVector); + mergeDatatypes(oDDL.getDatatypes(), ui32JoinFlags, &vecDeletionVector); + mergeEnums(oDDL.getEnums(), ui32JoinFlags, &vecDeletionVector); + mergeStructs(oDDL.getStructs(), ui32JoinFlags, &vecDeletionVector); + mergeStreams(oDDL.getStreams(), ui32JoinFlags, &vecDeletionVector); + + DDLRepair oRepair; + oRepair.visitDDL(this); + vecDeletionVector.deleteAll(); + + _header->setDateChange(a_util::datetime::getCurrentLocalDate()); + return a_util::result::SUCCESS; + } + + bool DDLDescription::isInitialized() const + { + return _init_flag; + } + + a_util::result::Result DDLDescription::restoreLevel(int nLevel) + { + for (DDLStreamIt itStream = _streams.begin(); + _streams.end() != itStream; ++itStream) + { + if ((*itStream)->getCreationLevel() >= nLevel) + { + *itStream = deleteChild(*itStream); + } + } + DDLStreamIt itRemStream = std::remove_if(_streams.begin(), + _streams.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _streams.erase(itRemStream, _streams.end()); + + for (DDLComplexIt itStruct = _structs.begin(); + _structs.end() != itStruct; ++itStruct) + { + if ((*itStruct)->getCreationLevel() >= nLevel) + { + *itStruct = deleteChild(*itStruct); + } + } + DDLComplexIt itRemStruct = std::remove_if(_structs.begin(), + _structs.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _structs.erase(itRemStruct, _structs.end()); + + for (DDLDTIt itDT = _data_types.begin(); _data_types.end() != itDT; + ++itDT) + { + if ((*itDT)->getCreationLevel() >= nLevel) + { + *itDT = deleteChild(*itDT); + } + } + DDLDTIt itRemDT = std::remove_if(_data_types.begin(), + _data_types.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _data_types.erase(itRemDT, _data_types.end()); + + for (DDLUnitIt itUnit = _units.begin(); _units.end() != itUnit; + ++itUnit) + { + if ((*itUnit)->getCreationLevel() >= nLevel) + { + *itUnit = deleteChild(*itUnit); + } + } + DDLUnitIt itRemUnit = std::remove_if(_units.begin(), + _units.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _units.erase(itRemUnit, _units.end()); + + for (DDLPrefixIt itPrefix = _prefixes.begin(); + _prefixes.end() != itPrefix; ++itPrefix) + { + if ((*itPrefix)->getCreationLevel() >= nLevel) + { + *itPrefix = deleteChild(*itPrefix); + } + } + DDLPrefixIt itRemPrefix = std::remove_if(_prefixes.begin(), + _prefixes.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _prefixes.erase(itRemPrefix, _prefixes.end()); + + for (DDLBaseunitIt itBU = _baseunits.begin(); + _baseunits.end() != itBU; ++itBU) + { + if ((*itBU)->getCreationLevel() >= nLevel) + { + *itBU = deleteChild(*itBU); + } + } + DDLBaseunitIt itRemBU = std::remove_if(_baseunits.begin(), + _baseunits.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _baseunits.erase(itRemBU, _baseunits.end()); + + + for (DDLEnumIt itEnum = _enums.begin(); + _enums.end() != itEnum; ++itEnum) + { + if ((*itEnum)->getCreationLevel() >= nLevel) + { + *itEnum = deleteChild(*itEnum); + } + } + DDLEnumIt itRemEnum = std::remove_if(_enums.begin(), + _enums.end(), std::bind1st(std::equal_to(), + static_cast(NULL))); + _enums.erase(itRemEnum, _enums.end()); + + DDLInspector oInspector; + return oInspector.visitDDL(this); + } + + DDLDescription * DDLDescription::createDefault(int const nCreationLevel, bool bSorted) + { + return createDefault(DDLVersion::ddl_version_invalid, nCreationLevel, bSorted); + } + + DDLDescription * DDLDescription::createDefault(const DDLVersion& version, int const nCreationLevel, bool bSorted) + { + DDLImporter oImporter(nCreationLevel, false, bSorted); + std::string strDescription; + if (version == DDLVersion::ddl_version_invalid) + { + strDescription = DESCRPTIONFILE_HEADER_DDLNEWST_DEFAULT_IMPORTER; + } + else if(version < DDLVersion::ddl_version_20) + { + strDescription = DESCRPTIONFILE_HEADER_DDL1_DEFAULT_IMPORTER; + } + else if (version < DDLVersion::ddl_version_30) + { + strDescription = DESCRPTIONFILE_HEADER_DDL2_DEFAULT_IMPORTER; + } + else if (version < DDLVersion::ddl_version_40) + { + strDescription = DESCRPTIONFILE_HEADER_DDL3_DEFAULT_IMPORTER; + } + else + { + strDescription = DESCRPTIONFILE_HEADER_DDL4_DEFAULT_IMPORTER; + } + + if (isFailed(oImporter.setXML(strDescription))) + { + return NULL; + } + + if (isFailed(oImporter.createNew(version))) + { + return NULL; + } + DDLDescription *poDDL = oImporter.getDDL(); + a_util::datetime::Date sDate = a_util::datetime::getCurrentLocalDate(); + DDLHeader* poHeader = poDDL->getHeader(); + poHeader->setDateCreation(sDate); + poHeader->setDateChange(sDate); + poHeader->setAuthor(a_util::system::getCurrentUserName()); + return poDDL; + } + + template + bool DDLDescription::mergePart(DDLContainer &vecMemberData, + DDLContainer &vecOtherData, + uint32_t ui32JoinFlags, + DDLVec* pvecDeleteData, + DDLDescription* pDesc, + const bool& bRefs, + const bool& bDeleteNonOverwritten) + { + typedef typename DDLContainer::iterator tMergeIt; + bool bVectorUpdated = false; + //fast merge only copies + if (vecMemberData.empty()) + { + if (!vecOtherData.empty()) + { + if (bRefs) + { + vecMemberData.copyFromRef(vecOtherData); + } + else + { + vecMemberData.cloneFrom(vecOtherData); + } + + bVectorUpdated = true; + } + } + else + { + bool bOverWrite = ((IDDL::ddl_merge_force_overwrite | ui32JoinFlags) == IDDL::ddl_merge_force_overwrite); + for (tMergeIt itRefOther = vecOtherData.begin(); + itRefOther != vecOtherData.end(); + itRefOther++) + { + //search if part of MemberData for the Member data and needs to be overwritten + tMergeIt itFound = vecMemberData.findIt((*itRefOther)->getName()); + + if (itFound != vecMemberData.end()) + { + T* pFound = *itFound; + + //found and copy content + if (bOverWrite) + { + auto data_type_ref = reinterpret_cast(*itRefOther); + auto data_type = reinterpret_cast(pFound); + if (data_type_ref && data_type && (std::is_same::value)) + { + copyMinMaxValues(data_type, data_type_ref); + } + + if (pFound->isOverwriteable()) + { + if (bRefs) + { + //nothing to do + } + else + { + *itFound = clone(*itRefOther); + } + if (pvecDeleteData) + { + pvecDeleteData->insert(pFound); + } + else + { + if (pDesc) + { + DDLRepair oDDLRepair; + oDDLRepair.visitDDL(pDesc); + } + pFound = deleteChild(pFound); + } + bVectorUpdated = (pFound != NULL); + } + else + { + if (bDeleteNonOverwritten) + { + deleteChild(*itRefOther); + *itRefOther = NULL; + } + } + } + else + { + //only delete from this Members!! + } + } + else + { + if (bRefs) + { + vecMemberData.insert(*itRefOther); + } + else + { + vecMemberData.insert(clone(*itRefOther)); + } + bVectorUpdated = true; + } + } + } + + return bVectorUpdated; + } + + void DDLDescription::copyMinMaxValues(DDLDataType* dest_container, DDLDataType* src_container) + { + // isValid is set if a value is defined + if (src_container->isMaxValid()) + { + dest_container->setMaxValue(src_container->getMaxValue()); + } + if (src_container->isMinValid()) + { + dest_container->setMinValue(src_container->getMinValue()); + } + } + + void DDLDescription::refEnums(DDLEnumVec& vecDDLEnums) + { + _enums.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + + _enums.cloneFrom(DDLDefault::getInstance(version, _enums.isSorted())->GetDefaultEnums()); + mergePart(_enums, vecDDLEnums, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + else + { + _enums.cloneFrom(vecDDLEnums); + } + } + + DDLEnumVec& DDLDescription::getEnums() + { + return _enums; + } + + const DDLEnumVec& DDLDescription::getEnums() const + { + return _enums; + } + + void DDLDescription::mergeEnums( DDLEnumVec vecDDLEnums, uint32_t ui32JoinFlags /*= 0*/, DDLVec* pvecDeleteData /*= NULL*/ ) + { + mergePart(_enums, vecDDLEnums, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::cloneEnums(const DDLEnumVec & vecDDLEnums) + { + _enums.deleteAll(); + if (_merge_defaults) + { + DDLVersion version = DDLVersion::getDefaultVersion(); + if (NULL != _header) + { + version = _header->getLanguageVersion(); + } + _enums.cloneFrom(DDLDefault::getInstance(version, vecDDLEnums.isSorted())->GetDefaultEnums()); + mergeEnums(vecDDLEnums, IDDL::ddl_merge_force_overwrite, NULL); + } + else + { + _enums.cloneFrom(vecDDLEnums); + } + } + + void DDLDescription::addEnum( DDLEnum* const poEnum, int nPos) + { + if (NULL != poEnum) + { + _enums.insert(poEnum, nPos); + } + } + + DDLEnum* DDLDescription::getEnumByName(const std::string& name) + { + return _enums.find(name); + } + + const DDLEnum* DDLDescription::getEnumByName(const std::string& name) const + { + return _enums.find(name); + } + + void DDLDescription::cloneStreamMetaTypes(const DDLStreamMetaTypeVec& vecStreamMetaTypes) + { + _stream_meta_types.deleteAll(); + _stream_meta_types.clear(); + //initdefault ... + mergeStreamMetaTypes(vecStreamMetaTypes, IDDL::ddl_merge_force_overwrite, NULL); + } + + void DDLDescription::refStreamMetaTypes(DDLStreamMetaTypeVec& vecStreamMetaTypes) + { + _stream_meta_types.deleteAll(); + _stream_meta_types.clear(); + //initdefault ... + mergePart(_stream_meta_types, vecStreamMetaTypes, IDDL::ddl_merge_force_overwrite, NULL, NULL, true, true); + } + + void DDLDescription::mergeStreamMetaTypes(DDLStreamMetaTypeVec vecStreamMetaTypes, uint32_t ui32JoinFlags, DDLVec* pvecDeleteData) + { + mergePart(_stream_meta_types, vecStreamMetaTypes, ui32JoinFlags, pvecDeleteData, this, false); + } + + void DDLDescription::addStreamMetaType(DDLStreamMetaType* poStreamMetaType, int nPos) + { + if (NULL != poStreamMetaType) + { + _stream_meta_types.insert(poStreamMetaType, nPos); + } + } + + DDLStreamMetaTypeVec& DDLDescription::getStreamMetaTypes() + { + return _stream_meta_types; + } + + const DDLStreamMetaTypeVec& DDLDescription::getStreamMetaTypes() const + { + return _stream_meta_types; + } + + DDLStreamMetaType* DDLDescription::getStreamMetaTypeByName(const std::string& name) + { + return _stream_meta_types.find(name); + } + + const DDLStreamMetaType* DDLDescription::getStreamMetaTypeByName(const std::string& name) const + { + return _stream_meta_types.find(name); + } + + a_util::result::Result DDLDescription::renameStreamMetaType(const std::string& strOldName, const std::string& strNewName) + { + DDLStreamMetaType * poStreamMetaType = getStreamMetaTypeByName(strOldName); + if (NULL == poStreamMetaType) + { + return ERR_NOT_FOUND; + } + poStreamMetaType->setName(strNewName); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLDescription::removeStreamMetaType(const std::string& name) + { + DDLStreamMetaTypeVec::iterator itFound = _stream_meta_types.findIt(name); + if (_stream_meta_types.end() == itFound) + { + return ERR_NOT_FOUND; + } + deleteChild(*itFound); + _stream_meta_types.erase(itFound); + return a_util::result::SUCCESS; + } + + void swap(DDLDescription& lhs, DDLDescription& rhs) noexcept + { + using std::swap; + swap(lhs._header, rhs._header); + swap(lhs._units, rhs._units); + swap(lhs._baseunits, rhs._baseunits); + swap(lhs._prefixes, rhs._prefixes); + swap(lhs._data_types, rhs._data_types); + swap(lhs._enums, rhs._enums); + swap(lhs._structs, rhs._structs); + swap(lhs._streams, rhs._streams); + swap(lhs._stream_meta_types, rhs._stream_meta_types); + swap(lhs._init_flag, rhs._init_flag); + swap(lhs._merge_defaults, rhs._merge_defaults); + } +} // namespace ddl diff --git a/ddlrepresentation/ddldescription.h b/ddlrepresentation/ddldescription.h new file mode 100644 index 0000000..5a3da89 --- /dev/null +++ b/ddlrepresentation/ddldescription.h @@ -0,0 +1,1007 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_DESCRIPTION_H_INCLUDED +#define DDL_DESCRIPTION_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlvisitor_intf.h" +#include "ddlcontainer.h" +#include "ddlversion.h" + + +namespace ddl +{ + /** + * Main class representing a whole DDL description + */ + class DDLDescription : public DDL + { + public: + /** + * CTOR + * @param[in] header - Pointer to Header object + * @param[in] units - Vector of units (optional) + * @param[in] baseunits - Vector of baseunits (optional) + * @param[in] prefixes - Vector of prefixes (optional) + * @param[in] dts - Vector of datatypes (optional) + * @param[in] structs - Vector of complex datatypes (optional) + * @param[in] streams - Vector of streams (optional) + * @param[in] enums - Vector of enums (optional) + * @param[in] merge_defaults Whether or not to merge DDL default elements (datatypes etc.). + */ + DDLDescription(DDLHeader* header, + const DDLUnitVec& units = DDLUnitVec(), + const DDLBaseunitVec& baseunits = DDLBaseunitVec(), + const DDLPrefixVec& prefixes = DDLPrefixVec(), + const DDLDTVec& dts = DDLDTVec(), + const DDLComplexVec& structs = DDLComplexVec(), + const DDLStreamVec& streams = DDLStreamVec(), + const DDLEnumVec& enums = DDLEnumVec(), + bool merge_defaults = true); + + /** + * Do not allow copying + * @param[in] other - Reference to description object to copy + */ + DDLDescription(const DDLDescription&) = delete; + + /** + * Assignment operator (moves) + * @param[in] other Description type to copy from + * @return @c *this + */ + DDLDescription& operator=(DDLDescription other); + + /** + * Move CTOR + * @param[in,out] other Complex DDL type to move from - empty but valid when finished + */ + DDLDescription(DDLDescription&& other); + + /** + * DTOR + */ + virtual ~DDLDescription(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + const std::string& getName() const; + + /** + * Creation method to fill the object with data. + * @param[in] header - Pointer to Header object + * @param[in] units - Vector of units (optional) + * @param[in] baseunits - Vector of baseunits (optional) + * @param[in] prefixes - Vector of prefixes (optional) + * @param[in] dts - Vector of datatypes (optional) + * @param[in] structs - Vector of complex datatypes (optional) + * @param[in] streams - Vector of streams (optional) + * @param[in] enums - Vector of enums (optional) + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(DDLHeader* header, + DDLUnitVec units = DDLUnitVec(), + DDLBaseunitVec baseunits = DDLBaseunitVec(), + DDLPrefixVec prefixes = DDLPrefixVec(), + DDLDTVec dts = DDLDTVec(), + DDLComplexVec structs = DDLComplexVec(), + DDLStreamVec streams = DDLStreamVec(), + DDLEnumVec enums = DDLEnumVec()); + + /** + * Getter for the DDL header. + * @return the header + */ + DDLHeader * getHeader() const; + + /** + * Setter for the units. + * @param[in] units - Vector of unit objects + * + * @return void + */ + void cloneUnits(const DDLUnitVec& units); + + /** + * Setter for the units. + * @param[in] units - Vector of unit objects + * + * @return void + */ + void refUnits(DDLUnitVec& units); + + /** + * Merger for the units. + * @param[in] units - Vector of unit objects + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in] delete_data - deletion vector for optimezed deletion + * + * @return void + */ + void mergeUnits(DDLUnitVec units, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for an unit object. + * @param[in] unit - Pointer to the unit object to add + * @param[in] pos - Position to add the unit object + * + * @return void + */ + void addUnit(DDLUnit* unit, int pos = -1); + + /** + * Getter for the units. + * @return vector of units + */ + DDLUnitVec& getUnits(); + + /** + * Getter for the units. + * @return vector of units + */ + const DDLUnitVec& getUnits() const; + + + /** + * Getter for a specific unit object. + * @param[in] name - Name of the unit to look for + * @return pointer to the unit object or \c NULL if not found + */ + const DDLUnit* getUnitByName(const std::string& name) const; + + /** + * Getter for a specific unit object. + * @param[in] name - Name of the unit to look for + * @return pointer to the unit object or \c NULL if not found + */ + DDLUnit* getUnitByName(const std::string& name); + + /** + * Setter for the baseunits. + * @param[in] baseunits - Vector of baseunit objects + * + * @return void + */ + void cloneBaseunits(const DDLBaseunitVec& baseunits); + + /** + * Setter for the baseunits. + * @param[in] baseunits - Vector of baseunit objects + * + * @return void + */ + void refBaseunits(DDLBaseunitVec& baseunits); + + /** + * Merger for the baseunits. + * @param[in] baseunits - Vector of baseunit objects + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeBaseunits(DDLBaseunitVec baseunits, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a baseunit object. + * @param[in] baseunit - Pointer to the baseunit object to add + * @param[in] pos - Position to add the baseunit object + * + * @return void + */ + void addBaseunit(DDLBaseunit* baseunit, int pos = -1); + + /** + * Getter for the baseunits. + * @return vector of baseunits + */ + DDLBaseunitVec getBaseunits() const; + + /** + * Getter for a specific baseunit object. + * @param[in] name - Name of the baseunit to look for + * @return pointer to the baseunit object or \c NULL if not found + */ + const DDLBaseunit* getBaseunitByName(const std::string& name) const; + + /** + * Getter for a specific baseunit object. + * @param[in] name - Name of the baseunit to look for + * @return pointer to the baseunit object or \c NULL if not found + */ + DDLBaseunit* getBaseunitByName(const std::string& name); + + /** + * Setter for the prefixes. + * @param[in] prefixes - Vector of prefix objects + * + * @return void + */ + void clonePrefixes(const DDLPrefixVec& prefixes); + + /** + * Setter for the prefixes. + * @param[in] prefixes - Vector of prefix objects + * + * @return void + */ + void refPrefixes(DDLPrefixVec& prefixes); + + /** + * Merger for the prefixes. + * @param[in] prefixes - Vector of prefix objects + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergePrefixes(DDLPrefixVec prefixes, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a prefix object + * @param[in] prefix - Pointer to the prefix object to add + * @param[in] pos - Position to add the prefix object + * + * @return void + */ + void addPrefix(DDLPrefix* prefix, int pos = -1); + + /** + * Getter for the prefixes + * @return vector of prefixes + */ + DDLPrefixVec getPrefixes() const; + + /** + * Getter for a specific prefix object. + * @param[in] name - Name of the prefix to look for + * @return pointer to the prefix object or \c NULL if not found + */ + DDLPrefix* getPrefixByName(const std::string& name); + + /** + * Getter for a specific prefix object. + * @param[in] name - Name of the prefix to look for + * @return pointer to the prefix object or \c NULL if not found + */ + const DDLPrefix* getPrefixByName(const std::string& name) const; + + /** + * Setter for the data types. + * @param[in] data_types - Vector of datatypes + * + * @return void + */ + void cloneDatatypes(const DDLDTVec& data_types); + + /** + * Setter for the data types. + * @param[in] data_types - Vector of datatypes + * + * @return void + */ + void refDatatypes(DDLDTVec& data_types); + + + /** + * Setter for the constants. + * @param[in] enums - Vector of enums + * + * @return void + */ + void refEnums(DDLEnumVec& enums); + + /** + * Merger for the constants. + * @param[in] enums - Vector of constants + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeEnums(DDLEnumVec enums, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Setter for the enums. + * @param[in] enumss - Vector of enums + * + * @return void + */ + void cloneEnums(const DDLEnumVec& enums); + + /** + * Adder for a enum object. + * @param[in] ddl_enum - Pointer to the enum object to add + * @param[in] pos - Position to add the enum object + * + * @return void + */ + void addEnum(DDLEnum* ddl_enum, int pos = -1); + + /** + * Getter for a specific enum object. + * @param[in] name - Name of the enum to look for + * @return pointer to the enum object or \c NULL if not found + */ + DDLEnum* getEnumByName(const std::string& name); + + /** + * Getter for a specific enum object. + * @param[in] name - Name of the enum to look for + * @return pointer to the enum object or \c NULL if not found + */ + const DDLEnum* getEnumByName(const std::string& name) const; + + /** + * Merger for the data types. + * @param[in] data_types - Vector of datatypes + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeDatatypes(DDLDTVec data_types, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a datatype object. + * @param[in] datatype - Pointer to the datatype object to add + * @param[in] pos - Position to add the datatype object + * + * @return void + */ + void addDatatype(DDLDataType* datatype, int pos = -1); + + /** + * Getter for the datatypes. + * @return vector of datatypes + */ + DDLDTVec& getDatatypes(); + + /** + * Getter for the datatypes. + * @return vector of datatypes + */ + const DDLDTVec& getDatatypes() const; + + /** + * Getter for the enums. + * @return vector of enums + */ + DDLEnumVec& getEnums(); + + /** + * Getter for the enums. + * @return vector of enums + */ + const DDLEnumVec& getEnums() const; + + /** + * Getter for a specific data-type object. + * @param[in] name - Name of the data type to look for + * @return pointer to the data-type object or \c NULL if not found + */ + DDLDataType* getDataTypeByName(const std::string& name); + + /** + * Getter for a specific data-type object. + * @param[in] name - Name of the data type to look for + * @return pointer to the data-type object or \c NULL if not found + */ + const DDLDataType* getDataTypeByName(const std::string& name) const; + + /** + * Setter for the complex datatypes. + * @param[in] structs - Vector of complex datatypes + * + * @return void + */ + void cloneStructs(const DDLComplexVec& structs); + + /** + * Setter for the complex datatypes. + * @param[in] structs - Vector of complex datatypes + * + * @return void + */ + void refStructs(DDLComplexVec& structs); + + /** + * Merger for the complex datatypes. + * @param[in] structs - Vector of complex datatypes + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeStructs(DDLComplexVec structs, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a complex datatype object. + * @param[in] ddl_struct - Pointer to the complex datatype object to add + * @param[in] pos - Position to add the complex datatype object + * + * @return void + */ + void addStruct(DDLComplex *ddl_struct, int pos = -1); + + /** + * Getter for the boolean identifying dynamic elements in structures. + * @return true if dynamic elements were found in at least one structure + */ + bool hasDynamicStructs(); + + /** + * Getter for the complex datatypes. + * @return vector of complex datatypes + */ + DDLComplexVec& getStructs(); + + /** + * Getter for the complex datatypes. + * @return vector of complex datatypes + */ + const DDLComplexVec& getStructs() const; + + /** + * Getter for a specific struct object. + * @param[in] name - Name of the struct to look for + * @return pointer to the struct object or \c NULL if not found + */ + const DDLComplex * getStructByName(const std::string& name) const; + + /** + * Getter for a specific struct object. + * @param[in] name - Name of the struct to look for + * @return pointer to the struct object or \c NULL if not found + */ + DDLComplex* getStructByName(const std::string& name); + + /** + * Removes the specified primitive or complex data-type. + * @param[in] name - Name of the type to remove + * @retval ERR_NOT_FOUND The specified data type was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed type! This possible + * dependency is not checked! + */ + a_util::result::Result removeType(const std::string& name); + + /** + * Removes the specified primitive data-type. + * @param[in] name - Name of the type to remove + * @retval ERR_NOT_FOUND The specified data type was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed type! This possible + * dependency is not checked! + */ + a_util::result::Result removeDataType(const std::string& name); + + /** + * Removes the specified complex data-type. + * @param[in] name - Name of the type to remove + * @retval ERR_NOT_FOUND The specified data type was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed type! This possible + * dependency is not checked! + */ + a_util::result::Result removeComplexDataType(const std::string& name); + + /** + * Method moves the specified external header declaration. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveHeaderExcDec(const int from, const int to); + + /** + * Method moves the specified base unit. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveBaseunit(const int from, const int to); + + /** + * Method moves the specified prefix. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result movePrefix(const int from, const int to); + + /** + * Method moves the specified unit. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveUnit(const int from, const int to); + + /** + * Method moves the specified element within a unit. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @param[in] parent - Unit name + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveRefUnit(const int from, + const int to, + const std::string& parent); + + /** + * Method moves the specified enum-type. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveEnum(const int from, const int to); + + /** + * Method moves the specified enum element. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @param[in] parent - Name of parent element + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveEnumElement(const int from, + const int to, + const std::string& parent); + + /** + * Method moves the specified data-type. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveDatatype(const int from, const int to); + + /** + * Method moves the specified complex data-type. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveComplexDataType(const int from, + const int to); + + /** + * Method moves the specified element within complex data-type. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @param[in] parent - Name of parent element + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveComplexDataTypeElement(const int from, + const int to, + const std::string& parent); + + /** + * Method moves the specified stream. + * @param[in] from - Current element position in the list + * @param[in] to - New element position in the list + * @retval ERR_OUT_OF_RANGE Input parameters are out of range. + */ + a_util::result::Result moveStream(const int from, const int to); + + /** + * Removes the specified BaseUnit type. + * @param[in] name - Name of the baseunit to remove + * @retval ERR_NOT_FOUND The specified base was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed unit! This possible + * dependency is not checked! + */ + a_util::result::Result removeBaseunit(const std::string& name); + + /** + * Removes the specified Unit type. + * @param[in] name - Name of the prefix to remove + * @retval ERR_NOT_FOUND The specified base was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed unit! This possible + * dependency is not checked! + */ + a_util::result::Result removePrefix(const std::string& name); + + /** + * Removes the specified Unit type. + * @param[in] name - Name of the unit to remove + * @retval ERR_NOT_FOUND The specified base was not found + * @attention Be careful with the removal of data types! There could + * be some streams which depend on the removed unit! This possible + * dependency is not checked! + */ + a_util::result::Result removeUnit(const std::string& name); + + /** + * Removes the specified enum. + * @param[in] name - Name of the enum to remove + * @retval ERR_NOT_FOUND The specified enum was not found + * @attention Be careful with the removal of enums! There could + * be some streams which depend on the removed type! This possible + * dependency is not checked! + */ + a_util::result::Result removeEnum(const std::string& name); + + + /** + * Setter for the streams. + * @param[in] streams - Vector of streams + * + * @return void + */ + void cloneStreams(const DDLStreamVec& streams); + + /** + * Setter for the streams. + * @param[in] streams - Vector of streams + * + * @return void + */ + void refStreams(DDLStreamVec& streams); + + /** + * Merger for the streams. + * @param[in] streams - Vector of stream objects + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeStreams(DDLStreamVec streams, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a stream object. + * @param[in] stream - Pointer to the stream object to add + * @param[in] pos - Position to add the stream object + * + * @return void + */ + void addStream(DDLStream* stream, int pos = -1); + + /** + * Getter for the streams. + * @return vector of streams + */ + DDLStreamVec& getStreams(); + + /** + * Getter for the streams. + * @return vector of streams + */ + const DDLStreamVec& getStreams() const; + + /** + * Getter for a specific stream object. + * @param[in] name - Name of the stream to look for + * @return pointer to the stream object or \c NULL if not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + DDLStream * getStreamByName(const std::string& name); + + /** + * Getter for a specific stream object. + * @param[in] name - Name of the stream to look for + * @return pointer to the stream object or \c NULL if not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + const DDLStream * getStreamByName(const std::string& name) const; + + /** + * Renames the specified stream. + * @param[in] old_name - Current name of the stream to rename + * @param[in] new_name - New name of the stream + * @retval ERR_NOT_FOUND The specified stream was not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + a_util::result::Result renameStream(const std::string& old_name, const std::string& new_name); + + /** + * Removes the specified stream from the description. + * @param[in] name - Name of the stream to remove + * @retval ERR_NOT_FOUND The specified stream was not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + a_util::result::Result removeStream(const std::string& name); + + /** + * Setter for the streams. + * @param[in] streams - Vector of streams + * + * @return void + */ + void cloneStreamMetaTypes(const DDLStreamMetaTypeVec& streams); + + /** + * Setter for the streams. + * @param[in] streams - Vector of streams + * + * @return void + */ + void refStreamMetaTypes(DDLStreamMetaTypeVec& streams); + + /** + * Merger for the streams. + * @param[in] streams - Vector of stream objects + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in, out] delete_data - temporary vector for data that can be deleted afterwards. + * + * @return void + */ + void mergeStreamMetaTypes(DDLStreamMetaTypeVec streams, uint32_t join_flags = 0, DDLVec* delete_data = NULL); + + /** + * Adder for a stream object. + * @param[in] stream - Pointer to the stream object to add + * @param[in] pos - Position to add the stream object + * + * @return void + */ + void addStreamMetaType(DDLStreamMetaType* stream, int pos = -1); + + /** + * Getter for the streams. + * @return vector of streams + */ + DDLStreamMetaTypeVec& getStreamMetaTypes(); + + /** + * Getter for the streams. + * @return vector of streams + */ + const DDLStreamMetaTypeVec& getStreamMetaTypes() const; + + /** + * Getter for a specific stream object. + * @param[in] name - Name of the stream to look for + * @return pointer to the stream object or \c NULL if not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + DDLStreamMetaType * getStreamMetaTypeByName(const std::string& name); + + /** + * Getter for a specific stream object. + * @param[in] name - Name of the stream to look for + * @return pointer to the stream object or \c NULL if not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + const DDLStreamMetaType * getStreamMetaTypeByName(const std::string& name) const; + + /** + * Renames the specified stream. + * @param[in] old_name - Current name of the stream to rename + * @param[in] new_name - New name of the stream + * @retval ERR_NOT_FOUND The specified stream was not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + a_util::result::Result renameStreamMetaType(const std::string& old_name, const std::string& new_name); + + /** + * Removes the specified stream from the description. + * @param[in] name - Name of the stream to remove + * @retval ERR_NOT_FOUND The specified stream was not found + * @remarks As the name attribute is optional only streams with + * originally defined name can be found. + */ + a_util::result::Result removeStreamMetaType(const std::string& name); + + /** + * Merges another DDL ito this one. + * @param[in] ddl - Reference to DDL object to merge ito this object + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @retval ERR_INVALID_VERSION Incompatible DDL descriptions detected (not the same DDL version) + */ + a_util::result::Result merge(DDLDescription &ddl, uint32_t join_flags = 0); + + /** + * Deprecated, see IMediaDescriptionStack for the mechanism provided by the Media + * Description Service that superseeds this functionality. + * + * Method to remove all representation objects of the specified level + * and above. + * @param[in] level - Creation level from which all representation + * objects should be removed + * @retval ERR_INVALID_HANDLE Validation of remaining DDL failed + */ + a_util::result::Result restoreLevel (int const level); + + /** + * Method to create a default DDL description. + * @param [in] creation_level Creation level to use (optional) + * @param [in] sorted Sorts all DDL items by name for better performance. (optional) + * @return pointer to the created description + * @attention The caller/user has the responsibility for the created + * DDL object! Especially take this aspect ito consideration in + * matters of the deallocation of memory! + */ + static DDLDescription * createDefault(int const creation_level = 1, bool sorted = true); + + /** + * Overloaded method. + * @copydoc DDLDescription::createDefault + * @param [in] version The version of the description. Pass 0 to get the newest version. + * @return pointer to the created description + */ + static DDLDescription * createDefault(const DDLVersion& version, int const creation_level = 1, bool sorted = true); + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl description + * @param[in,out] rhs Right-hand side ddl description + */ + friend void swap(DDLDescription& lhs, DDLDescription& rhs) noexcept; + + private: // methods + /** + * Hidden default CTOR + */ + DDLDescription() = default; + + /** + * Helper method to merge a vector of representation objects ito the + * according vector inside another DDL description. + * @tparam T - Representation object type (e.g. DDLUnit) + * @param[in] member_data - Vector of objects to merge ito + * @param[in] other_data - Vector of objects to merge + * @param[in] join_flags - Additional flags for join/merge process (optional) + * @param[in] delete_data_mem - pointer to Vector of Object that can be deleted + * @param[in] desc + * @param[in] refs - Add references or clone + * @param[in] delete_non_overwritten - default value is false + * @retval true if member_data was updated + * @retval false otherwise + */ + template + static bool mergePart(DDLContainer &member_data, + DDLContainer &other_data, + uint32_t join_flags, + DDLVec* delete_data_mem, + DDLDescription* desc, + const bool& refs, + const bool& delete_non_overwritten = false); + static void copyMinMaxValues(DDLDataType* dest_container, DDLDataType* src_container); + + private: // members + DDLHeader * _header; + DDLUnitVec _units; + DDLBaseunitVec _baseunits; + DDLPrefixVec _prefixes; + DDLDTVec _data_types; + DDLEnumVec _enums; + DDLComplexVec _structs; + DDLStreamVec _streams; + DDLStreamMetaTypeVec _stream_meta_types; + bool _init_flag; + bool _merge_defaults; + }; + + /** + * This class template provides a auto deletion for DDL vector content like DDLEnumVec, DDLUnitVec etc. + * @param [in] VECTOR_TYPE The Vector Type class name the auto deletion of the vector content is performed. + */ + template < class VECTOR_TYPE > class DDLAutoVec + { + private: + std::vector < VECTOR_TYPE* >* _sync_vec; + public: + /** + * CTOR. + * @param [in] sync_vec pointer to the vector is auto delete. + */ + DDLAutoVec(std::vector< VECTOR_TYPE* >* sync_vec) + { + set(sync_vec); + }; + + /** + * Copy CTOR + * @param[in] other DDL datatype object to copy from + */ + DDLAutoVec(const DDLAutoVec& other) = default; + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDL datatype object to copy from + * @return @c *this + */ + DDLAutoVec& operator= (DDLAutoVec other) + { + swap(*this, other); + return *this; + } + + /** + * Move CTOR + * @param[in,out] other DDL datatype object to move from - empty but valid when finished + */ + DDLAutoVec(DDLAutoVec&& other) + { + swap(*this, other); + } + + /** + * DTOR. + */ + ~DDLAutoVec() + { + autoDelete(); + }; + /** + * Reset the DDL vector pointer. + * @remark no deletion will be made at this time + * + * @return void + */ + void reset() + { + _sync_vec = NULL; + } + /** + * Reset the DDL vector pointer and set the given one. + * @remark no deletion will be made at this time. + * @param [in] sync_vec pointer to the vector is auto delete. + * + * @return void + */ + void set(std::vector< VECTOR_TYPE* >* sync_vec) + { + reset(); + _sync_vec = sync_vec; + } + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLAutoVec& lhs, DDLAutoVec& rhs) + { + using std::swap; + swap(lhs._sync_vec, rhs._sync_vec); + } + + private: + /** + * Deletes the current set sync pointer to an DDL Vector + */ + void autoDelete() + { + if (_sync_vec) + { + std::transform(_sync_vec->begin(), _sync_vec->end(), _sync_vec->begin(), ddl::DDLDescription::deleteChild< VECTOR_TYPE > ); + } + } + }; + +} // namespace ddl + +#endif // DDL_DESCRIPTION_H_INCLUDED diff --git a/ddlrepresentation/ddlelement.cpp b/ddlrepresentation/ddlelement.cpp new file mode 100644 index 0000000..8f20135 --- /dev/null +++ b/ddlrepresentation/ddlelement.cpp @@ -0,0 +1,475 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlelement.h" +#include + + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLElement::DDLElement(IDDLDataType* poType, + const std::string& name, + unsigned int const uiBytepos, + unsigned int const uiArraysize, + DDLByteorder::Byteorder const eByteorder, + DDLAlignment::AlignmentType const eAlignment, + IDDLUnit* poUnit, + unsigned int const uiBitpos, + unsigned int const uiNumBits, + const std::string& strDescription, + const std::string& strComment, + const std::string& strArraySizeSource, + const std::string& strValue, + bool const bMinValid, + const std::string& strMinValue, + bool const bMaxValid, + const std::string& strMaxValue, + bool const bDefaultValid, + const std::string& strDefaultValue, + bool const bScaleValid, + const std::string& strScaleValue, + bool const bOffsetValid, + const std::string& strOffsetValue) : + _type(poType), + _name(name), + _bytes_pos(uiBytepos), + _bit_pos(uiBitpos), + _num_bits(uiNumBits), + _description(strDescription), + _array_size(uiArraysize), + _array_size_source(strArraySizeSource), + _constant_value(strValue), + _unit(poUnit), + _byteorder(eByteorder), + _alignment(eAlignment), + _comment(strComment), + _init_flag(NULL != _type), + _min_valid(bMinValid), + _min_value(strMinValue), + _max_valid(bMaxValid), + _max_value(strMaxValue), + _default_valid(bDefaultValid), + _default_value(strDefaultValue), + _scale_valid(bScaleValid), + _scale_value(strScaleValue), + _offset_valid(bOffsetValid), + _offset_value(strOffsetValue) + { + } + + a_util::result::Result DDLElement::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLElement::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLElement::create(IDDLDataType* poType, + const std::string& name, + unsigned int const uiBytepos, + unsigned int const uiArraysize, + DDLByteorder::Byteorder const eByteorder, + DDLAlignment::AlignmentType const eAlignment, + IDDLUnit* poUnit, + unsigned int const uiBitpos, + unsigned int const uiNumBits, + const std::string& strDescription, + const std::string& strComment, + const std::string& strArraySizeSource, + const std::string& strValue, + bool const bMinValid, + const std::string& strMinValue, + bool const bMaxValid, + const std::string& strMaxValue, + bool const bDefaultValid, + const std::string& strDefaultValue, + bool const bScaleValid, + const std::string& strScaleValue, + bool const bOffsetValid, + const std::string& strOffsetValue) + { + if (!poType) { return ERR_POINTER; } + _type = poType; + _name = name; + _bytes_pos = uiBytepos; + _array_size = uiArraysize; + _byteorder = eByteorder; + _alignment = eAlignment; + _unit = poUnit; + _bit_pos = uiBitpos; + _num_bits = uiNumBits; + _description = strDescription; + _comment = strComment; + _array_size_source = strArraySizeSource; + _init_flag = true; + _constant_value = strValue; + _min_valid = bMinValid; + _min_value = strMinValue; + _max_valid = bMaxValid; + _max_value = strMaxValue; + _default_valid = bDefaultValid; + _default_value = strDefaultValue; + _scale_valid = bScaleValid; + _scale_value = strScaleValue; + _offset_valid = bOffsetValid; + _offset_value = strOffsetValue; + return a_util::result::SUCCESS; + } + + bool DDLElement::isPredefined() const + { + return false; + } + + int DDLElement::getCreationLevel() const + { + return 99; // cMediaManager::DL_Internal => error + } + + const std::string& DDLElement::getType() const + { + if (!_init_flag) + { + return a_util::strings::empty_string; + } + return _type->getName(); + } + + void DDLElement::setType(IDDLDataType* const pType) + { + _type = pType; + _init_flag = (_type != NULL); + } + + + IDDLDataType * DDLElement::getTypeObject() const + { + if (!_init_flag) + { + return NULL; + } + return _type; + } + + const std::string& DDLElement::getName() const + { + return _name; + } + + void DDLElement::setName(const std::string& name) + { + _name = name; + } + + unsigned int DDLElement::getBytepos() const + { + return _bytes_pos; + } + + void DDLElement::setBytepos(unsigned int const uiBytePos) + { + _bytes_pos = uiBytePos; + } + + unsigned int DDLElement::getArraysize() const + { + return _array_size; + } + + void DDLElement::setArraysize(unsigned int const uiArraySize ) + { + _array_size = uiArraySize; + } + + + DDLByteorder::Byteorder DDLElement::getByteorder() const + { + return _byteorder; + } + + void DDLElement::setByteorder(DDLByteorder::Byteorder const eByteOrder) + { + _byteorder = eByteOrder; + } + + DDLAlignment::AlignmentType DDLElement::getAlignment() const + { + return _alignment; + } + + void DDLElement::setAlignment(DDLAlignment::AlignmentType const eAlign) + { + _alignment = eAlign; + } + + void DDLElement::setBitpos(unsigned int const uiBitpos) + { + if (uiBitpos >= 0 && uiBitpos <= 7) + { + _bit_pos = uiBitpos; + } + } + + unsigned int DDLElement::getBitpos() const + { + return _bit_pos; + } + + void DDLElement::setNumBits(unsigned int const uiNumBits) + { + _num_bits = uiNumBits; + } + + unsigned int DDLElement::getNumBits() const + { + return _num_bits; + } + + void DDLElement::setDescription(const std::string& strDescription) + { + _description = strDescription; + } + + const std::string& DDLElement::getDescription() const + { + return _description; + } + + void DDLElement::setUnit(IDDLUnit* poUnit) + { + _unit = poUnit; + } + + const std::string& DDLElement::getUnit() const + { + if (NULL == _unit) + { + // no unit reference defined + return a_util::strings::empty_string; + } + return _unit->getName(); + } + + IDDLUnit * DDLElement::getUnitObject() const + { + if (!_init_flag) + { + return NULL; + } + return _unit; + } + + void DDLElement::setComment(const std::string& strComment) + { + _comment = strComment; + } + + const std::string& DDLElement::getComment() const + { + return _comment; + } + + bool DDLElement::isInitialized() const + { + return _init_flag; + } + + const std::string& DDLElement::getArraySizeSource() const + { + return _array_size_source; + } + + void DDLElement::setArraySizeSource( const std::string& strArraySizeSource ) + { + _array_size_source = strArraySizeSource; + } + + const std::string& DDLElement::getConstantValue() const + { + return _constant_value; + } + + void DDLElement::setConstantValue( const std::string& strConstantValue ) + { + _constant_value = strConstantValue; + } + + bool DDLElement::isDynamic() const + { + if (!getArraySizeSource().empty()) + { + return true; + } + + return false; + } + + void DDLElement::setMinValidity (bool const bMinValid) + { + _min_valid = bMinValid; + } + + bool DDLElement::isMinValid () const + { + return _min_valid; + } + + const std::string & DDLElement::getMinValue () const + { + if (_min_valid) + { + return _min_value; + } + else if (_init_flag) + { + DDLDataType *poDT = dynamic_cast(_type); + if (NULL != poDT && poDT->isMinValid()) + { + // inherit minimum value from primitive data type + return poDT->getMinValue(); + } + } + // no type information available or complex type or no min value valid + return a_util::strings::empty_string; + } + + a_util::result::Result DDLElement::setMinValue (const std::string& strMinVal) + { + // TODO validate new minimum value + _min_value = strMinVal; + return a_util::result::SUCCESS; + } + + void DDLElement::setMaxValidity (bool const bMaxValid) + { + _max_valid = bMaxValid; + } + + bool DDLElement::isMaxValid () const + { + return _max_valid; + } + + const std::string & DDLElement::getMaxValue () const + { + if (_max_valid) + { + return _max_value; + } + else if (_init_flag) + { + DDLDataType *poDT = dynamic_cast(_type); + if (NULL != poDT && poDT->isMaxValid()) + { + // inherit maximum value from primitive type + return poDT->getMaxValue(); + } + } + // no type information available or complex type or no min value valid + return a_util::strings::empty_string; + } + + a_util::result::Result DDLElement::setMaxValue (const std::string& strMaxVal) + { + // TODO validate new maximum value + _max_value = strMaxVal; + return a_util::result::SUCCESS; + } + + void DDLElement::setDefaultValidity (bool const bDefaultValid) + { + _default_valid = bDefaultValid; + } + + bool DDLElement::isDefaultValid () const + { + return _default_valid; + } + + const std::string & DDLElement::getDefaultValue () const + { + return _default_value; + } + + a_util::result::Result DDLElement::setDefaultValue (const std::string& strDefaultVal) + { + // TODO validate new default value + _default_value = strDefaultVal; + return a_util::result::SUCCESS; + } + + void DDLElement::setScaleValidity (bool const bScaleValid) + { + _scale_valid = bScaleValid; + } + + bool DDLElement::isScaleValid () const + { + return _scale_valid; + } + + const std::string & DDLElement::getScaleValue () const + { + return _scale_value; + } + + a_util::result::Result DDLElement::setScaleValue (const std::string& strScaleValue) + { + // TODO validate new scaling value + _scale_value = strScaleValue; + return a_util::result::SUCCESS; + } + + void DDLElement::setOffsetValidity (bool const bOffsetValid) + { + _offset_valid = bOffsetValid; + } + + bool DDLElement::isOffsetValid () const + { + return _offset_valid; + } + + const std::string & DDLElement::getOffsetValue () const + { + return _offset_value; + } + + a_util::result::Result DDLElement::setOffsetValue (const std::string& strOffsetValue) + { + // TODO validate new offset value + _offset_value = strOffsetValue; + return a_util::result::SUCCESS; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlelement.h b/ddlrepresentation/ddlelement.h new file mode 100644 index 0000000..5d73323 --- /dev/null +++ b/ddlrepresentation/ddlelement.h @@ -0,0 +1,572 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLELEMENT_H_INCLUDED +#define DDLELEMENT_H_INCLUDED + +#include "ddl_common.h" +#include "ddldatatype_intf.h" +#include "ddlbyteorder.h" +#include "ddlalignment.h" +#include "ddlunit_intf.h" + +namespace ddl +{ + + /** + * Representation of an element inside a struct in DDL a description. + */ + class DDLElement + { + public: + /** + * Default CTOR + */ + DDLElement() = default; + + /** + * CTOR + * @param[in] type - Pointer to the data-type object + * @param[in] name - Name of the created element + * @param[in] byte_pos - Byte position of the referenced data type + * @param[in] array_size - Array size of the element + * @param[in] byte_order - Byte order of the related data type + * @param[in] alignment - Alignment of the related data type + * @param[in] unit - Pointer to unit object + * @param[in] bit_pos - Bit position of the referenced data type (optional) + * @param[in] num_bits - The amount of bits used for the representation (optional) + * @param[in] description - Description of the created data type (optional) + * @param[in] comment - Additional comments (optional) + * @param[in] array_size_source - The name of the source element for the size of a dynamic array (optional) + * @param[in] value - The value of a constant element (optional) + * @param[in] min_valid - Validity flag for the minimum value (optional) + * @param[in] min_value - Minimum value of the element (optional) + * @param[in] max_valid - Validity flag for the maximum value (optional) + * @param[in] max_value - Maximum value of the element (optional) + * @param[in] default_valid - Validity flag for the default value (optional) + * @param[in] default_value - Default value of the element (optional) + * @param[in] scale_valid - Validity flag for the scaling value (optional) + * @param[in] scale_value - Scaling value of the element (optional) + * @param[in] offset_valid - Validity flag for the offset value (optional) + * @param[in] offset_value - Offset value of the element (optional) + */ + DDLElement(IDDLDataType* type, + const std::string& name, + unsigned int const byte_pos, + unsigned int const array_size, + DDLByteorder::Byteorder const byte_order, + DDLAlignment::AlignmentType const alignment, + IDDLUnit* unit = NULL, + unsigned int const bit_pos = 0, + unsigned int const num_bits = 0, + const std::string& description = a_util::strings::empty_string, + const std::string& comment = a_util::strings::empty_string, + const std::string& array_size_source = a_util::strings::empty_string, + const std::string& value = a_util::strings::empty_string, + bool const min_valid = false, + const std::string& min_value = a_util::strings::empty_string, + bool const max_valid = false, + const std::string& max_value = a_util::strings::empty_string, + bool const default_valid = false, + const std::string& default_value = a_util::strings::empty_string, + bool const scale_valid = false, + const std::string& scale_value = a_util::strings::empty_string, + bool const offset_valid = false, + const std::string& offset_value = a_util::strings::empty_string); + + /** + * @copydoc IDDL::accept() + */ + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + /** + * @copydoc IDDL::isInitialized() + */ + bool isInitialized() const; + + /* a_util::result::Result Serialize(void const *pvDeSerData, + size_t const &szSizeDeSerInByte, + size_t const &szAlignedOffsetInByte, + void *pvSerData, + size_t const &szSizeSerInByte, + size_t const &szOffsetInBit); + + a_util::result::Result Deserialize(void *pvDeSerData, + size_t const &szSizeDeSerInByte, + size_t const &szAlignedOffsetInByte, + void const *pvSerData, + size_t const &szSizeSerInByte, + size_t const &szOffsetInBit); + + size_t getSize() const;*/ + + /** + * @copydoc IDDL::isPredefined() + */ + bool isPredefined() const; + + /** + * @copydoc IDDL::getCreationLevel() + */ + int getCreationLevel() const; + + /** + * Creation method to fill the obejct with data. + * @param[in] type - Pointer to the datatype object + * @param[in] name - Name of the created element + * @param[in] byte_pos - Byte position of the referenced data type + * @param[in] array_size - Arraysize of the element + * @param[in] byte_order - Byteorder of the related data type + * @param[in] alignment - Alignment of the related data type + * @param[in] unit - Pointer to unit object + * @param[in] bit_pos - Bit position of the referenced data type (optional) + * @param[in] num_bits - The amount of bits used for the representation (optional) + * @param[in] description - Description of the created data type (optional) + * @param[in] comment - Additional comments (optional) + * @param[in] array_size_source - The name of the source element for the size of a dynamic array + * @param[in] value - The value of a constant element (optional) + * @param[in] min_valid - Validity flag for the minimum value (optional) + * @param[in] min_value - Minimum value of the element (optional) + * @param[in] max_valid - Validity flag for the maximum value (optional) + * @param[in] max_value - Maximum value of the element (optional) + * @param[in] default_valid - Validity flag for the default value (optional) + * @param[in] default_value - Default value of the element (optional) + * @param[in] scale_valid - Validity flag for the scaling value (optional) + * @param[in] scale_value - Scaling value of the element (optional) + * @param[in] offset_valid - Validity flag for the offset value (optional) + * @param[in] offset_value - Offset value of the element (optional) + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(IDDLDataType* type, + const std::string& name, + unsigned int const byte_pos, + unsigned int const array_size, + DDLByteorder::Byteorder const byte_order, + DDLAlignment::AlignmentType const alignment, + IDDLUnit* unit = NULL, + unsigned int const bit_pos = 0, + unsigned int const num_bits = 0, + const std::string& description = a_util::strings::empty_string, + const std::string& comment = a_util::strings::empty_string, + const std::string& array_size_source = a_util::strings::empty_string, + const std::string& value = a_util::strings::empty_string, + bool const min_valid = false, + const std::string& min_value = a_util::strings::empty_string, + bool const max_valid = false, + const std::string& max_value = a_util::strings::empty_string, + bool const default_valid = false, + const std::string& default_value = a_util::strings::empty_string, + bool const scale_valid = false, + const std::string& scale_value = a_util::strings::empty_string, + bool const offset_valid = false, + const std::string& offset_value = a_util::strings::empty_string); + + /** + * Getter for the data-type name. + * @return name of the data type + */ + const std::string& getType() const; + + /** + * Setter for the type of the element. + * @param [in] type Pointer to the type object + * + * @return void + */ + void setType(IDDLDataType* const type); + + /** + * Getter for the data-type object. + * @return pointer to the data-type object + */ + IDDLDataType * getTypeObject() const; + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the name of the element. + * @param [in] name Name of the element + * + * @return void + */ + void setName(const std::string& name); + + /** + * Getter for the b byte position. + * @return the byte position + */ + unsigned int getBytepos() const; + + /** + * Setter for the byte position of the element. + * @param [in] byte_pos Byte position of the element + * + * @return void + */ + void setBytepos(unsigned int const byte_pos); + + + /** + * Getter for the array size. + * @return the array size + */ + unsigned int getArraysize() const; + + /** + * Setter for the array size of the element. + * @param [in] array_size Array size of the element + * + * @return void + */ + void setArraysize(unsigned int const array_size); + + /** + * Getter for the byteorder. + * @return the byteorder + */ + DDLByteorder::Byteorder getByteorder() const; + + /** + * Setter for the byte order of the element. + * @param [in] byte_order Byte order of the element + * + * @return void + */ + void setByteorder(DDLByteorder::Byteorder const byte_order); + + /** + * Getter for the alignment. + * @return the alignment + */ + DDLAlignment::AlignmentType getAlignment() const; + + /** + * Setter for the alignment of the element. + * @param [in] alignment Alignment of the element + * + * @return void + */ + void setAlignment(DDLAlignment::AlignmentType const alignment); + + /** + * Setter for the bit position. + * @param[in] bit_pos - Bit position of the referenced data type + * + * @return void + */ + void setBitpos(unsigned int const bit_pos); + + /** + * Getter for the bit position. + * @return the bit position + */ + unsigned int getBitpos() const; + + /** + * Setter for the amount of bits. + * @param[in] num_bits - Amount of bits used for the representation + * + * @return void + */ + void setNumBits(unsigned int const num_bits); + + /** + * Getter for the amount of bits. + * @return the amount of bits + */ + unsigned int getNumBits() const; + + /** + * Setter for the description. + * @param[in] description - the description + * + * @return void + */ + void setDescription(const std::string& description); + + /** + * Getter for the description. + * @return the description + */ + const std::string& getDescription() const; + + /** + * Setter for the unit reference. + * @param[in] unit - Pointer to the unit object of the element + * + * @return void + */ + void setUnit(IDDLUnit* unit); + + /** + * Getter for the unit name. + * @return the unit name + */ + const std::string& getUnit() const; + + /** + * Getter for the unit object. + * @return pointer to the unit object + */ + IDDLUnit * getUnitObject() const; + + /** + * Setter for the comment. + * @param[in] comment - Additional comments + * + * @return void + */ + void setComment(const std::string& comment); + + /** + * Getter for the comment. + * @return the comment + */ + const std::string& getComment() const; + + /** + * Getter for the array size source. + * @return the array size source + */ + const std::string& getArraySizeSource() const; + + /** + * Setter for the array size source. + * @param[in] array_size_source - the array size source element + * + * @return void + */ + void setArraySizeSource(const std::string& array_size_source); + + + /** + * Getter for the value of a constant element. + * @return the value of a constant element + */ + const std::string& getConstantValue() const; + + /** + * Setter value of a constant element. + * @param[in] constant_value - constant value + * + * @return void + */ + void setConstantValue(const std::string& constant_value); + + /** + * Checks if element is dynamic + * @return true if it is a dynamic array + */ + bool isDynamic() const; + + /** + * Setter for the validity flag for the minimum value. + * + * @param [in] min_valid Validity flag for the minimum value. + * + * @return void + */ + void setMinValidity (bool const min_valid); + + /** + * Getter for the validity flag for the minimum value. + * + * @return the validity flag for the minimum value + */ + bool isMinValid () const; + + /** + * Getter for the minimum value of the data type. + * + * @return the minimum value + */ + const std::string& getMinValue() const; + + /** + * Setter for the minimum value of the data type. + * + * @param [in] min_value The new minimum value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setMinValue (const std::string& min_value); + + /** + * Setter for the validity flag for the maximum value. + * + * @param [in] max_valid Validity flag for the maximum value. + * + * @return void + */ + void setMaxValidity (bool const max_valid); + + /** + * Getter for the validity flag for the maximum value. + * + * @return the validity flag for the maximum value + */ + bool isMaxValid () const; + + /** + * Getter for the maximum value of the data type. + * + * @return the maximum value + */ + const std::string& getMaxValue () const; + + /** + * Setter for the maximum value of the data type. + * + * @param [in] max_value The new maximum value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setMaxValue (const std::string& max_value); + + /** + * Setter for the validity flag for the default value. + * + * @param [in] default_valid Validity flag for the default value + * + * @return void + */ + void setDefaultValidity (bool const default_valid); + + /** + * Getter for the validity flag for the default value. + * + * @return the validity flag for the default value + */ + bool isDefaultValid () const; + + /** + * Getter for the default value. + * + * @return the default value + */ + const std::string& getDefaultValue () const; + + /** + * Setter for the default value. + * + * @param [in] default_value The new default value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setDefaultValue (const std::string& default_value); + + /** + * Setter for the validity flag for the scaling value. + * + * @param [in] scale_valid Validity flag for the scaling value + * + * @return void + */ + void setScaleValidity (bool const scale_valid); + + /** + * Getter for the validity flag for the scaling value. + * + * @return the validity flag for the scaling value. + */ + bool isScaleValid () const; + + /** + * Getter for the scaling value. + * + * @return the scaling value + */ + const std::string& getScaleValue () const; + + /** + * Setter for the scaling value. + * + * @param [in] scale_value The new scaling value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setScaleValue (const std::string& scale_value); + + /** + * Setter for the validity flag for the offset value. + * + * @param [in] offset_valid Validity flag for the offset value + * + * @return void + */ + void setOffsetValidity (bool const offset_valid); + + /** + * Getter for the validity flag for the offset value. + * + * @return the validity flag for the offset value. + */ + bool isOffsetValid () const; + + /** + * Getter for the offset value. + * + * @return the offset value. + */ + const std::string& getOffsetValue () const; + + /** + * Setter for the offset value. + * + * @param [in] offset_value The new offset value + * + * @retval a_util::result::SUCCESS Everything went fine. + */ + a_util::result::Result setOffsetValue (const std::string& offset_value); + + private: + IDDLDataType * _type; + std::string _name; + unsigned int _bytes_pos; + unsigned int _bit_pos; + unsigned int _num_bits; + std::string _description; + unsigned int _array_size; + std::string _array_size_source; + std::string _constant_value; + IDDLUnit * _unit; + DDLByteorder::Byteorder _byteorder; + DDLAlignment::AlignmentType _alignment; + std::string _comment; + bool _init_flag; + + bool _min_valid; + std::string _min_value; + bool _max_valid; + std::string _max_value; + bool _default_valid; + std::string _default_value; + bool _scale_valid; + std::string _scale_value; + bool _offset_valid; + std::string _offset_value; + }; +} // namespace ddl + +#endif // DDLELEMENT_H_INCLUDED diff --git a/ddlrepresentation/ddlenum.cpp b/ddlrepresentation/ddlenum.cpp new file mode 100644 index 0000000..4ad8a6b --- /dev/null +++ b/ddlrepresentation/ddlenum.cpp @@ -0,0 +1,230 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlenum.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + + struct tEnumName + { + tEnumName(std::string const& strEnumName) : m_strEnumName(strEnumName) { } + + bool operator () (std::pair const& oPair) + { + return (oPair.first == m_strEnumName); + } + + std::string m_strEnumName; + }; + + DDLEnum::DDLEnum() : + _name{}, + _name_values{}, + _unit{}, + _type{}, + _init_flag{}, + _level{1} + { + } + + DDLEnum::DDLEnum(IDDLDataType* poType, + const std::string& name, + const EnumNameValueVec& vecNameValues, + IDDLUnit* poUnit /*= NULL*/, + int nCreationLevel /*= 1 */ ) : + _name(name), + _name_values(vecNameValues), + _unit(poUnit), + _type(poType), + _init_flag(true), + _level(nCreationLevel) + { + } + + a_util::result::Result DDLEnum::accept(IDDLVisitor *poVisitor) const + { + return poVisitor->visit(this); + } + a_util::result::Result DDLEnum::accept(IDDLChangeVisitor *poVisitor) + { + return poVisitor->visit(this); + } + + const std::string& DDLEnum::getName() const + { + return _name; + } + + void DDLEnum::setName(const std::string& name) + { + _name = name; + } + + const EnumNameValueVec& DDLEnum::getValues() const + { + return _name_values; + } + + void DDLEnum::setValues(const EnumNameValueVec& vecNameValues) + { + _name_values = vecNameValues; + } + + const std::string& DDLEnum::getType() const + { + if (_type != NULL) + { + return _type->getName(); + } + + return a_util::strings::empty_string; + } + + void DDLEnum::setType( IDDLDataType* const pType ) + { + _type = pType; + } + + IDDLDataType * DDLEnum::getTypeObject() const + { + return _type; + } + + bool DDLEnum::isInitialized() const + { + return _init_flag; + } + + int DDLEnum::getCreationLevel() const + { + return _level; + } + + + a_util::result::Result DDLEnum::create(IDDLDataType* poType, + const std::string& name, + const EnumNameValueVec& vecNameValues, + IDDLUnit* poUnit /*= NULL*/, + int nCreationLevel /*= 1*/ ) + { + if (!poUnit || !poType) { return ERR_POINTER; } + _name = name; + _unit = poUnit; + _init_flag = true; + _level = nCreationLevel; + _name_values = vecNameValues; + _type = poType; + return a_util::result::SUCCESS; + } + + void DDLEnum::setUnit(IDDLUnit* poUnit) + { + _unit = poUnit; + } + + std::string DDLEnum::getUnit() const + { + if (NULL == _unit) + { + return a_util::strings::empty_string; + } + return _unit->getName(); + } + + IDDLUnit * DDLEnum::getUnitObject() const + { + if (!_init_flag) + { + return NULL; + } + return _unit; + } + + bool DDLEnum::isPredefined() const + { + return _level == -1; // cMediaManager::DL_AlwaysThere + } + + bool DDLEnum::isOverwriteable() const + { + return _level > 0; + } + + a_util::result::Result DDLEnum::removeElement(const std::string& strElement) + { + EnumNameValueVec::iterator itNameVal = + find_if(_name_values.begin(), _name_values.end(), tEnumName(strElement)); + if (itNameVal != _name_values.end()) + { + _name_values.erase(itNameVal); + return a_util::result::SUCCESS; + } + + return ERR_NOT_FOUND; + } + + a_util::result::Result DDLEnum::getValue(const std::string& strElement, std::string& strValue) const + { + EnumNameValueVec::const_iterator itNameVal = + find_if(_name_values.begin(), _name_values.end(), tEnumName(strElement)); + + if (itNameVal != _name_values.end()) + { + strValue = itNameVal->second; + return a_util::result::SUCCESS; + } + + return ERR_NOT_FOUND; + } + + a_util::result::Result DDLEnum::setValue(const std::string& strElement, const std::string& strValue) + { + EnumNameValueVec::iterator itNameVal = + find_if(_name_values.begin(), _name_values.end(), tEnumName(strElement)); + + if (itNameVal != _name_values.end()) + { + itNameVal->second = strValue; + return a_util::result::SUCCESS; + } + + return ERR_NOT_FOUND; + } + + a_util::result::Result DDLEnum::getNameForValue(const std::string& strValue, std::string& strElement) + { + for (EnumNameValueVec::iterator itNameVal = _name_values.begin(); + itNameVal != _name_values.end(); + ++itNameVal) + { + if (itNameVal->second == strValue) + { + strElement = itNameVal->first; + return a_util::result::SUCCESS; + } + } + return ERR_NOT_FOUND; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlenum.h b/ddlrepresentation/ddlenum.h new file mode 100644 index 0000000..a13860a --- /dev/null +++ b/ddlrepresentation/ddlenum.h @@ -0,0 +1,206 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLCONSTANT_H_INCLUDED +#define DDLCONSTANT_H_INCLUDED + +#include "ddl_common.h" +#include "ddldatatype_intf.h" +#include "ddlunit_intf.h" + +namespace ddl +{ + /** + * Container type of DDL enum elements + */ + typedef std::vector > EnumNameValueVec; + /** + * Representation for an enum inside a DDL description. + */ + class DDLEnum : public IDDLDataType + { + public: + /** + * Default CTOR + */ + DDLEnum(); + + /** + * CTOR + * @param[in] type - Pointer to the data-type object + * @param[in] name - Name of the created enum + * @param[in] name_values - Values of the enum + * @param[in] unit - Pointer to the unit of the datatype (optional) + * @param[in] creation_level - Level at creation time (optional) + */ + DDLEnum(IDDLDataType* type, + const std::string& name, + const EnumNameValueVec& name_values, + IDDLUnit* unit = NULL, + int creation_level = 1); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isPredefined() const; + bool isOverwriteable() const; + + const std::string& getName() const; + + /** + * Setter for the name of the element. + * @param [in] name Name of the element + * + * @return void + */ + void setName(const std::string& name); + + /** + * Getter for the Container type of DDL enum elements. + * + * @return Container type of DDL enum elements. + */ + const EnumNameValueVec& getValues() const; + + /** + * Setter for the DDL enum elements. + * + * @param [in] values Container type of DDL enum elements + * + * @return void. + */ + void setValues(const EnumNameValueVec& values); + + /** + * Getter for the value of the element. + * + * @param [in] element Name of the element + * @param [out] value Value of the element + * + * @return Standard result code. + */ + a_util::result::Result getValue(const std::string& element, std::string& value) const; + + /** + * Setter for the value of the element. + * + * @param [in] element Name of the element + * @param [in] value Value of the element + * + * @return Standard result code. + */ + a_util::result::Result setValue(const std::string& element, const std::string& value); + + /** + * Getter for the name of the element. + * + * @param [in] value Value of the element + * @param [out] element Name of the element + * + * @return Standard result code. + */ + a_util::result::Result getNameForValue(const std::string& value, std::string& element); + + + /** + * Getter for the data-type name. + * @return name of the data type + */ + const std::string& getType() const; + + /** + * Setter for the data-type object. + * + * @param [in] type pointer to the data-type object + * + * @return void + */ + void setType(IDDLDataType* const type); + + /** + * Getter for the data-type object. + * @return pointer to the data-type object + */ + IDDLDataType * getTypeObject() const; + + int getCreationLevel() const; + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] type - Pointer to the data-type object + * @param[in] name - Name of the created enum + * @param[in] name_values - Values of the enum + * @param[in] unit - Pointer to the unit of the datatype (optional) + * @param[in] creation_level - Level at creation time (optional) + * @return Standard result. + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(IDDLDataType* type, + const std::string& name, + const EnumNameValueVec& name_values, + IDDLUnit* unit = NULL, + int creation_level = 1); + + + + /** + * Setter for the unit. + * @param[in] unit - Pointer to the unit object of the data type + * + * @return void + */ + void setUnit(IDDLUnit* unit); + + /** + * Getter for the unit name. + * @return name of the referenced unit (\c a_util::strings::empty_string if there is none) + */ + std::string getUnit() const; + + /** + * Getter for the unit object. + * @return pointer to the unit object (\c NULL if there is none) + */ + IDDLUnit * getUnitObject() const; + + /** + * Remove the element with the provided name. + * @param[in] element - name of the element to be removed + * @return Standard result. + * @retval ERR_NOT_FOUND element not found + */ + a_util::result::Result removeElement(const std::string& element); + + private: + std::string _name; + EnumNameValueVec _name_values; + IDDLUnit *_unit; + IDDLDataType * _type; + + + bool _init_flag; + int _level; + + }; + +} // namespace ddl + +#endif // DDLCONSTANT_H_INCLUDED diff --git a/ddlrepresentation/ddlextdeclaration.cpp b/ddlrepresentation/ddlextdeclaration.cpp new file mode 100644 index 0000000..9c5d072 --- /dev/null +++ b/ddlrepresentation/ddlextdeclaration.cpp @@ -0,0 +1,86 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlextdeclaration.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + + DDLExtDeclaration::DDLExtDeclaration(const std::string& key, + const std::string& value) : + _key(key), _value(value), _init_flag(true) + { + } + + a_util::result::Result DDLExtDeclaration::accept(IDDLVisitor *visitor) const + { + return visitor->visit(this); + } + a_util::result::Result DDLExtDeclaration::accept(IDDLChangeVisitor *visitor) + { + return visitor->visit(this); + } + + const std::string& DDLExtDeclaration::getName() const + { + return _key; + } + + bool DDLExtDeclaration::isInitialized() const + { + return _init_flag; + } + + a_util::result::Result DDLExtDeclaration::create(const std::string& key, + const std::string& value) + { + if (key.empty()) + { + return ERR_INVALID_ARG; + } + _key = key; + _value = value; + _init_flag = true; + return a_util::result::SUCCESS; + } + + std::string DDLExtDeclaration::getKey() const + { + return _key; + } + + void DDLExtDeclaration::setKey(const std::string& key) + { + _key = key; + } + + + std::string DDLExtDeclaration::getValue() const + { + return _value; + } + + void DDLExtDeclaration::setValue(const std::string& value) + { + _value = value; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlextdeclaration.h b/ddlrepresentation/ddlextdeclaration.h new file mode 100644 index 0000000..2a860b3 --- /dev/null +++ b/ddlrepresentation/ddlextdeclaration.h @@ -0,0 +1,93 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLEXT_DECLARATION_H_INCLUDED +#define DDLEXT_DECLARATION_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + + /** + * Representation of an external declaration inside the header of a DDL + * description. + */ + class DDLExtDeclaration : public DDL + { + public: + /// Default CTOR + DDLExtDeclaration() = default; + + /** + * CTOR + * @param[in] key - Name of the additional information + * @param[in] value - Value of the additional information + */ + DDLExtDeclaration(const std::string& key, const std::string& value); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + const std::string& getName() const; + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] key - Name of the additional information + * @param[in] value - Value of the additional information + * @retval ERR_INVALID_ARG Empty key committed + */ + a_util::result::Result create(const std::string& key, const std::string& value); + + /** + * Getter for the key + * @return the key + */ + std::string getKey() const; + + /** + * Setter for the key + */ + void setKey(const std::string& key); + + /** + * Getter for the value + * @return the value + */ + std::string getValue() const; + + /** + * Setter for the Value + */ + void setValue(const std::string& value); + + private: + std::string _key; + std::string _value; + + bool _init_flag; + }; + +} // namespace ddl + +#endif // DDLEXT_DECLARATION_H_INCLUDED diff --git a/ddlrepresentation/ddlfactorymethod_intf.h b/ddlrepresentation/ddlfactorymethod_intf.h new file mode 100644 index 0000000..2324d33 --- /dev/null +++ b/ddlrepresentation/ddlfactorymethod_intf.h @@ -0,0 +1,124 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_BUILDER_H_INCLUDED +#define DDL_BUILDER_H_INCLUDED + +#include "ddl_common.h" +#include "ddlversion.h" + +namespace ddl +{ + class DDLDescription; + + /** + * Abstract base class/interface for Factory Method design-pattern. + */ + class IDDLFactoryMethod + { + public: + /** + * Getter for the DDL object. + * @return the DDL object + * @attention The caller/user has the responsibility for the created + * DDL object! Especially take this aspect into consideration in + * matters of the deallocation of memory! + */ + virtual DDLDescription * getDDL() const = 0; + + /** + * Method to build up a new DDL hierarchy. + * @param[in] version The version of the DDL hierarchy to be created. 0 Means newest version. + * @retval ERR_NOT_INITIALIZED Not yet initialized (see setter methods + * in concrete classes, e.g. \c DDLImporter::setFile()) + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. refUnit) + * @retval ERR_UNKNOWN Cross reference has not been resolved + * @retval ERR_NOT_FOUND At least one mandatory element (e.g. header) + * was not found. + */ + virtual a_util::result::Result createNew(const DDLVersion& version = DDLVersion::ddl_version_invalid) = 0; + + /** + * Method to destroy the DDL object and all contained objects. + */ + virtual void destroyDDL() = 0; + + /** + * Method to build a header object. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + */ + virtual a_util::result::Result buildHeader() = 0; + + /** + * Method to build a units object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. refUnit) + * @retval ERR_UNKNOWN Not all firstly unknown units have been resolved + */ + virtual a_util::result::Result buildUnits() = 0; + + /** + * Method to build a datatypes object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. unit) + */ + virtual a_util::result::Result buildDatatypes() = 0; + + /** + * Method to build a enums object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. refEnums) + * @retval ERR_UNKNOWN Not all firstly unknown structs have been + * resolved + */ + virtual a_util::result::Result buildEnums() = 0; + + /** + * Method to build a structs object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. datatype) + * @retval ERR_UNKNOWN Not all firstly unknown structs have been + * resolved + */ + virtual a_util::result::Result buildStructs() = 0; + + /** + * Method to build a streams object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. struct) + */ + virtual a_util::result::Result buildStreams() = 0; + + /** + * Method to build a streams object hierarchy. + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. struct) + */ + virtual a_util::result::Result buildStreamMetaTypes() = 0; + + /** + * DTOR + */ + virtual ~IDDLFactoryMethod(){} + }; + +} // namespace ddl + +#endif // DDL_BUILDER_H_INCLUDED diff --git a/ddlrepresentation/ddlheader.cpp b/ddlrepresentation/ddlheader.cpp new file mode 100644 index 0000000..c67da73 --- /dev/null +++ b/ddlrepresentation/ddlheader.cpp @@ -0,0 +1,256 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlheader.h" + +#include "ddlextdeclaration.h" +#include "ddldescription.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-20, ERR_NOT_FOUND); + + static const std::string strRegExDate [] = { + std::string("^(\\d{4})(\\d{2})(\\d{2})$"), + std::string("^(\\d{2})-(\\d{2})-(\\d{4})$"), + std::string("^(\\d{4})-(\\d{2})-(\\d{2})$"), + std::string("^(\\d{2})\\.(\\d{2})\\.(\\d{4})$") + }; + + DDLHeader& DDLHeader::operator=(DDLHeader other) + { + swap(*this, other); + return *this; + } + + DDLHeader::DDLHeader(DDLHeader&& other) + { + swap(*this, other); + } + + DDLHeader::~DDLHeader() + { + std::transform(_ddl_ext_declarations.begin(), + _ddl_ext_declarations.end(), _ddl_ext_declarations.begin(), + deleteChild); + } + + DDLHeader::DDLHeader(const DDLVersion& language_version, + const std::string& strAuthor, a_util::datetime::Date const sDateCreation, + a_util::datetime::Date const sDateChange, const std::string& strDescription, + DDLExtDeclarationVec vecExtDecls) : + _language_version(language_version), _author(strAuthor), + _date_creation(sDateCreation), _date_change(sDateChange), + _description(strDescription), _ddl_ext_declarations(vecExtDecls), + _init_flag(true) + { + } + + a_util::result::Result DDLHeader::create(DDLVersion& language_version, + const std::string& strAuthor, a_util::datetime::Date const sDateCreation, + a_util::datetime::Date const sDateChange, const std::string& strDescription, + DDLExtDeclarationVec vecExtDecls) + { + _language_version = language_version; + _author = strAuthor; + _date_creation = sDateCreation; + _date_change = sDateChange; + _description = strDescription; + _ddl_ext_declarations = vecExtDecls; + _init_flag = true; + return a_util::result::SUCCESS; + } + + a_util::datetime::Date DDLHeader::dateFromString(const std::string& strDate) + { + int32_t nDay = 0; + int32_t nMonth = 0; + int32_t nYear = 0; + a_util::datetime::Date sDate(1900, 1, 1); + + std::string arg1, arg2, arg3; + a_util::regex::RegularExpression oRegExDate(strRegExDate[0]); + if (oRegExDate.fullMatch(strDate, arg1, arg2, arg3)) + { + nYear = a_util::strings::toInt32(arg1); + nMonth = a_util::strings::toInt32(arg2); + nDay = a_util::strings::toInt32(arg3); + sDate = a_util::datetime::Date(nYear, nMonth, nDay); + } + oRegExDate.setPattern(strRegExDate[1]); + if (oRegExDate.fullMatch(strDate, arg1, arg2, arg3)) + { + nDay = a_util::strings::toInt32(arg1); + nMonth = a_util::strings::toInt32(arg2); + nYear = a_util::strings::toInt32(arg3); + sDate = a_util::datetime::Date(nYear, nMonth, nDay); + } + oRegExDate.setPattern(strRegExDate[2]); + if (oRegExDate.fullMatch(strDate, arg1, arg2, arg3)) + { + nYear = a_util::strings::toInt32(arg1); + nMonth = a_util::strings::toInt32(arg2); + nDay = a_util::strings::toInt32(arg3); + sDate = a_util::datetime::Date(nYear, nMonth, nDay); + } + oRegExDate.setPattern(strRegExDate[3]); + if (oRegExDate.fullMatch(strDate, arg1, arg2, arg3)) + { + nDay = a_util::strings::toInt32(arg1); + nMonth = a_util::strings::toInt32(arg2); + nYear = a_util::strings::toInt32(arg3); + sDate = a_util::datetime::Date(nYear, nMonth, nDay); + } + + return sDate; + } + + a_util::result::Result DDLHeader::accept(IDDLVisitor *poVisitor) const + { + return poVisitor->visit(this); + } + a_util::result::Result DDLHeader::accept(IDDLChangeVisitor *poVisitor) + { + return poVisitor->visit(this); + } + + const std::string& DDLHeader::getName() const + { + static std::string s_Name("Header"); + return s_Name; + } + + bool DDLHeader::isInitialized() const + { + return _init_flag; + } + + DDLVersion DDLHeader::getLanguageVersion() const + { + return _language_version; + } + + void DDLHeader::setLanguageVersion(const DDLVersion& language_version) + { + _language_version = language_version; + } + + std::string DDLHeader::getAuthor() const + { + return _author; + } + + void DDLHeader::setAuthor(const std::string& strAuthor) + { + _author = strAuthor; + } + + a_util::datetime::Date DDLHeader::getDateCreation() const + { + return _date_creation; + } + + a_util::datetime::Date DDLHeader::getDateChange() const + { + return _date_change; + } + + void DDLHeader::setDateChange(a_util::datetime::Date const sDateChange) + { + _date_change = sDateChange; + } + + void DDLHeader::setDateCreation(a_util::datetime::Date const sDateCreation) + { + _date_creation = sDateCreation; + } + + std::string DDLHeader::getDescription() const + { + return _description; + } + + void DDLHeader::setDescription(const std::string& strDescription) + { + _description = strDescription; + } + + void DDLHeader::setExtDeclarations(DDLExtDeclarationVec vecDDLExtDeclarations) + { + _ddl_ext_declarations = vecDDLExtDeclarations; + } + + void DDLHeader::addExtDeclaration(DDLExtDeclaration * poExtDeclaration, int nPos) + { + if (NULL != poExtDeclaration) + { + const DDLExtDeclarationVec::size_type szPos = + static_cast(nPos); + if (0 <= szPos && szPos < _ddl_ext_declarations.size()) + { + _ddl_ext_declarations.insert(_ddl_ext_declarations.begin() + szPos, + poExtDeclaration); + } + else + { + _ddl_ext_declarations.push_back(poExtDeclaration); + } + } + } + + a_util::result::Result DDLHeader::removeExtDeclaration(const std::string& strKey) + { + DDLExtDeclarationIt oIt = _ddl_ext_declarations.begin(); + while (oIt != _ddl_ext_declarations.end()) + { + if ((*oIt)->getKey() == strKey) + { + DDLDescription::deleteChild(*oIt); + _ddl_ext_declarations.erase(oIt); + return a_util::result::SUCCESS; + } + oIt++; + } + return ERR_NOT_FOUND; + } + + const DDLExtDeclarationVec& DDLHeader::getExtDeclarations() const + { + return _ddl_ext_declarations; + } + + DDLExtDeclarationVec& DDLHeader::getExtDeclarations() + { + return _ddl_ext_declarations; + } + + void swap(DDLHeader& lhs, DDLHeader& rhs) noexcept + { + using std::swap; + swap(lhs._language_version, rhs._language_version); + swap(lhs._author, rhs._author); + swap(lhs._date_creation, rhs._date_creation); + swap(lhs._date_change, rhs._date_change); + swap(lhs._description, rhs._description); + swap(lhs._ddl_ext_declarations, rhs._ddl_ext_declarations); + swap(lhs._init_flag, rhs._init_flag); + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlheader.h b/ddlrepresentation/ddlheader.h new file mode 100644 index 0000000..54eb851 --- /dev/null +++ b/ddlrepresentation/ddlheader.h @@ -0,0 +1,253 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_HEADER_H_INCLUDED +#define DDL_HEADER_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlvisitor_intf.h" +#include "ddlversion.h" + +namespace ddl +{ + + class DDLExtDeclaration; + + /** + * Container type of DDLExtDeclaration objects + */ + typedef std::vector DDLExtDeclarationVec; + /** + * Iterator type for DDLExtDeclarationVec + */ + typedef DDLExtDeclarationVec::iterator DDLExtDeclarationIt; + + /** + * Representation of the header of a DDL description. + */ + class DDLHeader : public DDL + { + public: + /** + * Default CTOR + */ + DDLHeader() = default; + + /** + * CTOR + * @param[in] language_version - Version number of the file where this description is based on + * @param[in] author - Author + * @param[in] date_creation - Creation date of file + * @param[in] date_change - Date of last changes + * @param[in] description - Short description of the file + * @param[in] ext_decls - Vector of external declarations (optional) + */ + DDLHeader(const DDLVersion& language_version, + const std::string& author, + a_util::datetime::Date const date_creation, + a_util::datetime::Date const date_change, + const std::string& description, + DDLExtDeclarationVec ext_decls = DDLExtDeclarationVec()); + + /** + * Copy CTOR + * @param[in] other - Reference to header object that should be copied + */ + DDLHeader(const DDLHeader&) = default; + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDL header type to copy from + * @return @c *this + */ + DDLHeader& operator=(DDLHeader other); + + /** + * Move CTOR + * @param[in,out] other DDL header type to move from - empty but valid when finished + */ + DDLHeader(DDLHeader&& other); + + + /** + * DTOR + */ + virtual ~DDLHeader(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + const std::string& getName() const; + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] language_version - Version number of the file where this description is based on + * @param[in] author - Author + * @param[in] date_creation - Creation date of file + * @param[in] date_change - Date of last changes + * @param[in] description - Short description of the file + * @param[in] ext_decls - Vector of external declarations (optional) + * + * @return Standard result. + */ + a_util::result::Result create(DDLVersion& language_version, const std::string& author, + a_util::datetime::Date const date_creation, a_util::datetime::Date const date_change, + const std::string& description, + DDLExtDeclarationVec ext_decls = DDLExtDeclarationVec()); + + /** + * Getter for the language version. + * @return the language version + */ + DDLVersion getLanguageVersion() const; + + /** + * Setter for the language version. + * @param[in] language_version - the language version + * @return void + */ + void setLanguageVersion(const DDLVersion& language_version); + + /** + * Getter for the author. + * @return the author + */ + std::string getAuthor() const; + + /** + * Setter for the author. + * @param[in] author - Author + * + * @return void + */ + void setAuthor(const std::string& author); + + /** + * Getter for the creation date. + * @return the creation date + */ + a_util::datetime::Date getDateCreation() const; + + /** + * Setter for the creation date. + * @param[in] date_creation - Creation date to set + * + * @return void + */ + void setDateCreation(a_util::datetime::Date const date_creation); + + /** + * Getter for the change date. + * @return the change date + */ + a_util::datetime::Date getDateChange() const; + + /** + * Setter for the change date. + * @param[in] date_change - Change date to set + * + * @return void + */ + void setDateChange(a_util::datetime::Date const date_change); + + /** + * Getter for the description. + * @return the description + */ + std::string getDescription() const; + + /** + * Setter for the description. + */ + void setDescription(const std::string& description); + + /** + * Setter for the external declarations + * @param[in] ext_declarations - Vector of external declarations + * + * @return void + */ + void setExtDeclarations(DDLExtDeclarationVec ext_declarations); + + /** + * Adder for an external declaration + * @param[in] ext_declarations - Pointer to the external declaration + * @param[in] pos - Position to add the external declaration + * + * @return void + */ + void addExtDeclaration(DDLExtDeclaration * ext_declarations, int pos = -1); + + /** + * Removes the external declaration with the given key. + * @param [in] key - Key of the external declaration which should be removed + * @retval ERR_NOT_FOUND The specified key was not found + */ + a_util::result::Result removeExtDeclaration(const std::string& key); + + /** + * Getter for the external declarations + * @return the external declarations + */ + const DDLExtDeclarationVec& getExtDeclarations() const; + + /** + * Getter for the external declarations + * @return the external declarations + */ + DDLExtDeclarationVec& getExtDeclarations(); + + /** + * Helper method to extract a date out of a string. + * Following date formats are supported (complying with DDL spec):
    + *
  • yyyymmdd
  • + *
  • dd-mm-yyyy
  • + *
  • yyyy-mm-dd
  • + *
  • dd.mm.yyyy
+ * + * @param[in] date - String containing the date + * @return the date structure + */ + static a_util::datetime::Date dateFromString(const std::string& date); + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl header + * @param[in,out] rhs Right-hand side ddl header + */ + friend void swap(DDLHeader& lhs, DDLHeader& rhs) noexcept; + + + private: + DDLVersion _language_version; + std::string _author; + a_util::datetime::Date _date_creation; + a_util::datetime::Date _date_change; + std::string _description; + DDLExtDeclarationVec _ddl_ext_declarations; + + bool _init_flag; + }; + +} // namespace ddl + +#endif // DDL_HEADER_H_INCLUDED diff --git a/ddlrepresentation/ddlimporter.cpp b/ddlrepresentation/ddlimporter.cpp new file mode 100644 index 0000000..36cb992 --- /dev/null +++ b/ddlrepresentation/ddlimporter.cpp @@ -0,0 +1,2662 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlimporter.h" +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + +#include "ddlversion.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-2, ERR_UNKNOWN) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-15, ERR_RESOURCE_IN_USE) + _MAKE_RESULT(-18, ERR_NO_CLASS) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-27, ERR_OPEN_FAILED) + _MAKE_RESULT(-36, ERR_UNKNOWN_FORMAT) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + /** + * Iterator type for cDOMElementList + */ + typedef a_util::xml::DOMElementList::iterator tDOMElemIt; + + #define RETURN_IF_FAILED_AND_LOG_ERROR_STR_DDLIMPORTER(code, desc) \ + { \ + a_util::result::Result __err_code = code; \ + if (isFailed(__err_code)){ _fnLogOutput(( desc ), LOG_LVL_ERROR, __FILE__, (uint32_t) __LINE__, (code)); \ + ImporterMsg sError = {std::string(desc), importer_error}; \ + _errors.push_back(sError); \ + return (__err_code); }\ + } + + DDLImporter::DDLImporter(bool bBasicCheck, bool bSorted) : + _dom{}, + _ddl_desc{}, + _current_ref_ddl{}, + _unknown_units{}, + _unknown_structs{}, + _unknown_stream_meta_types{}, + _init_flag{}, + _creation_level{1}, + _full_check{}, + _errors{}, + _basic_check{bBasicCheck}, + _merge_defaults{true}, + _sorted{bSorted}, + _prefere_reference{true} + { + } + + DDLImporter::DDLImporter(const a_util::filesystem::Path& strFile, bool bBasicCheck, bool bSorted) : + DDLImporter(bBasicCheck, bSorted) + { + _init_flag = isOk(setFile(strFile)); + } + + DDLImporter::DDLImporter(const char* strFile, bool bBasicCheck, bool bSorted) : + DDLImporter(a_util::filesystem::Path(strFile), bBasicCheck, bSorted) + { + } + + DDLImporter::DDLImporter(int nCreationLevel, bool bBasicCheck, bool bSorted) : + DDLImporter(bBasicCheck, bSorted) + { + _creation_level = nCreationLevel; + } + + DDLImporter& DDLImporter::operator=(DDLImporter other) + { + swap(*this, other); + return *this; + } + + DDLImporter::DDLImporter(DDLImporter&& other) + { + swap(*this, other); + } + + DDLImporter::~DDLImporter() + { + // The DDL object does not get deleted because the caller/user of this + // object is responsible for it. + _ddl_desc = NULL; + _current_ref_ddl = NULL; + _unknown_units.deleteAll(); + _unknown_structs.deleteAll(); + _unknown_stream_meta_types.deleteAll(); + } + + void swap(DDLImporter& lhs, DDLImporter& rhs) noexcept + { + using std::swap; + swap(lhs._basic_check, rhs._basic_check); + swap(lhs._creation_level, rhs._creation_level); + swap(lhs._current_ref_ddl, rhs._current_ref_ddl); + swap(lhs._ddl_desc, rhs._ddl_desc); + swap(lhs._dom, rhs._dom); + swap(lhs._errors, rhs._errors); + swap(lhs._full_check, rhs._full_check); + swap(lhs._init_flag, rhs._init_flag); + swap(lhs._merge_defaults, rhs._merge_defaults); + swap(lhs._prefere_reference, rhs._prefere_reference); + swap(lhs._sorted, rhs._sorted); + swap(lhs._unknown_stream_meta_types, rhs._unknown_stream_meta_types); + swap(lhs._unknown_structs, rhs._unknown_structs); + swap(lhs._unknown_units, rhs._unknown_units); + } + + std::string DDLImporter::getErrorDesc() const + { + // compatibility to cDDLChecker + return getLastErrorDesc(); + } + + std::string DDLImporter::getLastErrorDesc() const + { + // return description of most recently added error element + for (ImporterMsgList::const_reverse_iterator itMsgs = _errors.rbegin(); + _errors.rend() != itMsgs; ++itMsgs) + { + if (importer_error == itMsgs->severity) + { + return std::string(itMsgs->desc); + } + } + return a_util::strings::empty_string; + } + + void DDLImporter::printAllMessages(ImporterMsgSeverity eLeastSeverity /* = importer_info */) + { + for (ImporterMsgList::const_iterator itMsg = _errors.begin(); + _errors.end() != itMsg; ++itMsg) + { + switch (itMsg->severity) + { + case importer_error: + { + LOG_ERROR(itMsg->desc.c_str()); + break; + } + case importer_warning: + { + if (importer_error != eLeastSeverity) + { + LOG_WARNING(itMsg->desc.c_str()); + } + break; + } + case importer_info: + { + if (importer_info == eLeastSeverity) + { + LOG_INFO(itMsg->desc.c_str()); + } + break; + } + default: + { + LOG_ERROR("Unknown message severity detected."); + break; + } + } + } + } + + ImporterMsgList DDLImporter::getAllMessages() const + { + return _errors; + } + + DDLDescription * DDLImporter::getDDL() const + { + return _ddl_desc; + } + + void DDLImporter::destroyDDL() + { + destroyDDL(_ddl_desc); + _ddl_desc = NULL; + // no DDL objects => no valid messages + _errors.clear(); + } + + void DDLImporter::destroyDDL(DDLDescription *poDDL) + { + delete poDDL; + } + + a_util::result::Result DDLImporter::setFile(const a_util::filesystem::Path& strFile) + { + _init_flag = _dom.load(strFile); + if (!_init_flag) + { + ImporterMsg sError = {_dom.getLastError(), importer_error }; + _errors.push_back(sError); + return ERR_OPEN_FAILED; + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::setXML(const std::string& strXML) + { + _init_flag = _dom.fromString(strXML); + if (!_init_flag) + { + ImporterMsg sError = {_dom.getLastError(), importer_error}; + _errors.push_back(sError); + LOG_ERROR(_dom.getLastError().c_str()); + return ERR_OPEN_FAILED; + } + return a_util::result::SUCCESS; + } + + void DDLImporter::setCreationLevel(int const nLevel) + { + _creation_level = nLevel; + } + + void DDLImporter::setFullCheckDescriptionMode(bool bFullCheck) + { + _full_check = bFullCheck; + } + + void DDLImporter::setMergeDefaults(bool bMergeDefaults) + { + _merge_defaults = bMergeDefaults; + } + + void DDLImporter::setPreferReferenceEntities(bool bPrefereReference) + { + _prefere_reference = bPrefereReference; + } + + a_util::result::Result DDLImporter::createNew(const DDLVersion& requestedVersion /* = 0 */) + { + DDLVersion version = requestedVersion; + if (version == DDLVersion::ddl_version_invalid) + { + version = DDLVersion::ddl_version_current; + } + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + // The DDL object does not get deleted because the caller/user of this + // object is responsible for it. + _ddl_desc = NULL; + // build up new DDL + if (_full_check) + { + if (isFailed(buildHeader()) && _ddl_desc == NULL) + { + _ddl_desc = new DDLDescription(new DDLHeader(), + DDLUnitVec(_sorted), + DDLBaseunitVec(_sorted), + DDLPrefixVec(_sorted), + DDLDTVec(_sorted), + DDLComplexVec(_sorted), + DDLStreamVec(_sorted), + DDLEnumVec(_sorted), + _merge_defaults); + } + buildUnits(); + buildDatatypes(); + buildEnums(); + buildStructs(); + buildStreams(); + if (version >= DDLVersion::ddl_version_40) buildStreamMetaTypes(); + // check if any error occurred during build up new DDL + for (ImporterMsgList::const_iterator itMsg = _errors.begin(); + _errors.end() != itMsg; ++itMsg) + { + if (itMsg->severity == importer_error) + { + return ERR_UNKNOWN_FORMAT; + } + } + } + else + { + RETURN_IF_FAILED(buildHeader()); + RETURN_IF_FAILED(buildUnits()); + RETURN_IF_FAILED(buildDatatypes()); + RETURN_IF_FAILED(buildEnums()); + RETURN_IF_FAILED(buildStructs()); + RETURN_IF_FAILED(buildStreams()); + if (version >= DDLVersion::ddl_version_40) RETURN_IF_FAILED(buildStreamMetaTypes()); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::createPartial(const DDLDescription* poRefDDL, const DDLVersion& requestedVersion) + { + DDLVersion version = requestedVersion; + if (!poRefDDL) { return ERR_POINTER; } + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + _current_ref_ddl = poRefDDL; + _ddl_desc = NULL; + std::string strElementType = _dom.getRoot().getName(); + + if (strElementType == "adtf:ddl" || + strElementType == "description" || + strElementType == "units" || + strElementType == "datatypes" || + strElementType == "structs" || + strElementType == "streams" || + strElementType == "enums" || + strElementType == "streammetatypes" || + (strElementType != "datatype" + && strElementType != "baseunit" + && strElementType != "prefixes" + && strElementType != "unit" + && strElementType != "datatype" + && strElementType != "struct" + && strElementType != "stream" + && strElementType != "enum" + && strElementType != "streammetatype")) + { + a_util::xml::DOMElement oRoot = _dom.getRoot(); + a_util::xml::DOMElement oTmpElement; + bool bValidElementFound = false; + bool bFoundEnums = false; + //this is to detect 2.0 MediaDescriptions + //i.e. the device-tb etc. uses enums!! and did not raise the version number at all!!! + if (_dom.findNode("//enums", oTmpElement)) + { + bFoundEnums = true; + if (version < DDLVersion::ddl_version_20) + { + version = DDLVersion::ddl_version_20; + } + } + if (oRoot.findNode("header", oTmpElement)) + { + RETURN_IF_FAILED(buildHeader()); + bValidElementFound = true; + } + else + { + _ddl_desc = DDLDescription::createDefault(version, _creation_level, _sorted); + } + //this is to detect 2.0 MediaDescriptions + //i.e. the device-tb etc. uses enums!! and did not raise the version number at all!!!device-tb etc. uses enums!! and did not raise the version number at all!!! + if (_ddl_desc && _ddl_desc->getHeader() && bFoundEnums) + { + if (_ddl_desc->getHeader()->getLanguageVersion() < DDLVersion::ddl_version_20) + { + _ddl_desc->getHeader()->setLanguageVersion(DDLVersion::ddl_version_20); + } + } + if (_dom.findNode("//units", oTmpElement)) + { + RETURN_IF_FAILED(buildUnits()); + bValidElementFound = true; + } + if (_dom.findNode("//datatypes", oTmpElement)) + { + RETURN_IF_FAILED(buildDatatypes()); + bValidElementFound = true; + } + if (_dom.findNode("//enums", oTmpElement)) + { + RETURN_IF_FAILED(buildEnums()); + bValidElementFound = true; + } + if (_dom.findNode("//structs", oTmpElement)) + { + RETURN_IF_FAILED(buildStructs()); + bValidElementFound = true; + } + if (_dom.findNode("//streams", oTmpElement)) + { + RETURN_IF_FAILED(buildStreams()); + bValidElementFound = true; + } + if (_dom.findNode("//streammetatypes", oTmpElement)) + { + RETURN_IF_FAILED(buildStreamMetaTypes()); + bValidElementFound = true; + } + + _current_ref_ddl = NULL; + if (!bValidElementFound) + { + return ERR_UNKNOWN_FORMAT; + } + return a_util::result::SUCCESS; + } + // _current_ref_ddl = NULL; + _ddl_desc = DDLDescription::createDefault(version, _creation_level, _sorted); + DDLBaseunit * poBUTmp = NULL; + if (strElementType == "baseunit") + { + RETURN_IF_FAILED(buildSingleBaseunit(&poBUTmp, _dom.getRoot())); + _ddl_desc->addBaseunit(poBUTmp); + return a_util::result::SUCCESS; + } + DDLPrefix * poPrefixTmp = NULL; + if (strElementType == "prefixes") + { + RETURN_IF_FAILED(buildSinglePrefix(&poPrefixTmp, _dom.getRoot())); + _ddl_desc->addPrefix(poPrefixTmp); + return a_util::result::SUCCESS; + } + DDLUnit * poUnitTmp = NULL; + if (strElementType == "unit") + { + RETURN_IF_FAILED(buildSingleUnit(&poUnitTmp, _dom.getRoot())); + _ddl_desc->addUnit(poUnitTmp); + return a_util::result::SUCCESS; + } + if (strElementType == "datatype") + { + DDLDataType * poDTTmp = NULL; + RETURN_IF_FAILED(buildSingleDatatype(&poDTTmp, _dom.getRoot())); + _ddl_desc->addDatatype(poDTTmp); + return a_util::result::SUCCESS; + } + if (strElementType == "enum") + { + DDLEnum * poEnumTmp = NULL; + RETURN_IF_FAILED(buildSingleEnum(&poEnumTmp, _dom.getRoot())); + _ddl_desc->addEnum(poEnumTmp); + return a_util::result::SUCCESS; + } + if (strElementType == "struct") + { + DDLComplex * poStructTmp = NULL; + RETURN_IF_FAILED(buildSingleStruct(&poStructTmp, _dom.getRoot())); + _ddl_desc->addStruct(poStructTmp); + return a_util::result::SUCCESS; + } + if (strElementType == "stream") + { + DDLStream * poStreamTmp = NULL; + RETURN_IF_FAILED(buildSingleStream(&poStreamTmp, _dom.getRoot())); + _ddl_desc->addStream(poStreamTmp); + return a_util::result::SUCCESS; + } + if (strElementType == "streammetatype") + { + RETURN_IF_FAILED(buildSingleStreamMetaType(_dom.getRoot(), + _ddl_desc->getStreamMetaTypes())); + return a_util::result::SUCCESS; + } + return ERR_UNKNOWN_FORMAT; + } + + a_util::result::Result DDLImporter::buildHeader() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oHeaderElement; + a_util::xml::DOMElement oTmpElement; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!_dom.findNode("//header", oHeaderElement)) + { + pushMessage(std::string("DDL does not contain a header."), importer_error); + return ERR_OPEN_FAILED; + } + else + { + std::string strVersion = a_util::strings::empty_string; + if (!oHeaderElement.findNode("language_version", oTmpElement)) + { + pushMessage(std::string("DDL does not contain a language_version in header"), importer_error); + nResult = ERR_NOT_FOUND; + if (false == _full_check) + { + return nResult; + } + } + else + { + strVersion = oTmpElement.getData(); + a_util::strings::trim(strVersion); + } + std::string strAuthor = a_util::strings::empty_string; + if (!oHeaderElement.findNode("author", oTmpElement)) + { + pushMessage(std::string("DDL does not contain an author in header."), importer_error); + nResult = ERR_NOT_FOUND; + if (false == _full_check) + { + return nResult; + } + } + else + { + strAuthor = oTmpElement.getData(); + } + a_util::datetime::Date sDateCreation(1900, 1, 1); + if (!oHeaderElement.findNode("date_creation", oTmpElement)) + { + pushMessage(std::string("DDL does not contain a creation date in header."), importer_error); + nResult = ERR_NOT_FOUND; + if (false == _full_check) + { + return nResult; + } + } + else + { + sDateCreation = DDLHeader::dateFromString(oTmpElement.getData()); + } + a_util::datetime::Date sDateChange(1900, 1, 1); + if (!oHeaderElement.findNode("date_change", oTmpElement)) + { + pushMessage(std::string("DDL does not contain a change date in header."), importer_error); + nResult = ERR_NOT_FOUND; + if (false == _full_check) + { + return nResult; + } + } + else + { + sDateChange = DDLHeader::dateFromString(oTmpElement.getData()); + } + std::string strDescription = a_util::strings::empty_string; + if (!oHeaderElement.findNode("description", oTmpElement)) + { + pushMessage(std::string("DDL does not contain a description in header."), importer_error); + nResult = ERR_NOT_FOUND; + if (false == _full_check) + { + return nResult; + } + } + else + { + strDescription = oTmpElement.getData(); + } + // do not continue with header, if any header property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + DDLExtDeclarationVec vecExtDecls; + _ddl_desc = new DDLDescription(new DDLHeader(DDLVersion::fromString(strVersion), + strAuthor, sDateCreation, sDateChange, strDescription, vecExtDecls), + DDLUnitVec(_sorted), + DDLBaseunitVec(_sorted), + DDLPrefixVec(_sorted), + DDLDTVec(_sorted), + DDLComplexVec(_sorted), + DDLStreamVec(_sorted), + DDLEnumVec(_sorted), + _merge_defaults); + return nResult; + } + a_util::xml::DOMElementList oExtDeclarations; + oHeaderElement.findNodes("ext_declaration", oExtDeclarations); + DDLExtDeclarationVec vecExtDecls; + for (tDOMElemIt it = oExtDeclarations.begin(); oExtDeclarations.end() != it; ++it) + { + a_util::result::Result nRes; + if (!it->hasAttribute("key")) + { + pushMessage(std::string("There is an external declaration without key in header."), importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + else + { + if (!it->hasAttribute("value")) + { + pushMessage(a_util::strings::format("The external declaration with key '%s' has no value.", + it->getAttribute("key").c_str()), importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + } + if (!it->hasAttribute("value")) + { + pushMessage(std::string("There is an external declaration without value in header."), importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + // do not create new DDLExtDeclaration, if any key property could not found (all properties are mandatory!) + continue; + } + vecExtDecls.push_back(new DDLExtDeclaration(it->getAttribute("key"), + it->getAttribute("value"))); + } + _ddl_desc = new DDLDescription(new DDLHeader(DDLVersion::fromString(strVersion), + strAuthor, sDateCreation, sDateChange, strDescription, vecExtDecls), + DDLUnitVec(_sorted), + DDLBaseunitVec(_sorted), + DDLPrefixVec(_sorted), + DDLDTVec(_sorted), + DDLComplexVec(_sorted), + DDLStreamVec(_sorted), + DDLEnumVec(_sorted), + _merge_defaults); + if (isFailed(nResult)) + { + return nResult; + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildSingleBaseunit(DDLBaseunit ** ppoNewBU, const a_util::xml::DOMElement& oBUElement) + { + if (!ppoNewBU) { return ERR_POINTER; } + *ppoNewBU = NULL; + std::string name = oBUElement.getAttribute("name"); + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!oBUElement.hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'baseunit' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + if (!oBUElement.hasAttribute("symbol")) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'baseunit' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'baseunit' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + if (!oBUElement.hasAttribute("description")) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'description' is missing in 'baseunit' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'description' is missing in 'baseunit' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + // do not create new DDLBaseunit, if any base unit property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + *ppoNewBU = new DDLBaseunit(oBUElement.getAttribute("name"), oBUElement.getAttribute("symbol"), + oBUElement.getAttribute("description"), _creation_level); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildSinglePrefix(DDLPrefix ** ppoNewPrefix, + const a_util::xml::DOMElement& oPrefixElement) + { + if (!ppoNewPrefix) { return ERR_POINTER; } + *ppoNewPrefix = NULL; + std::string name = oPrefixElement.getAttribute("name"); + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!oPrefixElement.hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'prefix' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + if (!oPrefixElement.hasAttribute("symbol")) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'prefix' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'symbol' is missing in 'prefix' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + if (!oPrefixElement.hasAttribute("power")) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'power' is missing in 'prefix' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'power' is missing in 'prefix' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + // do not create new DDLPrefix, if any prefix property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + *ppoNewPrefix = new DDLPrefix(oPrefixElement.getAttribute("name"), + oPrefixElement.getAttribute("symbol"), a_util::strings::toInt32(oPrefixElement.getAttribute("power")), + _creation_level); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildSingleUnit(DDLUnit ** ppoNewUnit, + const a_util::xml::DOMElement& oUnitElement) + { + if (!ppoNewUnit) { return ERR_POINTER; } + *ppoNewUnit = NULL; + + DDLBaseunitVec vecDDLBaseunits = _ddl_desc->getBaseunits(); + DDLPrefixVec vecDDLPrefixes = _ddl_desc->getPrefixes(); + DDLUnitVec vecDDLUnits = _ddl_desc->getUnits(); + + DDLBaseunitVec vecDDLBaseunitRefs; + DDLPrefixVec vecDDLPrefixeRefs; + DDLUnitVec vecDDLUnitRefs; + + if (_current_ref_ddl != NULL) + { + vecDDLUnitRefs = _current_ref_ddl->getUnits(); + vecDDLPrefixeRefs = _current_ref_ddl->getPrefixes(); + vecDDLBaseunitRefs = _current_ref_ddl->getBaseunits(); + } + + a_util::result::Result nResult = a_util::result::SUCCESS; + std::string name = oUnitElement.getAttribute("name"); + if (name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'unit' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + a_util::xml::DOMElement oTmpElement; + std::string strNumerator = a_util::strings::empty_string; + if (!oUnitElement.findNode("numerator", oTmpElement)) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'numerator' is missing in 'unit' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'numerator' is missing in 'unit' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + strNumerator = oTmpElement.getData(); + } + + std::string strDenominator = a_util::strings::empty_string; + if (!oUnitElement.findNode("denominator", oTmpElement)) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'denominator' is missing in 'unit' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'denominator' is missing in 'unit' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + strDenominator = oTmpElement.getData(); + } + + double fOffset = 0.0F; + if (!oUnitElement.findNode("offset", oTmpElement)) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'offset' is missing in 'unit' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'offset' is missing in 'unit' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + fOffset = static_cast (a_util::strings::toDouble(oTmpElement.getData())); + } + + a_util::xml::DOMElementList oRefUnits; + oUnitElement.findNodes("refUnit", oRefUnits); + DDLRefUnitVec vecDDLRefUnits; + a_util::result::Result nRes = a_util::result::SUCCESS; + for (tDOMElemIt itRU = oRefUnits.begin(); + oRefUnits.end() != itRU; ++itRU) + { + std::string strRefUnitName = a_util::strings::empty_string; + if (itRU->hasAttribute("name")) + { + strRefUnitName = itRU->getAttribute("name"); + } + nRes = a_util::result::SUCCESS; + if (!itRU->hasAttribute("name") || + !itRU->hasAttribute("power") || + !itRU->hasAttribute("prefix")) + { + std::transform(vecDDLRefUnits.begin(), vecDDLRefUnits.end(), vecDDLRefUnits.begin(), DDLDescription::deleteChild); + + if (!itRU->hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'refUnit' tag."), + importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + if (!itRU->hasAttribute("power")) + { + if (!strRefUnitName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'power' is missing in 'refUnit' tag '%s'.", + strRefUnitName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'power' is missing in 'refUnit' tag."), + importer_error); + } + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + if (!itRU->hasAttribute("prefix")) + { + if (!strRefUnitName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'prefix' is missing in 'refUnit' tag '%s'.", + strRefUnitName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'prefix' is missing in 'refUnit' tag."), + importer_error); + } + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nRes; + } + // do not continue with this ref unit, if any property could not found (all properties are mandatory!) + continue; + } + } + + DDLPrefix* pPrefix = tryToFind(itRU->getAttribute("prefix"), vecDDLPrefixeRefs, vecDDLPrefixes ); + if (pPrefix == NULL) + { + // not found in prefixes vector => not defined + if (!name.empty() && !strRefUnitName.empty()) + { + pushMessage(a_util::strings::format("RefUnit '%s' in unit '%s' references to unknown prefix '%s'", + strRefUnitName.c_str(), name.c_str(), itRU->getAttribute("prefix").c_str()), importer_error); + } + else if (!name.empty()) + { + pushMessage(a_util::strings::format("RefUnit in unit '%s' references to unknown prefix '%s'", + name.c_str(), itRU->getAttribute("prefix").c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("RefUnit in unit references to unknown prefix '%s'", + itRU->getAttribute("prefix").c_str()), importer_error); + } + std::transform(vecDDLRefUnits.begin(), vecDDLRefUnits.end(), vecDDLRefUnits.begin(), DDLDescription::deleteChild); + nRes = ERR_NO_CLASS; + if (false == _full_check) + { + return nRes; + } + } + + std::string strAttr = itRU->getAttribute("name"); + DDLBaseunit* pBaseUnit = tryToFind(strAttr, vecDDLBaseunitRefs, vecDDLBaseunits); + if (pBaseUnit == NULL) + { + DDLUnit* pUnit = tryToFind(strAttr, vecDDLUnitRefs, vecDDLUnits); + if (pUnit == NULL) + { + pUnit = tryToFind(strAttr, _unknown_units, vecDDLUnits); + if (pUnit == NULL) + { + // => create placeholder object, mark Unit object + // as unknown, and continue + pUnit = new DDLUnit(strAttr, "1", "1", 0.0f); + _unknown_units.insert(pUnit); + vecDDLRefUnits.push_back(new DDLRefUnit(pUnit, + a_util::strings::toInt32(itRU->getAttribute("power")), + pPrefix)); + } + else + { + // already marked as unknown + vecDDLRefUnits.push_back(new DDLRefUnit(pUnit, + a_util::strings::toInt32(itRU->getAttribute("power")), + pPrefix)); + } + } + else + { + // known Unit + vecDDLRefUnits.push_back(new DDLRefUnit(pUnit, + a_util::strings::toInt32(itRU->getAttribute("power")), + pPrefix)); + } + } + else + { + vecDDLRefUnits.push_back(new DDLRefUnit(pBaseUnit, + a_util::strings::toInt32(itRU->getAttribute("power")), + pPrefix)); + } + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + } + } + // do not create new DDLUnit, if any unit property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + DDLUnitIt itUnknown = std::find_if(_unknown_units.begin(), _unknown_units.end(), DDLCompareFunctor<>(name)); + if (_unknown_units.end() == itUnknown) + { + // create new object + *ppoNewUnit = new DDLUnit(name, strNumerator, strDenominator, fOffset, DDLRefUnitVec(), _creation_level); + + } + else + { + // use placeholder object + (*itUnknown)->create(name, strNumerator, strDenominator, fOffset, DDLRefUnitVec(), _creation_level); + *ppoNewUnit = *itUnknown; + // unmark object + _unknown_units.erase(itUnknown); + } + (*ppoNewUnit)->setRefUnits(vecDDLRefUnits); + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildUnits() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oUnits; + if (!_dom.findNode("//units", oUnits)) + { + // as units are not supported in ADTF => no error + pushMessage(std::string("DDL does not contain the 'units' element."), + importer_warning); + return a_util::result::SUCCESS; + } + else + { + a_util::result::Result nResult = a_util::result::SUCCESS; + + // build up base-unit objects + a_util::xml::DOMElementList oBaseunits; + if (!oUnits.findNodes("baseunit", oBaseunits)) + { + // no error + } + else + { + DDLBaseunitVec vecDDLBaseunits(_sorted); + a_util::result::Result nRes = a_util::result::SUCCESS; + for (tDOMElemIt itBU = oBaseunits.begin(); + oBaseunits.end() != itBU; ++itBU) + { + DDLBaseunit * poBUTmp = NULL; + nRes = buildSingleBaseunit(&poBUTmp, *itBU); + if (isFailed(nRes)) + { + vecDDLBaseunits.deleteAll(); + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + if (_basic_check && vecDDLBaseunits.find(poBUTmp->getName())) + { + pushMessage(a_util::strings::format("The baseunit '%s' is specified more than once.", + poBUTmp->getName().c_str()), importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + vecDDLBaseunits.insert(poBUTmp); + } + _ddl_desc->refBaseunits(vecDDLBaseunits); + } + + // build up prefix objects + a_util::xml::DOMElementList oPrefixes; + if (!oUnits.findNodes("prefixes", oPrefixes)) + { + // => no error + } + else + { + DDLPrefixVec vecDDLPrefixes(_sorted); + a_util::result::Result nRes = a_util::result::SUCCESS; + for (tDOMElemIt itP = oPrefixes.begin(); + oPrefixes.end() != itP; ++itP) + { + DDLPrefix * poPrefixTmp = NULL; + nRes = buildSinglePrefix(&poPrefixTmp, *itP); + if (isFailed(nRes)) + { + vecDDLPrefixes.deleteAll(); + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + if (_basic_check && vecDDLPrefixes.find(poPrefixTmp->getName())) + { + pushMessage(a_util::strings::format("The prefix '%s' is specified more than once.", + poPrefixTmp->getName().c_str()), importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + vecDDLPrefixes.insert(poPrefixTmp); + } + _ddl_desc->refPrefixes(vecDDLPrefixes); + } + + // build up unit objects + a_util::xml::DOMElementList oUnitList; + if (!oUnits.findNodes("unit", oUnitList)) + { + // => no error + } + else + { + DDLUnitVec vecDDLUnits(_sorted); + a_util::result::Result nRes = a_util::result::SUCCESS; + _ddl_desc->cloneUnits(vecDDLUnits); + for (tDOMElemIt itU = oUnitList.begin(); oUnitList.end() != itU; ++itU) + { + DDLUnit * poUnitTmp = NULL; + nRes = buildSingleUnit(&poUnitTmp, *itU); + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + if (_basic_check && _ddl_desc->getUnitByName(poUnitTmp->getName())) + { + pushMessage(a_util::strings::format("The unit '%s' is specified more than once.", + poUnitTmp->getName().c_str()), importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + _ddl_desc->addUnit(poUnitTmp); + } + } + for (DDLUnitIt itUnknown = _unknown_units.begin(); + _unknown_units.end() != itUnknown; ++itUnknown) + { + pushMessage(a_util::strings::format("The unit '%s' was referenced but not specified.", + (*itUnknown)->getName().c_str()), importer_error); + nResult = ERR_UNKNOWN; + if (false == _full_check) + { + return nResult; + } + } + if (!_unknown_units.empty()) + { + std::stringstream logUnspecifiedStructs; + logUnspecifiedStructs<< "The following units are unknown in this description: "; + for (DDLUnitIt itUnknown = _unknown_units.begin(); + _unknown_units.end() != itUnknown; ++itUnknown) + { + logUnspecifiedStructs << " " << (*itUnknown)->getName(); + if (false == _full_check) + { + logUnspecifiedStructs << "."; + pushMessage(logUnspecifiedStructs.str(), importer_error); + nResult = ERR_UNKNOWN; + return nResult; + } + logUnspecifiedStructs << ","; + } + logUnspecifiedStructs.seekp(-1, logUnspecifiedStructs.cur); + logUnspecifiedStructs << "."; + pushMessage(logUnspecifiedStructs.str(), importer_error); + nResult = ERR_UNKNOWN; + } + if (isFailed(nResult)) + { + return nResult; + } + } + return a_util::result::SUCCESS; + } + +a_util::result::Result DDLImporter::buildSingleDatatype(DDLDataType ** ppoNewDatatype, const a_util::xml::DOMElement& oDTElement) +{ + if (!ppoNewDatatype) { return ERR_POINTER; } + *ppoNewDatatype = NULL; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!oDTElement.hasAttribute("size")) + { + pushMessage(a_util::strings::format("Attribute 'size' is missing in 'datatype' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + std::string name = a_util::strings::empty_string; + if (_ddl_desc->getHeader()->getLanguageVersion() <= DDLVersion::ddl_version_11) + { + if (!oDTElement.hasAttribute("type")) + { + if (oDTElement.hasAttribute("name")) + { + //NF: ADTF ist robust!! + name = oDTElement.getAttribute("name"); + } + else + { + pushMessage(a_util::strings::format("Attribute 'type' is missing in 'datatype' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + } + else + { + name = oDTElement.getAttribute("type"); + } + } + else + { + if (!oDTElement.hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'datatype' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + name = oDTElement.getAttribute("name"); + } + } + std::string strDescription = a_util::strings::empty_string; + if (oDTElement.hasAttribute("description")) + { + strDescription = oDTElement.getAttribute("description"); + } + unsigned int uiArraysize = 1; + if (oDTElement.hasAttribute("arraysize")) + { + uiArraysize = static_cast + (a_util::strings::toUInt32(oDTElement.getAttribute("arraysize"))); + } + DDLAlignment::AlignmentType eAlignment = DDLAlignment::e1; + if (oDTElement.hasAttribute("alignment")) + { + eAlignment = DDLAlignment::fromString(oDTElement.getAttribute("alignment")); + if (eAlignment == DDLAlignment::e_invalid) + { + pushMessage(a_util::strings::format("Attribute 'alignment' is out of range in 'datatype' tag '%s'.", + name.c_str()), importer_error); + nResult = ERR_INVALID_ARG; + if (false == _full_check) + { + return nResult; + } + } + } + if (oDTElement.hasAttribute("size")) + { + std::string s = oDTElement.getAttribute("size"); + if (!a_util::strings::isInt32(s) || a_util::strings::toInt32(s) <= 0) + { + pushMessage(a_util::strings::format("Attribute 'size' is out of range in 'datatype' tag '%s'.", + name.c_str()), importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + } + std::string strMinVal; + bool bMinValid = false; + if (oDTElement.hasAttribute("min")) + { + strMinVal = oDTElement.getAttribute("min"); + bMinValid = true; + } + std::string strMaxVal; + bool bMaxValid = false; + if (oDTElement.hasAttribute("max")) + { + strMaxVal = oDTElement.getAttribute("max"); + bMaxValid = true; + } + IDDLUnit* pUnitRef = NULL; + if (oDTElement.hasAttribute("unit")) + { + DDLBaseunit* pBaseUnit = NULL; + DDLUnit* pUnit = NULL; + + DDLBaseunitVec vecDDLBaseunits = _ddl_desc->getBaseunits(); + DDLUnitVec vecDDLUnits = _ddl_desc->getUnits(); + + DDLUnitVec vecDDLUnitRefs; + DDLBaseunitVec vecDDLBaseunitRefs; + + if (_current_ref_ddl) + { + vecDDLBaseunitRefs = _current_ref_ddl->getBaseunits(); + vecDDLUnitRefs = _current_ref_ddl->getUnits(); + } + + std::string strAttr = oDTElement.getAttribute("unit"); + pBaseUnit = tryToFind(strAttr, vecDDLBaseunitRefs, vecDDLBaseunits); + if (pBaseUnit == NULL) + { + pUnit = tryToFind(strAttr, vecDDLUnitRefs, vecDDLUnits); + if (pUnit == NULL) + { + pushMessage(a_util::strings::format("No 'unit' or 'refUnit' found with name='%s' defined in datatype '%s'.", + strAttr.c_str(), name.c_str()), importer_error); + nResult = ERR_NO_CLASS; + if (false == _full_check) + { + return nResult; + } + } + else + { + pUnitRef = (IDDLUnit*) pUnit; + } + } + else + { + pUnitRef = (IDDLUnit*) pBaseUnit; + } + } + *ppoNewDatatype = new DDLDataType(name, + static_cast(a_util::strings::toUInt32(oDTElement.getAttribute("size"))), + pUnitRef, + strDescription, + eAlignment, + uiArraysize, + _creation_level, + a_util::strings::empty_string, + bMinValid, + strMinVal, + bMaxValid, + strMaxVal); + + // Add version information for behavior differentiation + DDLVersion language_version = DDLVersion::getDefaultVersion(); + DDLHeader* pHeader = _ddl_desc->getHeader(); + if (NULL != pHeader) + { + language_version = pHeader->getLanguageVersion(); + } + (*ppoNewDatatype)->setDDLVersion(language_version); + + return a_util::result::SUCCESS; +} + + a_util::result::Result DDLImporter::buildDatatypes() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oDatatypesNode; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!_dom.findNode("//datatypes", oDatatypesNode)) + { + pushMessage(std::string("DDL does not contain the 'datatypes' element"), + importer_error); + return ERR_NOT_FOUND; + } + a_util::xml::DOMElementList oDatatypes; + oDatatypesNode.findNodes("datatype", oDatatypes); + DDLDTVec vecDDLDataTypes(_sorted); + for (tDOMElemIt it = oDatatypes.begin(); oDatatypes.end() != it; ++it) + { + DDLDataType * poDTTmp = NULL; + a_util::result::Result nRes = buildSingleDatatype(&poDTTmp, *it); + if (isFailed(nRes)) + { + vecDDLDataTypes.deleteAll(); + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + if (_basic_check && vecDDLDataTypes.find(poDTTmp->getName())) + { + pushMessage(a_util::strings::format("The datatype '%s' is specified more than once.", + poDTTmp->getName().c_str()), + importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + vecDDLDataTypes.insert(poDTTmp); + } + _ddl_desc->refDatatypes(vecDDLDataTypes); + if (isFailed(nResult)) + { + return nResult; + } + return a_util::result::SUCCESS; + } + + static inline bool CheckAttrib(const a_util::xml::DOMAttributes oAttrs, const std::string& strAttrib, unsigned int& nRes) + { + a_util::xml::DOMAttributes::const_iterator itAttr = oAttrs.find(strAttrib); + if (itAttr != oAttrs.end()) + { + nRes = a_util::strings::toUInt32(itAttr->second); + return true; + } + + return false; + } + + static inline bool CheckAttrib(const a_util::xml::DOMAttributes oAttrs, const std::string& strAttrib, std::string& strRes) + { + a_util::xml::DOMAttributes::const_iterator itAttr = oAttrs.find(strAttrib); + if (itAttr != oAttrs.end()) + { + strRes = itAttr->second.c_str(); + return true; + } + + return false; + } + + a_util::result::Result DDLImporter::buildSingleStruct(DDLComplex ** ppoNewStruct, const a_util::xml::DOMElement& oStructElement) + { + if (!ppoNewStruct) { return ERR_POINTER; } + *ppoNewStruct = NULL; + + // get already defined types + DDLDTVec vecDTs = _ddl_desc->getDatatypes(); + DDLComplexVec vecStructs = _ddl_desc->getStructs(); + DDLEnumVec vecEnums = _ddl_desc->getEnums(); + + // get already defined types + DDLDTVec vecDTRefs; + DDLComplexVec vecStructRefs; + DDLEnumVec vecEnumRefs; + if (_current_ref_ddl) + { + vecDTRefs = _current_ref_ddl->getDatatypes(); + vecStructRefs = _current_ref_ddl->getStructs(); + vecEnumRefs = _current_ref_ddl->getEnums(); + } + + a_util::result::Result nResult = a_util::result::SUCCESS; + std::string strStructName = oStructElement.getAttribute("name"); + if (!oStructElement.hasAttribute("name")) + { + strStructName = oStructElement.getAttribute("type"); + if (!oStructElement.hasAttribute("type")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'struct' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + } + + // mandatory property, but no error (compatibility to former DDL versions) + std::string strVersion = a_util::strings::empty_string; + if (!oStructElement.hasAttribute("version")) + { + // mandatory property, but no error (compatibility to former DDL versions) + } + else + { + strVersion = oStructElement.getAttribute("version"); + } + std::string strComment = a_util::strings::empty_string; + if (oStructElement.hasAttribute("comment")) + { + strComment = oStructElement.getAttribute("comment"); + } + DDLAlignment::AlignmentType eAlignment = DDLAlignment::e1; + if (oStructElement.hasAttribute("alignment")) + { + std::string strAttr = oStructElement.getAttribute("alignment"); + eAlignment = DDLAlignment::fromString(strAttr); + if (eAlignment == DDLAlignment::e_invalid) + { + pushMessage(a_util::strings::format("The struct '%s' has an invalid alignment of '%s'", strStructName.c_str(), strAttr.c_str()), + importer_error); + nResult = ERR_INVALID_ARG; + if (false == _full_check) + { + return nResult; + } + } + } + a_util::xml::DOMElementList oElements; + oStructElement.findNodes("element", oElements); + DDLElementVec vecDDLElements; + for (tDOMElemIt itElem = oElements.begin(); + oElements.end() != itElem; + ++itElem) + { + std::string strElementName; + if (itElem->hasAttribute("name")) + { + strElementName = itElem->getAttribute("name"); + } + + if (_basic_check && + std::find_if(vecDDLElements.begin(), vecDDLElements.end(), + DDLCompareFunctor(strElementName)) != vecDDLElements.end()) + { + pushMessage(a_util::strings::format("The struct element name '%s.%s' is already used", strStructName.c_str(), strElementName.c_str()), + importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + + // check optional attributes + unsigned int uiBitpos = 0; + CheckAttrib(itElem->getAttributes(), "bitpos", uiBitpos); + + unsigned int uiNumBits = 0; + CheckAttrib(itElem->getAttributes(), "numbits", uiNumBits); + + a_util::result::Result nRes = a_util::result::SUCCESS; + bool bNoBytePosSet = !itElem->hasAttribute("bytepos"); + std::string strBytePos = itElem->getAttribute("bytepos"); + bool bNoByteOrderSet = !itElem->hasAttribute("byteorder"); + std::string strByteOrder = itElem->getAttribute("byteorder"); + bool bNoAlignmentSet = !itElem->hasAttribute("alignment"); + std::string strAlignment = itElem->getAttribute("alignment"); + + a_util::xml::DOMElement oDeserialized; + if (itElem->findNode("deserialized", oDeserialized)) + { + bNoAlignmentSet = !oDeserialized.hasAttribute("alignment"); + strAlignment = oDeserialized.getAttribute("alignment"); + } + a_util::xml::DOMElement oSerialized; + if (itElem->findNode("serialized", oSerialized)) + { + bNoBytePosSet = !oSerialized.hasAttribute("bytepos"); + strBytePos = oSerialized.getAttribute("bytepos"); + bNoByteOrderSet = !oSerialized.hasAttribute("byteorder"); + strByteOrder = oSerialized.getAttribute("byteorder"); + CheckAttrib(oSerialized.getAttributes(), "bitpos", uiBitpos); + CheckAttrib(oSerialized.getAttributes(), "numbits", uiNumBits); + } + + if (!itElem->hasAttribute("type") || + !itElem->hasAttribute("name") || + bNoBytePosSet || + !itElem->hasAttribute("arraysize") || + bNoByteOrderSet || + bNoAlignmentSet) + { + std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild); + if (!itElem->hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'struct' tag."), + importer_error); + } + if (!itElem->hasAttribute("type")) + { + if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'type' is missing in 'struct' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'type' is missing in 'struct' tag."), + importer_error); + } + } + if (bNoBytePosSet) + { + if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'bytepos' is missing in 'struct' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'bytepos' is missing in 'struct' tag."), + importer_error); + } + } + if (!itElem->hasAttribute("arraysize")) + { + if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'arraysize' is missing in 'struct' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'arraysize' is missing in 'struct' tag."), + importer_error); + } + } + if (bNoByteOrderSet) + { + if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'byteorder' is missing in 'struct' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'byteorder' is missing in 'struct' tag."), + importer_error); + } + } + if (bNoAlignmentSet) + { + if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("Attribute 'alignment' is missing in 'struct' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'alignment' is missing in 'struct' tag."), + importer_error); + } + + } + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + + if (itElem->getAttribute("type") == strStructName) + { + std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild); + pushMessage(a_util::strings::format("Unresolvable recursion in struct '%s'.", + strStructName.c_str()), importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + // resolve type + // if the Importer is called with createPartial then the DDL will search for Referenced first + // after that it will reference to a local DDL Type or put it to the unresolved types + DDLDataType * poDataType = NULL; + DDLComplex * poComplex = NULL; + DDLEnum* poEnum = NULL; + + std::string strTypeAttr = itElem->getAttribute("type"); + poDataType = tryToFind(strTypeAttr, vecDTRefs, vecDTs); + + if (poDataType == NULL) + { + poComplex = tryToFind(strTypeAttr, vecStructRefs, vecStructs); + if (poComplex == NULL) + { + poComplex = tryToFind(strTypeAttr, _unknown_structs, vecStructs); + if (poComplex == NULL) + { + poEnum = tryToFind(strTypeAttr, vecEnumRefs, vecEnums); + if(poEnum == NULL) + { + // => create object, mark it, and continue + poComplex = new DDLComplex(strTypeAttr, 1); + _unknown_structs.insert(poComplex); + } + } + } + } + + if (_basic_check && itElem->hasAttribute("arraysize")) + { + if (uiNumBits > 0 && a_util::strings::toInt32(itElem->getAttribute("arraysize")) > 1) + { + pushMessage(a_util::strings::format("Attribute 'numbits' is not allowed in array elements."), + importer_error); + return ERR_INVALID_ARG; + } + } + + std::string strDescription; + CheckAttrib(itElem->getAttributes(), "description", strDescription); + + std::string strComment; + CheckAttrib(itElem->getAttributes(), "comment", strComment); + + // value is used in combination with enums to implement constants + std::string strConstantValue; + CheckAttrib(itElem->getAttributes(), "value", strConstantValue); + + std::string strMinValue; + bool bMinValid = CheckAttrib(itElem->getAttributes(), "min", strMinValue); + + std::string strMaxValue; + bool bMaxValid = CheckAttrib(itElem->getAttributes(), "max", strMaxValue); + + std::string strDefaultValue; + bool bDefaultValid = CheckAttrib(itElem->getAttributes(), "default", strDefaultValue); + + std::string strScaleValue; + bool bScaleValid = CheckAttrib(itElem->getAttributes(), "scale", strScaleValue); + + std::string strOffsetValue; + bool bOffsetValid = CheckAttrib(itElem->getAttributes(), "offset", strOffsetValue); + + // resolve unit + // if the Importer is called with createPartial then the DDL will search for Referenced first + // after that it will reference to a local DDL Type or put it to the unresolved types + DDLUnit* poUnit = NULL; + DDLBaseunit* poBaseUnit = NULL; + IDDLUnit* pUnitRef = NULL; + + if (itElem->hasAttribute("unit")) + { + DDLUnitVec vecDDLUnits = _ddl_desc->getUnits(); + DDLUnitVec vecDDLUnitRefs; + if (_current_ref_ddl != NULL) + { + vecDDLUnitRefs = _current_ref_ddl->getUnits(); + } + DDLBaseunitVec vecDDLBaseUnits = _ddl_desc->getBaseunits(); + DDLBaseunitVec vecDDLBaseUnitRefs; + if (_current_ref_ddl != NULL) + { + vecDDLBaseUnitRefs = _current_ref_ddl->getBaseunits(); + } + + std::string strUnitAttr = itElem->getAttribute("unit"); + poUnit = tryToFind(strUnitAttr, vecDDLUnitRefs, vecDDLUnits); + if (poUnit == NULL) + { + poBaseUnit = tryToFind(strUnitAttr, vecDDLBaseUnitRefs, vecDDLBaseUnits); + if (poBaseUnit != NULL) + { + pUnitRef = (IDDLUnit*) poBaseUnit; + } + } + else + { + pUnitRef = (IDDLUnit*) poUnit; + } + if (pUnitRef == NULL) + { + std::transform(vecDDLElements.begin(), vecDDLElements.end(), vecDDLElements.begin(), DDLDescription::deleteChild); + pushMessage(a_util::strings::format("Missing class '%s' for unit in element '%s' in struct '%s'.", + strUnitAttr.c_str(), strElementName.c_str(), strStructName.c_str()), importer_error); + nRes = ERR_NO_CLASS; + if (false == _full_check) + { + return nRes; + } + } + } + + // do not continue with struct, if any mandatory property could not found + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + + if (DDLAlignment::fromString(strAlignment) == DDLAlignment::e_invalid) + { + pushMessage(a_util::strings::format("The struct element '%s.%s' has an invalid alignment of '%s'", strStructName.c_str(), strElementName.c_str(), strAlignment.c_str()), + importer_error); + nResult = ERR_INVALID_ARG; + if (false == _full_check) + { + return nResult; + } + } + + const std::string& strArraySize = itElem->getAttribute("arraysize"); + if (NULL == poDataType) + { + if (poEnum != NULL) + { + bool bIsDynamic = !a_util::strings::isUInt32(strArraySize); + + vecDDLElements.push_back(new DDLElement(poEnum, + strElementName, + static_cast(a_util::strings::toUInt32(strBytePos)), + bIsDynamic ? 0 : static_cast(a_util::strings::toUInt32(strArraySize)), + DDLByteorder::fromString(strByteOrder), + DDLAlignment::fromString(strAlignment), + pUnitRef, + uiBitpos, + uiNumBits, + strDescription, + strComment, + bIsDynamic ? strArraySize: a_util::strings::empty_string, + strConstantValue)); + } + else + { + bool bIsDynamic = !a_util::strings::isUInt32(strArraySize); + + vecDDLElements.push_back(new DDLElement(poComplex, + strElementName, + static_cast(a_util::strings::toUInt32(strBytePos)), + bIsDynamic ? 0 : static_cast(a_util::strings::toUInt32(strArraySize)), + DDLByteorder::fromString(strByteOrder), + DDLAlignment::fromString(strAlignment), + pUnitRef, + uiBitpos, + uiNumBits, + strDescription, + strComment, + bIsDynamic ? strArraySize : a_util::strings::empty_string)); + } + } + else + { + bool bIsDynamic = !a_util::strings::isUInt32(strArraySize); + + vecDDLElements.push_back(new DDLElement(poDataType, + strElementName, + static_cast(a_util::strings::toUInt32(strBytePos)), + bIsDynamic ? 0 : static_cast(a_util::strings::toUInt32(strArraySize)), + DDLByteorder::fromString(strByteOrder), + DDLAlignment::fromString(strAlignment), + pUnitRef, + uiBitpos, + uiNumBits, + strDescription, + strComment, + bIsDynamic ? strArraySize : a_util::strings::empty_string, + a_util::strings::empty_string, + bMinValid, + strMinValue, + bMaxValid, + strMaxValue, + bDefaultValid, + strDefaultValue, + bScaleValid, + strScaleValue, + bOffsetValid, + strOffsetValue)); + } + } + // do not create new DDLComplex, if any mandatory property could not found + if (isFailed(nResult)) + { + return nResult; + } + DDLComplexIt itUnknown = std::find_if(_unknown_structs.begin(), _unknown_structs.end(), DDLCompareFunctor<>(oStructElement.getAttribute("name"))); + if (_unknown_structs.end() == itUnknown) + { + // create new object + *ppoNewStruct = new DDLComplex(strStructName, + static_cast(a_util::strings::toUInt32(strVersion)), + strComment, + eAlignment, + DDLElementVec(), + _creation_level); + } + else + { + // use placeholder object and fill it with concrete data + (*itUnknown)->create(strStructName, + static_cast(a_util::strings::toUInt32(strVersion)), + strComment, + eAlignment, + DDLElementVec(), + _creation_level); + *ppoNewStruct = *itUnknown; + // unmark object + _unknown_structs.erase(itUnknown); + } + + if (oStructElement.hasAttribute("ddlversion")) + { + auto version = DDLVersion::fromString(oStructElement.getAttribute("ddlversion")); + (*ppoNewStruct)->setDDLVersion(version); + } + else + { + // Add version information for behavior differentiation + DDLVersion language_version = DDLVersion::getDefaultVersion(); + DDLHeader* pHeader = _ddl_desc->getHeader(); + if (NULL != pHeader) + { + language_version = pHeader->getLanguageVersion(); + } + (*ppoNewStruct)->setDDLVersion(language_version); + } + + (*ppoNewStruct)->setElements(vecDDLElements); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildStructs() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oStructs; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!_dom.findNode("//structs", oStructs)) + { + pushMessage(std::string("DDL does not contain the 'structs' element"), + importer_error); + return ERR_NOT_FOUND; + } + else + { + // build up struct objects + a_util::xml::DOMElementList oStructList; + if (!oStructs.findNodes("struct", oStructList)) + { + // => no error + } + else + { + DDLComplexVec vecStructs(_sorted); + _ddl_desc->cloneStructs(vecStructs); + for (tDOMElemIt it = oStructList.begin(); oStructList.end() != it; ++it) + { + DDLComplex * poStructTmp = NULL; + a_util::result::Result nRes = buildSingleStruct(&poStructTmp, *it); + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + if (_basic_check && vecStructs.find(poStructTmp->getName())) + { + pushMessage(a_util::strings::format("The struct '%s' is specified more than once.", + poStructTmp->getName().c_str()), + importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + _ddl_desc->addStruct(poStructTmp); + } + + for (DDLComplexIt itUnknown = _unknown_structs.begin(); + _unknown_structs.end() != itUnknown; ++itUnknown) + { + pushMessage(a_util::strings::format("The struct '%s' was referenced but not defined.", + (*itUnknown)->getName().c_str()), importer_error); + } + + if (!_unknown_structs.empty()) + { + + vecStructs.deleteAll(); + // unmark object + pushMessage(std::string("There are undefined types/structs in this description."), + importer_error); + nResult = ERR_UNKNOWN; + if (false == _full_check) + { + return nResult; + } + } + } + if (isFailed(nResult)) + { + return nResult; + } + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildSingleStream(DDLStream ** ppoNewStream, a_util::xml::DOMElement oStreamElement) + { + if (!ppoNewStream) { return ERR_POINTER; } + *ppoNewStream = NULL; + std::string name = a_util::strings::empty_string; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!oStreamElement.hasAttribute("name")) + { + if (!oStreamElement.hasAttribute("type")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'stream' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + // compatibility with old versions + oStreamElement.setAttribute("name", oStreamElement.getAttribute("type")); + name = oStreamElement.getAttribute("type"); + } + } + else + { + name = oStreamElement.getAttribute("name"); + } + + // resolve type + DDLComplexVec vecStructs = _ddl_desc->getStructs(); + DDLComplexVec vecStructRefs; + if (_current_ref_ddl) + { + vecStructRefs = _current_ref_ddl->getStructs(); + } + + DDLComplex* pTypeFound = tryToFind(oStreamElement.getAttribute("type"), vecStructRefs , vecStructs); + + if (pTypeFound == NULL) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("The type '%s' of the stream '%s' is not defined.", + oStreamElement.getAttribute("type").c_str(), name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("The type '%s' of an unnamed stream is not defined.", + oStreamElement.getAttribute("type").c_str()), importer_error); + } + nResult = ERR_NO_CLASS; + if (false == _full_check) + { + return nResult; + } + } + + // check optional attribute + std::string strDescription = a_util::strings::empty_string; + if (oStreamElement.hasAttribute("description")) + { + strDescription = oStreamElement.getAttribute("description"); + } + a_util::xml::DOMElementList oStructs; + oStreamElement.findNodes("struct", oStructs); + DDLStreamStructVec vecDDLStreamStructs; + for (tDOMElemIt itStruct = oStructs.begin(); + oStructs.end() != itStruct; ++itStruct) + { + std::string strElementName = itStruct->getAttribute("name"); + a_util::result::Result nRes = a_util::result::SUCCESS; + if (!itStruct->hasAttribute("type") || + !itStruct->hasAttribute("bytepos")) + { + std::transform(vecDDLStreamStructs.begin(), vecDDLStreamStructs.end(), vecDDLStreamStructs.begin(), DDLDescription::deleteChild); + if (!strElementName.empty() && !name.empty()) + { + pushMessage(a_util::strings::format("The struct '%s' in stream '%s' is missing required attributes (type/bytepos).", + strElementName.c_str(), name.c_str()), importer_error); + } + else if (!name.empty()) + { + pushMessage(a_util::strings::format("An unnamed struct in stream '%s' is missing required attributes (type/bytepos).", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("An unnamed struct in an unnamed stream is missing required attributes (type/bytepos)."), + importer_error); + } + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + + // resolve type + DDLComplex* pStreamStructType = tryToFind(itStruct->getAttribute("type"), vecStructRefs , vecStructs); + if (pStreamStructType == NULL) + { + std::transform(vecDDLStreamStructs.begin(), vecDDLStreamStructs.end(), vecDDLStreamStructs.begin(), DDLDescription::deleteChild); + pushMessage(a_util::strings::format("The type '%s' of a struct of stream '%s' is not defined.", + itStruct->getAttribute("type").c_str(), name.c_str()), importer_error); + nRes = ERR_NO_CLASS; + if (false == _full_check) + { + return nRes; + } + } + + // check optional attribute + std::string strStructName = pStreamStructType->getName(); + if (itStruct->hasAttribute("name")) + { + strStructName = itStruct->getAttribute("name"); + } + // do not continue with stream struct, if any mandatory property could not found + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + vecDDLStreamStructs.push_back(new DDLStreamStruct(pStreamStructType, + static_cast(a_util::strings::toUInt32(itStruct->getAttribute("bytepos"))), + strStructName)); + } + // do not create new DDLStream, if any mandatory property could not found + if (isFailed(nResult)) + { + return nResult; + } + *ppoNewStream = new DDLStream(pTypeFound, + name, + strDescription, + DDLStreamStructVec(), + _creation_level); + // Add version information for behavior differentiation + DDLVersion language_version = DDLVersion::ddl_version_invalid; + DDLHeader* pHeader = _ddl_desc->getHeader(); + if (NULL != pHeader) + { + language_version = pHeader->getLanguageVersion(); + } + (*ppoNewStream)->setDDLVersion(language_version); + (*ppoNewStream)->refStructs(vecDDLStreamStructs); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildStreams() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oStreams; + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!_dom.findNode("//streams", oStreams)) + { + pushMessage(std::string("DDL does not contain the 'streams' element"), + importer_error); + return nResult; + } + else + { + a_util::xml::DOMElementList oStreamList; + DDLStreamVec vecStreams(_sorted); + if (!oStreams.findNodes("stream", oStreamList)) + { + // => no error + } + else + { + for (tDOMElemIt it = oStreamList.begin(); oStreamList.end() != it; ++it) + { + DDLStream * poStreamTmp = NULL; + a_util::result::Result nRes = buildSingleStream(&poStreamTmp, *it); + if (isFailed(nRes)) + { + vecStreams.deleteAll(); + nResult = nRes; + if (isFailed(nResult)) + { + return nResult; + } + continue; + } + if (_basic_check && vecStreams.find(poStreamTmp->getName())) + { + pushMessage(a_util::strings::format("The stream '%s' is specified more than once.", + poStreamTmp->getName().c_str()), + importer_error); + nResult = ERR_RESOURCE_IN_USE; + if (false == _full_check) + { + return nResult; + } + } + vecStreams.insert(poStreamTmp); + } + // make all elements of stream vector unique + _ddl_desc->refStreams(vecStreams); + } + if (isFailed(nResult)) + { + return nResult; + } + } + return a_util::result::SUCCESS; + } + + void DDLImporter::pushMessage(const std::string& strMsg, ImporterMsgSeverity severity) + { + ImporterMsg sError = {strMsg, severity}; + _errors.push_back(sError); + } + + template + T* DDLImporter::tryToFind(const std::string& name, + DDLContainer& first_data, + DDLContainer& second_data) + { + T* pRes = NULL; + if (_prefere_reference) + { + pRes = first_data.find(name); + if (!pRes) + { + pRes = second_data.find(name); + } + } + else + { + pRes = second_data.find(name); + if (!pRes) + { + pRes = first_data.find(name); + } + } + + return pRes; + } + + a_util::result::Result DDLImporter::buildEnums() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oEnums; + if (!_dom.findNode("//enums", oEnums)) + { + //kompatibilit�t zu alten files!! + if (_ddl_desc->getHeader()->getLanguageVersion() < DDLVersion::ddl_version_20) + { + return a_util::result::SUCCESS; + } + else + { + pushMessage(std::string("DDL does not contain the 'enums' element."), + importer_warning); + } + return a_util::result::SUCCESS; + } + else + { + a_util::result::Result nResult = a_util::result::SUCCESS; + + // build up enum objects + a_util::xml::DOMElementList oEnumList; + if (!oEnums.findNodes("enum", oEnumList)) + { + // => no error + } + else + { + DDLEnumVec vecDDLEnums(_sorted); + for (tDOMElemIt it = oEnumList.begin(); oEnumList.end() != it; ++it) + { + DDLEnum * poEnumTmp = NULL; + a_util::result::Result nRes = buildSingleEnum(&poEnumTmp, *it); + if (isFailed(nRes)) + { + vecDDLEnums.deleteAll(); + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + vecDDLEnums.insert(poEnumTmp); + } + _ddl_desc->refEnums(vecDDLEnums); + } + if (isFailed(nResult)) + { + return nResult; + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildSingleEnum( DDLEnum** ppoNewEnum, const a_util::xml::DOMElement& oEnumElement ) + { + if (!ppoNewEnum) { return ERR_POINTER; } + *ppoNewEnum = NULL; + std::string name = oEnumElement.getAttribute("name"); + a_util::result::Result nResult = a_util::result::SUCCESS; + if (!oEnumElement.hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'enum' tag."), + importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + + std::string strType; + if (!oEnumElement.hasAttribute("type")) + { + if (!name.empty()) + { + pushMessage(a_util::strings::format("Attribute 'type' is missing in 'constant' tag '%s'.", + name.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("Attribute 'type' is missing in 'constant' tag."), + importer_error); + } + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + else + { + strType = oEnumElement.getAttribute("type"); + } + // do not continue with enum, if any enum property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + + EnumNameValueVec vecNameValues; + a_util::xml::DOMElementList oEnumElements; + oEnumElement.findNodes("element", oEnumElements); + a_util::result::Result nRes = a_util::result::SUCCESS; + for (a_util::xml::DOMElementList::iterator itEnumElement = oEnumElements.begin(); + itEnumElement != oEnumElements.end(); + ++itEnumElement) + { + nRes = a_util::result::SUCCESS; + + std::string strElementName; + if(!itEnumElement->hasAttribute("name")) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'enum/element' tag."), + importer_error); + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + else + { + strElementName = itEnumElement->getAttribute("name"); + } + + std::string strElementValue; + if(!itEnumElement->hasAttribute("value")) + { + if (!name.empty() && !strElementName.empty()) + { + pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag '%s/%s'.", + name.c_str(), strElementName.c_str()), importer_error); + } + else if (!strElementName.empty()) + { + pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag '%s'.", + strElementName.c_str()), importer_error); + } + else + { + pushMessage(a_util::strings::format("No 'value' defined in 'enum/element' tag."), + importer_error); + } + nRes = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nRes; + } + } + else + { + strElementValue = itEnumElement->getAttribute("value"); + } + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + return nResult; + } + continue; + } + vecNameValues.push_back(std::make_pair(std::string(strElementName), std::string(strElementValue))); + } + // do not continue with enum, if any enum element property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + + // get already defined types + DDLDTVec vecDTs = _ddl_desc->getDatatypes(); + + // get already defined types + DDLDTVec vecDTRefs; + if (_current_ref_ddl) + { + vecDTRefs = _current_ref_ddl->getDatatypes(); + } + + DDLDataType * poDataType = NULL; + + poDataType = tryToFind(strType, vecDTRefs, vecDTs); + if (poDataType == NULL) + { + pushMessage(a_util::strings::format("Data type '%s' could not be resolved.", + strType.c_str()), importer_error); + nResult = ERR_UNKNOWN_FORMAT; + if (false == _full_check) + { + return nResult; + } + } + // do not create new DDLEnum, if any enum property could not found (all properties are mandatory!) + if (isFailed(nResult)) + { + return nResult; + } + + *ppoNewEnum = new DDLEnum(poDataType, name, vecNameValues, NULL, _creation_level); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLImporter::buildStreamMetaTypes() + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + a_util::xml::DOMElement oTypes; + if (!_dom.findNode("//streammetatypes", oTypes)) + { + return a_util::result::SUCCESS; + } + + a_util::result::Result nResult = a_util::result::SUCCESS; + + // build up stream meta type objects + a_util::xml::DOMElementList oTypeList; + if (oTypes.findNodes("streammetatype", oTypeList)) + { + DDLStreamMetaTypeVec vecDDLStreamMetaTypes(_sorted); + for (a_util::xml::DOMElementList::iterator it = oTypeList.begin(); it != oTypeList.end(); ++it) + { + a_util::result::Result nRes = buildSingleStreamMetaType(*it, vecDDLStreamMetaTypes); + if (isFailed(nRes)) + { + nResult = nRes; + if (false == _full_check) + { + vecDDLStreamMetaTypes.deleteAll(); + return nRes; + } + continue; + } + } + + for (DDLStreamMetaTypeVec::iterator it = _unknown_stream_meta_types.begin(); it != _unknown_stream_meta_types.end(); ++it) + { + pushMessage(a_util::strings::format("The struct '%s' was referenced but not defined.", + (*it)->getName().c_str()), importer_error); + } + + if (!_unknown_stream_meta_types.empty()) + { + + vecDDLStreamMetaTypes.deleteAll(); + // unmark object + pushMessage(std::string("There are undefined streammetatypes in this description."), + importer_error); + nResult = ERR_UNKNOWN; + if (false == _full_check) + { + return nResult; + } + } + + + _ddl_desc->refStreamMetaTypes(vecDDLStreamMetaTypes); + } + + return nResult; + } + + a_util::result::Result DDLImporter::buildSingleStreamMetaType(const a_util::xml::DOMElement& oStreamMetaTypeElement, + DDLStreamMetaTypeVec& vecStreamMetaTypes) + { + const a_util::xml::DOMAttributes oAttributes = oStreamMetaTypeElement.getAttributes(); + a_util::xml::DOMAttributes::const_iterator itName = oAttributes.find("name"); + a_util::xml::DOMAttributes::const_iterator itVersion = oAttributes.find("version"); + a_util::xml::DOMAttributes::const_iterator itParent = oAttributes.find("parent"); + + if (itName == oAttributes.end()) + { + pushMessage(a_util::strings::format("Attribute 'name' is missing in 'streammetatype' tag."), + importer_error); + return ERR_UNKNOWN_FORMAT; + } + if (itVersion == oAttributes.end()) + { + pushMessage(a_util::strings::format("Attribute 'version' is missing in 'streammetatype' tag."), + importer_error); + return ERR_UNKNOWN_FORMAT; + } + + a_util::result::Result nResult = a_util::result::SUCCESS; + + DDLStreamMetaType* pParent = NULL; + if (itParent != oAttributes.end() && !itParent->second.empty()) + { + if (_current_ref_ddl) + { + pParent = const_cast(_current_ref_ddl->getStreamMetaTypeByName(itParent->second)); + } + if (!pParent) + { + pParent = tryToFind(itParent->second, _unknown_stream_meta_types, vecStreamMetaTypes); + if (!pParent) + { + pParent = new DDLStreamMetaType(itParent->second, "1"); + _unknown_stream_meta_types.insert(pParent); + } + } + } + + DDLPropertyVec oProps; + a_util::xml::DOMElementList oPropertyNodes; + if (oStreamMetaTypeElement.findNodes("property", oPropertyNodes)) + { + for (a_util::xml::DOMElementList::const_iterator it = oPropertyNodes.begin(); + it != oPropertyNodes.end(); ++it) + { + a_util::xml::DOMAttributes attrs = it->getAttributes(); + a_util::xml::DOMAttributes::const_iterator itName = attrs.find("name"); + a_util::xml::DOMAttributes::const_iterator itType = attrs.find("type"); + if (itName != attrs.end() && itType != attrs.end()) + { + oProps.push_back(new DDLProperty(itName->second, + itType->second)); + } + } + } + + a_util::memory::unique_ptr pStreamMetaType(new DDLStreamMetaType(itName->second, itVersion->second, + oProps, pParent)); + + DDLStreamMetaTypeVec::iterator itUnknown = std::find_if(_unknown_stream_meta_types.begin(), + _unknown_stream_meta_types.end(), + DDLCompareFunctor<>(itName->second)); + if (itUnknown != _unknown_stream_meta_types.end()) + { + *(*itUnknown) = *pStreamMetaType.get(); + vecStreamMetaTypes.insert(*itUnknown); + _unknown_stream_meta_types.erase(itUnknown); + } + else + { + vecStreamMetaTypes.insert(pStreamMetaType.release()); + } + + return nResult; + } + + +} // namespace ddl diff --git a/ddlrepresentation/ddlimporter.h b/ddlrepresentation/ddlimporter.h new file mode 100644 index 0000000..f6fcc45 --- /dev/null +++ b/ddlrepresentation/ddlimporter.h @@ -0,0 +1,394 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_IMPORTER_H_INCLUDED +#define DDL_IMPORTER_H_INCLUDED + +#include "ddl_common.h" +#include "ddlfactorymethod_intf.h" +#include "ddlvisitor_intf.h" +#include "ddlcontainer.h" + +namespace ddl +{ + class DDLDescription; + + /** + * \enum ImporterMsgSeverity + * enumeration type for message severity + */ + typedef enum + { + importer_info, + importer_warning, + importer_error + } ImporterMsgSeverity; + + /** + * \struct ImporterMsg + * error description structure type + */ + typedef struct + { + std::string desc; //!< string of the message + ImporterMsgSeverity severity; //!< enumeration type for message severity + } ImporterMsg; + + /** + * Container for error descriptions + */ + typedef std::list ImporterMsgList; + + + /** + * Concrete Factory Method for building up a DDL from a XML file. + */ + class DDLImporter : public IDDLFactoryMethod + { + public: + /** + * Default CTOR + * @param[in] basic_check Perform basic checks during Create* (unique element names etc.). + * For a full check use DDLInspector. + * @param[in] sorted Sorts all DDL items by name for better performance. + */ + DDLImporter(bool basic_check = true, bool sorted = true); + + /** + * CTOR with file name/path + * @param[in] file - Path to file to use + * @param[in] basic_check Perform basic checks during Create* (unique element names etc.). + * For a full check use DDLInspector. + * @param[in] sorted Sorts all DDL items by name for better performance. + */ + DDLImporter(const a_util::filesystem::Path& file, + bool basic_check = true, + bool sorted = true); + + /** + * CTOR with file name/path + * @param[in] file - Path to file to use + * @param[in] basic_check Perform basic checks during Create* (unique element names etc.). + * For a full check use DDLInspector. + * @param[in] sorted Sorts all DDL items by name for better performance. + */ + DDLImporter(const char* file, bool basic_check = true, bool sorted = true); + + /** + * CTOR with creation level. + * @param[in] creation_level - Creation level + * @param[in] basic_check Perform basic checks during Create* (unique element names etc.). + * For a full check use DDLInspector. + * @param[in] sorted Sorts all DDL items by name for better performance. + */ + DDLImporter(int creation_level, bool basic_check = true, bool sorted = true); + + /// Default copy constructor + DDLImporter(const DDLImporter&) = default; + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDLImporter object to copy from + * @return @c *this + */ + DDLImporter& operator=(DDLImporter other); + + /** + * Move CTOR + * @param[in,out] other DDLImporter object to move from - empty but valid when finished + */ + DDLImporter(DDLImporter&& other); + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLImporter& lhs, DDLImporter& rhs) noexcept; + + + public: // implements IDDLFactoryMethod + + virtual ~DDLImporter(); + + DDLDescription * getDDL() const; + + /** + * @copydoc IDDLFactoryMethod::createNew(double) + * @remarks If an error occurs, a list of detailed error descriptions + * can be obtained using \c GetAllErrors(). + */ + a_util::result::Result createNew(const DDLVersion& version = DDLVersion::ddl_version_invalid); + + void destroyDDL(); + + a_util::result::Result buildHeader(); + + a_util::result::Result buildUnits(); + + a_util::result::Result buildDatatypes(); + + a_util::result::Result buildStructs(); + + a_util::result::Result buildStreams(); + + a_util::result::Result buildEnums(); + + a_util::result::Result buildStreamMetaTypes(); + + public: + /** + * Static method to destroy the given DDL hierarchy. + * @param [in] ddl - Pointer to the DDL hierarchy which should be destroyed. + * + * @return void + */ + static void destroyDDL(DDLDescription *ddl); + + /** + * Setter for the creation level. + * @param[in] level - Creation level to use + * + * @return void + */ + void setCreationLevel(int const level = 1); + + /** + * Setter for the validation mode. + * @param[in] full_check - Validation mode to use. + * Set true for full description check. + * Set false for description check until first error. + * + * @return void + */ + void setFullCheckDescriptionMode(bool full_check = false); + + /** + * Setter to enable disable the merge of DDL defaults (units, datattypes, etc.) + * @param [in] merge_defaults See description + * @return void + */ + void setMergeDefaults(bool merge_defaults = true); + + /** + * Setter to switch from prefereing entities from the reference DDL, to using the reference + * enties only when there is no "local" aquivalent. + * Mind that reference entities are not cloned but only referenced. + * They are also not included into the containers. + * @param [in] prefere_reference See description + * @return void + */ + void setPreferReferenceEntities(bool prefere_reference = true); + + /** + * Method to create a partial DDL (e.g. streams only). + * @param[in] ref_ddl - Reference DDL object to be used for resolving + * matters + * @param[in] version The version the newly created description will have. Set 0 for + * newst version. + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_INITIALIZED Not yet initialized (see setter methods + * in concrete classes, e.g. \c DDLImporter::setFile()) + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. refUnit) + * @retval ERR_UNKNOWN Cross reference has not been resolved + */ + a_util::result::Result createPartial(const DDLDescription* ref_ddl, const DDLVersion& version); + + /** + * Setter for the source file. + * @param[in] file - Path to file to use + * @retval ERR_OPEN_FAILED Reading process failed + * @retval ERR_UNEXPECTED Invalid XML tag + */ + a_util::result::Result setFile(const a_util::filesystem::Path& file); + + /** + * Setter for a XML string containing the DDL to import. + * @param[in] xml - String containing the DDL + * @retval ERR_UNEXPECTED Invalid XML tag + */ + a_util::result::Result setXML(const std::string& xml); + + /** + * Getter for the description of the last error. + * @return the error description + */ + std::string getErrorDesc() const; + + /** + * Getter for the most recent error description. + * @return The error description or \c a_util::strings::empty_string if there was none. + * @remarks This method indeed returns the last \b error message + * (message with severity \c importer_error). + */ + std::string getLastErrorDesc() const; + + /** + * Getter for all detected errors. + * @return A list of all detected errors. + */ + ImporterMsgList getAllMessages() const; + + /** + * Method to log all messages which have at least the given severity + * to console. + * @param[in] least_severity - Minimum severity level (optional) + * + * @return void + */ + void printAllMessages(ImporterMsgSeverity least_severity = importer_info); + + private: // methods + /** + * Creates a baseunit object from the given DOMElement. + * @param[out] new_bu - Pointer to pointer to the newly created + * baseunit object + * @param[in] bu_element - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable + */ + a_util::result::Result buildSingleBaseunit(DDLBaseunit ** new_bu, + const a_util::xml::DOMElement& bu_element); + + /** + * Creates a prefix object from the given DOMElement. + * @param[out] new_prefix - Pointer to pointer to the newly created + * prefix object + * @param[in] prefix_element - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable + */ + a_util::result::Result buildSinglePrefix(DDLPrefix ** new_prefix, + const a_util::xml::DOMElement& prefix_element); + + /** + * Creates a unit object from the given DOMElement. + * @param[out] new_unit - Pointer to pointer to the newly created + * unit object + * @param[in] unit_element - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable + */ + a_util::result::Result buildSingleUnit(DDLUnit ** new_unit, + const a_util::xml::DOMElement& unit_element); + + /** + * Creates a datatype object from the given DOMElement. + * @param[out] new_datatype - Pointer to pointer to the newly + * created datatype object + * @param[in] dt_element -T he DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. unit) + */ + a_util::result::Result buildSingleDatatype(DDLDataType ** new_datatype, + const a_util::xml::DOMElement& dt_element); + + /** + * Creates an enum object from the given DOMElement. + * @param[out] new_enum - Pointer to pointer to the newly + * created enum object + * @param[in] oEnumElement - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. unit) + */ + a_util::result::Result buildSingleEnum(DDLEnum** new_enum, + const a_util::xml::DOMElement& enum_element); + + /** + * Creates a struct object from the given DOMElement. + * @param[out] new_struct - Pointer to pointer to the newly created + * struct object + * @param[in] struct_element - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. datatype) + * @retval ERR_UNKNOWN Not all firstly unknown structs have been + * resolved + */ + a_util::result::Result buildSingleStruct(DDLComplex ** new_struct, + const a_util::xml::DOMElement& struct_element); + + /** + * Creates a DDL stream object from the given DOMElement. + * @param[out] new_stream - Pointer to pointer to the newly created + * stream object + * @param[in] stream_element - The DOMElement with the information + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. struct) + */ + a_util::result::Result buildSingleStream(DDLStream ** new_stream, + a_util::xml::DOMElement stream_element); + + /** + * Creates a DDL stream object from the given DOMElement. + * @param[out] stream_meta_type_element + * @param[in] stream_meta_types + * @retval ERR_UNKNOWN_FORMAT Expected XML hierarchy not found + * @retval ERR_NO_CLASS Cross reference not resolvable (e.g. struct) + */ + a_util::result::Result buildSingleStreamMetaType(const a_util::xml::DOMElement& stream_meta_type_element, + DDLStreamMetaTypeVec& stream_meta_types); + + /** + * Helper method to create a message and save it in the appropriate + * container. + * @param[in] msg - Message text + * @param[in] severity - Message severity + * @return void + */ + void pushMessage(const std::string& msg, ImporterMsgSeverity severity); + + /** + * Helper method to find specific elements inside the given first_data by Name. + * If not found there have a look in second_data. + * @tparam T - Representation object type (e.g. DDLDataType) + * @param[in] name - Name of the element to find + * @param[in] first_data - Vector of representation objects to + * search through + * @param[in] second_data - second Vector of representation objects to + * search through + * @return pointer to the found element or \c NULL if not found + */ + template + T* tryToFind(const std::string& name, + DDLContainer& first_data, + DDLContainer& second_data); + + private: // members + a_util::xml::DOM _dom; + DDLDescription *_ddl_desc; + const DDLDescription *_current_ref_ddl; + + DDLUnitVec _unknown_units; + DDLComplexVec _unknown_structs; + DDLStreamMetaTypeVec _unknown_stream_meta_types; + bool _init_flag; + int _creation_level; + + bool _full_check; + ImporterMsgList _errors; + bool _basic_check; + bool _merge_defaults; + bool _sorted; + bool _prefere_reference; + }; + +} // namespace ddl + +#endif // DDL_IMPORTER_H_INCLUDED diff --git a/ddlrepresentation/ddlinspector.cpp b/ddlrepresentation/ddlinspector.cpp new file mode 100644 index 0000000..6cb4648 --- /dev/null +++ b/ddlrepresentation/ddlinspector.cpp @@ -0,0 +1,1175 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlinspector.h" +#include +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + +#include "ddlversion.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-8, ERR_INVALID_HANDLE) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-43, ERR_EMPTY) + + /// Alignment target + static size_t const s_szAlignSize = 4; + + DDLInspector::DDLInspector(bool bAutoCorrect /* = false */) : + _auto_correct{bAutoCorrect}, + _base_unit_names{}, + _complex_names{}, + _data_types_names{}, + _ddl_desc{}, + _enum_names{}, + _has_dynamic_arrays{}, + _has_struct_dynamic_arrays{}, + _prefix_names{}, + _stream_names{}, + _struct_infos{}, + _suggestions{}, + _unit_names{}, + _version(0, 0), + _warning_level{WarningLevel::moderate} + { + InitNewCheck(); + } + + a_util::result::Result DDLInspector::visitDDL(DDLDescription* poDescription) + { + InitNewCheck(); + + if (!poDescription) { return ERR_POINTER; } + + _ddl_desc = poDescription; + a_util::result::Result nResult = a_util::result::SUCCESS; + a_util::result::Result nRes = a_util::result::SUCCESS; + + nResult = poDescription->getHeader()->accept(this); + + _has_dynamic_arrays = false; + + //// validate Base Unit types + DDLBaseunitVec vecBaseUnits = poDescription->getBaseunits(); + for (DDLBaseunitIt itUnit = vecBaseUnits.begin(); itUnit != vecBaseUnits.end(); ++itUnit) + { + nRes = (*itUnit)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + //// validate Prefix types + DDLPrefixVec vecPrefix = poDescription->getPrefixes(); + for (DDLPrefixIt itPrefix = vecPrefix.begin(); itPrefix != vecPrefix.end(); ++itPrefix) + { + nRes = (*itPrefix)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + //// validate Unit data types + DDLUnitVec vecUnits = poDescription->getUnits(); + for (DDLUnitIt itUnit = vecUnits.begin(); itUnit != vecUnits.end(); ++itUnit) + { + nRes = (*itUnit)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + // validate primitive data types + DDLDTVec vecDTs = poDescription->getDatatypes(); + for (DDLDTIt itDT = vecDTs.begin(); itDT != vecDTs.end(); ++itDT) + { + nRes = (*itDT)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + //// validate Enum types + DDLEnumVec vecEnums = poDescription->getEnums(); + for (DDLEnumIt itEnum = vecEnums.begin(); itEnum != vecEnums.end(); ++itEnum) + { + nRes = (*itEnum)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + // validate complex data types + DDLComplexVec vecStructs = poDescription->getStructs(); + _complex_names.clear(); + for (DDLComplexIt itStruct = vecStructs.begin(); itStruct != vecStructs.end(); ++itStruct) + { + if (_has_struct_dynamic_arrays && !_has_dynamic_arrays) + { + _has_dynamic_arrays = true; + } + + _has_struct_dynamic_arrays = false; + + if (_complex_names.end() != _complex_names.find((*itStruct)->getName())) + { + addSuggestion(a_util::strings::format("The Name '%s' is duplicate", + (*itStruct)->getName().c_str()), importer_error); + nResult = ERR_INVALID_ARG; + } + else + { + _complex_names.insert((*itStruct)->getName()); + } + + nRes = (*itStruct)->accept(this); + if (isFailed(nRes)) + { + // store error but continue with the remaining structs + nResult = nRes; + } + } + + _ddl_desc->getHeader()->setDateChange(a_util::datetime::getCurrentLocalDate()); + + //// validate Stream types + DDLStreamVec vecStream = poDescription->getStreams(); + for (DDLStreamIt itStream = vecStream.begin(); itStream != vecStream.end(); ++itStream) + { + nRes = (*itStream)->accept(this); + if (isFailed(nRes)) + { + nResult = nRes; + } + } + + if (_has_dynamic_arrays) + { + addSuggestion(a_util::strings::format("Dynamic Arrays detected. (Performance is not good)."), + importer_warning); + nResult = ERR_INVALID_ARG; + } + RETURN_IF_FAILED(nResult); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLHeader* poHeader) + { + if (NULL == poHeader) + { + addSuggestion(a_util::strings::format("DDL does not contain a header."), + importer_error); + return ERR_POINTER; + } + _version = poHeader->getLanguageVersion(); + if (!_version.isValidVersion()) + { + addSuggestion(a_util::strings::format("The version %s is an invalid DDL version.", + _version.toString().c_str()), importer_error); + return ERR_INVALID_ARG; + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLExtDeclaration* poExtDeclaration) + { + // should not be called + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLInspector::visit(DDLBaseunit* poBaseunit) + { + if (!poBaseunit) { return ERR_POINTER; } + if (_base_unit_names.end() != _base_unit_names.find(poBaseunit->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Baseunit Type) '%s'.", + poBaseunit->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + else + { + _base_unit_names.insert(poBaseunit->getName()); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLPrefix* poPrefix) + { + if (!poPrefix) { return ERR_POINTER; } + // Check if an prefix name already exist. + if (_prefix_names.end() != _prefix_names.find(poPrefix->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Prefix Type) '%s'.", + poPrefix->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + else + { + _prefix_names.insert(poPrefix->getName()); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLUnit* poUnit) + { + if (!poUnit) { return ERR_POINTER; } + if (poUnit->getDenominator() == "0") + { + addSuggestion(a_util::strings::format("Unit '%s' with denominator '0' is not defined.", + poUnit->getName().c_str()), importer_warning); + } + DDLRefUnitVec vecRUs = poUnit->getRefUnits(); + for (DDLRefUnitIt itRU = vecRUs.begin(); vecRUs.end() != itRU; ++itRU) + { + RETURN_IF_FAILED((*itRU)->accept(this)); + } + _unit_names.insert(poUnit->getName()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLRefUnit* poRefUnit) + { + if (!poRefUnit) { return ERR_POINTER; } + if (_base_unit_names.end() == _base_unit_names.find(poRefUnit->getName())) + { + if (_base_unit_names.end() == _base_unit_names.find(poRefUnit->getName())) + { + addSuggestion(a_util::strings::format("(Base-)Unit '%s' not found.", + poRefUnit->getName().c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + } + if (_prefix_names.end() == _prefix_names.find(poRefUnit->getPrefix())) + { + addSuggestion(a_util::strings::format("Prefix '%s' not found.", + poRefUnit->getName().c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLDataType* poDataType) + { + if (!poDataType) { return ERR_POINTER; } + std::string strType = poDataType->getName(); + if (poDataType->isDynamic()) + { + if (_version < DDLVersion::ddl_version_12) + { + addSuggestion(a_util::strings::format("Datatype '%s' is a dynamic array and therefore not supported.", + strType.c_str()), importer_error); + return ERR_INVALID_ARG; + } + } + + // Check if an element name already exist as complex data type. + if (_complex_names.end() != _complex_names.find(strType)) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Complex_Datatype) '%s'.", + strType.c_str()), importer_error); + return ERR_INVALID_ARG; + } + + // Check if an element name already exist as enum. + if (_enum_names.end() != _enum_names.find(strType)) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Enum Type) '%s'.", + strType.c_str()), importer_error); + return ERR_INVALID_ARG; + } + + // Check if an element name already exist. + if (_data_types_names.end() != _data_types_names.find(strType)) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Data Type) '%s'.", + strType.c_str()), importer_error); + return ERR_INVALID_ARG; + } + + std::string strUnit = poDataType->getUnit(); + if (!strUnit.empty()) + { + if (_base_unit_names.end() == _base_unit_names.find(strUnit)) + { + if (_unit_names.end() == _unit_names.find(strUnit)) + { + addSuggestion(a_util::strings::format("(Base-)Unit '%s' not found.", + strUnit.c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + } + } + _data_types_names.insert(strType); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLEnum* poEnum) + { + if (!poEnum) { return ERR_POINTER; } + EnumNameValueVec vecNameValues = poEnum->getValues(); + EnumNameValueVec::iterator it = vecNameValues.begin(); + std::set setEnumsElementNames; + std::set enumValues; + for (; it != vecNameValues.end(); ++it) + { + if (setEnumsElementNames.end() != setEnumsElementNames.find(it->first)) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Enum Element Type) '%s'.", + it->first.c_str()), importer_warning); + } + else + { + setEnumsElementNames.insert(it->first); + } + + if (enumValues.end() != enumValues.find(it->second)) + { + addSuggestion(a_util::strings::format("Duplicate Element value (Enum Element Value) '%s' '%s'.", + it->first.c_str(), it->second.c_str()), importer_warning); + } + else + { + enumValues.insert(it->second); + } + } + + // Check if an element name already exist as data type. + if (_data_types_names.end() != _data_types_names.find(poEnum->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Data Type) '%s'.", + poEnum->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + // Check if an element name already exist as complex data type. + if (_complex_names.end() != _complex_names.find(poEnum->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Complex_Datatype) '%s'.", + poEnum->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + // Check if an element name already exist. + if (_enum_names.end() != _enum_names.find(poEnum->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Enum Type) '%s'.", + poEnum->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + else + { + _enum_names.insert(poEnum->getName()); + } + + // Check if no elements defined in enum + if (vecNameValues.size() == 0) + { + addSuggestion(a_util::strings::format("No elements defined in enum '%s'.", + poEnum->getName().c_str()), importer_warning); + } + + if (_data_types_names.end() == _data_types_names.find(poEnum->getType())) + { + addSuggestion(a_util::strings::format("Type '%s' not found.", + poEnum->getType().c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + + std::string strTypeName = poEnum->getType(); + for (EnumNameValueVec::iterator itValue = vecNameValues.begin(); + itValue != vecNameValues.end(); + ++itValue) + { + bool bError = false; + if (itValue->second.empty() || (!a_util::strings::isInt64(itValue->second) && !a_util::strings::isFloat(itValue->second))) + { + bError = true; + } + else if (strTypeName == "tBool") + { + if (itValue->second != "0" && itValue->second != "1") + { + bError = true; + } + } + else if (strTypeName == "tUInt8") + { + uint64_t ui64Val = a_util::strings::toUInt64(itValue->second); + if ((!itValue->second.empty() && itValue->second[0] == '-') || ui64Val > std::numeric_limits::max()) + { + bError = true; + } + } + else if (strTypeName == "tInt8" || strTypeName == "tChar") + { + int64_t i64Val = a_util::strings::toInt64(itValue->second); + if (i64Val > std::numeric_limits::max() || i64Val < std::numeric_limits::min()) + { + bError = true; + } + } + else if (strTypeName == "tInt16") + { + int64_t i64Val = a_util::strings::toInt64(itValue->second); + if (i64Val > std::numeric_limits::max() || i64Val < std::numeric_limits::min()) + { + bError = true; + } + } + else if (strTypeName == "tUInt16") + { + uint64_t ui64Val = a_util::strings::toUInt64(itValue->second); + if ((!itValue->second.empty() && itValue->second[0] == '-') || ui64Val > std::numeric_limits::max()) + { + bError = true; + } + } + else if (strTypeName == "tInt32") + { + int64_t i64Val = a_util::strings::toInt64(itValue->second); + if (i64Val > std::numeric_limits::max() || i64Val < std::numeric_limits::min()) + { + bError = true; + } + } + else if (strTypeName == "tUInt32") + { + uint64_t ui64Val = a_util::strings::toUInt64(itValue->second); + if ((!itValue->second.empty() && itValue->second[0] == '-') || ui64Val > std::numeric_limits::max()) + { + bError = true; + } + } + else if (strTypeName == "tInt64") + { + int64_t i64Val = a_util::strings::toInt64(itValue->second); + if (i64Val > std::numeric_limits::max() || i64Val < std::numeric_limits::min()) + { + bError = true; + } + } + else if (strTypeName == "tUInt64") + { + uint64_t ui64Val = a_util::strings::toUInt64(itValue->second); + if ((!itValue->second.empty() && itValue->second[0] == '-') || ui64Val > std::numeric_limits::max()) + { + bError = true; + } + } + else + { + bError = false; + } + if (bError) + { + addSuggestion( + a_util::strings::format("The element '%s' in the enumeration '%s' has a value of '%s' which is outside the range of the enumeration type '%s'.", + itValue->first.c_str(), poEnum->getName().c_str(), + itValue->second.c_str(), strTypeName.c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLComplex* poComplex) + { + if (!poComplex) { return ERR_POINTER; } + + StructInfo& sStructInfo = _struct_infos[poComplex]; + sStructInfo.valid = false; + sStructInfo.size = 0; + + // Check if an element name already exist as enum. + if (_enum_names.end() != _enum_names.find(poComplex->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Enum Type) '%s'.", + poComplex->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + // Check if an element name already exist as data type. + if (_data_types_names.end() != _data_types_names.find(poComplex->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Data Type) '%s'.", + poComplex->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + DDLElementVec vecElements = poComplex->getElements(); + + // Check if no elements defined in complex datatype + if (vecElements.size() == 0) + { + addSuggestion(a_util::strings::format("No elements defined in complex datatype '%s'.", + poComplex->getName().c_str()), importer_warning); + } + + // clone elements for own changes => save back on success + std::transform(vecElements.begin(), vecElements.end(), + vecElements.begin(), DDLDescription::clone); + + //this is cloned now !!!! We need to delete it then !!!! + DDLAutoVec m_oVecSync(&vecElements); + + for (DDLElementIt itElem = vecElements.begin(); + vecElements.end() != itElem; ++itElem) + { + const IDDLDataType * poDT = _ddl_desc->getDataTypeByName((*itElem)->getType()); + if (NULL == poDT) + { + // no primitive data type + poDT = _ddl_desc->getStructByName((*itElem)->getType()); + if (NULL == poDT) + { + poDT = _ddl_desc->getEnumByName((*itElem)->getType()); + if (NULL == poDT) + { + addSuggestion(a_util::strings::format("Type '%s' not found.", + (*itElem)->getType().c_str()), importer_error); + return ERR_INVALID_HANDLE; + } + + } + } + else if (/*poElement->getTypeObject()->isPredefined() && */ + (*itElem)->isDefaultValid() && + ((lessDDL((*itElem)->getDefaultValue(), (*itElem)->getMinValue(), + dynamic_cast((*itElem)->getTypeObject()))) || + (lessDDL((*itElem)->getMaxValue(), (*itElem)->getDefaultValue(), + dynamic_cast((*itElem)->getTypeObject()))))) + { + // primitive data type and default value out of range detected + addSuggestion(a_util::strings::format("Default value of element '%s' is out of range.", + (*itElem)->getName().c_str()), importer_error); + return ERR_INVALID_ARG; + } + } + + // validate of nested structs + std::string strLog = poComplex->getName(); + if (false == checkValidyOfNestedStructs(_ddl_desc, poComplex->getName(), poComplex->getName(), strLog)) + { + addSuggestion(a_util::strings::format("A complex data type is recursive defined: %s", + strLog.c_str()), importer_error); + return ERR_INVALID_ARG; + } + + std::string name = a_util::strings::empty_string; + unsigned int uiBytePos = 0; + unsigned int uiElementSize = 0; + size_t szLastElementSize = 0; + unsigned int szLastElementBytePos = 0; + bool bIsDymArraySize = false; + std::set setComplexElementName; + + for (DDLElementIt itElem = vecElements.begin(); + vecElements.end() != itElem; ++itElem) + { + name = (*itElem)->getName(); + + uint32_t ui32ArraySize = (*itElem)->getArraysize(); + + if (_has_struct_dynamic_arrays && !(*itElem)->isDynamic()) + { + addSuggestion(a_util::strings::format("Please use Dynamic arrays always as last element '%s'.'%s'", + poComplex->getName().c_str(), name.c_str()), importer_error); + // FIXME: RETURN_ERROR() needed + } + + // Check if an element name already exist. + if (setComplexElementName.end() != setComplexElementName.find(name)) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Complex_Datatypes Element Name) '%s' in %s.", + name.c_str(), poComplex->getName().c_str()), + importer_error); + return ERR_INVALID_ARG; + } + else + { + setComplexElementName.insert(name); + } + + if ((*itElem)->isDynamic() && _version < DDLVersion::ddl_version_12) + { + //Element '%s.%s' has an illegal array size of 0 + addSuggestion(a_util::strings::format("Element (Complex_Datatypes) '%s.%s' is a dynamic array " + "and therefore not supported in v%s. ", + poComplex->getName().c_str(), name.c_str(), _version.toString().c_str()), + importer_error); + return ERR_INVALID_ARG; + } + + if (0 == ui32ArraySize && (*itElem)->getArraySizeSource() == "") + { + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name) '%s.%s' has an illegal array size of 0.", + poComplex->getName().c_str(), name.c_str()), + importer_warning); + // FIXME: RETURN_ERROR(ERR_INVALID_ARG) ?? + } + + std::string strType = (*itElem)->getType(); + const DDLDataType *poDT = _ddl_desc->getDataTypeByName(strType); + if (NULL == poDT) + { + const DDLEnum *poEnum = _ddl_desc->getEnumByName(strType); + if (NULL == poEnum) + { + // complex data type + DDLComplex* pSubStruct = _ddl_desc->getStructByName(strType); + if (!pSubStruct) + { + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name) '%s.%s' has an unkown type '%s'.", + poComplex->getName().c_str(), name.c_str(), + strType.c_str()), importer_error); + return ERR_NOT_FOUND; + } + if (isFailed(pSubStruct->accept(this)) || + !_struct_infos[pSubStruct].valid) + { + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name) '%s.%s' has type '%s' that contains errors.", + poComplex->getName().c_str(), name.c_str(), + strType.c_str()), importer_error); + return ERR_INVALID_ARG; + } + + uiElementSize = _struct_infos[pSubStruct].size; + } + else + { + // enum type => treat like primitive data type + poDT = _ddl_desc->getDataTypeByName(poEnum->getType()); + uiElementSize = poDT->getNumBits() / 8; + } + } + else + { + // primitive data type + uiElementSize = poDT->getNumBits() / 8; + + // Verify Min and Max values + std::string strMax = (*itElem)->getMaxValue(); + if ((*itElem)->getType() == "tBool") + { + if (strMax == "tTrue") + { + strMax = "1"; + } + } + if (!a_util::strings::isDouble(strMax)) + { + if (_auto_correct) + { + double d = a_util::strings::toDouble(strMax); + // Try to remove multiple points + if (strMax.find(".") != std::string::npos) + { + strMax = a_util::strings::replace(strMax, ".", ""); + d = a_util::strings::toDouble(strMax); + } + (*itElem)->setMaxValue(a_util::strings::format("%f", d)); + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name)\ + '%s.%s' maximum value was set to the floating point value %f.", + poComplex->getName().c_str(), name.c_str(), + d), importer_info); + } + else + { + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name)\ + '%s.%s' maximum value is \'%s\' but it should be a floating point value or tTrue " + "if using type tBool.", + poComplex->getName().c_str(), name.c_str(), + strMax.c_str()), importer_error); + } + } + std::string strMin = (*itElem)->getMinValue(); + if ((*itElem)->getType() == "tBool") + { + if (strMin == "tFalse") + { + strMin = "0"; + } + } + if (!a_util::strings::isDouble(strMin)) + { + if (_auto_correct) + { + double d = a_util::strings::toDouble(strMin); + // Try to remove multiple points + if (strMin.find(".") != std::string::npos) + { + strMin = a_util::strings::replace(strMin, ".", ""); + d = a_util::strings::toDouble(strMin); + } + (*itElem)->setMinValue(a_util::strings::format("%f", d)); + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name)\ + '%s.%s' minimum value was set to the floating point value %f.", + poComplex->getName().c_str(), name.c_str(), + d), importer_info); + } + else + { + addSuggestion(a_util::strings::format("Element (Complex_Datatypes Element Name)\ + '%s.%s' minimum value is \'%s\' but it should be a floating point value or tFalse " + "if using type tBool.", + poComplex->getName().c_str(), name.c_str(), + strMin.c_str()), importer_error); + } + } + } + + if (uiElementSize > szLastElementSize && szLastElementSize != 0) + { + if (_warning_level == WarningLevel::verbose) + { + addSuggestion(a_util::strings::format("Please use the biggest elements/types first " + "and then the smaller ones (Complex_Datatypes) " + "'%s.%s'.", poComplex->getName().c_str(), + name.c_str()), importer_warning); + } + } + + // check continuity of elements + if ((*itElem)->getBytepos() != uiBytePos) + { + // element byte-position is different from calculated + // byte-position + if (_auto_correct) + { + if ((*itElem)->getBytepos() < uiBytePos) + { + // one or more preceding elements have been altered by + // the DDLInspector so that the elements would overlap + // now => adapt byte-position + (*itElem)->setBytepos(uiBytePos); + + addSuggestion(a_util::strings::format("Byte-position of (Complex_Datatypes) " + "'%s.%s' has been modified.", poComplex->getName().c_str(), + name.c_str()), importer_info); + } + else + { + (*itElem)->setBytepos(uiBytePos); + + addSuggestion(a_util::strings::format("Correct the Byte position (Complex_Datatypes) " + "'%s.%s'.", poComplex->getName().c_str(), + name.c_str()), importer_info); + } + } + else + { + addSuggestion(a_util::strings::format("Gap / Padding element '%s.%s' detected.", + poComplex->getName().c_str(), name.c_str()), + importer_warning); + } + } + + uiElementSize *= ui32ArraySize; + + sStructInfo.last_byte_pos_real = (*itElem)->getBytepos() + uiElementSize; + + uiBytePos += uiElementSize; + szLastElementSize = uiElementSize; + szLastElementBytePos = uiBytePos; + + if ((*itElem)->isDynamic() && !bIsDymArraySize) + { + bIsDymArraySize = (*itElem)->isDynamic(); + + if (!_has_struct_dynamic_arrays) + { + _has_struct_dynamic_arrays = true; + } + } + } //end of for iterator!! + + if (_auto_correct) + { + m_oVecSync.reset(); + // save back changed element vector + poComplex->setElements(vecElements); + } + + // save struct size + sStructInfo.size = uiBytePos; + sStructInfo.last_byte_pos = szLastElementBytePos; + sStructInfo.valid = true; + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLElement* poElement) + { + // should not be called + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLInspector::visit(DDLStream* const poStream) + { + if (!poStream) { return ERR_POINTER; } + + DDLStreamStructVec vecStreamStruct = poStream->getStructs(); + + // Check if no strucs defined in stream + if (vecStreamStruct.size() == 0) + { + addSuggestion(a_util::strings::format("No complex datatypes defined in stream '%s'.", + poStream->getName().c_str()), importer_warning); + } + + std::set setStreamsElementNames; + for (size_t posI = 0; posI < vecStreamStruct.size(); posI++) + { + if ((vecStreamStruct[posI]->getName() != "") && _version < DDLVersion::ddl_version_12) + { + addSuggestion(a_util::strings::format("Name in Streams is not supported '%s' " + "in this Version v%s. ", vecStreamStruct[posI]->getName().c_str(), + _version.toString().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + if ((vecStreamStruct[posI]->getType() != "") && _version < DDLVersion::ddl_version_10) + { + addSuggestion(a_util::strings::format("Types in Streams is not supported '%s' " + "in this Version v%s. ", vecStreamStruct[posI]->getName().c_str(), + _version.toString().c_str()), importer_error); + return ERR_INVALID_ARG; + } + + if (setStreamsElementNames.end() != setStreamsElementNames.find(vecStreamStruct[posI]->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Stream Element) '%s'.", + vecStreamStruct[posI]->getName().c_str()), importer_error); + } + else + { + setStreamsElementNames.insert(vecStreamStruct[posI]->getName()); + } + } + + // Check if an stream name already exist. + if (_stream_names.end() != _stream_names.find(poStream->getName())) + { + addSuggestion(a_util::strings::format("Duplicate identifier (Stream Type) '%s'.", + poStream->getName().c_str()), importer_error); + } + else + { + _stream_names.insert(poStream->getName()); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLInspector::visit(DDLStreamStruct* poStreamStruct) + { + // should not be called + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLInspector::visit(DDLStreamMetaType* poStreamMetaType) + { + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLInspector::visit(DDLProperty* poProperty) + { + return ERR_NOT_IMPL; + } + + bool DDLInspector::isAlignable(size_t const posBytePos, + size_t const szElementSize) + { + if (0 == posBytePos % s_szAlignSize) + { + // previous elements (if there are any) are aligned => accept everything + return true; + } + if (posBytePos % s_szAlignSize + szElementSize <= s_szAlignSize && + 0 == posBytePos % szElementSize) + { + // element is alignable + return true; + } + // element is not alignable + return false; + } + + ImporterMsgList DDLInspector::getSuggestions() const + { + return _suggestions; + } + + std::string DDLInspector::getLastErrorDesc() const + { + // return description of most recently added error element + for (ImporterMsgList::const_reverse_iterator itMsgs = _suggestions.rbegin(); + _suggestions.rend() != itMsgs; ++itMsgs) + { + if (importer_error == itMsgs->severity) + { + return std::string(itMsgs->desc); + } + } + return a_util::strings::empty_string; + } + + void DDLInspector::InitNewCheck() + { + _complex_names.clear(); + _data_types_names.clear(); + + _enum_names.clear(); + + _base_unit_names.clear(); + + _stream_names.clear(); + + _prefix_names.clear(); + + _version = DDLVersion::ddl_version_invalid; + + _has_struct_dynamic_arrays = false; + + _suggestions.clear(); + } + + bool DDLInspector::foundDynamicArrays() + { + return _has_dynamic_arrays; + } + + unsigned int DDLInspector::getLastBytePosOfAStructCorrected(const std::string& strStructName) + { + DDLComplex *poComplex = _ddl_desc->getStructByName(strStructName); + visit(poComplex); + return _struct_infos[poComplex].last_byte_pos; + } + + unsigned int DDLInspector::getLastBytePosOfAStructReal(const std::string& strStructName) + { + DDLComplex *poComplex = _ddl_desc->getStructByName(strStructName); + visit(poComplex); + return _struct_infos[poComplex].last_byte_pos_real; + } + + void DDLInspector::setAutoCorrect(bool autoCorrection) + { + _auto_correct = autoCorrection; + } + + void DDLInspector::setWarningLevel(WarningLevel warning_level) + { + _warning_level = warning_level; + } + + ddl::WarningLevel DDLInspector::getWarningLevel() const + { + return _warning_level; + } + + uint64_t boolToInt(const std::string& bVar) + { + if ((bVar) == "true" || (bVar) == "on" || (bVar) == "1" || (bVar) == "tTrue") + { + return 1; + } + else if ((bVar) == "false" || (bVar) == "off" || (bVar) == "0" || (bVar) == "tFalse") + { + return 0; + } + else if(a_util::strings::toUInt64(bVar) == 0) + { + return 0; + } + return 1; + } + + bool DDLInspector::lessDDL(const std::string& strLHS, + const std::string& strRHS, const DDLDataType* poType) + { + if (NULL == poType || !poType->isPredefined()) + { + // not interpretable + return false; + } + + if (poType->getName() == "tBool") + { + // compare boolean type + return boolToInt(strLHS) < boolToInt(strRHS); + } + if (poType->getName() == "tChar" || + poType->getName() == "tUInt8" || + poType->getName() == "tUInt16" || + poType->getName() == "tUInt32" || + poType->getName() == "tUInt64") + { + // compare unsigned integer types + return a_util::strings::toUInt64(strLHS) < a_util::strings::toUInt64(strRHS); + } + if (poType->getName() == "tInt8" || + poType->getName() == "tInt16" || + poType->getName() == "tInt32" || + poType->getName() == "tInt64") + { + // compare signed integer types + return a_util::strings::toInt64(strLHS) < a_util::strings::toInt64(strRHS); + } + if (poType->getName() == "tFloat32" || + poType->getName() == "tFloat64") + { + // compare floating-point types + return a_util::strings::toDouble(strLHS) < a_util::strings::toDouble(strRHS); + } + + // other type => not interpretable + return false; + } + + ImporterMsgList DDLInspector::checkValidyOfNestedStructs(const DDLDescription* poDescription) + { + ImporterMsgList lstErrors; + if (!poDescription) + { + ImporterMsg sMsg = + { + a_util::strings::format("Description is invalid."), + importer_error + }; + lstErrors.push_back(sMsg); + return lstErrors; + } + // validate of nested structs + DDLComplexVec vecStructs = poDescription->getStructs(); + for (DDLComplexIt itStruct = vecStructs.begin(); itStruct != vecStructs.end(); ++itStruct) + { + std::string strStructTypeName = (*itStruct)->getName(); + std::string strLog = strStructTypeName; + if (false == checkValidyOfNestedStructs(poDescription, strStructTypeName, strStructTypeName, strLog)) + { + ImporterMsg sMsg = + { + a_util::strings::format(strLog.c_str()), + importer_error + }; + lstErrors.push_back(sMsg); + } + } + return lstErrors; + } + + bool DDLInspector::checkValidyOfNestedStructs(const DDLDescription* poDescription, + const std::string& strStructTypeName, + const std::string& strNestedStructTypeName, + std::string& strLog, + int nStructDepth /*=1*/) + { + if (!poDescription) + { + strLog = a_util::strings::format("Description is invalid."); + return false; + } + if (nStructDepth > DDL_MAX_DESC_HIERARCHY) + { + strLog = a_util::strings::format("The depth of the hierarchy of the complex data type '%s' is higher than %u.", strStructTypeName.c_str(), DDL_MAX_DESC_HIERARCHY); + return false; + } + const DDLComplex * poComplex = poDescription->getStructByName(strNestedStructTypeName); + if (NULL != poComplex) + { + DDLElementVec vecElements = poComplex->getElements(); + + for (DDLElementIt itElem = vecElements.begin(); + vecElements.end() != itElem; ++itElem) + { + std::string strStructElementName = (*itElem)->getType(); + const DDLComplex * poDT = poDescription->getStructByName(strStructElementName); + if (NULL != poDT) + { + // complex data type + std::vector vecStructs = a_util::strings::split(strLog, ",", true); + strLog.append(a_util::strings::format(",%s", strStructElementName.c_str())); + if (std::find(vecStructs.begin(), vecStructs.end(), strStructElementName) != vecStructs.end()) + { + // includes nested struct element with same data type as nested struct above + return false; + } + else + { + if (false == checkValidyOfNestedStructs(poDescription, strStructTypeName, strStructElementName, strLog, nStructDepth + 1)) + { + // includes nested struct with same data type as base complex data type or hierarchy of the complex data type is higher than 5 + return false; + } + } + } + } + } + strLog = a_util::strings::empty_string; + return true; + } + + a_util::result::Result DDLInspector::addSuggestion(std::string const &desc, + ImporterMsgSeverity const severity) + { + if (_warning_level != WarningLevel::silent) + { + if (desc.empty()) + { + return ERR_EMPTY; + } + if (importer_info > severity || + importer_error < severity) + { + return ERR_INVALID_ARG; + } + ImporterMsg sMsg = { desc, severity }; + _suggestions.push_back(sMsg); + } + return a_util::result::SUCCESS; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlinspector.h b/ddlrepresentation/ddlinspector.h new file mode 100644 index 0000000..5fd582f --- /dev/null +++ b/ddlrepresentation/ddlinspector.h @@ -0,0 +1,287 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_INSPECTOR_H_INCLUDED +#define DDL_INSPECTOR_H_INCLUDED + +#include "ddl_common.h" +#include "ddlvisitor_intf.h" +#include "ddlimporter.h" +#include "ddlversion.h" + +namespace ddl +{ + enum WarningLevel + /* see "rules for changing an enumeration" (#27200) before doing any change! */ + { + /** + * Inform about all warnings + */ + verbose = 0, + /** + * Suppress some minor warnings + */ + moderate = 1, + /** + * Suppress all warnings + */ + silent = 2 + }; + + /// Maximum depth of the hierarchy of a complex data type in a DDL File + #define DDL_MAX_DESC_HIERARCHY 100 + + /** + * Validation and correction class for ADTF DDL for use with the + */ + class DDLInspector : public IDDLChangeVisitor + { + public: + /** + * CTOR. + * @param[in] auto_correct - Flag for implicit auto-correction (optional) + */ + DDLInspector(bool auto_correct = false); + + virtual a_util::result::Result visitDDL(DDLDescription* description); + virtual a_util::result::Result visit(DDLHeader* header); + virtual a_util::result::Result visit(DDLDataType* data_type); + virtual a_util::result::Result visit(DDLComplex* complex); + virtual a_util::result::Result visit(DDLStream* stream); + virtual a_util::result::Result visit(DDLUnit* unit); + virtual a_util::result::Result visit(DDLBaseunit* baseunit); + virtual a_util::result::Result visit(DDLExtDeclaration* ext_declaration); + virtual a_util::result::Result visit(DDLElement* element); + virtual a_util::result::Result visit(DDLPrefix* prefix); + virtual a_util::result::Result visit(DDLRefUnit* ref_unit); + virtual a_util::result::Result visit(DDLStreamStruct* stream_struct); + virtual a_util::result::Result visit(DDLEnum* ddl_enum); + virtual a_util::result::Result visit(DDLStreamMetaType* stream_meta_type); + virtual a_util::result::Result visit(DDLProperty* property); + + /** + * Setter for the auto-correction flag. + * @param[in] auto_correct - New value of the flag + * @return void + */ + void setAutoCorrect(bool auto_correct); + + /** + * Getter for the auto-correction flag. + * @returns the flag + */ + bool getAutoCorrect() const; + + /** + * Setter for the auto-correction flag. + * @param[in] auto_correct - New value of the flag + * @return void + */ + void setWarningLevel(WarningLevel warning_level); + + /** + * Getter for the auto-correction flag. + * @returns the flag + */ + WarningLevel getWarningLevel() const; + + /** + * Getter for the list of suggestions. + * @returns the list of suggestions + */ + ImporterMsgList getSuggestions() const; + + /** + * Getter for the most recent error description. + * @return The error description or \c a_util::strings::empty_string if there was none. + * @remarks This method indeed returns the last \b error message (message with severity \c importer_error). + */ + std::string getLastErrorDesc() const; + + /** + * Init a new Check, clear all list and init all variables. + */ + void InitNewCheck(); + + /** + * Check if the description contains dynamic arrays + * @retval true if a dynamic array was found + */ + bool foundDynamicArrays(); + + /** + * Returns the last corrected Bytepos position inclusive the + * last Element size. + * @param[in] struct_name - name of the Struct where you want the last element + * @return Last corrected Bytepos position inclusive the last Element size. + */ + unsigned int getLastBytePosOfAStructCorrected(const std::string& struct_name); + + /** + * Returns the actual last Bytepos inclusive the last Element size. + * @param[in] struct_name - name of the Struct where you want the last element + * @return Actual last Bytepos inclusive the last Element size. + */ + unsigned int getLastBytePosOfAStructReal(const std::string& struct_name); + + /** + * Check the validy of nested structs. + * @param[in] description - pointer of the Description within you want to check a vality of nested structs + * @retval Error message list + */ + static ImporterMsgList checkValidyOfNestedStructs(const DDLDescription* description); + + protected: + /** + * Method for derived classes to add an own suggestion. + * @param [in] desc Suggestion message + * @param [in] severity Message severity + * @retval ERR_EMPTY The suggestion message must not be empty. + * @retval ERR_INVALID_ARG The message severity must have a valid value + * of type \c adtf::ImporterMsgSeverity. + */ + a_util::result::Result addSuggestion(std::string const &desc, + ImporterMsgSeverity const severity); + + /** + * Helper method to check if the element is alignable. + * @param[in] byte_pos - Current byte position inside the structure + * @param[in] element_size - Size of the element + * @retval true Element is alignable + * @retval false Element is not alignable + */ + virtual bool isAlignable(size_t const byte_pos, + size_t const element_size); + + /** + * Helper method which returns whether the left-hand-side argument + * compares less than the right-hand-side one (as returned by operator <) + * based on given DDL type information. + * + * @param [in] lhs String of the left-hand-side + * @param [in] rhs String of the right-hand-side + * @param [in] type Pointer to common type information + * + * @retval true LHS is lower than RHS + * @retval false LHS is not lower than RHS or type is not interpretable + */ + static bool lessDDL (const std::string& lhs, + const std::string& rhs, + const DDLDataType* type); + + private: // methods + /** + * Recursive helper function for check of the validy of nested structs within a struct. + * @param[in] description - pointer of the Description within you want to check a vality of a struct + * @param[in] struct_type_name - name of the Struct where you want to check for invalid nested structs + * @param[in] nested_struct_type_name - name of the nested Struct + * @param[out] log - Log of error message, if validy is failed + * @param[in] struct_depth - Depth of the nested stuct + * @retval true if valid + * @retval false otherwise + */ + static bool checkValidyOfNestedStructs(const DDLDescription* description, + const std::string& struct_type_name, + const std::string& nested_struct_type_name, + std::string& log, + int struct_depth = 1); + + private: // members + DDLDescription* _ddl_desc; + bool _auto_correct; + /** + * The list contains all warnings and errors. + */ + ImporterMsgList _suggestions; + + /** + * The set contains all names of the structs. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _complex_names; + + /** + * The list contains all names of the data types. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _data_types_names; + + /** + * The list contains all names of the enum. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _enum_names; + + /** + * The list contains all names of the base unit names. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _base_unit_names; + + /** + * The list contains all names of the streams. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _stream_names; + + /** + * The list contains all names of the prefixes. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _prefix_names; + + /** + * The list contains all names of the unit names. + * If the list contains two equal names, it will be set + * an error in the ImporterMsgList. + */ + std::set _unit_names; + + DDLVersion _version; + + WarningLevel _warning_level; + + /* + * Boolean to know if a file contains a dynamic array + */ + bool _has_dynamic_arrays; + /* + * Boolean to know if a structure contains a dynamic array + */ + bool _has_struct_dynamic_arrays; + + struct StructInfo + { + unsigned int size; + unsigned int last_byte_pos_real; + unsigned int last_byte_pos; + bool valid; + }; + + std::map _struct_infos; + }; +} +#endif // DDL_INSPECTOR_H_INCLUDED + diff --git a/ddlrepresentation/ddlprefix.cpp b/ddlrepresentation/ddlprefix.cpp new file mode 100644 index 0000000..acbe909 --- /dev/null +++ b/ddlrepresentation/ddlprefix.cpp @@ -0,0 +1,107 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlprefix.h" +#include + +namespace ddl +{ + DDLPrefix::DDLPrefix() : + _name{}, + _symbol{}, + _power{}, + _init_flag{}, + _level{1} + { + } + + DDLPrefix::DDLPrefix(const std::string& name, const std::string& symbol, + int const power, int const creation_level) : + _name(name), _symbol(symbol), _power(power), + _init_flag(true), _level(creation_level) + { + } + + a_util::result::Result DDLPrefix::accept(IDDLVisitor *visitor) const + { + return visitor->visit(this); + } + a_util::result::Result DDLPrefix::accept(IDDLChangeVisitor *visitor) + { + return visitor->visit(this); + } + + const std::string& DDLPrefix::getName() const + { + return _name; + } + + void DDLPrefix::setName(const std::string& name) + { + _name = name; + } + + bool DDLPrefix::isInitialized() const + { + return _init_flag; + } + + a_util::result::Result DDLPrefix::create(const std::string& name, const std::string& symbol, + int const power, int const creation_level) + { + _name = name; + _symbol = symbol; + _power = power; + _init_flag = true; + _level = creation_level; + return a_util::result::SUCCESS; + } + + std::string DDLPrefix::getSymbol() const + { + return _symbol; + } + + void DDLPrefix::setSymbol(const std::string& symbol) + { + _symbol = symbol; + } + + + int DDLPrefix::getPower() const + { + return _power; + } + + void DDLPrefix::setPower(int const power) + { + _power = power; + } + + bool DDLPrefix::isPredefined() const + { + return -1 == _level; // cMediaManager::DL_AlwaysThere + } + + int DDLPrefix::getCreationLevel() const + { + return _level; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlprefix.h b/ddlrepresentation/ddlprefix.h new file mode 100644 index 0000000..f4905ac --- /dev/null +++ b/ddlrepresentation/ddlprefix.h @@ -0,0 +1,119 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLPREFIX_H_INCLUDED +#define DDLPREFIX_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" + +namespace ddl +{ + + /** + * Representation of a prefix in a DDL description. + */ + class DDLPrefix : public DDL + { + public: + /** + * Default CTOR + */ + DDLPrefix(); + + /** + * CTOR + * @param[in] name - Name of the prefix + * @param[in] symbol - Represents the short symbol (e.g. "k") + * @param[in] power - Power of the prefix + * @param[in] creation_level - Level at creation time (optional) + */ + DDLPrefix(const std::string& name, + const std::string& symbol, + int const power, + int const creation_level = 1); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isPredefined() const; + + bool isInitialized() const; + + int getCreationLevel() const; + + /** + * Creation method to fill the object with data. + * @param[in] name - Name of the prefix + * @param[in] symbol - Represents the short symbol (e.g. "k") + * @param[in] power - Power of the prefix + * @param[in] creation_level - Level at creation time (optional) + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(const std::string& name, + const std::string& symbol, + int const power, + int const creation_level = 1); + + /** + * Getter for the name + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the name + */ + void setName(const std::string& name); + + /** + * Getter for the symbol + * @return the symbol + */ + std::string getSymbol() const; + + /** + * Setter for the symbol + */ + void setSymbol(const std::string& symbol); + + /** + * Getter for the power + * @return the power + */ + int getPower() const; + + /** + * Setter for the power + */ + void setPower(int const power); + + + private: + std::string _name; + std::string _symbol; + int _power; + + bool _init_flag; + int _level; + }; + +} // namespace ddl + +#endif // _PREFIX_H_INCLUDED_ diff --git a/ddlrepresentation/ddlprinter.cpp b/ddlrepresentation/ddlprinter.cpp new file mode 100644 index 0000000..c9ee751 --- /dev/null +++ b/ddlrepresentation/ddlprinter.cpp @@ -0,0 +1,631 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlprinter.h" +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddlcontainer.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + +#include "ddlversion.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) + _MAKE_RESULT(-44, ERR_INVALID_VERSION) + + DDLPrinter::DDLPrinter(const bool& full_out): + _dom{}, + _version(DDLVersion::ddl_version_invalid), + _full_out{full_out}, + _last_path{}, + _forced_version(DDLVersion::ddl_version_invalid) + { +#if defined(WIN32) && _MSC_VER < 1900 + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif // WIN32 + } + + template + a_util::result::Result AcceptAll(DDLContainer& oElems, V* pVisitor) + { + for (typename DDLContainer::iterator itElem = oElems.begin(); + itElem != oElems.end(); ++itElem) + { + RETURN_IF_FAILED((*itElem)->accept(pVisitor)); + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visitDDL(const DDLDescription* poDescription) + { + if (!poDescription) { return ERR_POINTER; } + _dom.reset(); + _dom.fromString("\n \ + \n \ + "); + RETURN_IF_FAILED(poDescription->getHeader()->accept(this)); + + _dom.getRoot().createChild("units"); + + DDLContainer vecDDLBaseunits = poDescription->getBaseunits(); + RETURN_IF_FAILED(AcceptAll(vecDDLBaseunits, this)); + + DDLContainer vecDDLPrefixes = poDescription->getPrefixes(); + RETURN_IF_FAILED(AcceptAll(vecDDLPrefixes, this)); + + DDLContainer vecDDLUnits = poDescription->getUnits(); + RETURN_IF_FAILED(AcceptAll(vecDDLUnits, this)); + + _dom.getRoot().createChild("datatypes"); + + DDLContainer vecDDLDataTypes = poDescription->getDatatypes(); + RETURN_IF_FAILED(AcceptAll(vecDDLDataTypes, this)); + + _dom.getRoot().createChild("enums"); + + DDLContainer vecDDLEnums = poDescription->getEnums(); + RETURN_IF_FAILED(AcceptAll(vecDDLEnums, this)); + + _dom.getRoot().createChild("structs"); + + DDLContainer vecStructs = poDescription->getStructs(); + RETURN_IF_FAILED(AcceptAll(vecStructs, this)); + + _dom.getRoot().createChild("streams"); + + DDLContainer vecStreams = poDescription->getStreams(); + RETURN_IF_FAILED(AcceptAll(vecStreams, this)); + + if (poDescription->getHeader()->getLanguageVersion() >= DDLVersion::ddl_version_40) + { + _dom.getRoot().createChild("streammetatypes"); + + DDLContainer vecStreamMetaTypes = poDescription->getStreamMetaTypes(); + RETURN_IF_FAILED(AcceptAll(vecStreamMetaTypes, this)); + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLHeader* poHeader) + { + if (!poHeader) { return ERR_POINTER; } + a_util::xml::DOMElement oHeaderElem = _dom.getRoot().createChild("header"); + a_util::xml::DOMElement oLangElem = oHeaderElem.createChild("language_version"); + if (_forced_version == DDLVersion::ddl_version_invalid) + { + _version = poHeader->getLanguageVersion(); + } + else + { + _version = _forced_version; + } + oLangElem.setData(_version.toString()); + a_util::xml::DOMElement oAutElem = oHeaderElem.createChild("author"); + oAutElem.setData(poHeader->getAuthor()); + a_util::xml::DOMElement oDateElem = oHeaderElem.createChild("date_creation"); + a_util::datetime::Date sDateTmp = poHeader->getDateCreation(); + oDateElem.setData(sDateTmp.format("%d.%m.%Y")); + a_util::xml::DOMElement oChangeElem = oHeaderElem.createChild("date_change"); + sDateTmp = poHeader->getDateChange(); + oChangeElem.setData(sDateTmp.format("%d.%m.%Y")); + a_util::xml::DOMElement oDescElem = oHeaderElem.createChild("description"); + oDescElem.setData(poHeader->getDescription()); + DDLExtDeclarationVec vecExtDecls = poHeader->getExtDeclarations(); + for (DDLExtDeclarationIt itED = vecExtDecls.begin(); + vecExtDecls.end() != itED; ++itED) + { + RETURN_IF_FAILED((*itED)->accept(this)); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLExtDeclaration* poExtDeclaration) + { + if (!poExtDeclaration) { return ERR_POINTER; } + a_util::xml::DOMElement oHeader; + if (!_dom.getRoot().findNode("header", oHeader)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oEDElement = oHeader.createChild("ext_declaration"); + oEDElement.setAttribute("key", poExtDeclaration->getKey()); + oEDElement.setAttribute("value", poExtDeclaration->getValue()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLBaseunit* poBaseunit) + { + if (!poBaseunit) { return ERR_POINTER; } + a_util::xml::DOMElement oUnits; + if (!_dom.getRoot().findNode("units", oUnits)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oBUElement = oUnits.createChild("baseunit"); + oBUElement.setAttribute("name", poBaseunit->getName()); + oBUElement.setAttribute("symbol", poBaseunit->getSymbol()); + oBUElement.setAttribute("description", poBaseunit->getDescription()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLPrefix* poPrefix) + { + if (!poPrefix) { return ERR_POINTER; } + a_util::xml::DOMElement oUnits; + if (!_dom.getRoot().findNode("units", oUnits)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oPrefixElement = oUnits.createChild("prefixes"); + oPrefixElement.setAttribute("name", poPrefix->getName()); + oPrefixElement.setAttribute("symbol", poPrefix->getSymbol()); + oPrefixElement.setAttribute("power", + a_util::strings::toString((int32_t)poPrefix->getPower())); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLUnit* poUnit) + { + if (!poUnit) { return ERR_POINTER; } + a_util::xml::DOMElement oUnits; + if (!_dom.getRoot().findNode("units", oUnits)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oUnitElement = oUnits.createChild("unit"); + oUnitElement.setAttribute("name", poUnit->getName()); + a_util::xml::DOMElement oTmpElement = oUnitElement.createChild("numerator"); + oTmpElement.setData(poUnit->getNumerator()); + oTmpElement = oUnitElement.createChild("denominator"); + oTmpElement.setData(poUnit->getDenominator()); + oTmpElement = oUnitElement.createChild("offset"); + oTmpElement.setData(a_util::strings::toString(static_cast + (poUnit->getOffset()))); + std::vector vecDDLRefUnits = poUnit->getRefUnits(); + _last_path = a_util::strings::format("%s[@name='%s']", + oUnitElement.getPath().c_str(), + oUnitElement.getAttribute("name").c_str()); + for (size_t i = 0; i < vecDDLRefUnits.size(); i++) + { + RETURN_IF_FAILED(vecDDLRefUnits[i]->accept(this)); + } + _last_path.clear(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLRefUnit* poRefUnit) + { + if (!poRefUnit) { return ERR_POINTER; } + a_util::xml::DOMElement oParent; + if (!_dom.findNode(_last_path, oParent)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oRUElement = oParent.createChild("refUnit"); + oRUElement.setAttribute("name", poRefUnit->getName()); + oRUElement.setAttribute("power", + a_util::strings::toString((int32_t)poRefUnit->getPower())); + oRUElement.setAttribute("prefix", poRefUnit->getPrefix()); + if (_full_out) + { + a_util::xml::DOMElement oElem; + if (!_dom.findNode(a_util::strings::format("//units/prefixes[@name=\"%s\"]", poRefUnit->getPrefix().c_str()), oElem)) + { + RETURN_IF_FAILED(poRefUnit->getPrefixObject()->accept(this)); + } + if (!_dom.findNode(a_util::strings::format("//units/baseunit[@name=\"%s\"]", poRefUnit->getName().c_str()), oElem)) + { + if (!_dom.findNode(a_util::strings::format("//units/unit[@name=\"%s\"]", poRefUnit->getName().c_str()), oElem)) + { + RETURN_IF_FAILED(poRefUnit->getUnitObject()->accept(this)); + } + } + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLDataType* poDataType) + { + if (!poDataType) { return ERR_POINTER; } + a_util::xml::DOMElement oDatatypes; + if (!_dom.getRoot().findNode("datatypes", oDatatypes)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oDTElement = oDatatypes.createChild("datatype"); + if (_version < DDLVersion::ddl_version_11) + { + oDTElement.setAttribute("type", poDataType->getName()); + } + else + { + oDTElement.setAttribute("name", poDataType->getName()); + } + oDTElement.setAttribute("size", + a_util::strings::toString(static_cast(poDataType->getNumBits()))); + if (!poDataType->getDescription().empty()) + { + oDTElement.setAttribute("description", + poDataType->getDescription()); + } + if(poDataType->getArraysize() > 1) + { + oDTElement.setAttribute("arraysize", + a_util::strings::toString(static_cast + (poDataType->getArraysize()))); + } + if (!poDataType->getUnit().empty()) + { + oDTElement.setAttribute("unit", poDataType->getUnit()); + } + if (_version >= DDLVersion::ddl_version_30) + { + // min and max values are supported since DDL 3.0 + if (poDataType->isMinValid()) + { + oDTElement.setAttribute("min", poDataType->getMinValue()); + } + if (poDataType->isMaxValid()) + { + oDTElement.setAttribute("max", poDataType->getMaxValue()); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLComplex* poStruct) + { + if (!poStruct) { return ERR_POINTER; } + a_util::xml::DOMElement oStructs; + if (_dom.findNode(a_util::strings::format("//structs/struct[@name=\"%s\"]", poStruct->getName().c_str()), oStructs)) + { + //already added + return a_util::result::SUCCESS; + } + if (!_dom.getRoot().findNode("structs", oStructs)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oStructElement = oStructs.createChild("struct"); + oStructElement.setAttribute("name", poStruct->getName()); + oStructElement.setAttribute("version", + a_util::strings::toString(static_cast(poStruct->getVersion()))); + if (!poStruct->getComment().empty()) + { + oStructElement.setAttribute("comment", poStruct->getComment()); + } + if (_version >= DDLVersion::ddl_version_11) + { + oStructElement.setAttribute("alignment", + DDLAlignment::toString(poStruct->getAlignment())); + } + if (_version != poStruct->getDDLVersion()) + { + oStructElement.setAttribute("ddlversion", poStruct->getDDLVersion().toString()); + } + + std::vector vecDDLElements = poStruct->getElements(); + for (size_t i = 0; i < vecDDLElements.size(); i++) + { + _last_path = a_util::strings::format("%s[@name='%s']", + oStructElement.getPath().c_str(), poStruct->getName().c_str()); + RETURN_IF_FAILED(vecDDLElements[i]->accept(this)); + } + _last_path.clear(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLElement* poElement) + { + if (!poElement) { return ERR_POINTER; } + a_util::xml::DOMElement oParent; + a_util::xml::DOMElement oDomElem; + if (!_dom.findNode(_last_path, oParent)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oElem = oParent.createChild("element"); + oElem.setAttribute("type", poElement->getType()); + oElem.setAttribute("name", poElement->getName()); + + if (_full_out) + { + if (!_dom.findNode(a_util::strings::format("//structs/struct[@name=\"%s\"]", poElement->getType().c_str()), oDomElem)) + { + if (!_dom.findNode(a_util::strings::format("//datatypes/datatype[@name=\"%s\"]", poElement->getType().c_str()), oDomElem)) + { + if (!_dom.findNode(a_util::strings::format("//enums/enum[@name=\"%s\"]", poElement->getType().c_str()), oDomElem)) + { + RETURN_IF_FAILED(poElement->getTypeObject()->accept(this)); + } + } + } + } + + a_util::xml::DOMElement oDeserializedElement = oElem; + a_util::xml::DOMElement oSerializedElement = oElem; + if (_version >= DDLVersion::ddl_version_40) + { + oDeserializedElement = oElem.createChild("deserialized"); + oSerializedElement = oElem.createChild("serialized"); + } + oSerializedElement.setAttribute("bytepos", + a_util::strings::toString(static_cast + (poElement->getBytepos()))); + if ((_version < DDLVersion::ddl_version_11 && poElement->getBitpos() != 1) || + (_version >= DDLVersion::ddl_version_11 && poElement->getBitpos() > 0)) + { + oSerializedElement.setAttribute("bitpos", + a_util::strings::toString(static_cast + (poElement->getBitpos()))); + } + if (poElement->getNumBits() > 0) + { + oSerializedElement.setAttribute("numbits", + a_util::strings::toString(static_cast + (poElement->getNumBits()))); + } + oSerializedElement.setAttribute("byteorder", + DDLByteorder::toString(poElement->getByteorder())); + oDeserializedElement.setAttribute("alignment", + DDLAlignment::toString(poElement->getAlignment())); + + if (!poElement->getDescription().empty()) + { + oElem.setAttribute("description", poElement->getDescription()); + } + if(poElement->getArraysize() == 0 || !poElement->getArraySizeSource().empty()) + { + oElem.setAttribute("arraysize", poElement->getArraySizeSource()); + } + else + { + oElem.setAttribute("arraysize", + a_util::strings::toString(static_cast + (poElement->getArraysize()))); + } + + if (!poElement->getUnit().empty()) + { + oElem.setAttribute("unit", poElement->getUnit()); + } + + if (!poElement->getComment().empty()) + { + oElem.setAttribute("comment", poElement->getComment()); + } + + if (!poElement->getConstantValue().empty()) + { + oElem.setAttribute("value", poElement->getConstantValue()); + } + + if (_version >= DDLVersion::ddl_version_30) + { + // min, max, default, scale, and offset values are supported since DDL 3.0 + if (poElement->isMinValid()) + { + oElem.setAttribute("min", poElement->getMinValue()); + } + + if (poElement->isMaxValid()) + { + oElem.setAttribute("max", poElement->getMaxValue()); + } + + if (poElement->isDefaultValid()) + { + oElem.setAttribute("default", poElement->getDefaultValue()); + } + + if (poElement->isScaleValid()) + { + oElem.setAttribute("scale", poElement->getScaleValue()); + } + + if (poElement->isOffsetValid()) + { + oElem.setAttribute("offset", poElement->getOffsetValue()); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLStream* poStream) + { + if (!poStream) { return ERR_POINTER; } + a_util::xml::DOMElement oStreams; + if (!_dom.getRoot().findNode("streams", oStreams)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oStreamElement = oStreams.createChild("stream"); + if (!poStream->getName().empty()) + { + oStreamElement.setAttribute("name", poStream->getName()); + } + oStreamElement.setAttribute("type", poStream->getType()); + if (_full_out) + { + a_util::xml::DOMElement oElem; + if (!_dom.findNode(a_util::strings::format("//structs/struct[@name=\"%s\"]", poStream->getType().c_str()), oElem)) + { + RETURN_IF_FAILED(poStream->getTypeObject()->accept(this)); + } + } + if (!poStream->getDescription().empty()) + { + oStreamElement.setAttribute("description", + poStream->getDescription()); + } + std::vector vecStructs = poStream->getStructs(); + _last_path = a_util::strings::format("%s[@name='%s']", + oStreamElement.getPath().c_str(), + oStreamElement.getAttribute("name").c_str()); + for (size_t i = 0; i < vecStructs.size(); i++) + { + RETURN_IF_FAILED(vecStructs[i]->accept(this)); + } + _last_path.clear(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLStreamStruct* poStreamStruct) + { + if (!poStreamStruct) { return ERR_POINTER; } + a_util::xml::DOMElement oParent; + if (!_dom.findNode(_last_path, oParent)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oStruct = oParent.createChild("struct"); + oStruct.setAttribute("type", poStreamStruct->getType()); + if (!poStreamStruct->getName().empty()) + { + oStruct.setAttribute("name", poStreamStruct->getName()); + } + if (_full_out) + { + a_util::xml::DOMElement oElem; + if (!_dom.findNode(a_util::strings::format("//structs/struct[@name=\"%s\"]", poStreamStruct->getType().c_str()), oElem)) + { + RETURN_IF_FAILED(poStreamStruct->getTypeObject()->accept(this)); + } + } + oStruct.setAttribute("bytepos", + a_util::strings::toString(static_cast + (poStreamStruct->getBytepos()))); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLEnum* poEnum ) + { + if (!poEnum) { return ERR_POINTER; } + a_util::xml::DOMElement oEnums; + if (_dom.findNode(a_util::strings::format("//enums/enum[@name=\"%s\"]", poEnum->getName().c_str()), oEnums)) + { + //already added + return a_util::result::SUCCESS; + } + if (!_dom.getRoot().findNode("enums", oEnums)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oEnumElement = oEnums.createChild("enum"); + oEnumElement.setAttribute("name", poEnum->getName()); + + if (!poEnum->getType().empty()) + { + oEnumElement.setAttribute("type", poEnum->getType()); + } + + EnumNameValueVec vecNameValues = poEnum->getValues(); + for (EnumNameValueVec::iterator itElement = vecNameValues.begin(); itElement != vecNameValues.end(); ++itElement) + { + a_util::xml::DOMElement oEnumValueElement = oEnumElement.createChild("element"); + + oEnumValueElement.setAttribute("name", itElement->first); + oEnumValueElement.setAttribute("value", itElement->second); + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLStreamMetaType* poStreamMetaType) + { + a_util::xml::DOMElement oStreamMetaTypes; + if (!_dom.getRoot().findNode("streammetatypes", oStreamMetaTypes)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oElement = oStreamMetaTypes.createChild("streammetatype"); + oElement.setAttribute("name", poStreamMetaType->getName()); + oElement.setAttribute("version", poStreamMetaType->getVersion()); + if (poStreamMetaType->getParentObject()) + { + oElement.setAttribute("parent", poStreamMetaType->getParent()); + } + + const DDLPropertyVec& vecProperties = poStreamMetaType->getProperties(); + for (DDLPropertyVec::const_iterator it = vecProperties.cbegin(); it != vecProperties.cend(); ++it) + { + a_util::xml::DOMElement oPropertyNode = oElement.createChild("property"); + oPropertyNode.setAttribute("name", (*it)->getName()); + oPropertyNode.setAttribute("type", (*it)->getType()); + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::visit(const DDLProperty* poProperty) + { + return ERR_NOT_IMPL; + } + + std::string DDLPrinter::getXML() const + { + return std::string(_dom.toString()); + } + + a_util::result::Result DDLPrinter::toFile(const std::string& strFilename) const + { + if (!_dom.save(strFilename)) + { + return ERR_FAILED; + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLPrinter::forceVersion(const DDLVersion& forced_version) + { + if (!forced_version.isValidVersion()) + { + return ERR_INVALID_VERSION; + } + else + { + _forced_version = forced_version; + return a_util::result::SUCCESS; + } + } +} // namespace ddl diff --git a/ddlrepresentation/ddlprinter.h b/ddlrepresentation/ddlprinter.h new file mode 100644 index 0000000..3e634dd --- /dev/null +++ b/ddlrepresentation/ddlprinter.h @@ -0,0 +1,94 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + + +#ifndef DDL_PRINTER_H_INCLUDED +#define DDL_PRINTER_H_INCLUDED + +#include "ddlvisitor_intf.h" +#include "ddldescription.h" +#include "ddlversion.h" + +namespace ddl +{ + + /** + * Concrete Visitor to collect the data of a DDL in object-representation + * and convert it back to XML (string or file). + */ + class DDLPrinter : public IDDLVisitor + { + public: + /** + * Constructor + */ + DDLPrinter(const bool& full_out=true); + + public: + a_util::result::Result visitDDL(const DDLDescription* description); + a_util::result::Result visit(const DDLHeader* header); + a_util::result::Result visit(const DDLDataType* data_type); + a_util::result::Result visit(const DDLComplex* complex); + a_util::result::Result visit(const DDLStream* stream); + a_util::result::Result visit(const DDLUnit* unit); + a_util::result::Result visit(const DDLBaseunit* baseunit); + a_util::result::Result visit(const DDLExtDeclaration* ext_declaration); + a_util::result::Result visit(const DDLElement* element); + a_util::result::Result visit(const DDLPrefix* prefix); + a_util::result::Result visit(const DDLRefUnit* ref_unit); + a_util::result::Result visit(const DDLStreamStruct* stream_struct); + a_util::result::Result visit(const DDLEnum* ddl_enum); + a_util::result::Result visit(const DDLStreamMetaType* stream_meta_type); + a_util::result::Result visit(const DDLProperty* property); + + /** + * Getter for the XML string of the collected DDL information. + * @return the XML string containing the DDL description + */ + std::string getXML() const; + + /** + * Saves the collected DDL information as XML to the specified file. + * @param[in] filename - Path to file to use + * @retval ERR_FAILED Saving process failed + */ + a_util::result::Result toFile(const std::string& filename) const; + + /** + * The method forceVersion makes the printer ignore the DDL language version set in the + * header of the description to be printed. To take effect, this method must be called + * before calling visitDDL() + * + * @param [in] forced_version The version the printer use for output. + * @returns Standard result code. + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_INVALID_VERSION Unknown version passed. + */ + a_util::result::Result forceVersion(const DDLVersion& forced_version); + + private: // members + a_util::xml::DOM _dom; + DDLVersion _version; + bool _full_out; + std::string _last_path; + DDLVersion _forced_version; + }; +} // namespace ddl + +#endif // DDL_PRINTER_H_INCLUDED diff --git a/ddlrepresentation/ddlproperty.cpp b/ddlrepresentation/ddlproperty.cpp new file mode 100644 index 0000000..fa19e6c --- /dev/null +++ b/ddlrepresentation/ddlproperty.cpp @@ -0,0 +1,73 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlproperty.h" +#include + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLProperty::DDLProperty(const std::string& name, const std::string& type) : + _name(name), + _type(type), + _init_flag{true} + { + } + + a_util::result::Result DDLProperty::accept(IDDLVisitor *visitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return visitor->visit(this); + } + + a_util::result::Result DDLProperty::accept(IDDLChangeVisitor *visitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return visitor->visit(this); + } + + const std::string& DDLProperty::getName() const + { + return _name; + } + + const std::string& DDLProperty::getType() const + { + return _type; + } + + bool DDLProperty::isInitialized() const + { + return _init_flag; + } + + int DDLProperty::getCreationLevel() const + { + return 0; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlproperty.h b/ddlrepresentation/ddlproperty.h new file mode 100644 index 0000000..c307ab4 --- /dev/null +++ b/ddlrepresentation/ddlproperty.h @@ -0,0 +1,76 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_PROPERTY_H_INCLUDED +#define DDL_PROPERTY_H_INCLUDED + +#include "ddl_common.h" +#include "ddlvisitor_intf.h" +#include "ddl_type.h" + +namespace ddl +{ + /** + * Representation of a stream inside a DDL description. + */ + class DDLProperty : public DDL + { + public: + /** + * Default CTOR + */ + DDLProperty() = default; + + /** + * CTOR + * @param[in] name - Name of the property + * @param[in] type - Type of the property + */ + DDLProperty(const std::string& name, const std::string& type); + + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + int getCreationLevel() const; + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Getter for the type. + * @return the type + */ + const std::string& getType() const; + + + private: + std::string _name; + std::string _type; + bool _init_flag; + }; + +} // namespace ddl + +#endif diff --git a/ddlrepresentation/ddlrefunit.cpp b/ddlrepresentation/ddlrefunit.cpp new file mode 100644 index 0000000..3a0b943 --- /dev/null +++ b/ddlrepresentation/ddlrefunit.cpp @@ -0,0 +1,130 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlrefunit.h" +#include + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLRefUnit::DDLRefUnit(IDDLUnit* poUnit, int const nPower, DDLPrefix* poPrefix) : + _unit{poUnit}, + _power{nPower}, + _prefix{poPrefix}, + _init_flag{(NULL != poUnit) && (NULL != poPrefix)} + { + } + + a_util::result::Result DDLRefUnit::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLRefUnit::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + const std::string& DDLRefUnit::getName() const + { + if (NULL == _unit) + { + return a_util::strings::empty_string; + } + return _unit->getName(); + } + + IDDLUnit * DDLRefUnit::getUnitObject() const + { + if (!_init_flag) + { + return NULL; + } + return _unit; + } + + void DDLRefUnit::setUnitObject(IDDLUnit* pUnit) + { + _unit = pUnit; + _init_flag = (NULL != _unit) && + (NULL != _prefix); + } + + int DDLRefUnit::getPower() const + { + return _power; + } + + void DDLRefUnit::setPower(int const nPower) + { + _power = nPower; + } + + std::string DDLRefUnit::getPrefix() const + { + if (!_init_flag) + { + return a_util::strings::empty_string; + } + return _prefix->getName(); + } + + DDLPrefix * DDLRefUnit::getPrefixObject() const + { + if (!_init_flag) + { + return NULL; + } + return _prefix; + } + + void DDLRefUnit::setPrefixObject(DDLPrefix* pPrefix) + { + _prefix = pPrefix; + _init_flag = (NULL != _unit) && + (NULL != _prefix); + } + + + bool DDLRefUnit::isInitialized() const + { + return _init_flag; + } + + a_util::result::Result DDLRefUnit::create(IDDLUnit* poUnit, int const nPower, DDLPrefix* poPrefix) + { + if (!poUnit || !poPrefix) { return ERR_POINTER; } + _unit = poUnit; + _power = nPower; + _prefix = poPrefix; + _init_flag = true; + return a_util::result::SUCCESS; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlrefunit.h b/ddlrepresentation/ddlrefunit.h new file mode 100644 index 0000000..276a163 --- /dev/null +++ b/ddlrepresentation/ddlrefunit.h @@ -0,0 +1,124 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef REF_UNIT_H_INCLUDED +#define REF_UNIT_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlunit_intf.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + + /** + * Decorator class for IDDLUnit objects to be used inside other DDLUnit objects. + */ + class DDLRefUnit : public DDL + { + public: + /** + * Default CTOR + */ + DDLRefUnit() = default; + + /** + * CTOR with unit object. + * @param[in] unit - Pointer to the unit object + * @param[in] power - Power of the new unit related to the base units + * @param[in] prefix - Pointer to the prefix object + */ + DDLRefUnit(IDDLUnit* unit, int const power, DDLPrefix* prefix); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] unit - Pointer to the unit object + * @param[in] power - Power of the new unit related to the base units + * @param[in] prefix - Pointer to the prefix object + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(IDDLUnit* unit, int const power, DDLPrefix* prefix); + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Getter for the unit object. + * @return pointer to the unit object + */ + IDDLUnit * getUnitObject() const; + + /** + * Setter for the unit object. + * @param unit the unit object to set + * @return void + */ + void setUnitObject(IDDLUnit* const unit); + + /** + * Getter for the power. + * @return the power + */ + int getPower() const; + + /** + * Setter for the power. + * @param power the power + * @return void + */ + void setPower(int const power); + + /** + * Getter for the prefix name. + * @return the prefix name + */ + std::string getPrefix() const; + + /** + * Getter for the prefix object. + * @return pointer to the prefix object + */ + DDLPrefix * getPrefixObject() const; + + /** + * Setter for the prefix object. + * @param prefix pointer to the prefix object + * @return void + */ + void setPrefixObject(DDLPrefix* const prefix); + + private: + IDDLUnit *_unit; + int _power; + DDLPrefix *_prefix; + bool _init_flag; + }; + +} // namespace ddl + +#endif // REF_UNIT_H_INCLUDED diff --git a/ddlrepresentation/ddlrepair.cpp b/ddlrepresentation/ddlrepair.cpp new file mode 100644 index 0000000..46dbb19 --- /dev/null +++ b/ddlrepresentation/ddlrepair.cpp @@ -0,0 +1,359 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlrepair.h" +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddlcontainer.h" +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-8, ERR_INVALID_HANDLE) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + + a_util::result::Result DDLRepair::visitDDL(DDLDescription* poDescription) + { + if (!poDescription) { return ERR_POINTER; } + + _ref_ddl = poDescription; + + DDLStreamVec vecStreams = poDescription->getStreams(); + for (DDLStreamIt itStream = vecStreams.begin(); + vecStreams.end() != itStream; ) + { + if (isFailed((*itStream)->accept(this))) + { + _ref_ddl->removeStream((*itStream)->getName()); + vecStreams = poDescription->getStreams(); + itStream = vecStreams.begin(); + } + else + { + ++itStream; + } + } + + DDLUnitVec vecDDLUnits = poDescription->getUnits(); + for (DDLUnitIt itUnit = vecDDLUnits.begin(); vecDDLUnits.end() != itUnit; + ++itUnit) + { + RETURN_IF_FAILED((*itUnit)->accept(this)); + } + + DDLComplexVec vecStructs = poDescription->getStructs(); + for (DDLComplexIt itStruct = vecStructs.begin(); + vecStructs.end() != itStruct; ++itStruct) + { + RETURN_IF_FAILED((*itStruct)->accept(this)); + } + + DDLEnumVec vecEnums = poDescription->getEnums(); + for (DDLEnumIt itEnum = vecEnums.begin(); vecEnums.end() != itEnum; ++itEnum) + { + RETURN_IF_FAILED((*itEnum)->accept(this)); + } + + + DDLDTVec vecDTs = poDescription->getDatatypes(); + for (DDLDTIt itDT = vecDTs.begin(); vecDTs.end() != itDT; ++itDT) + { + RETURN_IF_FAILED((*itDT)->accept(this)); + } + + + + // All representation objects are valid. + _ref_ddl = NULL; + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLHeader* poHeader) + { + // Nothing to resolve/validate + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLExtDeclaration* poExtDeclaration) + { + // Nothing to resolve/validate + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLBaseunit* poBaseunit) + { + // Nothing to resolve/validate + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLPrefix* poPrefix) + { + // Nothing to resolve/validate + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLUnit* poUnit) + { + if (!poUnit ||! _ref_ddl) { return ERR_POINTER; } + DDLRefUnitVec vecRUs = poUnit->getRefUnits(); + for (DDLRefUnitIt itRU = vecRUs.begin(); vecRUs.end() != itRU; ) + { + if (isFailed((*itRU)->accept(this))) + { + poUnit->removeRefUnit((*itRU)->getName()); + vecRUs = poUnit->getRefUnits(); + itRU = vecRUs.begin(); + } + else + { + ++itRU; + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLRefUnit* poRefUnit) + { + if (!poRefUnit || !_ref_ddl) { return ERR_POINTER; } + IDDLUnit * poUnit = _ref_ddl->getBaseunitByName(poRefUnit->getName()); + if (NULL == poUnit) + { + poUnit = _ref_ddl->getUnitByName(poRefUnit->getName()); + if (NULL == poUnit) + { + return ERR_INVALID_HANDLE; + } + else + { + poRefUnit->setUnitObject(poUnit); + } + } + else + { + poRefUnit->setUnitObject(poUnit); + } + DDLPrefix * poPrefix = _ref_ddl->getPrefixByName(poRefUnit->getPrefix()); + if (NULL == poPrefix) + { + return ERR_INVALID_HANDLE; + } + else + { + poRefUnit->setPrefixObject(poPrefix); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLDataType* poDataType) + { + if (!poDataType || !_ref_ddl) { return ERR_POINTER; } + std::string strUnit = poDataType->getUnit(); + if (!strUnit.empty()) + { + IDDLUnit * poUnit = _ref_ddl->getBaseunitByName(strUnit); + if (NULL == poUnit) + { + poUnit = _ref_ddl->getUnitByName(strUnit); + if (NULL == poUnit) + { + poDataType->setUnit(NULL); + } + else + { + poDataType->setUnit(poUnit); + } + } + else + { + poDataType->setUnit(poUnit); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLComplex* poComplex) + { + if (!poComplex) { return ERR_POINTER; } + if (!_ref_ddl) { return ERR_POINTER; } + DDLElementVec vecDDLElements = poComplex->getElements(); + for (DDLElementIt itElem = vecDDLElements.begin(); + vecDDLElements.end() != itElem; ) + { + if (isFailed(((*itElem)->accept(this)))) + { + poComplex->removeElement((*itElem)->getName()); + vecDDLElements = poComplex->getElements(); + itElem = vecDDLElements.begin(); + } + else + { + ++itElem; + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLElement* poElement) + { + if (!poElement || !_ref_ddl) { return ERR_POINTER; } + IDDLDataType * poDT = _ref_ddl->getDataTypeByName(poElement->getType()); + if (NULL == poDT) + { + poDT = _ref_ddl->getStructByName(poElement->getType()); + if (NULL == poDT) + { + poDT = _ref_ddl->getEnumByName(poElement->getType()); + if (NULL == poDT) + { + return ERR_INVALID_HANDLE; + } + else + { + poElement->setType(poDT); + } + } + else + { + poElement->setType(poDT); + } + } + else + { + poElement->setType(poDT); + } + std::string strUnit = poElement->getUnit(); + if (!strUnit.empty()) + { + IDDLUnit * poUnit = _ref_ddl->getBaseunitByName(strUnit); + if (NULL == poUnit) + { + poUnit = _ref_ddl->getUnitByName(strUnit); + if (NULL == poUnit) + { + poElement->setUnit(NULL); + } + else + { + poElement->setUnit(poUnit); + } + } + else + { + poElement->setUnit(poUnit); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLStream* poStream) + { + if (!poStream || !_ref_ddl) { return ERR_POINTER; } + IDDLDataType * poDT = _ref_ddl->getDataTypeByName(poStream->getType()); + if (NULL == poDT) + { + DDLComplex* poDTComp = _ref_ddl->getStructByName(poStream->getType()); + if (NULL == poDTComp) + { + return ERR_INVALID_HANDLE; + } + else + { + poStream->setType(poDTComp); + } + } + DDLStreamStructVec vecStrmStructs = poStream->getStructs(); + for (DDLStreamStructIt itStrmStruct = vecStrmStructs.begin(); + vecStrmStructs.end() != itStrmStruct; ) + { + if (isFailed((*itStrmStruct)->accept(this))) + { + poStream->removeStruct((*itStrmStruct)->getName()); + vecStrmStructs = poStream->getStructs(); + itStrmStruct = vecStrmStructs.begin(); + } + else + { + ++itStrmStruct; + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLStreamStruct* poStreamStruct) + { + if (!poStreamStruct || !_ref_ddl) { return ERR_POINTER; } + IDDLDataType * poDT = _ref_ddl->getDataTypeByName(poStreamStruct->getType()); + if (NULL == poDT) + { + DDLComplex* poDTComp = _ref_ddl->getStructByName(poStreamStruct->getType()); + if (NULL == poDTComp) + { + return ERR_INVALID_HANDLE; + } + else + { + poStreamStruct->setType(poDTComp); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLEnum* poEnum ) + { + if (!poEnum || !_ref_ddl) { return ERR_POINTER; } + IDDLDataType * poDT = _ref_ddl->getDataTypeByName(poEnum->getType()); + if (NULL == poDT) + { + poEnum->setType(NULL); + } + else + { + poEnum->setType(poDT); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLRepair::visit(DDLStreamMetaType* poStreamMetaType) + { + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLRepair::visit(DDLProperty* poProperty) + { + return ERR_NOT_IMPL; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlrepair.h b/ddlrepresentation/ddlrepair.h new file mode 100644 index 0000000..00aae3c --- /dev/null +++ b/ddlrepresentation/ddlrepair.h @@ -0,0 +1,57 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_REPAIR_H_INCLUDED +#define DDL_REPAIR_H_INCLUDED + +#include "ddl_common.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + /** + * Implementation of IDDLVisitor that will repair and update references after deleting. + * I.e.: Deleting a Unit the DDLRepair will search for this unit within the elements of structs and resets the unit if set. + */ + class DDLRepair : public IDDLChangeVisitor + { + public: + a_util::result::Result visitDDL(DDLDescription* description); + a_util::result::Result visit(DDLHeader* header); + a_util::result::Result visit(DDLDataType* data_type); + a_util::result::Result visit(DDLComplex* complex); + a_util::result::Result visit(DDLStream* stream); + a_util::result::Result visit(DDLUnit* unit); + a_util::result::Result visit(DDLBaseunit* baseunit); + a_util::result::Result visit(DDLExtDeclaration* ext_declaration); + a_util::result::Result visit(DDLElement* element); + a_util::result::Result visit(DDLPrefix* prefix); + a_util::result::Result visit(DDLRefUnit* ref_unit); + a_util::result::Result visit(DDLStreamStruct* stream_struct); + a_util::result::Result visit(DDLEnum* ddl_enum); + a_util::result::Result visit(DDLStreamMetaType* stream_meta_type); + a_util::result::Result visit(DDLProperty* property); + + private: + DDLDescription* _ref_ddl; + }; + +} // namespace ddl + +#endif // DDL_REPAIR_H_INCLUDED diff --git a/ddlrepresentation/ddlresolver.cpp b/ddlrepresentation/ddlresolver.cpp new file mode 100644 index 0000000..3113c09 --- /dev/null +++ b/ddlrepresentation/ddlresolver.cpp @@ -0,0 +1,571 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlresolver.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddldescription.h" +#include "ddlunit.h" +#include "ddlbaseunit.h" +#include "ddlprefix.h" +#include "ddldatatype.h" +#include "ddlenum.h" +#include "ddlcomplex.h" +#include "ddlstream.h" +#include "ddlstreammetatype.h" +#include "ddlheader.h" +#include "ddlextdeclaration.h" +#include "ddlrefunit.h" +#include "ddlelement.h" +#include "ddlstreamstruct.h" + + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLResolver::DDLResolver() : + _dom{}, + _target{}, + _version(DDLVersion::ddl_version_invalid), + _stack_parents{}, + _resolved_types{}, + _units{}, + _data_types{}, + _enums{}, + _structs{}, + _streams{} + { +#if defined(WIN32) && _MSC_VER < 1900 + _set_output_format(_TWO_DIGIT_EXPONENT); +#endif // WIN32 + } + + DDLResolver::DDLResolver(const std::string& strTarget) : + DDLResolver() + { + _target = strTarget; + } + + a_util::result::Result DDLResolver::createBase(const DDLDescription* poDescription) + { + _resolved_types.clear(); + _dom.fromString("\n \ + \n \ + "); + RETURN_IF_FAILED(poDescription->getHeader()->accept(this)); + + _units = _dom.getRoot().createChild("units"); + _data_types = _dom.getRoot().createChild("datatypes"); + if (_version >= DDLVersion::ddl_version_20) + { + _enums = _dom.getRoot().createChild("enums"); + } + _structs = _dom.getRoot().createChild("structs"); + _streams = _dom.getRoot().createChild("streams"); + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visitDDL(const DDLDescription* poDescription) + { + if (!poDescription) { return ERR_POINTER; } + if (_target.empty()) + { + // no target specified + return ERR_NOT_INITIALIZED; + } + + RETURN_IF_FAILED(createBase(poDescription)); + + a_util::result::Result nResult = ERR_NOT_FOUND; + + DDLUnitVec vecDDLUnits = poDescription->getUnits(); + DDLUnitIt itUnitFound = std::find_if(vecDDLUnits.begin(), vecDDLUnits.end(), + DDLCompareFunctor<>(_target)); + + if (vecDDLUnits.end() != itUnitFound) + { + nResult = (*itUnitFound)->accept(this); + return nResult; + } + + DDLDTVec vecDTs = poDescription->getDatatypes(); + DDLDTIt itDTFound = std::find_if(vecDTs.begin(), vecDTs.end(), DDLCompareFunctor<>(_target)); + + if (itDTFound != vecDTs.end()) + { + // primitive data type + nResult = (*itDTFound)->accept(this); + return nResult; + } + + DDLComplexVec vecStructs = poDescription->getStructs(); + DDLComplexIt itStructFound = std::find_if(vecStructs.begin(), + vecStructs.end(), DDLCompareFunctor<>(_target)); + + if (itStructFound != vecStructs.end()) + { + // complex data type + nResult = (*itStructFound)->accept(this); + return nResult; + } + + DDLStreamVec vecStreams = poDescription->getStreams(); + DDLStreamIt itStreamFound = std::find_if(vecStreams.begin(), + vecStreams.end(), DDLCompareFunctor<>(_target)); + + if (itStreamFound != vecStreams.end()) + { + // stream + nResult = (*itStreamFound)->accept(this); + return nResult; + } + return nResult; + } + + a_util::result::Result DDLResolver::visit(const DDLHeader* poHeader) + { + if (!poHeader) { return ERR_POINTER; } + a_util::xml::DOMElement oHeaderElement = _dom.getRoot().createChild("header"); + a_util::xml::DOMElement oTmpElement; + oTmpElement = oHeaderElement.createChild("language_version"); + _version = poHeader->getLanguageVersion(); + oTmpElement.setData(_version.toString()); + oTmpElement = oHeaderElement.createChild("author"); + oTmpElement.setData(poHeader->getAuthor()); + // Use current date for creation and change date + oTmpElement = oHeaderElement.createChild("date_creation"); + oTmpElement.setData(poHeader->getDateCreation().format("%d.%m.%Y")); + oTmpElement = oHeaderElement.createChild("date_change"); + oTmpElement.setData(poHeader->getDateChange().format("%d.%m.%Y")); + oTmpElement = oHeaderElement.createChild("description"); + oTmpElement.setData(poHeader->getDescription()); + DDLExtDeclarationVec vecExtDecls = poHeader->getExtDeclarations(); + for (DDLExtDeclarationIt itED = vecExtDecls.begin(); + vecExtDecls.end() != itED; ++itED) + { + RETURN_IF_FAILED((*itED)->accept(this)); + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLExtDeclaration* poExtDeclaration) + { + if (!poExtDeclaration) { return ERR_POINTER; } + a_util::xml::DOMElement oHeader; + if (!_dom.getRoot().findNode("header", oHeader)) + { + return ERR_NOT_FOUND; + } + a_util::xml::DOMElement oEDElement = oHeader.createChild("ext_declaration"); + oEDElement.setAttribute("key", poExtDeclaration->getKey()); + oEDElement.setAttribute("value", poExtDeclaration->getValue()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLBaseunit* poBaseunit) + { + if (!poBaseunit) { return ERR_POINTER; } + a_util::xml::DOMElement oBUElement; + if (_units.findNode(a_util::strings::format("baseunit[@name='%s']", + poBaseunit->getName().c_str()), oBUElement)) + { + // this element was already visited + return a_util::result::SUCCESS; + } + oBUElement = _units.createChild("baseunit"); + oBUElement.setAttribute("name", poBaseunit->getName()); + oBUElement.setAttribute("symbol", poBaseunit->getSymbol()); + oBUElement.setAttribute("description", poBaseunit->getDescription()); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLPrefix* poPrefix) + { + if (!poPrefix) { return ERR_POINTER; } + a_util::xml::DOMElement oUnits; + a_util::xml::DOMElement oPrefixElement; + if (!_dom.getRoot().findNode("units", oUnits)) + { + return ERR_NOT_FOUND; + } + if (oUnits.findNode(a_util::strings::format("prefixes[@name='%s']", + poPrefix->getName().c_str()), oPrefixElement)) + { + // this element was already visited + return a_util::result::SUCCESS; + } + oPrefixElement = oUnits.createChild("prefixes"); + oPrefixElement.setAttribute("name", poPrefix->getName()); + oPrefixElement.setAttribute("symbol", poPrefix->getSymbol()); + oPrefixElement.setAttribute("power", + a_util::strings::toString((int32_t)poPrefix->getPower())); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLUnit* poUnit) + { + if (!poUnit) { return ERR_POINTER; } + a_util::xml::DOMElement oUnitElement; + a_util::xml::DOMElement oTmpElement; + if (_units.findNode(a_util::strings::format("unit[@name='%s']", + poUnit->getName().c_str()), oUnitElement)) + { + // this element was already visited + return a_util::result::SUCCESS; + } + oUnitElement = _units.createChild("unit"); + oUnitElement.setAttribute("name", poUnit->getName()); + oTmpElement = oUnitElement.createChild("numerator"); + oTmpElement.setData(poUnit->getNumerator()); + oTmpElement = oUnitElement.createChild("denominator"); + oTmpElement.setData(poUnit->getDenominator()); + oTmpElement = oUnitElement.createChild("offset"); + oTmpElement.setData(a_util::strings::toString(static_cast + (poUnit->getOffset()))); + std::vector vecDDLRefUnits = poUnit->getRefUnits(); + _stack_parents.push(oUnitElement); + for (size_t i = 0; i < vecDDLRefUnits.size(); i++) + { + RETURN_IF_FAILED(vecDDLRefUnits[i]->accept(this)); + } + _stack_parents.pop(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLRefUnit* poRefUnit) + { + if (!poRefUnit) { return ERR_POINTER; } + a_util::xml::DOMElement oRUElement; + oRUElement = _stack_parents.top().createChild("refUnit"); + oRUElement.setAttribute("name", poRefUnit->getName()); + RETURN_IF_FAILED(poRefUnit->getUnitObject()->accept(this)); + oRUElement.setAttribute("power", + a_util::strings::toString((int32_t)poRefUnit->getPower())); + oRUElement.setAttribute("prefix", poRefUnit->getPrefix()); + return poRefUnit->getPrefixObject()->accept(this); + } + + a_util::result::Result DDLResolver::visit(const DDLDataType* poDataType) + { + if (!poDataType) { return ERR_POINTER; } + a_util::xml::DOMElement oDTElement; + if (_resolved_types.find(poDataType->getName()) != _resolved_types.end()) + { + return a_util::result::SUCCESS; + } + _resolved_types.insert(poDataType->getName()); + + oDTElement = _data_types.createChild("datatype"); + if (_version < DDLVersion::ddl_version_11) + { + oDTElement.setAttribute("type", poDataType->getName()); + } + else + { + oDTElement.setAttribute("name", poDataType->getName()); + } + oDTElement.setAttribute("size", + a_util::strings::toString(static_cast(poDataType->getNumBits()))); + if (!poDataType->getDescription().empty()) + { + oDTElement.setAttribute("description", + poDataType->getDescription()); + } + if (poDataType->getArraysize() > 1) + { + oDTElement.setAttribute("arraysize", + a_util::strings::toString(static_cast + (poDataType->getArraysize()))); + } + if (!poDataType->getUnit().empty()) + { + oDTElement.setAttribute("unit", poDataType->getUnit()); + RETURN_IF_FAILED(poDataType->getUnitObject()->accept(this)); + } + if (_version >= DDLVersion::ddl_version_30) + { + // min and max values are supported since DDL 3.0 + if (poDataType->isMinValid()) + { + oDTElement.setAttribute("min", poDataType->getMinValue()); + } + if (poDataType->isMaxValid()) + { + oDTElement.setAttribute("max", poDataType->getMaxValue()); + } + } + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLComplex* poStruct) + { + if (!poStruct) { return ERR_POINTER; } + a_util::xml::DOMElement oStructElement; + if (_resolved_types.find(poStruct->getName()) != _resolved_types.end()) + { + return a_util::result::SUCCESS; + } + _resolved_types.insert(poStruct->getName()); + + oStructElement = _structs.createChild("struct"); + oStructElement.setAttribute("name", poStruct->getName()); + oStructElement.setAttribute("version", + a_util::strings::toString(static_cast(poStruct->getVersion()))); + if (!poStruct->getComment().empty()) + { + oStructElement.setAttribute("comment", poStruct->getComment()); + } + if (_version >= DDLVersion::ddl_version_11) + { + oStructElement.setAttribute("alignment", + DDLAlignment::toString(poStruct->getAlignment())); + } + _stack_parents.push(oStructElement); + std::vector vecDDLElements = poStruct->getElements(); + for (size_t i = 0; i < vecDDLElements.size(); i++) + { + RETURN_IF_FAILED(vecDDLElements[i]->accept(this)); + } + _stack_parents.pop(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLElement* poElement) + { + if (!poElement) { return ERR_POINTER; } + a_util::xml::DOMElement oElem; + oElem = _stack_parents.top().createChild("element"); + oElem.setAttribute("type", poElement->getType()); + IDDLDataType* pTypeObject = poElement->getTypeObject(); + if (!pTypeObject) + { + return ERR_NOT_FOUND; + } + RETURN_IF_FAILED(pTypeObject->accept(this)); + oElem.setAttribute("name", poElement->getName()); + oElem.setAttribute("bytepos", + a_util::strings::toString(static_cast + (poElement->getBytepos()))); + if ((_version < DDLVersion::ddl_version_11 && poElement->getBitpos() != 1) || + (_version >= DDLVersion::ddl_version_11 && poElement->getBitpos() > 0)) + { + oElem.setAttribute("bitpos", + a_util::strings::toString(static_cast + (poElement->getBitpos()))); + } + if (poElement->getNumBits() > 0) + { + if (1 == poElement->getArraysize()) + { + // only check the "numbits"-attribute for data-types (DDLDataType), because + // "numbits"-attribute for complex-types (DDLComplex) may tempt to configuration errors + DDLDataType *poDT = dynamic_cast(pTypeObject); + if (NULL != poDT) + { + if (poElement->getNumBits() == poDT->getNumBits()) + { + oElem.setAttribute("numbits", a_util::strings::toString(static_cast + (poElement->getNumBits()))); + } + else + { + return ERR_INVALID_ARG; + } + } + } + else + { + return ERR_INVALID_ARG; + } + } + if (!poElement->getDescription().empty()) + { + oElem.setAttribute("description", poElement->getDescription()); + } + if(poElement->getArraysize() == 0 || !poElement->getArraySizeSource().empty()) + { + oElem.setAttribute("arraysize",poElement->getArraySizeSource()); + } + else + { + oElem.setAttribute("arraysize", + a_util::strings::toString(static_cast + (poElement->getArraysize()))); + } + if (!poElement->getUnit().empty()) + { + oElem.setAttribute("unit", poElement->getUnit()); + RETURN_IF_FAILED(poElement->getUnitObject()->accept(this)); + } + oElem.setAttribute("byteorder", + DDLByteorder::toString(poElement->getByteorder())); + oElem.setAttribute("alignment", + DDLAlignment::toString(poElement->getAlignment())); + if (!poElement->getComment().empty()) + { + oElem.setAttribute("comment", poElement->getComment()); + } + + std::string strConstValue = poElement->getConstantValue(); + if (!strConstValue.empty()) + { + oElem.setAttribute("value", strConstValue); + } + + if (_version >= DDLVersion::ddl_version_30) + { + // min, max, default, scale, and offset values are supported since DDL 3.0 + if (poElement->isMinValid()) + { + oElem.setAttribute("min", poElement->getMinValue()); + } + + if (poElement->isMaxValid()) + { + oElem.setAttribute("max", poElement->getMaxValue()); + } + + if (poElement->isDefaultValid()) + { + oElem.setAttribute("default", poElement->getDefaultValue()); + } + + if (poElement->isScaleValid()) + { + oElem.setAttribute("scale", poElement->getScaleValue()); + } + + if (poElement->isOffsetValid()) + { + oElem.setAttribute("offset", poElement->getOffsetValue()); + } + } + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLStream* poStream) + { + if (!poStream) { return ERR_POINTER; } + a_util::xml::DOMElement oStreamElement; + oStreamElement = _streams.createChild("stream"); + if (!poStream->getName().empty()) + { + oStreamElement.setAttribute("name", poStream->getName()); + } + oStreamElement.setAttribute("type", poStream->getType()); + RETURN_IF_FAILED(poStream->getTypeObject()->accept(this)); + if (!poStream->getDescription().empty()) + { + oStreamElement.setAttribute("description", + poStream->getDescription()); + } + std::vector vecStructs = poStream->getStructs(); + _stack_parents.push(oStreamElement); + for (size_t i = 0; i < vecStructs.size(); i++) + { + RETURN_IF_FAILED(vecStructs[i]->accept(this)); + } + _stack_parents.pop(); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLStreamStruct* poStreamStruct) + { + if (!poStreamStruct) { return ERR_POINTER; } + a_util::xml::DOMElement oStruct; + oStruct = _stack_parents.top().createChild("struct"); + oStruct.setAttribute("type", poStreamStruct->getType()); + RETURN_IF_FAILED(poStreamStruct->getTypeObject()->accept(this)); + if (!poStreamStruct->getName().empty()) + { + oStruct.setAttribute("name", poStreamStruct->getName()); + } + oStruct.setAttribute("bytepos", + a_util::strings::toString(static_cast + (poStreamStruct->getBytepos()))); + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLEnum* poEnum) + { + if (!poEnum) { return ERR_POINTER; } + a_util::xml::DOMElement oDTElement; + if (_enums.findNode(a_util::strings::format("enum[@name='%s']", + poEnum->getName().c_str()), oDTElement)) + { + // this element was already visited + return a_util::result::SUCCESS; + } + oDTElement = _enums.createChild("enum"); + + oDTElement.setAttribute("name", poEnum->getName()); + // oDTElement->setAttribute("value", poEnum->getValue()); + oDTElement.setAttribute("type", poEnum->getType()); + + EnumNameValueVec vecNameValues = poEnum->getValues(); + a_util::xml::DOMElement oEnumElement; + for (EnumNameValueVec::iterator itElem = vecNameValues.begin(); itElem != vecNameValues.end(); ++itElem) + { + oEnumElement = oDTElement.createChild("element"); + + oEnumElement.setAttribute("name", itElem->first); + oEnumElement.setAttribute("value", itElem->second); + } + + + return a_util::result::SUCCESS; + } + + a_util::result::Result DDLResolver::visit(const DDLStreamMetaType* poStreamMetaType) + { + return ERR_NOT_IMPL; + } + + a_util::result::Result DDLResolver::visit(const DDLProperty* poProperty) + { + return ERR_NOT_IMPL; + } + + std::string DDLResolver::getResolvedXML() const + { + std::string strResult = _dom.toString().c_str(); + if (strResult == "") + { + // DOM is empty + return a_util::strings::empty_string; + } + return strResult; + } + + void DDLResolver::setTargetName(const std::string& name) + { + _target = name; + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlresolver.h b/ddlrepresentation/ddlresolver.h new file mode 100644 index 0000000..539b31a --- /dev/null +++ b/ddlrepresentation/ddlresolver.h @@ -0,0 +1,103 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_RESOLVER_H_INCLUDED +#define DDL_RESOLVER_H_INCLUDED + +#include "ddl_common.h" +#include "ddlvisitor_intf.h" +#include "ddlversion.h" + +namespace ddl +{ + /** + * Implementation of IDDLVisitor for resolving of a specified unit, + * datatype, struct, or stream out of an existing DDL hierarchy. + * So a minimal DDL description for the specified target is built. + */ + class DDLResolver : public IDDLVisitor + { + public: + /** + * Default CTOR + */ + DDLResolver(); + + /** + * CTOR with target name. + * @param[in] target - Name of the target to resolve + */ + DDLResolver(const std::string& target); + + a_util::result::Result visitDDL(const DDLDescription* description); + a_util::result::Result visit(const DDLHeader* header); + a_util::result::Result visit(const DDLDataType* data_type); + a_util::result::Result visit(const DDLComplex* complex); + a_util::result::Result visit(const DDLStream* stream); + a_util::result::Result visit(const DDLUnit* unit); + a_util::result::Result visit(const DDLBaseunit* baseunit); + a_util::result::Result visit(const DDLExtDeclaration* ext_declaration); + a_util::result::Result visit(const DDLElement* element); + a_util::result::Result visit(const DDLPrefix* prefix); + a_util::result::Result visit(const DDLRefUnit* ref_unit); + a_util::result::Result visit(const DDLStreamStruct* stream_struct); + a_util::result::Result visit(const DDLEnum* ddl_enum); + a_util::result::Result visit(const DDLStreamMetaType* stream_meta_type); + a_util::result::Result visit(const DDLProperty* property); + + /** + * Getter for a minimalistic DDL which only resolves the specified DDL object. + * @return the XML string containing the minimalistic DDL description + */ + std::string getResolvedXML() const; + + /** + * Setter for the name of the target to resolve. + * @param[in] name - Name of the DDL object to resolve + * @remarks Only targets of the types "unit", "datatype", "struct", and + * "stream" are supported. + * @return void + */ + void setTargetName(const std::string& name); + + protected: + /** + * Create the base items + * @param [in] description pointer to the DDL Description + * + * @return Standard result code. + */ + a_util::result::Result createBase(const DDLDescription* description); + + protected: // members + a_util::xml::DOM _dom; ///< Internal DOM for XML handling + std::string _target; ///< Name of the resolving target + DDLVersion _version; ///< DDL version (needed for some conversions for compatibility with DDL1.0) + std::stack _stack_parents; ///< stack of parents + std::set _resolved_types; ///< set of the resolved types + a_util::xml::DOMElement _units; ///< DOM-Element of type Unit + a_util::xml::DOMElement _data_types; ///< DOM-Element of type DataType + a_util::xml::DOMElement _enums; ///< DOM-Element of type Enum + a_util::xml::DOMElement _structs; ///< DOM-Element of type Struct + a_util::xml::DOMElement _streams; ///< DOM-Element of type Stream + }; + +} // namespace ddl + +#endif // DDL_RESOLVER_H_INCLUDED diff --git a/ddlrepresentation/ddlserializable_intf.h b/ddlrepresentation/ddlserializable_intf.h new file mode 100644 index 0000000..830bd7c --- /dev/null +++ b/ddlrepresentation/ddlserializable_intf.h @@ -0,0 +1,28 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _DDL_SERIALIZABLE_INTF_H_INCLUDED_ +#define _DDL_SERIALIZABLE_INTF_H_INCLUDED_ + +namespace ddl +{ + +} // namespace ddl + +#endif // _DDL_SERIALIZABLE_INTF_H_INCLUDED_ diff --git a/ddlrepresentation/ddlstream.cpp b/ddlrepresentation/ddlstream.cpp new file mode 100644 index 0000000..7458252 --- /dev/null +++ b/ddlrepresentation/ddlstream.cpp @@ -0,0 +1,251 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlstream.h" +#include + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLStream::DDLStream() : + _name{}, + _type{}, + _description{}, + _structs{}, + _init_flag{false}, + _level{4}, + _language_version(DDLVersion::ddl_version_invalid) + { + } + + DDLStream::DDLStream(DDLComplex* poType, + const std::string& name, + const std::string& strDescription, + DDLStreamStructVec vecStructs, + int const nCreationLevel) : + _name(name), + _type{poType}, + _description(strDescription), + _structs{}, + _init_flag{NULL != poType}, + _level{nCreationLevel}, + _language_version(DDLVersion::ddl_version_invalid) + { + cloneStructs(vecStructs); + } + + DDLStream::DDLStream(const DDLStream &oStream) : + _name(oStream.getName()), + _type{oStream.getTypeObject()}, + _description(oStream.getDescription()), + _structs{}, + _init_flag{NULL != oStream.getTypeObject()}, + _level{oStream.getCreationLevel()}, + _language_version(oStream.getDDLVersion()) + { + cloneStructs(oStream.getStructs()); + } + + DDLStream& DDLStream::operator=(DDLStream other) + { + swap(*this, other); + return *this; + } + + DDLStream::DDLStream(DDLStream&& other) + { + swap(*this, other); + } + + DDLStream::~DDLStream() + { + std::transform(_structs.begin(), _structs.end(), _structs.begin(), deleteChild); + // The type object needs not to be deleted as this pointer only is a + // reference to an object in the struct vector of the central + // description object! + _structs.clear(); + _type = NULL; + } + + a_util::result::Result DDLStream::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + a_util::result::Result DDLStream::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLStream::create(DDLComplex* poType, + const std::string& name, + const std::string& strDescription, + DDLStreamStructVec vecStructs, + int const nCreationLevel) + { + if (!poType) { return ERR_POINTER; } + _type = poType; + _name = name; + _description = strDescription; + cloneStructs(vecStructs); + _init_flag = true; + _level = nCreationLevel; + return a_util::result::SUCCESS; + } + + std::string DDLStream::getType() const + { + if (!_init_flag) + { + return a_util::strings::empty_string; + } + return _type->getName(); + } + + void DDLStream::setType(DDLComplex* const pType) + { + _type = pType; + _init_flag = (_type != NULL); + } + + DDLComplex * DDLStream::getTypeObject() const + { + if (!_init_flag) + { + return NULL; + } + return _type; + } + + DDLVersion DDLStream::getDDLVersion() const + { + return _language_version; + } + + a_util::result::Result DDLStream::setDDLVersion(DDLVersion& language_version) + { + _language_version = language_version; + return a_util::result::SUCCESS; + } + + void DDLStream::setName(const std::string& name) + { + _name = name; + } + + const std::string& DDLStream::getName() const + { + return _name; + } + + void DDLStream::setDescription(const std::string& strDescription) + { + _description = strDescription; + } + + std::string DDLStream::getDescription() const + { + return _description; + } + + void DDLStream::cloneStructs(DDLStreamStructVec vecStructs) + { + std::transform(_structs.begin(), _structs.end(), _structs.begin(), DDLDescription::deleteChild); + _structs.clear(); + + _structs = vecStructs; + std::transform(_structs.begin(), _structs.end(), _structs.begin(), DDLDescription::clone); + } + + void DDLStream::refStructs(DDLStreamStructVec vecStructs) + { + std::transform(_structs.begin(), _structs.end(), _structs.begin(), DDLDescription::deleteChild); + _structs.clear(); + + _structs = vecStructs; + } + + + void DDLStream::addStruct(DDLStreamStruct* poStruct) + { + if (NULL != poStruct) + { + _structs.push_back(poStruct); + } + } + a_util::result::Result DDLStream::removeStruct(const std::string& strStructName) + { + DDLStreamStructIt oIt = _structs.begin(); + while (oIt != _structs.end()) + { + if ((*oIt)->getName() == strStructName) + { + DDLDescription::deleteChild(*oIt); + _structs.erase(oIt); + return a_util::result::SUCCESS; + } + oIt++; + } + return ERR_NOT_FOUND; + } + + + DDLStreamStructVec& DDLStream::getStructs() + { + return _structs; + } + + const DDLStreamStructVec& DDLStream::getStructs() const + { + return _structs; + } + + bool DDLStream::isInitialized() const + { + return _init_flag; + } + + int DDLStream::getCreationLevel() const + { + return _level; + } + + void swap(DDLStream& lhs, DDLStream& rhs) noexcept + { + using std::swap; + swap(lhs._description, rhs._description); + swap(lhs._init_flag, rhs._init_flag); + swap(lhs._language_version, rhs._language_version); + swap(lhs._level, rhs._level); + swap(lhs._name, rhs._name); + swap(lhs._structs, rhs._structs); + swap(lhs._type, rhs._type); + } +} // namespace ddl diff --git a/ddlrepresentation/ddlstream.h b/ddlrepresentation/ddlstream.h new file mode 100644 index 0000000..fbd891f --- /dev/null +++ b/ddlrepresentation/ddlstream.h @@ -0,0 +1,231 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_STREAM_H_INCLUDED +#define DDL_STREAM_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlversion.h" + +namespace ddl +{ + class DDLStreamStruct; + class DDLComplex; + + /** + * Container type of DDLStreamStruct objects + */ + typedef std::vector DDLStreamStructVec; + /** + * Iterator type for DDLStreamStructVec + */ + typedef DDLStreamStructVec::iterator DDLStreamStructIt; + + /** + * Representation of a stream inside a DDL description. + */ + class DDLStream : public DDL + { + public: + /** + * Default CTOR + */ + DDLStream(); + + /** + * CTOR + * @param[in] type - Pointer to complex datatype object + * @param[in] name - Name of the stream (optional) + * @param[in] description - Description (optional) + * @param[in] structs - Vector of \c DDLStreamStruct objects (optional) + * @param[in] creation_level - Level at creation time (optional) + */ + DDLStream(DDLComplex* type, + const std::string& name = a_util::strings::empty_string, + const std::string& description = a_util::strings::empty_string, + DDLStreamStructVec structs = DDLStreamStructVec(), + int const creation_level = 4); + + /** + * Copy CTOR + * @param[in] other - Reference to stream object to copy + */ + DDLStream(const DDLStream &other); + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDL stream object to copy from + * @return @c *this + */ + DDLStream& operator=(DDLStream other); + + /** + * Move CTOR + * @param[in,out] other DDL stream object to move from - empty but valid when finished + */ + DDLStream(DDLStream&& other); + + /** + * DTOR + */ + virtual ~DDLStream(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + int getCreationLevel() const; + + /** + * Creation method to fill the object with data. + * @param[in] type - Pointer to complex datatype object + * @param[in] name - Name of the stream (optional) + * @param[in] description - Description (optional) + * @param[in] structs - Vector of \c DDLStreamStruct objects (optional) + * @param[in] creation_level - Level at creation time (optional) + * @retval ERR_POINTER Null-pointer committed + */ + a_util::result::Result create(DDLComplex* type, + const std::string& name = a_util::strings::empty_string, + const std::string& description = a_util::strings::empty_string, + DDLStreamStructVec structs = DDLStreamStructVec(), + int const creation_level = 4); + + /** + * Getter for the name of the complex data type. + * @return name of the complex data type + */ + std::string getType() const; + + /** + * Setter for the object of the complex data type. + * @param[in] type - the type object referencing to + * @return void + */ + void setType(DDLComplex* const type); + + /** + * Getter for the DDL version. + * @return the DDL version + */ + DDLVersion getDDLVersion() const; + + /** + * Setter for the DDL version. + * @param language_version the DDL version to set + * @return Standard result code. + * @retval a_util::result::SUCCESS + */ + a_util::result::Result setDDLVersion(DDLVersion& language_version); + + + /** + * Getter for the complex data-type object. + * @return pointer to the complex data-type object + */ + DDLComplex * getTypeObject() const; + + /** + * Setter for the name. + * @param[in] name - Name of the stream + * @return void + */ + void setName(const std::string& name); + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the description. + * @param[in] description - Description of the stream + * @return void + */ + void setDescription(const std::string& description); + + /** + * Getter for the description. + * @return the description + */ + std::string getDescription() const; + + /** + * Setter for the contained structs. + * @param[in] structs - Vector of structures (complex data types) + * @return void + */ + void cloneStructs(DDLStreamStructVec structs); + + /** + * Setter for the contained structs. + * @param[in] structs - Vector of structures (complex data types) + * @return void + */ + void refStructs(DDLStreamStructVec structs); + + /** + * Adder for a struct. + * @param[in] ddl_struct - Pointer to the struct object to add + * @return void + */ + void addStruct(DDLStreamStruct* ddl_struct); + + /** + * removal for a struct item. + * @param[in] struct_name - name of struct object to remove + * @retval ERR_NOT_FOUND if not exists + */ + a_util::result::Result removeStruct(const std::string& struct_name); + + /** + * Getter for the contained structs. + * @return the vector of structs + */ + DDLStreamStructVec& getStructs(); + + /** + * Getter for the contained structs. + * @return the vector of structs + */ + const DDLStreamStructVec& getStructs() const; + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLStream& lhs, DDLStream& rhs) noexcept; + + private: + std::string _name; + DDLComplex * _type; + std::string _description; + DDLStreamStructVec _structs; + bool _init_flag; + int _level; + DDLVersion _language_version; + }; + +} // namespace ddl + +#endif // DDL_STREAM_H_INCLUDED diff --git a/ddlrepresentation/ddlstreammetatype.cpp b/ddlrepresentation/ddlstreammetatype.cpp new file mode 100644 index 0000000..7ba8780 --- /dev/null +++ b/ddlrepresentation/ddlstreammetatype.cpp @@ -0,0 +1,151 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlstreammetatype.h" +#include + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLStreamMetaType::DDLStreamMetaType(const std::string& name, + const std::string& strVersion, + const DDLPropertyVec& vecProperties, + const DDLStreamMetaType* pParent) : + _name{name}, + _version{strVersion}, + _properties{vecProperties}, + _parent{pParent}, + _init_flag{true} + { + } + + DDLStreamMetaType::DDLStreamMetaType(const DDLStreamMetaType &oStreamMetaType) : + _name{oStreamMetaType._name}, + _version{oStreamMetaType._version}, + _properties{}, + _parent{oStreamMetaType._parent}, + _init_flag{true} + { + cloneProperties(oStreamMetaType._properties); + } + + DDLStreamMetaType& DDLStreamMetaType::operator=(DDLStreamMetaType other) + { + swap(*this, other); + return *this; + } + + DDLStreamMetaType::DDLStreamMetaType(DDLStreamMetaType&& other) + { + swap(*this, other); + } + + DDLStreamMetaType::~DDLStreamMetaType() + { + std::transform(_properties.begin(), _properties.end(), _properties.begin(), deleteChild); + } + + a_util::result::Result DDLStreamMetaType::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLStreamMetaType::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + const std::string& DDLStreamMetaType::getName() const + { + return _name; + } + + void DDLStreamMetaType::setName(const std::string& name) + { + _name = name; + } + + const std::string& DDLStreamMetaType::getVersion() const + { + return _version; + } + + void DDLStreamMetaType::cloneProperties(const DDLPropertyVec& vecProperties) + { + std::transform(_properties.begin(), _properties.end(), _properties.begin(), DDLDescription::deleteChild); + _properties = vecProperties; + std::transform(_properties.begin(), _properties.end(), _properties.begin(), DDLDescription::clone); + } + + DDLPropertyVec& DDLStreamMetaType::getProperties() + { + return _properties; + } + + const DDLPropertyVec& DDLStreamMetaType::getProperties() const + { + return _properties; + } + + const DDLStreamMetaType* DDLStreamMetaType::getParentObject() const + { + return _parent; + } + + const std::string& DDLStreamMetaType::getParent() const + { + if (_parent) + { + return _parent->getName(); + } + + return a_util::strings::empty_string; + } + + bool DDLStreamMetaType::isInitialized() const + { + return _init_flag; + } + + int DDLStreamMetaType::getCreationLevel() const + { + return 0; + } + + void swap(DDLStreamMetaType& lhs, DDLStreamMetaType& rhs) noexcept + { + using std::swap; + swap(lhs._name, rhs._name); + swap(lhs._version, rhs._version); + swap(lhs._properties, rhs._properties); + swap(lhs._parent, rhs._parent); + swap(lhs._init_flag, rhs._init_flag); + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlstreammetatype.h b/ddlrepresentation/ddlstreammetatype.h new file mode 100644 index 0000000..9ce6c3c --- /dev/null +++ b/ddlrepresentation/ddlstreammetatype.h @@ -0,0 +1,150 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_STREAM_META_TYPE_H_INCLUDED +#define DDL_STREAM_META_TYPE_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlproperty.h" + +namespace ddl +{ + typedef std::vector DDLPropertyVec; + + /** + * Representation of a stream inside a DDL description. + */ + class DDLStreamMetaType : public DDL + { + public: + /** + * Default CTOR + */ + DDLStreamMetaType() = default; + + /** + * CTOR + * @param[in] name - Name of the stream meta type + * @param[in] version - Version of the stream meta type + * @param[in] properties - The properties. + * @param[in] parent - the stream meta type parent (optional) + */ + DDLStreamMetaType(const std::string& name, + const std::string& version, + const DDLPropertyVec& properties = DDLPropertyVec(), + const DDLStreamMetaType* parent = NULL); + + /** + * Copy CTOR + * @param[in] other - Reference to stream meta type object to copy + */ + DDLStreamMetaType(const DDLStreamMetaType& other); + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDL stream meta type object to copy from + * @return @c *this + */ + DDLStreamMetaType& operator=(DDLStreamMetaType other); + + /** + * Move CTOR + * @param[in,out] other Stream meta type object to move from - empty but valid when finished + */ + DDLStreamMetaType(DDLStreamMetaType&& other); + + /// DTOR + virtual ~DDLStreamMetaType(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + int getCreationLevel() const; + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the name. + * @param[in] name - Name of the stream + * @return void + */ + void setName(const std::string& name); + + /** + * Getter for the version. + * @return the version + */ + const std::string& getVersion() const; + + /** + * Setter for the contained structs. + * @param[in] structs - Vector of structures (complex data types) + * @return void + */ + void cloneProperties(const DDLPropertyVec& structs); + + /** + * Getter for the contained properties. + * @return the vector of properties + */ + DDLPropertyVec& getProperties(); + + /** + * Getter for the contained properties. + * @return the vector of properties + */ + const DDLPropertyVec& getProperties() const; + + /** + * Pointer to the parent stream meta type. + * @return Pointer to the parent stream meta type. + */ + const DDLStreamMetaType* getParentObject() const; + + /** + * Getter for the name of the parent. + * @return The name of the parent. + */ + const std::string& getParent() const; + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLStreamMetaType& lhs, DDLStreamMetaType& rhs) noexcept; + + private: + std::string _name; + std::string _version; + DDLPropertyVec _properties; + const DDLStreamMetaType* _parent; + bool _init_flag; + }; + +} // namespace ddl + +#endif // DDL_STREAM_META_TYPE_H_INCLUDED diff --git a/ddlrepresentation/ddlstreamstruct.cpp b/ddlrepresentation/ddlstreamstruct.cpp new file mode 100644 index 0000000..0b2f673 --- /dev/null +++ b/ddlrepresentation/ddlstreamstruct.cpp @@ -0,0 +1,121 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlstreamstruct.h" +#include + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-37, ERR_NOT_INITIALIZED) + + DDLStreamStruct::DDLStreamStruct(DDLComplex* poType, + unsigned int const uiBytepos, + const std::string& name) : + + _type{poType}, + _bytes_pos{uiBytepos}, + _name{name}, + _init_flag{NULL != poType} + { + } + + a_util::result::Result DDLStreamStruct::accept(IDDLVisitor *poVisitor) const + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + a_util::result::Result DDLStreamStruct::accept(IDDLChangeVisitor *poVisitor) + { + if (!_init_flag) + { + return ERR_NOT_INITIALIZED; + } + return poVisitor->visit(this); + } + + a_util::result::Result DDLStreamStruct::create(DDLComplex* poType, + unsigned int const uiBytepos, + const std::string& name) + { + if (!poType) { return ERR_POINTER; } + _type = poType; + _bytes_pos = uiBytepos; + _name = name; + _init_flag = true; + return a_util::result::SUCCESS; + } + + const std::string& DDLStreamStruct::getType() const + { + if (!_init_flag) + { + return a_util::strings::empty_string; + } + return _type->getName(); + } + + void DDLStreamStruct::setType(DDLComplex* const pType) + { + _type = pType; + _init_flag = (_type != NULL); + } + + DDLComplex * DDLStreamStruct::getTypeObject() const + { + if (!_init_flag) + { + return NULL; + } + return _type; + } + + void DDLStreamStruct::setName(const std::string& name) + { + _name = name; + } + + const std::string& DDLStreamStruct::getName() const + { + if (_name.empty()) + { + return getType(); + } + return _name; + } + + unsigned int DDLStreamStruct::getBytepos() const + { + return _bytes_pos; + } + + void DDLStreamStruct::setBytepos(unsigned int const uiBytepos) + { + _bytes_pos = uiBytepos; + } + + bool DDLStreamStruct::isInitialized() const + { + return _init_flag; + } +} // namespace ddl diff --git a/ddlrepresentation/ddlstreamstruct.h b/ddlrepresentation/ddlstreamstruct.h new file mode 100644 index 0000000..41c6be0 --- /dev/null +++ b/ddlrepresentation/ddlstreamstruct.h @@ -0,0 +1,125 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef STREAM_STRUCT_H_INCLUDED +#define STREAM_STRUCT_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_type.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + /** + * Decorator class for DDLComplex to be used inside DDLStream objects. + */ + class DDLStreamStruct : public DDL + { + public: + /** + * Default CTOR. + */ + DDLStreamStruct() = default; + + /** + * CTOR + * @param[in] type - Pointer to complex datatype object + * @param[in] byte_pos - Byte position of the complex datatype + * @param[in] name - Name of the stream structure (optional) + * @remarks If the name of the stream structure is not set then the + * type name is used. + */ + DDLStreamStruct(DDLComplex* type, + unsigned int const byte_pos, + const std::string& name = a_util::strings::empty_string); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + /** + * Creation method to fill the object with data. + * @param[in] type - Pointer to complex datatype object + * @param[in] byte_pos - Byte position of the complex datatype + * @param[in] name - Name of the stream structure (optional) + * @retval ERR_POINTER Null-pointer committed + * @remarks If the name of the stream structure is not set then the + * type name is used. + */ + a_util::result::Result create(DDLComplex* type, + unsigned int const byte_pos, + const std::string& name = a_util::strings::empty_string); + + /** + * Getter for the name of the complex data type. + * @return name of the type object + */ + const std::string& getType() const; + + /** + * Setter for the complex data-type object. + * @param[in] type - complex data-type object + * @return void + */ + void setType(DDLComplex* const type); + + /** + * Getter for the complex data-type object. + * @return pointer to the complex data-type object + */ + DDLComplex * getTypeObject() const; + + /** + * Setter for the name. + * @param[in] name - Name of the stream structure + * @return void + */ + void setName(const std::string& name); + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Getter for the byte position. + * @return the byte position + */ + unsigned int getBytepos() const; + + /** + * Setter for the byte position. + * @param[in] byte_pos - the byte position + * @return void + */ + void setBytepos(unsigned int const byte_pos); + + + private: + DDLComplex * _type; + unsigned int _bytes_pos; + std::string _name; + bool _init_flag; + }; + +} // namespace ddl + +#endif // STREAM_STRUCT_H_INCLUDED diff --git a/ddlrepresentation/ddlunit.cpp b/ddlrepresentation/ddlunit.cpp new file mode 100644 index 0000000..b0b853b --- /dev/null +++ b/ddlrepresentation/ddlunit.cpp @@ -0,0 +1,247 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlunit.h" +#include "ddl_type.h" +#include "ddlrefunit.h" +#include "ddldescription.h" + +namespace ddl +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + + DDLUnit::DDLUnit() : + _name{}, + _numerator{}, + _denominator{}, + _offset{}, + _ddl_ref_units{}, + _init_flag{}, + _level{1} + { + } + + DDLUnit::DDLUnit(DDLUnit&& other) + { + swap(*this, other); + } + + DDLUnit::~DDLUnit() + { + std::transform(_ddl_ref_units.begin(), _ddl_ref_units.end(), + _ddl_ref_units.begin(), DDL::deleteChild); + _ddl_ref_units.clear(); + } + + DDLUnit::DDLUnit(const std::string& name, + const std::string& strNumerator, + const std::string& strDenominator, + double const fOffset, + DDLRefUnitVec vecDDLRefUnits, + int const nCreationLevel) : + _name{name}, + _numerator{strNumerator}, + _denominator{strDenominator}, + _offset{fOffset}, + _ddl_ref_units{}, + _init_flag{true}, + _level{nCreationLevel} + { + cloneRefUnits(vecDDLRefUnits); + } + + DDLUnit::DDLUnit(const DDLUnit& oUnit) : + _name{oUnit.getName()}, + _numerator{oUnit.getNumerator()}, + _denominator{oUnit.getDenominator()}, + _offset{oUnit.getOffset()}, + _ddl_ref_units{}, + _init_flag{true}, + _level{oUnit.getCreationLevel()} + { + cloneRefUnits(oUnit.getRefUnits()); + } + + DDLUnit& DDLUnit::operator=(DDLUnit other) + { + swap(*this, other); + return *this; + } + + a_util::result::Result DDLUnit::accept(IDDLVisitor *poVisitor) const + { + return poVisitor->visit(this); + } + a_util::result::Result DDLUnit::accept(IDDLChangeVisitor *poVisitor) + { + return poVisitor->visit(this); + } + + bool DDLUnit::isInitialized() const + { + return _init_flag; + } + + bool DDLUnit::isPredefined() const + { + return -1 == _level; // cMediaManager::DL_AlwaysThere + } + + bool DDLUnit::isOverwriteable() const + { + return _level > 0; + } + + int DDLUnit::getCreationLevel() const + { + return _level; + } + + a_util::result::Result DDLUnit::create(const std::string& name, + const std::string& strNumerator, + const std::string& strDenominator, + double const fOffset, + DDLRefUnitVec vecDDLRefUnits, + int const nCreationLevel) + { + if (name.empty()) + { + return ERR_INVALID_ARG; + } + _name = name; + _numerator = strNumerator; + _denominator = strDenominator; + _offset = fOffset; + cloneRefUnits(vecDDLRefUnits); + _init_flag = true; + _level = nCreationLevel; + return a_util::result::SUCCESS; + } + + const std::string& DDLUnit::getName() const + { + return _name; + } + + void DDLUnit::setName(const std::string& name) + { + _name = name; + } + + + std::string DDLUnit::getNumerator() const + { + return _numerator; + } + + void DDLUnit::setNumerator(const std::string& strNumerator) + { + _numerator = strNumerator; + } + + std::string DDLUnit::getDenominator() const + { + return _denominator; + } + + void DDLUnit::setDenominator(const std::string& strDenominator) + { + _denominator = strDenominator; + } + + double DDLUnit::getOffset() const + { + return _offset; + } + + void DDLUnit::setOffset(double const fOffset) + { + _offset = fOffset; + } + + DDLRefUnitVec& DDLUnit::getRefUnits() + { + return _ddl_ref_units; + } + + const DDLRefUnitVec& DDLUnit::getRefUnits() const + { + return _ddl_ref_units; + } + + void DDLUnit::addRefUnit(DDLRefUnit* poRefUnit, int nPos) + { + const DDLRefUnitVec::size_type szPos = static_cast(nPos); + if (0 <= szPos && szPos < _ddl_ref_units.size()) + { + _ddl_ref_units.insert(_ddl_ref_units.begin() + szPos, + poRefUnit); + } + else + { + _ddl_ref_units.push_back(poRefUnit); + } + } + + a_util::result::Result DDLUnit:: removeRefUnit(const std::string& strRefUnit) + { + DDLRefUnitIt oIt = _ddl_ref_units.begin(); + while (oIt != _ddl_ref_units.end()) + { + if ((*oIt)->getName() == strRefUnit) + { + delete (*oIt); + _ddl_ref_units.erase(oIt); + return a_util::result::SUCCESS; + } + oIt++; + } + return ERR_NOT_FOUND; + } + + void DDLUnit::cloneRefUnits(DDLRefUnitVec vecDDLRefUnits) + { + std::transform(_ddl_ref_units.begin(), _ddl_ref_units.end(), _ddl_ref_units.begin(), DDLDescription::deleteChild); + _ddl_ref_units.clear(); + _ddl_ref_units = vecDDLRefUnits; + std::transform(_ddl_ref_units.begin(), _ddl_ref_units.end(), _ddl_ref_units.begin(), DDLDescription::clone); + } + + void DDLUnit::setRefUnits(DDLRefUnitVec vecDDLRefUnits) + { + std::transform(_ddl_ref_units.begin(), _ddl_ref_units.end(), _ddl_ref_units.begin(), DDLDescription::deleteChild); + _ddl_ref_units.clear(); + _ddl_ref_units = vecDDLRefUnits; + } + + void swap(DDLUnit & lhs, DDLUnit & rhs) noexcept + { + using std::swap; + swap(lhs._ddl_ref_units, rhs._ddl_ref_units); + swap(lhs._denominator, rhs._denominator); + swap(lhs._init_flag, rhs._init_flag); + swap(lhs._level, rhs._level); + swap(lhs._name, rhs._name); + swap(lhs._numerator, rhs._numerator); + swap(lhs._offset, rhs._offset); + } + +} // namespace ddl diff --git a/ddlrepresentation/ddlunit.h b/ddlrepresentation/ddlunit.h new file mode 100644 index 0000000..1b45004 --- /dev/null +++ b/ddlrepresentation/ddlunit.h @@ -0,0 +1,228 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef UNIT_H_INCLUDED +#define UNIT_H_INCLUDED + +#include "ddl_common.h" +#include "ddlunit_intf.h" +#include "ddlvisitor_intf.h" + +namespace ddl +{ + + class DDLRefUnit; + + /** + * Container type of DDLRefUnit objects + */ + typedef std::vector DDLRefUnitVec; + /** + * Iterator type for DDLRefUnitVec + */ + typedef DDLRefUnitVec::iterator DDLRefUnitIt; + + /** + * Representation object of a unit + */ + class DDLUnit : public IDDLUnit + { + public: + /** + * Default CTOR + */ + DDLUnit(); + + /** + * CTOR + * @param[in] name - Name of the new unit + * @param[in] numerator - Numerator of the new unit + * @param[in] denominator - Denominator of the new unit + * @param[in] offset - Offset to the base units + * @param[in] ddl_ref_units - Vector of reference units (optional) + * @param[in] creation_level - Level at creation time (optional) + */ + DDLUnit(const std::string& name, + const std::string& numerator, + const std::string& denominator, + double const offset, + DDLRefUnitVec ddl_ref_units = DDLRefUnitVec(), + int const creation_level = 1); + + /** + * Copy CTOR + * @param[in] other - Reference to unit object to copy + */ + DDLUnit(const DDLUnit& other); + + /** + * Assignment operator (either copies or moves) + * @param[in] other DDL unit object to copy from + * @return @c *this + */ + DDLUnit& operator=(DDLUnit other); + + /** + * Move CTOR + * @param[in,out] other DDL unit object to move from - empty but valid when finished + */ + DDLUnit(DDLUnit&& other); + + /** + * DTOR + */ + virtual ~DDLUnit(); + + a_util::result::Result accept(IDDLVisitor *visitor) const; + a_util::result::Result accept(IDDLChangeVisitor *visitor); + + bool isInitialized() const; + + bool isPredefined() const; + bool isOverwriteable() const; + + int getCreationLevel() const; + + /** + * Creation method to fill the object with data. + * @param[in] name - Name of the new unit + * @param[in] numerator - Numerator of the new unit + * @param[in] denominator - Denominator of the new unit + * @param[in] offset - Offset to the base units + * @param[in] ddl_ref_units - Vector of reference units (optional) + * @param[in] creation_level - Level at creation time (optional) + * @retval ERR_INVALID_ARG Empty name committed + */ + a_util::result::Result create(const std::string& name, + const std::string& numerator, + const std::string& denominator, + double const offset, + DDLRefUnitVec ddl_ref_units = DDLRefUnitVec(), + int const creation_level = 4); + + /** + * Getter for the name. + * @return the name + */ + const std::string& getName() const; + + /** + * Setter for the Name. + */ + void setName(const std::string& name); + + + /** + * Getter for the numerator. + * @return the numerator + */ + std::string getNumerator() const; + + /** + * Setter for the Denominator. + */ + void setNumerator(const std::string& numerator); + + /** + * Getter for the denominator. + * @return the denominator + */ + std::string getDenominator() const; + + /** + * Setter for the Denominator. + */ + void setDenominator(const std::string& denominator); + + /** + * Getter for the offset. + * @return the offset + */ + double getOffset() const; + + /** + * Setter for the offset. + */ + void setOffset(double const offset); + + /** + * Getter for the reference unit. + * @return the reference unit + */ + DDLRefUnitVec& getRefUnits(); + + /** + * Getter for the reference unit. + * @return the reference unit + */ + const DDLRefUnitVec& getRefUnits() const; + + /** + * Adder for a reference unit. + * @param[in] ref_unit - Pointer to the reference unit to add + * @param[in] pos - Position to add the reference unit + * + * @return void + */ + void addRefUnit(DDLRefUnit* ref_unit, int pos = -1); + + /** + * Remover for a reference unit. + * @param[in] ref_unit - name of the reference unit to remove + * @retval ERR_NOT_FOUND Specified reference unit not found. + */ + a_util::result::Result removeRefUnit(const std::string& ref_unit); + + /** + * Setter for the reference units + * @param[in] ddl_ref_units - Vector of reference units + * + * @return void + */ + void cloneRefUnits(DDLRefUnitVec ddl_ref_units); + + /** + * Setter for the reference units + * @param[in] ddl_ref_units - Vector of reference units + * + * @return void + */ + void setRefUnits(DDLRefUnitVec ddl_ref_units); + + /** + * Add swap functionality, also enabling the copy-swap-idiom + * @param[in,out] lhs Left-hand side ddl type + * @param[in,out] rhs Right-hand side ddl type + */ + friend void swap(DDLUnit& lhs, DDLUnit& rhs) noexcept; + + private: + std::string _name; + std::string _numerator; + std::string _denominator; + double _offset; + DDLRefUnitVec _ddl_ref_units; + + bool _init_flag; + int _level; + }; + +} // namespace ddl + +#endif // _UNIT_H_INCLUDED diff --git a/ddlrepresentation/ddlunit_intf.h b/ddlrepresentation/ddlunit_intf.h new file mode 100644 index 0000000..1c23761 --- /dev/null +++ b/ddlrepresentation/ddlunit_intf.h @@ -0,0 +1,43 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLUNIT_INTF_H_INCLUDED +#define DDLUNIT_INTF_H_INCLUDED + +#include "ddl_common.h" +#include "ddl_intf.h" + +namespace ddl +{ + /** + * Interface for unit classes of the object representation for + * DDL descriptions. + */ + class IDDLUnit : public IDDL + { + public: + /** + * Virtual DTOR + */ + virtual ~IDDLUnit(){} + }; + +} // namespace ddl + +#endif // _UNIT_INTF_H_INCLUDED_ diff --git a/ddlrepresentation/ddlversion.cpp b/ddlrepresentation/ddlversion.cpp new file mode 100644 index 0000000..ff0612a --- /dev/null +++ b/ddlrepresentation/ddlversion.cpp @@ -0,0 +1,175 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "ddlversion.h" + + +namespace ddl +{ + + const DDLVersion DDLVersion::ddl_version_invalid = DDLVersion(0, 0); + const DDLVersion DDLVersion::ddl_version_10 = DDLVersion(1, 0); + const DDLVersion DDLVersion::ddl_version_11 = DDLVersion(1, 1); + const DDLVersion DDLVersion::ddl_version_12 = DDLVersion(1, 2); + const DDLVersion DDLVersion::ddl_version_20 = DDLVersion(2, 0); + const DDLVersion DDLVersion::ddl_version_30 = DDLVersion(3, 0); + const DDLVersion DDLVersion::ddl_version_40 = DDLVersion(4, 0); + const DDLVersion DDLVersion::ddl_version_41 = DDLVersion(4, 1); + const DDLVersion DDLVersion::ddl_version_current = ddl_version_41; + + DDLVersion::DDLVersion(): DDLVersion(DDLVersion::getDefaultVersion()) + { + + } + + DDLVersion::DDLVersion(uint32_t major, uint32_t minor) : + _major(major), _minor(minor) + { + + } + + uint32_t DDLVersion::getMajor() const + { + return _major; + } + + uint32_t DDLVersion::getMinor() const + { + return _minor; + } + + std::string DDLVersion::toString() const + { + if (*this == DDLVersion(1, 1)) + { + return std::string("1.0+"); + } + return a_util::strings::format("%u.%02u", _major, _minor); + } + + DDLVersion DDLVersion::fromString(const std::string& version) + { + if (version.size() == 0) + { + return ddl_version_invalid; + } + auto tokens = a_util::strings::split(version, "."); + + uint32_t major = 0, minor = 0; + + if (a_util::strings::isUInt32(tokens.at(0))) + { + major = a_util::strings::toUInt32(tokens.at(0)); + } + else + { + return ddl_version_invalid; + } + + if (tokens.size() == 2) + { + //special case 1.0+ + if (tokens.at(1) == "0+" || tokens.at(1) == "00+") + { + minor = 1; + } + // standard case + else if (a_util::strings::isUInt32(tokens.at(1))) + { + minor = a_util::strings::toUInt32(tokens.at(1)); + } + } + return DDLVersion(major, minor); + } + + bool DDLVersion::isValidVersion() const + { + if (*this < ddl_version_10) + { + return false; + } + + if (*this > ddl_version_current) + { + return false; + } + + return true; + } + + bool DDLVersion::operator ==(const DDLVersion& other) const + { + if (_major == other._major && _minor == other._minor) + { + return true; + } + return false; + } + + bool DDLVersion::operator !=(const DDLVersion& other) const + { + return !(*this == other); + } + + bool DDLVersion::operator >(const DDLVersion& other) const + { + if (_major > other._major) + { + return true; + } + else if (_major < other._major) + { + return false; + } + + if (_minor > other._minor) + { + return true; + } + return false; + } + + bool DDLVersion::operator <(const DDLVersion& other) const + { + if (_major < other._major) + { + return true; + } + else if (_major > other._major) + { + return false; + } + + if (_minor < other._minor) + { + return true; + } + return false; + } + + bool DDLVersion::operator <=(const DDLVersion& other) const + { + return !(*this > other); + } + + bool DDLVersion::operator >=(const DDLVersion& other) const + { + return !(*this < other); + } +} \ No newline at end of file diff --git a/ddlrepresentation/ddlversion.h b/ddlrepresentation/ddlversion.h new file mode 100644 index 0000000..a22ddc9 --- /dev/null +++ b/ddlrepresentation/ddlversion.h @@ -0,0 +1,75 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDLVERSION_H_INCLUDED +#define DDLVERSION_H_INCLUDED + +#include "ddl_common.h" + +namespace ddl +{ + class DDLVersion + { + public: + DDLVersion(); + + DDLVersion(uint32_t major, uint32_t minor); + + uint32_t getMajor() const; + uint32_t getMinor() const; + + std::string toString() const; + + bool isValidVersion() const; + + static DDLVersion fromString(const std::string& version); + + static const DDLVersion& getDefaultVersion() + { + return ddl_version_current; + } + + /* ignore patch version for all comparisons */ + bool operator ==(const DDLVersion& other) const; + bool operator !=(const DDLVersion& other) const; + bool operator >(const DDLVersion& other) const; + bool operator <(const DDLVersion& other) const; + bool operator <=(const DDLVersion& other) const; + bool operator >=(const DDLVersion& other) const; + + // known Versions + static const DDLVersion ddl_version_invalid; + static const DDLVersion ddl_version_10; + static const DDLVersion ddl_version_11; + static const DDLVersion ddl_version_12; + static const DDLVersion ddl_version_20; + static const DDLVersion ddl_version_30; + static const DDLVersion ddl_version_40; + static const DDLVersion ddl_version_41; + static const DDLVersion ddl_version_current; + + + private: + uint32_t _major; + uint32_t _minor; + }; + +} + +#endif \ No newline at end of file diff --git a/ddlrepresentation/ddlvisitor_intf.h b/ddlrepresentation/ddlvisitor_intf.h new file mode 100644 index 0000000..3b77b0e --- /dev/null +++ b/ddlrepresentation/ddlvisitor_intf.h @@ -0,0 +1,291 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_VISITOR_H_INCLUDED +#define DDL_VISITOR_H_INCLUDED + +#include "ddl_common.h" + +namespace ddl +{ + class DDLHeader; + class DDLDataType; + class DDLComplex; + class DDLStream; + class DDLUnit; + class DDLBaseunit; + class DDLExtDeclaration; + class DDLElement; + class DDLDescription; + class DDLPrefix; + class DDLRefUnit; + class DDLStreamStruct; + class DDLEnum; + class DDLStreamMetaType; + class DDLProperty; + + /** + * Abstract base class/interface for Visitor design-pattern. + */ + class IDDLVisitor + { + public: + /** + * DTOR + */ + virtual ~IDDLVisitor(){} + + /** + * Visitor for a whole DDL description. + * @param[in] description - Pointer to the description object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_INITIALIZED Not yet initialized + */ + virtual a_util::result::Result visitDDL(const DDLDescription* description) = 0; + /** + * Visitor for DDL header objects. + * @param[in] header - Pointer to the header object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLHeader* header) = 0; + /** + * Visitor for DDL datatype objects. + * @param[in] data_type - Pointer to the datatype object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_SUPPORTED Data type detected which is not supported. + */ + virtual a_util::result::Result visit(const DDLDataType* data_type) = 0; + /** + * Visitor for DDL struct objects. + * @param[in] ddl_struct - Pointer to the struct object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLComplex* ddl_struct) = 0; + /** + * Visitor for DDL stream objects. + * @param[in] stream - Pointer to the stream object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLStream* stream) = 0; + /** + * Visitor for DDL unit objects. + * @param[in] unit - Pointer to the unit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLUnit* unit) = 0; + /** + * Visitor for DDL baseunit objects. + * @param[in] baseunit - Pointer to the baseunit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLBaseunit* baseunit) = 0; + /** + * Visitor for external DDL declaration objects. + * @param[in] ext_declaration - Pointer to the extdeclaration object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLExtDeclaration* ext_declaration) = 0; + /** + * Visitor for DDL element objects. + * @param[in] element - Pointer to the element object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLElement* element) = 0; + /** + * Visitor for DDL prefix objects. + * @param[in] prefix - Pointer to the prefix object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLPrefix* prefix) = 0; + /** + * Visitor for DDL reference unit objects. + * @param[in] ref_unit - Pointer to the refunit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLRefUnit* ref_unit) = 0; + /** + * Visitor for DDL streamstruct objects. + * @param[in] stream_struct - Pointer to the streamstruct object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLStreamStruct* stream_struct) = 0; + + /** + * Visitor for DDL enum objects. + * @param[in] ddl_enum - Pointer to the enum object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLEnum* ddl_enum) = 0; + + /** + * Visitor for DDL stream meta type objects. + * @param[in] stream_meta_type - Pointer to the object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLStreamMetaType* stream_meta_type) = 0; + + /** + * Visitor for DDL property objects. + * @param[in] ddl_property - Pointer to the object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(const DDLProperty* ddl_property) = 0; + }; + + /** + * Abstract base class/interface for Visitor design-pattern. + */ + class IDDLChangeVisitor + { + public: + /** + * DTOR + */ + virtual ~IDDLChangeVisitor() {} + + /** + * Visitor for a whole DDL description. + * @param[in] description - Pointer to the description object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_INITIALIZED Not yet initialized + */ + virtual a_util::result::Result visitDDL(DDLDescription* description) = 0; + /** + * Visitor for DDL header objects. + * @param[in] header - Pointer to the header object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLHeader* header) = 0; + /** + * Visitor for DDL datatype objects. + * @param[in] data_type - Pointer to the datatype object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + * @retval ERR_NOT_SUPPORTED Data type detected which is not supported. + */ + virtual a_util::result::Result visit(DDLDataType* data_type) = 0; + /** + * Visitor for DDL struct objects. + * @param[in] ddl_struct - Pointer to the struct object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLComplex* ddl_struct) = 0; + /** + * Visitor for DDL stream objects. + * @param[in] stream - Pointer to the stream object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLStream* stream) = 0; + /** + * Visitor for DDL unit objects. + * @param[in] unit - Pointer to the unit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLUnit* unit) = 0; + /** + * Visitor for DDL baseunit objects. + * @param[in] baseunit - Pointer to the baseunit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLBaseunit* baseunit) = 0; + /** + * Visitor for external DDL declaration objects. + * @param[in] ext_declaration - Pointer to the extdeclaration object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLExtDeclaration* ext_declaration) = 0; + /** + * Visitor for DDL element objects. + * @param[in] element - Pointer to the element object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLElement* element) = 0; + /** + * Visitor for DDL prefix objects. + * @param[in] prefix - Pointer to the prefix object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLPrefix* prefix) = 0; + /** + * Visitor for DDL reference unit objects. + * @param[in] ref_unit - Pointer to the refunit object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLRefUnit* ref_unit) = 0; + /** + * Visitor for DDL streamstruct objects. + * @param[in] stream_struct - Pointer to the streamstruct object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLStreamStruct* stream_struct) = 0; + + /** + * Visitor for DDL enum objects. + * @param[in] ddl_enum - Pointer to the enum object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLEnum* ddl_enum) = 0; + + /** + * Visitor for DDL stream meta type objects. + * @param[in] stream_meta_type - Pointer to the object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLStreamMetaType* stream_meta_type) = 0; + + /** + * Visitor for DDL property objects. + * @param[in] ddl_property - Pointer to the object + * @retval ERR_POINTER Null-pointer committed + * @retval ERR_NOT_FOUND Required node not found. + */ + virtual a_util::result::Result visit(DDLProperty* ddl_property) = 0; + }; + +} // namespace ddl + +#endif // DDL_VISITOR_H_INCLUDED diff --git a/ddlrepresentation/pkg_ddlrepresentation.h b/ddlrepresentation/pkg_ddlrepresentation.h new file mode 100644 index 0000000..1acd569 --- /dev/null +++ b/ddlrepresentation/pkg_ddlrepresentation.h @@ -0,0 +1,109 @@ +/** + * @file + * Package header for DDL + * This package provides the DDL Represantations and Coder. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _PACKAGE_DDL_REPRESENTATION_HEADER_ +#define _PACKAGE_DDL_REPRESENTATION_HEADER_ + + // forward declarations + // very ugly hack, but linearizing all dependencies is not an option right now +namespace ddl { + class DDL; + class DDLError; + class IDDL; + class DDLAlignment; + class DDLBaseunit; + class IDDLUnit; + class DDLByteorder; + class DDLCloner; + class DDLCompare; + class DDLComplex; + class IDDLDataType; + class DDLDataType; + class DDLDescription; + class DDLElement; + class DDLEnum; + class DDLExtDeclaration; + class IDDLFactoryMethod; + class DDLHeader; + class DDLImporter; + class DDLInspector; + class DDLPrefix; + class DDLPrinter; + class DDLProperty; + class DDLRefUnit; + class DDLRepair; + class DDLResolver; + class DDLStream; + class DDLStreamMetaType; + class DDLStreamStruct; + class DDLUnit; + class IDDLUnit; + class IDDLVisitor; +} + + + #include + #include + + //common errordefintion + #include "ddl_error.h" + //common supported versions + #include "ddlversion.h" + + // OO-DDL interfaces + #include "ddl_intf.h" + #include "ddl_type.h" + #include "ddlalignment.h" + + #include "ddlserializable_intf.h" + #include "ddlunit_intf.h" + #include "ddldatatype_intf.h" + #include "ddlvisitor_intf.h" + #include "ddlfactorymethod_intf.h" + + // DDL object representation (OO-DDL) + #include "ddlbyteorder.h" + #include "ddlcomplex.h" + #include "ddldatatype.h" + #include "ddlheader.h" + #include "ddlstream.h" + #include "ddlenum.h" + #include "ddlcontainer.h" + #include "ddldescription.h" + #include "ddlunit.h" + #include "ddlrefunit.h" + #include "ddlprefix.h" + #include "ddlextdeclaration.h" + #include "ddlelement.h" + #include "ddlbaseunit.h" + #include "ddlstreamstruct.h" + #include "ddlstreammetatype.h" + #include "ddlproperty.h" + #include "ddlprinter.h" + #include "ddlimporter.h" + #include "ddlcloner.h" + #include "ddlresolver.h" + #include "ddlrepair.h" + #include "ddlinspector.h" + #include "ddlcompare.h" + +#endif // _PACKAGE_DDL_REPRESENTATION_HEADER_ + diff --git a/ddlrepresentation/pkg_ddlrepresentation.sources b/ddlrepresentation/pkg_ddlrepresentation.sources new file mode 100644 index 0000000..2413dc2 --- /dev/null +++ b/ddlrepresentation/pkg_ddlrepresentation.sources @@ -0,0 +1,82 @@ +set(DDLREPRESENTATION_DIR ddlrepresentation) + +set(DDLREPRESENTATION_H + ${DDLREPRESENTATION_DIR}/ddl_common.h + ${DDLREPRESENTATION_DIR}/pkg_ddlrepresentation.h + + ${DDLREPRESENTATION_DIR}/ddl_error.h + ${DDLREPRESENTATION_DIR}/ddlversion.h + + ${DDLREPRESENTATION_DIR}/ddl_intf.h + ${DDLREPRESENTATION_DIR}/ddl_type.h + ${DDLREPRESENTATION_DIR}/ddlalignment.h + + ${DDLREPRESENTATION_DIR}/ddlserializable_intf.h + ${DDLREPRESENTATION_DIR}/ddlunit_intf.h + ${DDLREPRESENTATION_DIR}/ddldatatype_intf.h + ${DDLREPRESENTATION_DIR}/ddlvisitor_intf.h + ${DDLREPRESENTATION_DIR}/ddlfactorymethod_intf.h + + ${DDLREPRESENTATION_DIR}/ddlbyteorder.h + ${DDLREPRESENTATION_DIR}/ddlcomplex.h + ${DDLREPRESENTATION_DIR}/ddldatatype.h + ${DDLREPRESENTATION_DIR}/ddlheader.h + ${DDLREPRESENTATION_DIR}/ddlstream.h + ${DDLREPRESENTATION_DIR}/ddlenum.h + ${DDLREPRESENTATION_DIR}/ddlcontainer.h + ${DDLREPRESENTATION_DIR}/ddldescription.h + ${DDLREPRESENTATION_DIR}/ddlunit.h + ${DDLREPRESENTATION_DIR}/ddlrefunit.h + ${DDLREPRESENTATION_DIR}/ddlprefix.h + ${DDLREPRESENTATION_DIR}/ddlextdeclaration.h + ${DDLREPRESENTATION_DIR}/ddlelement.h + ${DDLREPRESENTATION_DIR}/ddlbaseunit.h + ${DDLREPRESENTATION_DIR}/ddlstreamstruct.h + ${DDLREPRESENTATION_DIR}/ddlprinter.h + ${DDLREPRESENTATION_DIR}/ddlimporter.h + ${DDLREPRESENTATION_DIR}/ddlcloner.h + ${DDLREPRESENTATION_DIR}/ddlresolver.h + ${DDLREPRESENTATION_DIR}/ddlrepair.h + ${DDLREPRESENTATION_DIR}/ddlinspector.h + ${DDLREPRESENTATION_DIR}/ddlcompare.h + ${DDLREPRESENTATION_DIR}/ddlstreammetatype.h + ${DDLREPRESENTATION_DIR}/ddlproperty.h +) + +set(DDLREPRESENTATION_CPP + + ${DDLREPRESENTATION_DIR}/ddl_error.cpp + ${DDLREPRESENTATION_DIR}/ddlversion.cpp + + ${DDLREPRESENTATION_DIR}/ddl_type.cpp + ${DDLREPRESENTATION_DIR}/ddlalignment.cpp + + ${DDLREPRESENTATION_DIR}/ddlbyteorder.cpp + ${DDLREPRESENTATION_DIR}/ddlcomplex.cpp + ${DDLREPRESENTATION_DIR}/ddldatatype.cpp + ${DDLREPRESENTATION_DIR}/ddlheader.cpp + ${DDLREPRESENTATION_DIR}/ddlstream.cpp + ${DDLREPRESENTATION_DIR}/ddlenum.cpp + ${DDLREPRESENTATION_DIR}/ddlcontainer.cpp + ${DDLREPRESENTATION_DIR}/ddldescription.cpp + ${DDLREPRESENTATION_DIR}/ddlunit.cpp + ${DDLREPRESENTATION_DIR}/ddlrefunit.cpp + ${DDLREPRESENTATION_DIR}/ddlprefix.cpp + ${DDLREPRESENTATION_DIR}/ddlextdeclaration.cpp + ${DDLREPRESENTATION_DIR}/ddlelement.cpp + ${DDLREPRESENTATION_DIR}/ddlbaseunit.cpp + ${DDLREPRESENTATION_DIR}/ddlstreamstruct.cpp + ${DDLREPRESENTATION_DIR}/ddlprinter.cpp + ${DDLREPRESENTATION_DIR}/ddlimporter.cpp + ${DDLREPRESENTATION_DIR}/ddlcloner.cpp + ${DDLREPRESENTATION_DIR}/ddlresolver.cpp + ${DDLREPRESENTATION_DIR}/ddlrepair.cpp + ${DDLREPRESENTATION_DIR}/ddlinspector.cpp + ${DDLREPRESENTATION_DIR}/ddlcompare.cpp + ${DDLREPRESENTATION_DIR}/ddlstreammetatype.cpp + ${DDLREPRESENTATION_DIR}/ddlproperty.cpp +) + +set(DDLREPRESENTATION_INSTALL ${DDLREPRESENTATION_H}) +source_group(${DDLREPRESENTATION_DIR} FILES ${DDLREPRESENTATION_H} ${DDLREPRESENTATION_CPP}) + diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..4b3f0d9 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,57 @@ +option(ddl_cmake_enable_documentation "If enabled, generate the source code documentation -\ + requires doxygen (default: ON)" ON) +option(ddl_cmake_enable_post_install_doc_generation "If enabled, doxygen will generate the\ + documentation as post-install event. Disable only for development purposes. (default: ON)" ON) +option(DOXYGEN_SKIP_DOT "If true this module will skip trying to find Dot (default: OFF)" OFF) + +install(DIRECTORY input DESTINATION doc/ + FILES_MATCHING PATTERN "*.md" + PATTERN "license" EXCLUDE ) +install(FILES input/mapping_configuration.xsd DESTINATION doc/) +install(FILES input/ddl3.xsd DESTINATION doc/) +install(FILES input/ddl4.xsd DESTINATION doc/) +install(FILES changelog.md DESTINATION doc/) + +set (AEV_PRODUCT_FULL_NAME "ddl_library") + +if(NOT EXCLUDE_PRODUCT_LICENSES) + set(LICENSE_FILES_EXTENSION "* [mpl.md](../license/mpl.md#)\n\ +* [MPL2.0.txt](../license/MPL2.0.txt)\n\ +* [used_licenses.md](../license/used_licenses.md#)\n") +endif() + +##continue only if enabled +if(ddl_cmake_enable_documentation) + ## Doxygen is not required. But only built html Doku if doxygen is found + ## Otherwise just the Markdown docu will be copied. + find_package(Doxygen) + if(NOT DOXYGEN_FOUND) + message(STATUS "No doxygen executable found.") + return() + endif(NOT DOXYGEN_FOUND) + if(NOT DOXYGEN_SKIP_DOT AND NOT DOXYGEN_DOT_FOUND) + message(FATAL_ERROR "No dot executable found. Either set the " + "correct DOXYGEN_DOT_EXECUTABLE or enable DOXYGEN_SKIP_DOT.") + elseif(NOT DOXYGEN_SKIP_DOT AND DOXYGEN_DOT_FOUND) + EXECUTE_PROCESS(COMMAND ${DOXYGEN_DOT_EXECUTABLE} -V OUTPUT_VARIABLE dot_version_info + ERROR_VARIABLE dot_version_info + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + set(dot_version_info "(found version: \"${dot_version_info}\")") + message(STATUS "Found dot: ${DOXYGEN_DOT_EXECUTABLE} ${dot_version_info}") + unset(dot_version_info) + endif(NOT DOXYGEN_SKIP_DOT AND NOT DOXYGEN_DOT_FOUND) +else() + return() +endif(ddl_cmake_enable_documentation) + +configure_file(run_doxygen.cmake.in run_doxygen.cmake @ONLY) +##create seperate target excluded from all +add_custom_target(ddl_DOC ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/run_doxygen.cmake) +set_target_properties(ddl_DOC PROPERTIES FOLDER process) + +##post install script +if(ddl_cmake_enable_post_install_doc_generation) + install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/run_doxygen.cmake) + install(FILES static/ddl.html DESTINATION doc/) +endif(ddl_cmake_enable_post_install_doc_generation) \ No newline at end of file diff --git a/doc/changelog.md b/doc/changelog.md new file mode 100644 index 0000000..db43fe5 --- /dev/null +++ b/doc/changelog.md @@ -0,0 +1,16 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0) and this project adheres to [Semantic Versioning](https://semver.org/lang/en). + + +Release Notes - DDL Library - Version DDL 4.4.0 + +## [4.4.0] - 2019-09-12 +#### Change + * initial commit for github + +## [4.3.0] - 2019-06-14 +## [4.2.1] - 2019-03-19 +## [4.2.0] - 2018-11-08 +## [4.1.0] - 2018-06-30 diff --git a/doc/input/codec.md b/doc/input/codec.md new file mode 100644 index 0000000..c1cedbe --- /dev/null +++ b/doc/input/codec.md @@ -0,0 +1,114 @@ +# DDL Decoder/Codec {#page_codec} + +# Accessing Data with a Decoder/Codec + +Let's take a look at a basic structure: + +````xml + + + + + + + + + + + + + + + + + + +```` + +# Decoding + +Read access is handled with the ddl::Decoder class: + +````cpp +tFloat64 readData(const void* const_data, size_t data_size) +{ + // this should of course be cached (as a member etc.) + ddl::CodecFactory factory("tTest", "...."); + + auto decoder = factory.makeDecoderFor(const_data, data_size); + + adtf_util::cVariant value; + + // for name based lookup use the access_element namespace + { + value = ddl::access_element::get_value(decoder, "fFloat32"); + } + + // alternativley you can of course use indexed based lookup + { + decoder.getElementValue(3, value); + } + + return value; +} +```` + + +# Encoding + +Write access is handled with the ddl::Codec class: + +````cpp +void writeData(void* data, size_t data_size, tFloat64 value) +{ + // this should of course be cached (as a member etc.) + ddl::CodecFactory factory("tTest", "...."); + + auto codec = factory.makeCodecFor(data, data_size); + + // name based lookup + ddl::access_element::set_value(codec, "fFloat32", value); + // or index based + codec.setElementValue(3, value); +} +```` + +# Selecting the Data Representation + +By default decoders/codecs are created for the deserialized representation. +To create them for the serialized representation pass the correct parameters to the make... methods. + +````cpp +auto decoder = factory.makeDecoderFor(const_data, data_size, + DataRepresentation::serialized); +```` + +# Inspection + +You can inspect the struct handled by a decoder/codec with the help of ddl::StaticDecoder::getElement: + +````cpp +void dumstruct_elements(const ddl::StaticDecoder& decoder) +{ + for (size_t element = 0; element < decoder.getElementCount(); ++element) + { + const ddl::StructElement* struct_element; + decoder.GetElement(element, struct_element); + std::cout << struct_element->strName << std::endl; + } +} +```` + +# Transformation + +Converting between the representations can be done with ddl::serialization::transform: + +````cpp +tSize serialized_size = decoder.getBufferSize(ddl::DataRepresentation::serialized); +uint8_t* buffer = new uint8_t[serialized_size]; +auto Codec = decoder.makeCodecFor(buffer, serialized_size, ddl::DataRepresentation::serialized); +ddl::serialization::transform(decoder, codec); +```` + +There is also a convienence method ddl::serialization::transform_to_buffer that handles the allocation of memory for you with the help of an adtf_util::cMemoryBlock. + diff --git a/doc/input/ddl3.xsd b/doc/input/ddl3.xsd new file mode 100644 index 0000000..cd6d005 --- /dev/null +++ b/doc/input/ddl3.xsd @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/input/ddl4.xsd b/doc/input/ddl4.xsd new file mode 100644 index 0000000..53cf110 --- /dev/null +++ b/doc/input/ddl4.xsd @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/input/ddl_generators.md b/doc/input/ddl_generators.md new file mode 100644 index 0000000..845c646 --- /dev/null +++ b/doc/input/ddl_generators.md @@ -0,0 +1,77 @@ +# DDL Generators (ddl2header, header2ddl) {#page_ddl_generators} + +ddl2header and header2ddl are command line utilites to automatically generate +C/C++ header files from DDL desriptions and vice versa. + +# Usage + +## ddl2header + +```` +ddl2header [options] + ++++++++++++++++++++++++++++++ ++++ Command line option: +++ ++++++++++++++++++++++++++++++ + +To create a header file from an existing description file. You have to set the +following options: + + -headerfile= - [Mandatory] The path to the header + file (target). + + -descriptionfile= - [Mandatory] The path to the description + file (source). + + -struct= - [Optional] Just create the header + file for the given struct + of the description file. + +++++++++++++++++ ++++ Example +++ +++++++++++++++++ +-headerfile=c:/myHeaderFile.h -descriptionfile=c:/myDescriptionFile.description +or-headerfile=c:/myHeaderFile.h -descriptionfile=c:/myDescriptionFile.description -struct= +tMyStruct +```` + +## header2ddl + +```` +header2ddl [options] + ++++++++++++++++++++++++++++++ ++++ Command line option: +++ ++++++++++++++++++++++++++++++ + +To create a header file from an existing description file. You have to set the +following options: + + -headerfile= - [Mandatory] The path to the header + file (source). + + -descriptionfile= - [Mandatory] The path to the description + file (target). + + -struct= - [Optional] Just create the description + file for the given struct + of the header file. + + -ddlversion= - [Optional] Default value is ddl4. + Supported formats are + 3.0 and 4.0 + +++++++++++++++++ ++++ Example +++ +++++++++++++++++ +-headerfile=c:/myHeaderFile.h -descriptionfile=c:/myDescriptionFile.description +or-headerfile=c:/myHeaderFile.h -descriptionfile=c:/myDescriptionFile.description -struct= +tMyStruct +```` + +## Notes + +- Target files are never just overwritten (independent of conversion direction). +If the target file exists the generators will try to merge the contents of source and target. +**Warning:** If the target file contains content that can not be parsed by the ddl library +it might be missing from the result file. **Keep a backup!** diff --git a/doc/input/ddl_specification.md b/doc/input/ddl_specification.md new file mode 100644 index 0000000..155bdab --- /dev/null +++ b/doc/input/ddl_specification.md @@ -0,0 +1,758 @@ +# DDL Definition File Format {#page_ddl_specification} + +With ADTF a default DDL Definition File 'adtf.description' is provided. The +format of this file is XML and it contains all common datatypes and structs +which are used within ADTF. + +Which DDL Definition File is used in ADTF can be specified either in global +settings or in configuration settings. *It is possible to specify more than +one DDL Definition File within the property 'media_descripton_files' by +separating them with a semicolon (;)*. If more than one DDL Definition +File is provided, the contained information will be merged. + +The DDL were released with several versions. This table will show the +the supported DDL versions of different ADTF releases. + +**Warning:** +Keep in mind, that the DDL language version 1.0 is not supported +within ADTF. + +*The currently valid version is DDL 3.0.* + +|ADTF Version|DDL Version supported| +|--- |--- | +|2.4.x|1.0+| +|2.5.x|1.0+| +|2.6.x|1.0+| +|2.7.x|1.0+ and 1.02| +|2.8.x|1.0+, 1.02, and 2.0| +|2.9.x|1.0+, 1.02, and 2.0| +|2.10.x and newer|1.0+, 1.02, 2.0, and 3.0| +|3.0.x and newer|1.0+, 1.02, 2.0, 3.0 and 4.0| + +Changes to definitions between the language versions are explicitly explained in the tables below. + +  + +# Specification + +The newer versions of the DDL Definition File Format are also specified by a XSD specification file. +See the XSD specification for further details: +- [DDL 3 XSD specification](../ddl3.xsd) +- [DDL 4 XSD specification](../ddl4.xsd) + +# Description of General Datatypes in this specification + +There are several types that are used in attributes and as tag data in the +DDL. The following table lists the types with a description of the values +and/or their formatting. + +|Type|Allowed values| +|--- |--- | +|Char|Single character of [a-z][A-Z][0-9] _.-+/| +|String|Characters of [a-z][A-Z][0-9] _.-+/| +|Text|All visible ASCII characters| +|UInt|Unsigned integer values| +|Int|signed integer values| +|Float|signed float values| +|Date|Allowed formats: yyyymmdd, dd-mm-yyyy, yyyy-mm-dd or dd.mm.yyyy| +|Class|any name value of another DDL element| +|Enum|A predefined value from the description of the attribute| + + +ADTF provides several predefined baseunits, prefixes, datatypes and enums. + +  + +# header +The header section contains meta information about the document and version +information. Example: +````xml +
+ 2.0 + AUDI Electronics Venture GmbH + 20100407 + + ADTF Common Description File +
+```` + +  + +|Tag|Type|Description| +|--- |--- |--- | +|language_version|Float|Version number of the file| +|author|String|Author| +|date_creation|Date|Creation date| +|date_change|Date|Last modification date| +|description|Text|Short description| + + +All previously mentioned header tags are *mandatory*. + +Additional information can be added by using the `ext_declaration` tag. +Example: + +````xml +
+ ... + +
+```` + +  + +|Attribute|Type|Description| +|--- |--- |--- | +|key|String|Name of the additional information| +|Value|Text|Value of the additional information| + +  + +# units + +The definition of units will be divided in SI-base units and own units. The +SI-based units are the following ones: + +|SI (see ISO 1000)|no SI, but needed for daily usage| +|--- |--- | +|Metre|Degree| +|Gram|Radiant| +|Second|Unitless| +|Ampere| | +|Candela| | +|Kelvin| | +|Mole| | + +Units are defined within the tags `` and ``. +Example: +````xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +```` + + +## baseunits +A concrete base unit definition will be specified by the tag +`` and `` + +The baseunit needs the following mandatory attributes: + +|Name|Value|Description| +|--- |--- |--- | +|name|STRING|Name of the base unit e.g. metre| +|symbol|STRING|Symbol of the base unit e.g. m| +|description|TEXT|Description of the represented base unit| + + +## prefixes +Prefixes between 10 power(-24) and 10 power(24) are predefined. +A prefix can be defined by the `` tag. + +Every `` tag needs the following mandatory attributes: + +|Name|Value|Description|changes between 1.02 and 1.0+| +|--- |--- |--- |--- | +|name|STRING|Name of the prefix| | +|symbol|STRING|Represents a short symbol e.g. k|changed to STRING from CHAR in DDL1.02| +|power|INT|Defines the power of the prefix| | + + +## units +A self defined unit is specified within the `` and `` +tag and needs the following mandatory attributes: + +|Name|Value|Description| +|--- |--- |--- | +|name|STRING|Name of the new unit| + + +The `` tags needs the following mandatory sub-tags: + +|Name|Value|Description| +|--- |--- |--- | +|numerator|STRING containing pi/PI or afloating-point value|Numerator of the new unit related to the baseunits| +|denominator|STRING containing pi/PI or afloating-point value. The value '0' is not defined.|Denominator of the new unit related to the baseunits| +|offset|FLOAT|Offset to the baseunits| + + +The new unit is able to use several base units. To represent this, it is +possible to specify the related base units by the `` tag. This +tag uses the following mandatory attributes: + +|Name|Value|Description|changes between 1.02 and 1.0+| +|--- |--- |--- |--- | +|name|CLASS|The referenced unit|changed to CLASS from STRING in DDL1.02| +|power|INT|Power of the new unit related to the base one| | +|prefix|CLASS|Reference to the prefix to use|changed to CLASS from STRING in DDL1.02| + + +## Calculation of new unit + +The newly defined unit relates to the SI base units like this: + +newUnit = offset + (numerator / denominator) * Product (prefix(n) * baseUnit(n) ^ power(n)) + +  + +# datatypes +This section describes the primitive data types which can be used within the +struct elements. Example: + +````xml + + + + + + ... + +```` + +  + +|Name|Type|Required|Description|changes between 2.0 and 3.0|changes between 1.0+ and 1.0| +|--- |--- |--- |--- |--- |--- | +|name|String|mandatory|Name of the primitive data type|attribute name changed to "name" from "type"| +|size|UInt|mandatory|Number of bits (relevant for serialization)| | | +|description|String|optional|Description of the primitive data type| | | +|arraysize|UInt|optional|= 1 -> primitive presentation> 1 -> array with number of elements. This feature is not supported within DDL.| | | +|unit|Class|optional|Unit of the data type| | | +|min|String|optional|Minimum value of the data type|introduced in DDL 3.0| | +|max|String|optional|Maximum value of the data type|introduced in DDL 3.0| | + + +The following predefined data types are provided with @c adtf.description: + +|Type|Description|Number of bits| +|--- |--- |--- | +|tBool|Boolean|8 (C++ data type)| +|tBit|Bit|1| +|tChar|Character|8| +|tInt8|Signed integer|8| +|tUInt8|Unsigned integer|8| +|tInt16|Signed integer|16| +|tUInt16|Unsigned integer|16| +|tInt32|Signed integer|32| +|tUInt32|Unsigned integer|32| +|tInt64|Signed integer|64| +|tUInt64|Unsigned integer|64| +|tFloat32|IEEE Float|32| +|tFloat64|IEEE Float|64| + + +# enums +This section describes the enum type which can be used within the struct +elements. Example: + +````xml + + + + + + + ... + + + + +```` + +  + +Enum Attributes + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the enum| +|type|String|mandatory|Data type of the enum| + + +Enum Element Attributes + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the element| +|value|Type specific|mandatory|Value of the element| + + +**Remarks:** +- An enum is also valid without enum elements. + +  + +# constants +This section describes constants which are implemented using the enum type. Example: + +````xml + + + + + + ... + + + + +```` + +  + +# structs + +The definition of structs allows to build complex data types. Example: + +````xml + + + + + + + + + + + + + + + + + + +```` + +The tag `` uses the following attributes: + +|Name|Type|Required|Description|changes between 2.0 and 3.0|changes between 1.0+ and 1.0| +|--- |--- |--- |--- |--- |--- | +|name|String|mandatory|Description of the data type| | | +|version|UInt|mandatory|Version number of the specified data type| | | +|comment|Text|optional|Additional comments| | | +|alignment|Enum of 0/1/2/4/8/16/32/64 (defaut 1)|optional|Alignment value to get the whole packing of the complex data type which is important to get the calculated size of the structure (relevant for serialization)|From version 3.0 on, the alignment influences the size of the struct. The size will always be a multiple of the alignment.|introduced in DDL 1.0+| +|ddlversion|String|optional|The version of the size calculation scheme, see alignment. If not specified the version from the containing definition will be used.| | | + + +**Remarks:** +- If the alignment is set to "0", the alignment will be set to the sum of the sizes of all types the struct contains! + +The tag `` uses the following attributes: + +|Name|Type|Required|Description|changes between 3.0 and 4.0|changes between 2.0 and 3.0|changes between 1.02 and 2.0|changes between 1.02 and 1.0+|changes between 1.0+ and 1.0| +|--- |--- |--- |--- |--- |--- |--- |--- |--- | +|type|Class|mandatory|Reference to an existing data type| | | | | | +|name|String|mandatory|Name of the created element| | | | | | +|bytepos|UInt|deprecated|Byte position of the data in the serialized representation of the containing struct. This is NOT relevant for the struct layout in memory (deserialized)!Started with '0'Elements following a dynamic arraymust have a byte pos of '-1'|From version 4.0 on this information is specified within the `` tag.| | | | | +|bitpos|UInt|deprecated|Bit position of the data in the serialized representation of the containing struct. This is NOT relevant for the struct layout in memory (deserialized)!default = 0(in the range of 0 to 7) (relevant for serialization)|From version 4.0 on this information is specified within the `` tag.| | | |default value changes from 1 to 0 in DDL1.0+| +|numbits|UInt|deprecated|Specifies the amount of bits used in the serialized representation, if not set the size of the type will be used. e.g. tInt8 with numbits of 7 (numbits can only be used to non-arrays)This is NOT relevant for the struct layout in memory (deserialized)!|From version 4.0 on this information is specified within the `` tag.| | | | | +|byteorder|Enum of LE/BE/Motorola/Intel|deprecated|Defines the byte order in the serialized representation.|From version 4.0 on this information is specified within the `` tag.| | | | | +|alignment|Enum of 0/1/2/4/8/16/32/64|deprecated|Defines the alignment of the element in the deserialized representation.|From version 4.0 on this information is specified within the `` tag.|From version 3.0 on, the alignment influences the size of the element. The size will always be a the lowest common multiple of the alignment and the size of the type of the element.| | | | +|description|String|optional|Description of the created data type| | | | | | +|unit|Class|optional|Unit of the element|Changed to optional| | | | | +|comment|Text|optional|Additional comments| | | | | | +|arraysize|tUInt or String|mandatory|Defines the array size of the element. The default is arraysize="1". Starting with DDL 2.0 the name of a preceding struct element can be used to specify a dynamic array.arraysize="elementName" For a detailed explanation of dynamic arrays refer to *dynamic arrays*| | |Dynamic array support| | | +|value|Enum element|optional|Constant value for element| | |introduced in DDL 2.0| | | +|min|String|optional|Minimum value of the element| |introduced in DDL 3.0| | | | +|max|String|optional|Maximum value of the element| |introduced in DDL 3.0| | | | +|default|String|optional|Default value of the element| |introduced in DDL 3.0| | | | +|scale|String|optional|Scaling value of the element| |introduced in DDL 3.0| | | | +|offset|String|optional|Offset value of the element| |introduced in DDL 3.0| | | | + + +The tag `` uses the following attributes: + +|Name|Type|Required|Description|changes between 2.0 and 3.0|changes between 1.02 and 2.0|changes between 1.02 and 1.0+|changes between 1.0+ and 1.0| +|--- |--- |--- |--- |--- |--- |--- |--- | +|bytepos|UInt|mandatory|Byte position of the data in the serialized representation of the containing struct. This is NOT relevant for the struct layout in memory (deserialized)!Started with '0'Elements following a dynamic arraymust have a byte pos of '-1'| | | | | +|bitpos|UInt|optional|Bit position of the data in the serialized representation of the containing struct. This is NOT relevant for the struct layout in memory (deserialized)!default = 0(in the range of 0 to 7) (relevant for serialization)| | | |default value changes from 1 to 0 in DDL1.0+| +|numbits|UInt|optional|Specifies the amount of bits used in the serialized representation, if not set the size of the type will be used. e.g. tInt8 with numbits of 7 (numbits can only be used to non-arrays)This is NOT relevant for the struct layout in memory (deserialized)!| | | | | +|byteorder|Enum of LE/BE/Motorola/Intel|mandatory|Defines the byte order in the serialized representation.| | | | | + + +The tag `` uses the following attributes: + +|Name|Type|Required|Description|changes between 2.0 and 3.0| +|--- |--- |--- |--- |--- | +|alignment|Enum of 0/1/2/4/8/16/32/64|deprecated|Defines the alignment of the element in the deserialized representation.|From version 3.0 on, the alignment influences the size of the element. The size will always be a the lowest common multiple of the alignment and the size of the type of the element.| + +**Remarks:** +- The number of structs defined in a DDL description file is not limited. +- If the name of another struct is used as type for an element, a hierarchical structure is created. +- The maximum depth of such hierarchical structures is limited by the value of the define `ADTF_DDL_MAX_DESC_HIERARCHY`. +- If the alignment is set to "0", the alignment will be set to the size of the elements type! + +## Alignment of structs and in structs + +This section will explain the different meanings of alignment used in the DDL. Since alignment +is only needed for deserialized representation, this section will only consider this kind of +representation. + +Inside a struct, every element has a explicit alignment value. This value influences, at what +position the element will be placed inside the struct. The memory placement is initially +determined by the order of the element tags inside the struct. After that the alignment takes +effect. An element inside a struct will only be placed at memory positions that are multiples +of the alignment value. The considered memory address is always relative to the beginning of the +struct (memory position 0). +As an example we assume having the following struct definition: + +````xml + + + + + + + + + + +```` + +In this case, ui8Array will be placed at address 0. Because of the order of the element tags, +ui32Value has to be placed after ui8Array. The next memory position after ui8Array is 5. But +since the element ui32Value has an alignment of 4 and therfore the memory address has to be a +multiple of 4, ui32Value will be placed at address 8 since this is the first address to matches +all requirements. The attibute bytepos is only valid for serialized representation. + +The alignment of a struct does not affect the alignment of its elements. A struct's alignment only +determines the positioning of this struct inside of arrays. +Assuming we have the following struct: + +````xml + + + + + + + + + + +```` + +Lets now assume we have another struct `tOuterStruct`, that contains an array element and the +element's type is the struct `tInnerStruct`: + +````xml + + + + + + +```` + +Inside the array, the array element's positions are influenced by the alignment of the type +(`tInnerStruct`). This means that the first array element is at position 0, in relation to the +beginning of the array. The next free memory address would be 2, but since the alignment of the +struct is 4, the memory address has to be a multiple of 4 and the second element of the array now +is situated at memory address 4. The third will be at 8, the fourth at 12 and so on. + +## Why should I use anything else but an alignment of 1? + +If for example you are planning to describe data with DDL that was originally defined as a struct +in a header file, you should also define the alignment values inside your DDL file accordingly. +If on the other hand you are shure, that the data you are using is always interpreted using DDL, +there is no need to use an alignment other than 1. + +## What consequences do the changes in DDL 3.0 have regarding alignment? + +The changes in DDL 3.0 regarding alignment are meant to make it more easy to describe structs +defined in C(++). Since C(++) does not use alignment but packing for its structs, the alignment +in DDL now also influences the size of a struct defined in DDL (see new definition of alignment +in DDL 3.0). This means that arrays and structs may now become bigger in DDL 3.0 as they were in +DDL 2.x. For example the struct + +````xml + + + + + + +```` + +has the deserialized size of 1 byte in DDL 2.x and a deserialized size of 2 byte in DDL 3.0. +The struct + +````xml + + + + + + +```` + +has a size of 5 bytes in DDL 2.x and a size of 6 Bytes in DDL 3.0. +This is due to the fact, that in 2.x the array looks like this: + +|Bytepos|Element| +|--- |--- | +|0|aValue[0]| +|1|padding Element| +|2|aValue[1]| +|3|padding Element| +|4|aValue[2]| + + +resulting in a size of 5 bytes. +The padding elements are inserted, so that the *following* Element is correctly aligned. +In DDL 3.0 the `tFirstStruct` has already a padding alement attached to its end so that its +size matches the requirements of the alignment attribute (multiple of 2). Therefore, the array +in 3.0 will look like this: + +|Bytepos|Element| +|--- |--- | +|0 to 1|aValue[0]| +|2 to 3|aValue[1]| +|4 to 5|aValue[2]| + +resulting in a size of 6 bytes. + +## Changing from DDL 2.x to 3.0 + +Assuming you have a couple of structs defined in DDL 2.x, if you now plan to change the language +version from 2.x to 3.0, that you are creating new structs, that may not be compatible to its +namesakes defined in DDL 2.x. Its better to use new names for the structs to differentiate +between the different versions. + +## dynamic arrays + +Detailed explanation of the dynamic array functionality. + + +Dynamic arrays were introduced in DDL 2.0. + +**Attention:** + +The use of dynamic arrays will cause a severe performance drop +compared to static arrays. +It is therefore recommended to use static arrays whenever possible. + +To minimize the performance impact of dynamic arrays the user should adhere +to the following guidelines:
+- Always place dynamic data the end of a structure or structure hirarchy so +all static data precede the dynamic data. +- Use the struct element directly preceding the dynamic array for array size. +- Use dynamic arrays of primitive data types instead of complex data types. +- Prefer flat data over deeply structured data. +- Do not use nested dynamic arrays! +- Use alignment=1 for all elements. +- Use default values bitpos. +- Use a bytepos that matches the position in memory when alignment=1. + +Dynamic Arrays cannot be used with the ADTF Signal Registry. + +### Fastest way to use dynamic arrays: + +````xml + + + + + + + + + + + + + + +```` + +### When the dynamic data is not the last element the bytepos of the following elements must be -1 + +````xml + + + + + + + + + + + + + + +```` + +### Dynamic array of complex data: + +````xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + +```` + + +# streammetatypes + +Stream Meta Types are defined within the tags `` and ``. +Example: + +````xml + + + + + + + + + + +```` + +The tag `` uses the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|The identifier of the stream meta type| +|version|UInt|mandatory|Version number of the specified stream meta type| +|parent|Text|optional|Identifier of a parent stream meta type| + +The tag `` uses the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|The name of the property| +|type|UInt|mandatory|The type of the property| + + +# predefined elements + +The following base units are provided as default: + +|Base Unit Name|Description|Symbol| +|--- |--- |--- | +|Metre|Fundamental unit for length|m| +|Kilogram|Fundamental unit for mass|kg| +|Second|Fundamental unit for time|s| +|Ampere|Fundamental unit for electric current|A| +|Kelvin|Fundamental unit for thermodynamic temperature|K| +|Mole|Fundamental unit for amount of substance|mol| +|Candela|Fundamental unit for luminous intensity|cd| +|Degree|Non-SI standard unit for angle|deg| +|Radiant|Non-SI standard unit for angle|rad| +|Unitless|No SI, but needed for own unit definitions| | +|nou|No SI, but needed for no unit definitions| | + +The following prefixes are provided as default: + +|Prefix Name|Power|Symbol| +|--- |--- |--- | +|yotta|24|Y| +|zetta|21|Z| +|exa|18|E| +|peta|15|P| +|tera|12|T| +|giga|9|G| +|mega|6|M| +|kilo|3|k| +|hecto|2|h| +|deca|1|da| +|deci|-1|d| +|centi|-2|c| +|milli|-3|m| +|micro|-6|u| +|nano|-9|n| +|pico|-12|p| +|femto|-15|f| +|atto|-18|a| +|zepto|-21|z| +|yocto|-24|y| + +The following data types are provided as default: + +|Data Type Name|Description|Size| +|--- |--- |--- | +|tBool|predefined ADTF tBool datatype|8| +|tChar|predefined ADTF tChar datatype|8| +|tUInt8|Upredefined ADTF tUInt8 datatype|8| +|tInt8|predefined ADTF tInt8 datatype|8| +|tUInt16|predefined ADTF tUInt16 datatype|16| +|tInt16|predefined ADTF tInt16 datatype|16| +|tUInt32|predefined ADTF tUInt32 datatype|32| +|tInt32|predefined ADTF tInt32 datatype|32| +|tUInt64|predefined ADTF tUInt64 datatype|64| +|tInt64|predefined ADTF tInt64 datatype|64| +|tFloat32|predefined ADTF tFloat32 datatype|32| +|tFloat64|predefined ADTF tFloat64 datatype|64| + + +The following enums are provided as default: + +|Enum Name|Type| +|--- |--- | +|tMediaTypeMajor|tUInt32| +|tPixelFormat|tInt16| + + + + diff --git a/doc/input/mapping_configuration.xsd b/doc/input/mapping_configuration.xsd new file mode 100644 index 0000000..723894a --- /dev/null +++ b/doc/input/mapping_configuration.xsd @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/input/mapping_specification.md b/doc/input/mapping_specification.md new file mode 100644 index 0000000..9b28251 --- /dev/null +++ b/doc/input/mapping_specification.md @@ -0,0 +1,261 @@ +# Signal Mapping Format Specification {#page_signal_mapping_spec} + +# Configuration format + +The actual mapping of signals is configured using a xml-based configuration format. + +## Overview +A mapping configuration file contains a header with meta information about the file, source signal declarations, target signal definitions and transformation definitions. A source signal consists of a name and a signal type. Target signals also consist of a name and a signal type. They define any number of signal element assignments as well as any trigger conditions. + +Conceptionally, signal element assignments define how the target signal is assembled while triggers define when the target signal buffer is submitted to the user. + +A target signal element can be assigned a constant numeric value or a source signal element. In the later case, a transformation can be used to alter the source signal element value during assignment. For details see \ref subsec_features_types. Trigger conditions are optional, since it is always possible to actively get the current target signal buffer. For now, only periodic triggers can be defined, using a period and a unit of time. + +## Specification + +This specification contains the following parts: +- Header +- Sources +- Targets +- Transformations + +These sections will be described in the following paragraphs, see the [XSD specification](../mapping_configuration.xsd) for more details. + + +### Header + +The header section contains meta information about the document and version information. +It is similar to the header informations in the DDL Definition File Format. + +|Tag|Type|Required|Description| +|--- |--- |--- |--- | +|language_version|Float|mandatory|Version number of the mapping format| +|author|String|mandatory|Author| +|date_creation|Date|mandatory|Creation date| +|date_change|Date|mandatory|Last modification date| +|description|Text|mandatory|Short description| + + +### Sources + +This section defines the source signals that can be used in assignments to any target signal elements(s). + +The tag `<source>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the signal| +|type|String|mandatory|DDL structured type of the signal| + + +### Targets + +This section contains definitions of target signals, assignement to their target elements as well as any trigger definitions. + +The tag `<target>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the signal| +|type|String|mandatory|DDL structured type of the signal| + +The tag `<assignment>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|to|String|mandatory|Name of the target signal element to be assign| +|constant|String|optional*|Float value which will assigned during initialisation| +|function|String|optional*|Macro to assign| +|from|String|optional*|Source signal or source signal element to assign| +|transformation|String|optional|Transformation to apply to the source element| + + +__*__: The attributes _constant_, _function_ and _from_ are mutually exclusive but one of them is required. +The attribute _transformation_ can only be applied when the attribute _from_ is defined. + +The attribute _function_ can have the values: + +|Function|Parameter|Description| +|--- |--- |--- | +|simulation_time()|None|Evaluates to the current simulation time| +|trigger_counter()|None|Trigger counter, incremented whenever a trigger for the target fires| +|trigger_counter()|Positive numeric value, modulo parameter|Trigger counter with wrap-around| +|received()|Name of the source signal|Received indicator, evaluates to true if the source signal has been received| + + +The tag `<trigger>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|type|String|mandatory|Trigger type| +|period|String|optional|Float value defining the length of the period| +|unit|String|optional|unit to interpret the given _period_| +|variable|String|optional|For _signal_ triggers: name of the source signal, for _data triggers: name of the source signal element| +|operator|String|optional|Operator used for data triggers: less_than, greater_than, less_than_equal, greater_than_equal, equal or not_equal| +|value|String|optional|Float value to compare with the source element| + + +The attribute _type_ has three acceptable values: +- _periodic_ +- _data_ +- _signal_ + +For the _periodic_ Trigger type, the attributes _period_ and _unit_ are mandatory. +For the _data_ Trigger type, the attributes _variable_, _operator_ and _value_ are mandatory. +For the _signal_ Trigger type, the attribute _variable_ is mandatory. + +### Transformations + +This section contains definitions of transformations that can be used in assignements. +For the moment the only transformations available are polynomial tranformations and enum to enum transformations. + +The tag `<polynomial>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the transformation| +|a|String|optional|parameter of the polynom for X^0| +|b|String|optional|parameter of the polynom for X^1| +|c|String|optional|parameter of the polynom for X^2| +|d|String|optional|parameter of the polynom for X^3| +|e|String|optional|parameter of the polynom for X^4| + + +The tag `<enum_table>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|name|String|mandatory|Name of the transformation| +|from|String|mandatory|Enumeration type used as transformation source| +|to|String|mandatory|Enumeration type used as transformation target| +|default|String|mandatory|Default value used when no conversion is defined. It must be an element of the target enumeration| + + +The tag `<conversion>` supports the following attributes: + +|Name|Type|Required|Description| +|--- |--- |--- |--- | +|from|String|mandatory|Element from the enumeration type used as transformation source| +|to|String|mandatory|Element from the enumeration type used as transformation target| + + +## Example +The following example shows the mapping of the target signals `LightSource` and `Object`. +`LightSource` elements are mapped from two source signals, `LightOrientation` and `LightPos`, as well as some constants. + Two of its assignments are also transformed during mapping. The entire target is triggered by a periodic trigger with a period of 5s, and when LightPos is received and LightPos.f64X is lesser than 2. + `Object` element is an enumeration, mapped with transformation from `SourceObject`. + The Enumeration Type _tObjectType_ is mapped in an obsolete Enumeration created for the example. + This Target is trigger when `LightOrientation` is received. + +````xml + + +
+ 1.00 + AUDI Electronic Ventures GmbH + 2016-Jun-08 + 2016-Jun-08 + Example mapping configuration +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+```` + +# Features + +## Constants and Macros + +A target signal element can be assigned a constant numeric value. This value will be parsed as a floating point number and casted to the target element type. + +A target signal element can also be assigned the simulation time, a trigger counter or a received flag. + +**Note:** + +Constants and Macros can only be used to initialize scalar as well as arrays of scalar elements +Any unassigned target elements will be assigned the default value configured in the DDL definition of the target signal type + +## Transformations + +Transformations can be used to alter the value of an assignment during runtime. +Polynomial and enum to enum transformations are supported. + +Polynomial transformations use the following polynomial to transform the assignments: + +```` +value = a*value^0 + b*value^1 + c*value^2 + d*value^3 + e*value^4 +```` + +Any undefined coefficients are set to 0. + + +**Note:** + +Transformations are only supported for scalar as well as arrays of scalar elements + +## Supported types and cross-type assignments + +Assignments from one type to another are supported in the following way + +Source | Target | Specification +------------- | ------------- | ------------- +Constant | Scalar | Datatype conversion using standard C++ casting methods +Simulation time | Scalar | Datatype conversion using standard C++ casting methods +Trigger counter | Scalar | Datatype conversion using standard C++ casting methods +Received Flag | Scalar | Only for boolean +Scalar | Scalar | Datatype conversion using standard C++ casting methods. Transformations allowed +Array | Array | Only for arrays of same size. Datatype conversion using standard C++ casting methods. Transformations allowed +Structure | Structure | Only for structures of same type +Array | Array | Only for arrays of same size and structures of same type +Enum | Enum | Datatype conversion to the underlying numerical datatype using standard C++ casting methods +Array | Array | Only for arrays of same size. Datatype conversion using standard C++ casting methods. + +Scalar datatypes are enumerations, `tBool`, `tChar`, `tUInt8`, `tInt8`, `tUInt16`, `tInt16`, `tUInt32`, `tInt32`, `tUInt64`, `tInt64`, `tFloat32` and `tFloat64`. + +Array and structure elements can be used separately in assignments, for example: + +````xml + + +```` + +**Note:** + +A target element can only be assigned once. For instance, if one element in a substructure is already assigned, the whole substructure can not be assigned and reciprocally. + +Target and source signals may only use structured types + diff --git a/doc/input/migration_4_1.md b/doc/input/migration_4_1.md new file mode 100644 index 0000000..c867a0b --- /dev/null +++ b/doc/input/migration_4_1.md @@ -0,0 +1,81 @@ +# Migration to DDL 4.1 {#page_migration_4_1} + +DDL version 4.1.0 introduced an updated coding style which led to changes in all APIs. +This guide aims to make the migration as easy as possible. + +# Changes in DDL 4.1 + +The updated coding style brought numerous changes. Relevant for the API are: + +* No hungarian notation anymore: Class names are no longer preceded by 'c', i.e. `cDDLDescription` -> `DDLDescription` +* Class methods and static functions are now lower case, i.e. `GetValue()` -> `getValue()` +* Change of enum values to lower case, i.e. `PLATFORM_LITTLE_ENDIAN_8` -> `plattform_little_endian_8` + +## Version variables changes + +In DDL 4.1 all DDL Version variables were changed from a plain floating point value to objects of type `DDLVersion`. +This change made `DDLVersionHelper` obsolete and incorporated most of its functionality in DDLVersion. +The necessary adaptions in DDL user code for these changes can not be done automatically by the migration scripts +and therefore have to be done manually. + + +# Migration scripts + +To assist in the migration process a new cmake function gets delivered with the DDL package. +After having called `find_package(ddl)` somewhere in your CMake script, the CMake function `ddl_migrate_4_1()` +is available. This function will create a migration script for the specified target. It should be called after +a target was defined. Example call: + +````cmake +ddl_migrate_4_1(TARGET ddl_editor) +```` + +This will create the migration script in the targets build dir +(i.e. `build_Debug/src/ddl_editor/gui/ddl_editor_migrate_to_ddl_4_1.sh`) +during the CMake build process. + +## The migration script TARGET_migrate_to_ddl_4_1.sh + +**Important** The resulting script is a `bash` script that uses POSIX tools like `find` and `sed`. Therefore the migration should either be done using a +Linux operating system or using a Windows environment that offers a bash runtime and those tools (like MinGW or the Git Bash console) + +The migration is done in two steps: + +* Replacing all DDL class names and enum values with the changed ones. This is a simple text replacement, +without any syntax awareness. Therefore it will replace these symbols even in disabled code etc. +* Running clang-tidy to automatically fix the remaining issues. This will basically compile the code +and tries to fix the arising problems. + +The process will run automatically when executing the migrate script. + +**Warning:** There are several things to note: + +* clang-tidy is called several times, since there will be a lot of issues which obscure each other. +*This can take quite some time.* +* clang-tidy is very strict concerning include directories. While the 'normal' build process might not +have problems discovering header files in sub folder of include directories, clang-tidy will not find +them. You have to correctly specify all include directories for your target in the CMake script +(which is a good idea anyways). This might happen for example if the target is not explicitly linked +against Qt::Gui (but other Qt libs). Qt::Gui has to be added to the linked libraries for clang-tidy +to find those headers. +* If your target uses generated header files (like Qt applications usually do) those have to be +generated before the migration script can do it's work. If the CMake build fails before those are +generated you have to fix the dependant targets and run the CMake build process again. Also make sure +that the destination of those headers is part of the include dirs. +* After the migration is done, clang-tidy might output some remaining warnings. These might not be +directly related to the migration process and originate from the static code analysis. While fixing +them is probably a good idea, they are usually not build breaking. +* The migration script changes your code. A lot. There might be things that get broken by it that are +not even related to the DDL code. You should check the code after the migration is done. And of course +have it under source control so that any changes can easily be reverted. +* If you have serveral targets that depend on each other and use the DDL library, you should migrate +them one-by-one along the dependency graph beginning at the leafes. + +## Remaining issues + +Not all issues will be fixed by the migration script. After the script is done try to build the +application and fix any build errors manually. These are usually minor issues like `GetValue` or `IsEqual` +instead of `getValue` and `isEqual`. + +After the migration is done the calls to `ddl_migrate_4_1()` can be removed from the CMake scripts. + diff --git a/doc/input/mpl.md b/doc/input/mpl.md new file mode 100644 index 0000000..a3f6fd8 --- /dev/null +++ b/doc/input/mpl.md @@ -0,0 +1,376 @@ +Mozilla Public License Version 2.0 {#page_mpl} +================================== + +1. Definitions +-------------- + +### 1.1. "Contributor" + +means each individual or legal entity that creates, contributes to +the creation of, or owns Covered Software. + +### 1.2. "Contributor Version" + +means the combination of the Contributions of others (if any) used +by a Contributor and that particular Contributor's Contribution. + +### 1.3. "Contribution" + +means Covered Software of a particular Contributor. + +### 1.4. "Covered Software" + +means Source Code Form to which the initial Contributor has attached +the notice in Exhibit A, the Executable Form of such Source Code +Form, and Modifications of such Source Code Form, in each case +including portions thereof. + +### 1.5. "Incompatible With Secondary Licenses" + +means + +a. that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + +b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +### 1.6. "Executable Form" + +means any form of the work other than Source Code Form. + +### 1.7. "Larger Work" + +means a work that combines Covered Software with other material, in +a separate file or files, that is not Covered Software. + +### 1.8. "License" + +means this document. + +### 1.9. "Licensable" + +means having the right to grant, to the maximum extent possible, +whether at the time of the initial grant or subsequently, any and +all of the rights conveyed by this License. + +### 1.10. "Modifications" + +means any of the following: + +a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + +b. any new file in Source Code Form that contains any Covered + Software. + +### 1.11. "Patent Claims" of a Contributor + +means any patent claim(s), including without limitation, method, +process, and apparatus claims, in any patent Licensable by such +Contributor that would be infringed, but for the grant of the +License, by the making, using, selling, offering for sale, having +made, import, or transfer of either its Contributions or its +Contributor Version. + +### 1.12. "Secondary License" + +means either the GNU General Public License, Version 2.0, the GNU +Lesser General Public License, Version 2.1, the GNU Affero General +Public License, Version 3.0, or any later versions of those +licenses. + +### 1.13. "Source Code Form" + +means the form of the work preferred for making modifications. + +### 1.14. "You" (or "Your") + +means an individual or a legal entity exercising rights under this +License. For legal entities, "You" includes any entity that +controls, is controlled by, or is under common control with You. For +purposes of this definition, "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of more than +fifty percent (50%) of the outstanding shares or beneficial +ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +### 2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +b. under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +### 2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +### 2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +a. for any code that a Contributor has removed from Covered Software; + or + +b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +### 2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +### 2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +### 2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +### 2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +### 3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +### 3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +a. such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +### 3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +### 3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +### 3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under +Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +6. Disclaimer of Warranty +------------------------- + +*Covered Software is provided under this License on an "as is" basis, +without warranty of any kind, either expressed, implied, or statutory, +including, without limitation, warranties that the Covered Software is +free of defects, merchantable, fit for a particular purpose or +non-infringing. The entire risk as to the quality and performance of the +Covered Software is with You. Should any Covered Software prove +defective in any respect, You (not any Contributor) assume the cost of +any necessary servicing, repair, or correction. This disclaimer of +warranty constitutes an essential part of this License. No use of any +Covered Software is authorized under this License except under this +disclaimer.* + +7. Limitation of Liability +-------------------------- + +*Under no circumstances and under no legal theory, whether tort +(including negligence), contract, or otherwise, shall any Contributor, +or anyone who distributes Covered Software as permitted above, be liable +to You for any direct, indirect, special, incidental, or consequential +damages of any character including, without limitation, damages for lost +profits, loss of goodwill, work stoppage, computer failure or +malfunction, or any and all other commercial damages or losses, even if +such party shall have been informed of the possibility of such damages. +This limitation of liability shall not apply to liability for death or +personal injury resulting from such party's negligence to the extent +applicable law prohibits such limitation. Some jurisdictions do not +allow the exclusion or limitation of incidental or consequential +damages, so this exclusion and limitation may not apply to You.* + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +### 10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in +Section 10.3, no one other than the license steward has the right to +modify or publish new versions of this License. Each version will be +given a distinguishing version number. + +### 10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +### 10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + +> This Source Code Form is subject to the terms of the Mozilla Public +> License, v. 2.0. If a copy of the MPL was not distributed with this +> file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + +> This Source Code Form is "Incompatible With Secondary Licenses", as +> defined by the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/doc/input/oo-ddl.md b/doc/input/oo-ddl.md new file mode 100644 index 0000000..9d41039 --- /dev/null +++ b/doc/input/oo-ddl.md @@ -0,0 +1,63 @@ +# Object-oriented representation of the DDL (OO-DDL) {#page_oo_ddl} + +# Introduction +To facilitate the handling of DDL hierarchies there is an object-oriented +approach of representation, called OO-DDL. + +Within the class structure of OO-DDL every node type inside the DDL definition +is representated by an own class. + +**Note:** + +These classes are associated by using the GoF design patterns "Visitor", +"Decorator", and "Factory Method". +The main classes are described in the following section. + +# Structure of classes +The basic interface of nearly all classes of the OO-DDL is `ddl::IDDL`. +The root element of every DDL structure is an instance of +`ddl::cDDLDescription`. For example a DDL Definition File may be +represented by `cDDLDescription`. This object holds references to the main +parts like the header (`ddl::cDDLHeader`) or the datatypes +(`ddl::IDDLDataType`). For further information on all available OO-DDL +classes see the SDK documentation of `ddl::IDDL`. + +Every link between DDL-representing objects is realized as pointer to the +according object. So lots of string comparisons for matching e.g. child +elements could be removed. + +# Building up - using ddl::IDDLFactoryMethod +For all creation tasks concerning OO-DDL implementations of the interface +`IDDLFactoryMethod` are used. A basic implementation of `IDDLFactoryMethod` +is `ddl::cDDLImporter`. + +# Processing DDL - using ddl::IDDLVisitor +For every task of processing DDL implementations of `ddl::IDDLVisitor` are +used. Utilizing this interface the DDL-representing hierarchy can be walked +through and appropriate actions may be taken. The basic implementation of +`IDDLVisitor` is `ddl::cDDLPrinter`. + +# The Correlation Between OO-DDL and DDL. +Every tag and some attributes in the DDL have a correspondent in the OO-DDL. +The following table shows the OO-DDL classes with their matching DDL tag or attribute: + +|DDL Tag/Attribute|OO-DDL Class| +|--- |--- | +|``|cDDLDescription| +|`
`|cDDLHeader| +|``|cDDLExtDeclaration| +|``|cDDLBaseunit| +|``|cDDLPrefix| +|``|cDDLUnit| +|``|cDDLRefUnit| +|``|cDDLDataType| +|``|cDDLEnum| +|``|cDDLComplex| +|``|cDDLElement| +|alignment=xxx|cDDLAlignment| +|byteorder=xxx|cDDLByteorder| +|``|cDDLStream| +|`` (within a `` tag)|cDDLStreamStruct| + + + diff --git a/doc/input/used_licenses.md b/doc/input/used_licenses.md new file mode 100644 index 0000000..0a3a26b --- /dev/null +++ b/doc/input/used_licenses.md @@ -0,0 +1,404 @@ +# 3rdparty Software we are very glad to use {#page_used_licenses} + +# a_util Library + +~~~~ +Mozilla Public License Version 2.0 {#page_mpl} +================================== + +1. Definitions +-------------- + +### 1.1. "Contributor" + +means each individual or legal entity that creates, contributes to +the creation of, or owns Covered Software. + +### 1.2. "Contributor Version" + +means the combination of the Contributions of others (if any) used +by a Contributor and that particular Contributor's Contribution. + +### 1.3. "Contribution" + +means Covered Software of a particular Contributor. + +### 1.4. "Covered Software" + +means Source Code Form to which the initial Contributor has attached +the notice in Exhibit A, the Executable Form of such Source Code +Form, and Modifications of such Source Code Form, in each case +including portions thereof. + +### 1.5. "Incompatible With Secondary Licenses" + +means + +a. that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + +b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +### 1.6. "Executable Form" + +means any form of the work other than Source Code Form. + +### 1.7. "Larger Work" + +means a work that combines Covered Software with other material, in +a separate file or files, that is not Covered Software. + +### 1.8. "License" + +means this document. + +### 1.9. "Licensable" + +means having the right to grant, to the maximum extent possible, +whether at the time of the initial grant or subsequently, any and +all of the rights conveyed by this License. + +### 1.10. "Modifications" + +means any of the following: + +a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + +b. any new file in Source Code Form that contains any Covered + Software. + +### 1.11. "Patent Claims" of a Contributor + +means any patent claim(s), including without limitation, method, +process, and apparatus claims, in any patent Licensable by such +Contributor that would be infringed, but for the grant of the +License, by the making, using, selling, offering for sale, having +made, import, or transfer of either its Contributions or its +Contributor Version. + +### 1.12. "Secondary License" + +means either the GNU General Public License, Version 2.0, the GNU +Lesser General Public License, Version 2.1, the GNU Affero General +Public License, Version 3.0, or any later versions of those +licenses. + +### 1.13. "Source Code Form" + +means the form of the work preferred for making modifications. + +### 1.14. "You" (or "Your") + +means an individual or a legal entity exercising rights under this +License. For legal entities, "You" includes any entity that +controls, is controlled by, or is under common control with You. For +purposes of this definition, "control" means (a) the power, direct +or indirect, to cause the direction or management of such entity, +whether by contract or otherwise, or (b) ownership of more than +fifty percent (50%) of the outstanding shares or beneficial +ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +### 2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +b. under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +### 2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +### 2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +a. for any code that a Contributor has removed from Covered Software; + or + +b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +### 2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +### 2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +### 2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +### 2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +### 3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +### 3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +a. such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +### 3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +### 3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +### 3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under +Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +6. Disclaimer of Warranty +------------------------- + +*Covered Software is provided under this License on an "as is" basis, +without warranty of any kind, either expressed, implied, or statutory, +including, without limitation, warranties that the Covered Software is +free of defects, merchantable, fit for a particular purpose or +non-infringing. The entire risk as to the quality and performance of the +Covered Software is with You. Should any Covered Software prove +defective in any respect, You (not any Contributor) assume the cost of +any necessary servicing, repair, or correction. This disclaimer of +warranty constitutes an essential part of this License. No use of any +Covered Software is authorized under this License except under this +disclaimer.* + +7. Limitation of Liability +-------------------------- + +*Under no circumstances and under no legal theory, whether tort +(including negligence), contract, or otherwise, shall any Contributor, +or anyone who distributes Covered Software as permitted above, be liable +to You for any direct, indirect, special, incidental, or consequential +damages of any character including, without limitation, damages for lost +profits, loss of goodwill, work stoppage, computer failure or +malfunction, or any and all other commercial damages or losses, even if +such party shall have been informed of the possibility of such damages. +This limitation of liability shall not apply to liability for death or +personal injury resulting from such party's negligence to the extent +applicable law prohibits such limitation. Some jurisdictions do not +allow the exclusion or limitation of incidental or consequential +damages, so this exclusion and limitation may not apply to You.* + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +### 10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in +Section 10.3, no one other than the license steward has the right to +modify or publish new versions of this License. Each version will be +given a distinguishing version number. + +### 10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +### 10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + +> This Source Code Form is subject to the terms of the Mozilla Public +> License, v. 2.0. If a copy of the MPL was not distributed with this +> file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + +> This Source Code Form is "Incompatible With Secondary Licenses", as +> defined by the Mozilla Public License, v. 2.0. +~~~~ + +# Google Test 1.8.0 + +## googletest + +@include googletest/googletest-release-1.8.0/googletest/LICENSE + +## googlemock + +@include googletest/googletest-release-1.8.0/googlemock/LICENSE + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/license/MPL2.0.txt b/doc/license/MPL2.0.txt new file mode 100644 index 0000000..bec7bef --- /dev/null +++ b/doc/license/MPL2.0.txt @@ -0,0 +1,376 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + + means + + a. that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + b. that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + + means this document. + +1.9. "Licensable" + + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + + means any of the following: + + a. any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + b. any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +### 2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +a. under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +b. under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +### 2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +### 2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +a. for any code that a Contributor has removed from Covered Software; + or + +b. for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +c. under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +### 2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +### 2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +### 2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +### 2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +### 3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +### 3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +a. such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +b. You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +### 3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +### 3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +### 3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under +Section 2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +6. Disclaimer of Warranty +------------------------- + +*Covered Software is provided under this License on an "as is" basis, +without warranty of any kind, either expressed, implied, or statutory, +including, without limitation, warranties that the Covered Software is +free of defects, merchantable, fit for a particular purpose or +non-infringing. The entire risk as to the quality and performance of the +Covered Software is with You. Should any Covered Software prove +defective in any respect, You (not any Contributor) assume the cost of +any necessary servicing, repair, or correction. This disclaimer of +warranty constitutes an essential part of this License. No use of any +Covered Software is authorized under this License except under this +disclaimer.* + +7. Limitation of Liability +-------------------------- + +*Under no circumstances and under no legal theory, whether tort +(including negligence), contract, or otherwise, shall any Contributor, +or anyone who distributes Covered Software as permitted above, be liable +to You for any direct, indirect, special, incidental, or consequential +damages of any character including, without limitation, damages for lost +profits, loss of goodwill, work stoppage, computer failure or +malfunction, or any and all other commercial damages or losses, even if +such party shall have been informed of the possibility of such damages. +This limitation of liability shall not apply to liability for death or +personal injury resulting from such party's negligence to the extent +applicable law prohibits such limitation. Some jurisdictions do not +allow the exclusion or limitation of incidental or consequential +damages, so this exclusion and limitation may not apply to You.* + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +### 10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in +Section 10.3, no one other than the license steward has the right to +modify or publish new versions of this License. Each version will be +given a distinguishing version number. + +### 10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +### 10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +### 10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + +> This Source Code Form is subject to the terms of the Mozilla Public +> License, v. 2.0. If a copy of the MPL was not distributed with this +> file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + +> This Source Code Form is "Incompatible With Secondary Licenses", as +> defined by the Mozilla Public License, v. 2.0. \ No newline at end of file diff --git a/doc/run_doxygen.cmake.in b/doc/run_doxygen.cmake.in new file mode 100644 index 0000000..2ad5d31 --- /dev/null +++ b/doc/run_doxygen.cmake.in @@ -0,0 +1,49 @@ +##generate the doxyfile to stdout +execute_process(COMMAND @DOXYGEN_EXECUTABLE@ -s -g - OUTPUT_VARIABLE doxygen_out) + +##set any doxygen tag according to our needs, leave the rest untouched (= default) +# never use the absolute path for INPUT, otherwise call graphs might be generated with absolute +# paths inside. Use relative path and execute doxygen from within install dir WORKING_DIRECTORY +# We could just use @CMAKE_CURRENT_SOURCE_DIR@/input to include all *.md files, but this way we can specify their order for the index +string(REGEX REPLACE "(INPUT +[=])" + "\\1 codec ddlrepresentation mapping serialization @CMAKE_CURRENT_SOURCE_DIR@/../README.md \ + @CURRENT_IMPORTS_DIR@/licenses/list_used_licenses.md \ + @CMAKE_CURRENT_SOURCE_DIR@/changelog.md @CMAKE_CURRENT_SOURCE_DIR@/input/ddl_specification.md \ + @CMAKE_CURRENT_SOURCE_DIR@/input/oo-ddl.md \ + @CMAKE_CURRENT_SOURCE_DIR@/input/codec.md @CMAKE_CURRENT_SOURCE_DIR@/input/ddl_generators.md \ + @CMAKE_CURRENT_SOURCE_DIR@/input/mapping_specification.md @CMAKE_CURRENT_SOURCE_DIR@/input/mpl.md \ + @CMAKE_CURRENT_SOURCE_DIR@/input/migration_4_1.md \ + @CMAKE_CURRENT_SOURCE_DIR@/input/used_licenses.md" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(RECURSIVE +[=]) NO" + "\\1 YES" doxygen_out ${doxygen_out}) +#string(REGEX REPLACE "(FILE_PATTERNS +[=])" +# "\\1 readme.txt " doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(PROJECT_NAME +[=]) \"My Project\"" + "\\1 \"ddl_library\"" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(PROJECT_NUMBER +[=])" + "\\1 v@PROJECT_VERSION@" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(OUTPUT_DIRECTORY +[=])" + "\\1 @CMAKE_INSTALL_PREFIX@/doc" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(SHORT_NAMES +[=]) NO" + "\\1 YES" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(GENERATE_LATEX +[=]) YES" + "\\1 NO" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(HAVE_DOT +[=]) NO" + "\\1 @DOXYGEN_DOT_FOUND@" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(DOT_PATH +[=])" + "\\1 @DOXYGEN_DOT_EXECUTABLE@" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(PREDEFINED +[=])" + "\\1 ${_predefined}" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(EXAMPLE_PATH +[=])" + "\\1 ../doc/license" doxygen_out ${doxygen_out}) +string(REGEX REPLACE "(GENERATE_TREEVIEW +[=]) NO" + "\\1 YES" doxygen_out ${doxygen_out}) + + +##generate the documentation with doxygen + +file(WRITE @CMAKE_CURRENT_BINARY_DIR@/Doxyfile ${doxygen_out}) +execute_process(COMMAND @DOXYGEN_EXECUTABLE@ @CMAKE_CURRENT_BINARY_DIR@/Doxyfile + WORKING_DIRECTORY @CMAKE_INSTALL_PREFIX@/include/) + +unset(_predefined) diff --git a/doc/static/ddl.html b/doc/static/ddl.html new file mode 100644 index 0000000..4889bf8 --- /dev/null +++ b/doc/static/ddl.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/legacy_error_macros.h b/legacy_error_macros.h new file mode 100644 index 0000000..f9f5a9b --- /dev/null +++ b/legacy_error_macros.h @@ -0,0 +1,31 @@ +/** + * @file + * This header provides the legacy error macros. + * Important: This header may not be included in ddl.h! + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef LEGACY_ERROR_MACROS_H_ +#define LEGACY_ERROR_MACROS_H_ + +#define RETURN_IF_FAILED(s) \ +{ \ + a_util::result::Result _errcode(s); \ + if ( a_util::result::isFailed(_errcode) ) { return (_errcode); } \ +} + +#endif // LEGACY_ERROR_MACROS_H_ diff --git a/mapping/configuration/map_assignment.cpp b/mapping/configuration/map_assignment.cpp new file mode 100644 index 0000000..7ee331c --- /dev/null +++ b/mapping/configuration/map_assignment.cpp @@ -0,0 +1,364 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_assignment.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) +} +} + +using namespace mapping::oo; + +MapAssignment::MapAssignment() : _is_valid(true) +{ +} + +MapAssignment::MapAssignment(std::string strTo) : _to(strTo), _is_valid(true) +{ +} + +bool MapAssignment::isValid() const +{ + return _is_valid; +} + +const std::string& MapAssignment::getFrom() const +{ + return _from; +} + +const std::string& MapAssignment::getSource() const +{ + return _source; +} + +a_util::result::Result MapAssignment::connect(const std::string& strSourceElementPath) +{ + _constant.clear(); + _function.clear(); + _modulo.clear(); + _transform.clear(); + + _from = strSourceElementPath; + a_util::strings::trim(_from); + _source.clear(); + // parse source out of + // parse source + size_t idx = _from.find('.'); + if (idx != std::string::npos) + { + _source = _from.substr(0, idx); + _from = _from.substr(idx + 1); + } + else + { + // no path when the signal itself is referenced + _source = _from; + _from.clear(); + } + + if(_source.empty()) + { + return ERR_INVALID_ARG; + } + + return a_util::result::SUCCESS; +} + +const std::string& MapAssignment::getConstant() const +{ + return _constant; +} + +a_util::result::Result MapAssignment::setConstant(const std::string& strConstant) +{ + _from.clear(); + _source.clear(); + _function.clear(); + _modulo.clear(); + _transform.clear(); + + _constant = strConstant; + a_util::strings::trim(_constant); + if(_constant.empty()) + { + return ERR_INVALID_ARG; + } + return a_util::result::SUCCESS; +} + +const std::string& MapAssignment::getFunction() const +{ + return _function; +} + +a_util::result::Result MapAssignment::setSimulationTimeFunction() +{ + _from.clear(); + _source.clear(); + _constant.clear(); + _modulo.clear(); + _transform.clear(); + + _function = "simulation_time"; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapAssignment::setTriggerCounterFunction(const std::string& strModulo) +{ + _from.clear(); + _source.clear(); + _constant.clear(); + _transform.clear(); + _function.clear(); + + _modulo = strModulo; + a_util::strings::trim(_modulo); + _function = "trigger_counter"; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapAssignment::setReceivedFunction(const std::string& strSource) +{ + _from.clear(); + _source.clear(); + _constant.clear(); + _modulo.clear(); + _transform.clear(); + + _source = strSource; + a_util::strings::trim(_source); + if(_source.empty()) + { + return ERR_INVALID_ARG; + } + _function = "received"; + return a_util::result::SUCCESS; +} + +const std::string& MapAssignment::getModulo() const +{ + return _modulo; +} + +const std::string& MapAssignment::getTo() const +{ + return _to; +} + +const std::string& MapAssignment::getTransformation() const +{ + return _transform; +} + +a_util::result::Result MapAssignment::setTransformation(const std::string& strTransformationName) +{ + _transform.clear(); + if(_source.empty()||_from.empty()) + { + return ERR_INVALID_ARG; + } + _transform = strTransformationName; + a_util::strings::trim(_transform); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapAssignment::removeTransformation() +{ + _transform.clear(); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapAssignment::loadFromDOM(const a_util::xml::DOMElement& oAssignment, MapErrorList& lstErrors) +{ + // parse attributes + const a_util::xml::DOMAttributes mapAttrs = oAssignment.getAttributes(); + // find target element + a_util::xml::DOMAttributes::const_iterator itAttrTo = mapAttrs.find("to"); + if (itAttrTo == mapAttrs.end() || itAttrTo->second.empty()) + { + lstErrors.push_back("Missing attribute for an "); + return ERR_INVALID_ARG; + } + _to = itAttrTo->second; + a_util::strings::trim(_to); + + // find Source or constant + a_util::xml::DOMAttributes::const_iterator itAttrFrom = mapAttrs.find("from"); + a_util::xml::DOMAttributes::const_iterator itAttrConst = mapAttrs.find("constant"); + a_util::xml::DOMAttributes::const_iterator itAttrFct = mapAttrs.find("function"); + if (itAttrFrom == mapAttrs.end() && itAttrConst == mapAttrs.end() && itAttrFct == mapAttrs.end()) + { + lstErrors.push_back(a_util::strings::format("Missing , or attribute for to '%s'", + itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + if (itAttrFrom != mapAttrs.end() && itAttrConst != mapAttrs.end()) + { + lstErrors.push_back(a_util::strings::format(" and attributes set at the same time for to '%s'", + itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + if (itAttrFrom != mapAttrs.end() && itAttrFct != mapAttrs.end()) + { + lstErrors.push_back(a_util::strings::format(" and attributes set at the same time for to '%s'", + itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + if (itAttrFct != mapAttrs.end() && itAttrConst != mapAttrs.end()) + { + lstErrors.push_back(a_util::strings::format(" and attributes set at the same time for to '%s'", + itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + + if (itAttrFrom != mapAttrs.end()) + { + if(itAttrFrom->second.empty()) + { + lstErrors.push_back(a_util::strings::format(" attribute empty for to '%s'", + itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + connect(itAttrFrom->second); + } + else if(itAttrConst != mapAttrs.end()) + { + if(isFailed(setConstant(itAttrConst->second))) + { + lstErrors.push_back(a_util::strings::format(" attribute empty for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + } + else + { + if(itAttrFct->second.empty()) + { + lstErrors.push_back(a_util::strings::format(" attribute empty for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + _function = itAttrFct->second; + + size_t nIdx1 = _function.find('('); + size_t nIdx2 = _function.find(')'); + if (nIdx1 == std::string::npos || nIdx2 == std::string::npos || + nIdx1 == 0 || nIdx2 == 0 || nIdx1 > nIdx2 + || !(_function.find("simulation_time") == 0 + || _function.find("trigger_counter") == 0 + || _function.find("received") == 0)) + { + lstErrors.push_back(a_util::strings::format(" should be of type 'simulation_time()', \ + 'trigger_counter([Modulo])' or 'received([Signal])' for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + + int64_t nLength = (int64_t)nIdx2 - (int64_t)nIdx1 - 1; + if(_function.find("simulation_time") == 0) + { + if(nLength > 0) + { + lstErrors.push_back(a_util::strings::format(" of type 'simulation_time()' takes no argument for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + setSimulationTimeFunction(); + } + if(_function.find("trigger_counter") == 0) + { + if(isFailed(setTriggerCounterFunction(_function.substr(nIdx1 + 1, (size_t)nLength)))) + { + lstErrors.push_back(a_util::strings::format(" of type 'trigger_counter()' takes a positive Integer as argument for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + } + else if(_function.find("received") == 0) + { + if(isFailed(setReceivedFunction(_function.substr(nIdx1 + 1, (size_t)nLength)))) + { + lstErrors.push_back(a_util::strings::format(" of type'received([Signal])' has no argument for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + } + } + + a_util::xml::DOMAttributes::const_iterator itAttr = mapAttrs.find("transformation"); + if (itAttr != mapAttrs.end() && !itAttr->second.empty()) + { + if(isFailed(setTransformation(itAttr->second))) + { + lstErrors.push_back(a_util::strings::format(" is only accepted for connection for \ + to '%s'", itAttrTo->second.c_str())); + return ERR_INVALID_ARG; + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapAssignment::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("assignment"); + oDOMElement.setAttribute("to", _to); + if(!_function.empty()) + { + std::string strDOMFunction = _function; + if(strDOMFunction == "simulation_time") + { + strDOMFunction.append("()"); + } + else if(strDOMFunction == "trigger_counter") + { + strDOMFunction.append(a_util::strings::format("(%s)", _modulo.c_str())); + } + else if(strDOMFunction == "received") + { + strDOMFunction.append(a_util::strings::format("(%s)", _source.c_str())); + } + oDOMElement.setAttribute("function", strDOMFunction); + } + else if(!_source.empty()) + { + std::string strDOMFrom = _source; + if(!_from.empty()) + { + strDOMFrom.push_back('.'); + strDOMFrom.append(_from); + } + oDOMElement.setAttribute("from", strDOMFrom); + if(!_transform.empty()) + { + oDOMElement.setAttribute("transformation", _transform); + } + } + else if(!_constant.empty()) + { + oDOMElement.setAttribute("constant", _constant); + } + return a_util::result::SUCCESS; +} diff --git a/mapping/configuration/map_assignment.h b/mapping/configuration/map_assignment.h new file mode 100644 index 0000000..0a5f795 --- /dev/null +++ b/mapping/configuration/map_assignment.h @@ -0,0 +1,194 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_ASSIGNMENT_H +#define HEADER_MAP_ASSIGNMENT_H + +#include "a_util/result.h" +#include "a_util/xml.h" + +namespace mapping +{ +namespace oo +{ + typedef std::vector MapErrorList; +/** + * MapAssignment + */ +class MapAssignment +{ +public: + /** + * CTOR + */ + MapAssignment(); + + /** + * CTOR + * @param [in] name Name of assigned signal or element + */ + MapAssignment(std::string to); + + /** + * Returns the validity for the current description + */ + bool isValid() const; + + /** + * Returns the source element name of the assignment (or an empty string) + */ + const std::string& getFrom() const; + + /** + * Returns the source name of the assignment (or an empty string) + */ + const std::string& getSource() const; + + /** + * Connects the target element or signal with a source + * @param [in] source_element_path The complete path to the source element + * it is constructed with [SignalName].[ElementName] + * @retval ERR_INVALID_ARG Source is empty + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result connect(const std::string& source_element_path); + + /** + * Returns the constant of the assignment (or an empty string) + */ + const std::string& getConstant() const; + + /** + * Setter for the constant of the assignment + * @param [in] constant The constant to assign + * @retval ERR_INVALID_ARG Constant is empty + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setConstant(const std::string& constant); + + /** + * Returns the constant of the assignment (or an empty string) + */ + const std::string& getFunction() const; + + /** + * Setter for the SimulationTime assignment + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setSimulationTimeFunction(); + + /** + * Setter for the TriggerCounter assignment + * @param [in] modulo The modulo for the function + * it represents the maximal value that can be assigned before going back to 0 + * if left empty, the limit will be the maximal value of Float64 + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setTriggerCounterFunction(const std::string& modulo); + + /** + * Setter for the Received assignment + * @param [in] source The name of the source to consider + * @retval ERR_INVALID_ARG Source is empty + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setReceivedFunction(const std::string& source); + + /** + * Returns the constant of the assignment (or an empty string) + */ + const std::string& getModulo() const; + + /** + * Returns the name of the target element that is assigned + */ + const std::string& getTo() const; + + /** + * Returns the associated transformation of this assignment (or an empty string) + */ + const std::string& getTransformation() const; + + /** + * Associates the transformation to this assignment + * @param [in] transformation_name The name of the transformation to add + * @retval ERR_INVALID_ARG Source or from is empty (no signal connected) + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setTransformation(const std::string& transformation_name); + + /** + * Remove the transformation from this assignment + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeTransformation(); + +private: + /** + * Initializes the assignment from a assignment-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] errors The error list for debug + * @retval ERR_INVALID_ARG Missing name or type + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOM(const a_util::xml::DOMElement& assignment, MapErrorList& errors); + + /** + * Export assignment to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + +private: + /// @cond nodoc + friend class MapConfiguration; + friend class MapTarget; + std::string _from; + std::string _source; + std::string _constant; + std::string _function; // "simulation_time" -> no args, "trigger_counter" -> arg in modulo, "received" -> arg in from + std::string _modulo; + std::string _to; + std::string _transform; + bool _is_valid; + /// @endcond +}; + +inline bool operator==(const MapAssignment& a, const MapAssignment& b) +{ + return a.getConstant() == b.getConstant() && a.getFrom() == b.getFrom() && + a.getSource() == b.getSource() && a.getTo() == b.getTo() && + a.getFunction() == b.getFunction() && a.getModulo() == b.getModulo() && + a.getTransformation() == b.getTransformation(); +} + +inline bool operator!=(const MapAssignment& a, const MapAssignment& b) +{ + return !(a == b); +} + +/// Public composite types used in the mapping::oo namespace +typedef std::vector MapAssignmentList; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_ASSIGNMENT_H diff --git a/mapping/configuration/map_configuration.cpp b/mapping/configuration/map_configuration.cpp new file mode 100644 index 0000000..e83d3f9 --- /dev/null +++ b/mapping/configuration/map_configuration.cpp @@ -0,0 +1,1282 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_configuration.h" + +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddlrepresentation/ddlelement.h" +#include "ddlrepresentation/ddlcomplex.h" +#include "ddlrepresentation/ddldatatype.h" + +#include "mapping/ddl_helper.h" + + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-9, ERR_INVALID_FLAGS) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-19, ERR_NOT_SUPPORTED) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) + _MAKE_RESULT(-40, ERR_INVALID_STATE) + _MAKE_RESULT(-42, ERR_INVALID_TYPE) +} +} + +using namespace mapping::oo; + +MapConfiguration::MapConfiguration() + : _ddl_ref(NULL) + , _checked_for_consistency(false) + , _is_consistent(false) +{ +} + +MapConfiguration::MapConfiguration(const ddl::DDLDescription* pDDL) + : _ddl_ref(pDDL) + , _checked_for_consistency(false) + , _is_consistent(false) +{ +} + +MapConfiguration::~MapConfiguration() +{ + reset(); +} + +MapConfiguration::MapConfiguration(const MapConfiguration& oOther) +{ + _ddl_ref = oOther._ddl_ref; + _header = oOther._header; + _sources = oOther._sources; + _targets = oOther._targets; + _checked_for_consistency = oOther._checked_for_consistency; + _is_consistent = oOther._is_consistent; + + for (MapTransformationList::const_iterator it = oOther._transforms.begin(); + it != oOther._transforms.end(); ++it) + { + _transforms.push_back((*it)->clone()); + } + + repairConfigReferences(*this); +} + +MapConfiguration& MapConfiguration::operator=(const MapConfiguration& oOther) +{ + MapConfiguration oCopy(oOther); + oCopy.swap(*this); + + return *this; +} + +void MapConfiguration::reset() +{ + _errors.clear(); + _header.reset(); + _sources.clear(); + _targets.clear(); + _checked_for_consistency = false; + _is_consistent = false; + + for (MapTransformationList::iterator it = _transforms.begin(); + it != _transforms.end(); ++it) + { + delete *it; + } + + _transforms.clear(); +} + +a_util::result::Result MapConfiguration::loadFromFile(const std::string& strFilePath, + uint32_t ui32Flags) +{ + a_util::xml::DOM oDom; + if(!oDom.load(strFilePath)) + { + appendError(oDom.getLastError()); + return ERR_INVALID_FILE; + } + return loadFromDOM(oDom, ui32Flags); +} + +a_util::result::Result MapConfiguration::loadFromDOM(a_util::xml::DOM& oDom, uint32_t ui32Flags) +{ + + bool bLoad = (ui32Flags & mc_load_mapping) == mc_load_mapping; + bool bMerge = (ui32Flags & mc_merge_mapping) == mc_merge_mapping; + // only one of them supported + if (!(bLoad | bMerge)) + { + return ERR_NOT_SUPPORTED; + } + + // Clear list and verify ddl description exists + resetErrors(); + + // we parse into a temporary config to be able to check for validity before + // overwriting/resetting the current configuration + MapConfiguration oTmp(_ddl_ref); + + if (isFailed(MapConfiguration::loadMappingFromDOM(oDom, oTmp))) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + + if (bLoad) + { + // check for consistency + if (isFailed(oTmp.checkMappingConsistency())) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + if (isFailed(oTmp.checkDDLConsistency())) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_INVALID_TYPE; + } + // the config should replace the current one -> swap + swap(oTmp); + } + else if (bMerge) + { + // since we allow partial mapping configurations, + // we need to merge before checking consistency + MapConfiguration oCopy(*this); + a_util::result::Result nResult = oCopy.merge(oTmp); + if (isOk(nResult)) + { + nResult = oCopy.checkMappingConsistency(); + } + if (isFailed(nResult)) + { + // preserve errors + std::swap(_errors, oCopy._errors); + return ERR_FAILED; + } + if (isFailed(oCopy.checkDDLConsistency())) + { + // preserve errors + std::swap(_errors, oCopy._errors); + return ERR_INVALID_TYPE; + } + // all ok? now we can swap + swap(oCopy); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::loadFromDOMWithoutDDLConsistency(a_util::xml::DOM& oDom, + uint32_t ui32Flags) +{ + bool bLoad = (ui32Flags & mc_load_mapping) == mc_load_mapping; + bool bMerge = (ui32Flags & mc_merge_mapping) == mc_merge_mapping; + // only one of them supported + if (!(bLoad | bMerge)) + { + return ERR_NOT_SUPPORTED; + } + + // Clear list + _errors.clear(); + + // we parse into a temporary config to be able to check for validity before + // overwriting/resetting the current configuration + MapConfiguration oTmp(_ddl_ref); + + if (isFailed(MapConfiguration::loadMappingFromDOM(oDom, oTmp))) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + + if (bLoad) + { + // check for consistency + if (isFailed(oTmp.checkMappingConsistency())) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + // the config should replace the current one -> swap + swap(oTmp); + } + else if (bMerge) + { + // since we allow partial mapping configurations, + // we need to merge before checking consistency + MapConfiguration oCopy(*this); + a_util::result::Result nResult = oCopy.merge(oTmp); + if (isOk(nResult)) + { + nResult = oCopy.checkMappingConsistency(); + } + if (isFailed(nResult)) + { + // preserve errors + std::swap(_errors, oCopy._errors); + return ERR_FAILED; + } + // all ok? now we can swap + swap(oCopy); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::loadPartiallyFromFile(const std::string& strFilePath, + uint32_t ui32Flags) +{ + a_util::xml::DOM oDom; + if(!oDom.load(strFilePath)) + { + appendError(oDom.getLastError()); + return ERR_INVALID_FILE; + } + + return loadPartiallyFromDOM(oDom, ui32Flags); +} + +a_util::result::Result MapConfiguration::loadPartiallyFromDOM(a_util::xml::DOM& oDom, + uint32_t ui32Flags) +{ + _errors.clear(); + + bool bLoad = (ui32Flags & mc_load_mapping) == mc_load_mapping; + bool bMerge = (ui32Flags & mc_merge_mapping) == mc_merge_mapping; + // only one of them supported + if (!(bLoad | bMerge)) + { + return ERR_INVALID_FLAGS; + } + + // we parse into a temporary config to be able to check for validity before + // overwriting/resetting the current configuration + MapConfiguration oTmp(_ddl_ref); + // IF is failed, map-file is corrupted + if (isFailed(MapConfiguration::loadMappingFromDOM(oDom, oTmp))) + { + // preserve errors + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + + a_util::result::Result nResult = a_util::result::SUCCESS; + if (bLoad) + { + // check for consistency + if (isFailed(oTmp.checkMappingConsistency())) + { + std::swap(_errors, oTmp._errors); + return ERR_FAILED; + } + //Check DDL consistency only to set the validity booleans + nResult = oTmp.checkDDLConsistency(); + // the config should replace the current one -> swap + swap(oTmp); + + } + else if (bMerge) + { + // since we allow partial mapping configurations, + // we need to merge before checking consistency + MapConfiguration oCopy(*this); + nResult = oCopy.merge(oTmp); + if (isOk(nResult)) + { + nResult = oCopy.checkMappingConsistency(); + } + if (isFailed(nResult)) + { + // preserve errors + std::swap(_errors, oCopy._errors); + return ERR_FAILED; + } + //Check DDL consistency only to set the validity booleans + nResult = oCopy.checkDDLConsistency(); + // all ok? now we can swap + swap(oCopy); + } + + return nResult; +} + +a_util::result::Result MapConfiguration::writeToFile(const std::string& strFilePath) +{ + a_util::xml::DOM oDom; + oDom.fromString(""); + + a_util::result::Result nRes = writeToDOM(oDom); + if(isOk(nRes)) + { + if(!oDom.save(strFilePath)) + { + appendError(oDom.getLastError()); + nRes = ERR_INVALID_FILE; + } + } + return nRes; +} + +a_util::result::Result MapConfiguration::writeToDOM(a_util::xml::DOM& oDom) +{ + resetErrors(); + + // Verify consistency + + RETURN_IF_FAILED(checkMappingConsistency()); + RETURN_IF_FAILED(checkDDLConsistency()); + + oDom.reset(); + a_util::xml::DOMElement oRoot = oDom.getRoot(); + + // set
+ a_util::xml::DOMElement oHeader = oRoot.createChild("header"); + RETURN_IF_FAILED(_header.writeToDOM(oHeader)); + + // set + a_util::xml::DOMElement oSourcesElement = oRoot.createChild("sources"); + for(MapSourceList::const_iterator itSrc = _sources.begin(); itSrc != _sources.end(); itSrc++) + { + a_util::xml::DOMElement oSourceElement = oSourcesElement.createChild("source"); + RETURN_IF_FAILED(itSrc->writeToDOM(oSourceElement)); + } + + // set + a_util::xml::DOMElement oTargetsElement = oRoot.createChild("targets"); + for(MapTargetList::const_iterator itTrg = _targets.begin(); itTrg != _targets.end(); itTrg++) + { + a_util::xml::DOMElement oTargetElement = oTargetsElement.createChild("target"); + RETURN_IF_FAILED(itTrg->writeToDOM(oTargetElement)); + } + + // set + a_util::xml::DOMElement oTransformationsElement = oRoot.createChild("transformations"); + for(MapTransformationList::const_iterator itTransform = _transforms.begin(); itTransform != _transforms.end(); itTransform++) + { + a_util::xml::DOMElement oTransformationElement = oTransformationsElement.createChild(""); + RETURN_IF_FAILED((*itTransform)->writeToDOM(oTransformationElement)); + } + + // the root element + oRoot.setName("mapping"); + return a_util::result::SUCCESS; +} + +const MapHeader& MapConfiguration::getHeader() const +{ + return _header; +} + +a_util::result::Result MapConfiguration::setHeaderDescription(const std::string& desc) +{ + return _header.setDescription(desc); +} + +a_util::result::Result MapConfiguration::setHeaderDdlPaths(const std::string& strDdl) +{ + return _header.setDdlPaths(strDdl); +} + +const std::string& MapConfiguration::getHeaderDdlPaths() const +{ + return _header.getDllPaths(); +} + +const MapTransformationList& MapConfiguration::getTransformationList() const +{ + return _transforms; +} + +const MapTransformationBase* MapConfiguration:: + getTransformation(const std::string& strTransformationName) const +{ + for (MapTransformationList::const_iterator it = _transforms.begin(); + it != _transforms.end(); ++it) + { + if ((*it)->getName() == strTransformationName) + { + return *it; + } + } + + return NULL; +} + +MapTransformationBase* MapConfiguration::getTransformation(const std::string& strTransformationName) +{ + for (MapTransformationList::iterator it = _transforms.begin(); + it != _transforms.end(); ++it) + { + if ((*it)->getName() == strTransformationName) + { + return *it; + } + } + return NULL; +} + + +a_util::result::Result MapConfiguration::addTransformation(const std::string& strTransformationName, const std::string& strTransformationType) +{ + if(getTransformation(strTransformationName)) + { + appendError("A transformation with this name already exists"); + return ERR_INVALID_ARG; + } + + MapTransformationBase* pTrans = NULL; + RETURN_IF_FAILED(MapTransformationBase::create(this, strTransformationName, strTransformationType, pTrans)); + _transforms.push_back(pTrans); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::removeTransformation(const std::string& strTransformationName) +{ + _errors.clear(); + if(strTransformationName.empty()) + { + return a_util::result::SUCCESS; + } + for(MapTransformationList::iterator itTrf = _transforms.begin(); itTrf != _transforms.end(); itTrf++) + { + if((*itTrf)->getName() == strTransformationName) + { + // Remove all assignments that use this transformation + for (MapTargetList::iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + // Copy from list to remove assignments form original list + // while iterating through the copy + MapAssignmentList oAssignList = it->getAssignmentList(); + for (MapAssignmentList::iterator itA = oAssignList.begin(); + itA != oAssignList.end(); ++itA) + { + if(itA->getTransformation() == strTransformationName) + { + RETURN_IF_FAILED(it->removeAssignmentWithoutClear(itA->getTo())); + } + } + } + delete *itTrf; + _transforms.erase(itTrf); + return a_util::result::SUCCESS; + } + } + return ERR_NOT_FOUND; +} + + +const MapSource* MapConfiguration::getSource(const std::string& strSourceName) const +{ + for (MapSourceList::const_iterator it = _sources.begin(); + it != _sources.end(); ++it) + { + if (it->getName() == strSourceName) + { + return &(*it); + } + } + + return NULL; +} + +MapSource* MapConfiguration::getSource(const std::string& strSourceName) +{ + for (MapSourceList::iterator it = _sources.begin(); + it != _sources.end(); ++it) + { + if (it->getName() == strSourceName) + { + return &(*it); + } + } + + return NULL; +} + +a_util::result::Result MapConfiguration::addSource(const std::string& name, const std::string& strType) +{ + RETURN_IF_FAILED(resetErrors()); + RETURN_IF_FAILED(checkSignalType(strType)); + MapSource oSource(this, name, strType); + return addSource(oSource); +} + +a_util::result::Result MapConfiguration::removeSource(const std::string& name) +{ + _errors.clear(); + for (MapTargetList::iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + // Copy from list to remove assignments form original list + // while iterating through the copy + MapAssignmentList oAssignList = it->getAssignmentList(); + for (MapAssignmentList::iterator itA = oAssignList.begin(); + itA != oAssignList.end(); ++itA) + { + if(itA->getSource() == name) + { + RETURN_IF_FAILED(it->removeAssignmentWithoutClear(itA->getTo())); + } + } + // Copy from list to remove triggers form original list + // while iterating through the copy + MapTriggerList oTriggerList = it->getTriggerList(); + for (MapTriggerList::iterator itTrigger = oTriggerList.begin(); + itTrigger != oTriggerList.end(); ++itTrigger) + { + if((*itTrigger)->getSourceDependency() == name) + { + RETURN_IF_FAILED(it->removeTrigger(*itTrigger)); + } + } + } + for (MapSourceList::iterator it = _sources.begin(); + it != _sources.end(); ++it) + { + if (it->getName() == name) + { + _sources.erase(it); + return a_util::result::SUCCESS; + } + } + return ERR_NOT_FOUND; +} + +const MapSourceList& MapConfiguration::getSourceList() const +{ + return _sources; +} + +const MapTarget* MapConfiguration::getTarget(const std::string& strTargetName) const +{ + for (MapTargetList::const_iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + if (it->getName() == strTargetName) + { + return &(*it); + } + } + + return NULL; +} + +MapTarget* MapConfiguration::getTarget(const std::string& strTargetName) +{ + for (MapTargetList::iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + if (it->getName() == strTargetName) + { + return &(*it); + } + } + + return NULL; +} + +a_util::result::Result MapConfiguration::addTarget(const std::string& name, const std::string& strType) +{ + RETURN_IF_FAILED(resetErrors()); + RETURN_IF_FAILED(checkSignalType(strType)); + MapTarget oTarget(this, name, strType); + return addTarget(oTarget); +} + +a_util::result::Result MapConfiguration::removeTarget(const std::string& _name) +{ + _errors.clear(); + for (MapTargetList::iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + if (it->getName() == _name) + { + _targets.erase(it); + return a_util::result::SUCCESS; + } + } + return ERR_NOT_FOUND; +} + +const MapTargetList& MapConfiguration::getTargetList() const +{ + return _targets; +} + +a_util::result::Result MapConfiguration::setDescription(const ddl::DDLDescription* pDDL) +{ + _ddl_ref = pDDL; + MapConfiguration oCopy = *this; + oCopy._ddl_ref = pDDL; + // reset mapping configuration if we got a ddl that doesn't fit to the current mapping config + if (isFailed(oCopy.checkDDLConsistency())) + { + reset(); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::setDescriptionWithoutConsistency(const ddl::DDLDescription* pDDL) +{ + _ddl_ref = pDDL; + _checked_for_consistency = false; + _is_consistent = false; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::modifyDescription(const ddl::DDLDescription* pDDL) +{ + _ddl_ref = pDDL; + _errors.clear(); + return checkDDLConsistency(); +} + +const ddl::DDLDescription* MapConfiguration::getDescription() const +{ + return _ddl_ref; +} + +const MapErrorList& MapConfiguration::getErrorList() const +{ + return _errors; +} + +a_util::result::Result MapConfiguration::resetErrors() +{ + _errors.clear(); + if (!_ddl_ref) + { + appendError("No Description found"); + return ERR_INVALID_STATE; + } + return a_util::result::SUCCESS; +} + +void MapConfiguration::swap(MapConfiguration& oOther) +{ + using std::swap; + swap(_ddl_ref, oOther._ddl_ref); + swap(_header, oOther._header); + swap(_sources, oOther._sources); + swap(_targets, oOther._targets); + swap(_transforms, oOther._transforms); + swap(_errors, oOther._errors); + repairConfigReferences(*this); + repairConfigReferences(oOther); +} + +void MapConfiguration::repairConfigReferences(MapConfiguration& oConfig) +{ + // Sources + for(MapSourceList::iterator itSrc = oConfig._sources.begin(); itSrc != oConfig._sources.end(); itSrc++) + { + itSrc->_config = &oConfig; + } + + // Targets + for(MapTargetList::iterator itTrg = oConfig._targets.begin(); itTrg != oConfig._targets.end(); itTrg++) + { + itTrg->_config = &oConfig; + for(MapTriggerList::iterator itTrigger = itTrg->_triggers.begin(); itTrigger != itTrg->_triggers.end(); itTrigger++) + { + (*itTrigger)->_config = &oConfig; + } + } + // Transformations + for(MapTransformationList::iterator itTrf = oConfig._transforms.begin(); itTrf != oConfig._transforms.end(); itTrf++) + { + (*itTrf)->_config = &oConfig; + } +} + +a_util::result::Result MapConfiguration::addTarget(const MapTarget& oTarget) +{ + RETURN_IF_FAILED(checkSignalName(oTarget.getName())); + _targets.push_back(oTarget); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::addSource(const MapSource& oSource) +{ + RETURN_IF_FAILED(checkSignalName(oSource.getName())); + _sources.push_back(oSource); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::merge(const MapConfiguration& oOther) +{ + MapConfiguration oCopy(*this); + + const MapSourceList& lstSources = oOther.getSourceList(); + for (MapSourceList::const_iterator it = lstSources.begin(); + it != lstSources.end(); ++it) + { + const MapSource* pSrc = getSource(it->getName()); + if (pSrc) + { + if (*pSrc != *it) + { + appendError(a_util::strings::format( + "Trying to merge conflicting source definition for '%s'", + it->getName().c_str())); + return ERR_INVALID_ARG; + } + } + else + { + RETURN_IF_FAILED(oCopy.addSource(*it)); + } + } + + const MapTargetList& lstTargets = oOther.getTargetList(); + for (MapTargetList::const_iterator it = lstTargets.begin(); + it != lstTargets.end(); ++it) + { + const MapTarget* pTarget = getTarget(it->getName()); + if (pTarget) + { + if (*pTarget != *it) + { + appendError(a_util::strings::format( + "Trying to merge conflicting target definition for '%s'", + it->getName().c_str())); + return ERR_INVALID_ARG; + } + } + else + { + RETURN_IF_FAILED(oCopy.addTarget(*it)); + } + } + + const MapTransformationList& lstTrafos = oOther.getTransformationList(); + for (MapTransformationList::const_iterator it = lstTrafos.begin(); + it != lstTrafos.end(); ++it) + { + const MapTransformationBase* pSrc = getTransformation((*it)->getName()); + if (pSrc) + { + if (!pSrc->isEqual(*(*it))) + { + appendError(a_util::strings::format( + "Trying to merge conflicting transformation definition for '%s'", + (*it)->getName().c_str())); + return ERR_INVALID_ARG; + } + } + else + { + oCopy._transforms.push_back((*it)->clone()); + } + } + + swap(oCopy); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::loadMappingFromDOM(a_util::xml::DOM& oDom, MapConfiguration& oTmpConfig) +{ + a_util::result::Result nResult = a_util::result::SUCCESS; + + // the root element + a_util::xml::DOMElement oMapping = oDom.getRoot(); + if (oMapping.getName() != "mapping") + { + oTmpConfig.appendError("Missing root element"); + return ERR_INVALID_ARG; // no need to continue + } + + // parse
+ a_util::xml::DOMElement oElement = oMapping.getChild("header"); + if (!oElement.isNull()) + { + nResult = oTmpConfig._header.loadFromDOM(oElement, oTmpConfig._errors); + } + else + { + oTmpConfig.appendError("Missing
element"); + nResult = ERR_INVALID_ARG; + } + + // parse + oElement = oMapping.getChild("sources"); + if (!oElement.isNull()) + { + const a_util::xml::DOMElementList lstSources = oElement.getChildren(); + for (a_util::xml::DOMElementList::const_iterator it = lstSources.begin(); + it != lstSources.end(); ++it) + { + if (it->getName() == "source") + { + MapSource oSrc(&oTmpConfig); + a_util::result::Result nRes = oSrc.loadFromDOM(*it); + if (isOk(nRes)) + { + nRes = oTmpConfig.addSource(oSrc); + } + if (isFailed(nRes)) + { + nResult = nRes; + } + } + } + } + else + { + // optional + } + + // parse + oElement = oMapping.getChild("targets"); + if (!oElement.isNull()) + { + const a_util::xml::DOMElementList lstTargets = oElement.getChildren(); + for (a_util::xml::DOMElementList::const_iterator it = lstTargets.begin(); + it != lstTargets.end(); ++it) + { + MapTarget oTarget(&oTmpConfig); + a_util::result::Result nRes = oTarget.loadFromDOM(*it); + if (isOk(nRes)) + { + nRes = oTmpConfig.addTarget(oTarget); + } + if (isFailed(nRes)) + { + nResult = nRes; + } + } + } + else + { + // optional + } + + // parse + oElement = oMapping.getChild("transformations"); + if (!oElement.isNull()) + { + const a_util::xml::DOMElementList lstTrans = oElement.getChildren(); + for (a_util::xml::DOMElementList::const_iterator it = lstTrans.begin(); + it != lstTrans.end(); ++it) + { + MapTransformationBase* pTrans = NULL; + a_util::result::Result nRes = MapTransformationBase::createFromDOM(&oTmpConfig, + *it, pTrans); + if(isOk(nRes)) + { + oTmpConfig._transforms.push_back(pTrans); + } + else + { + nResult = nRes; + } + } + } + else + { + // optional + } + return nResult; +} + +a_util::result::Result MapConfiguration::checkMappingConsistency() +{ + a_util::result::Result nResult =a_util::result::SUCCESS; + // If import was succesful, check if the mapping is consistent + // All referenced Sources and Transformations must exist in Mapping + if(isOk(nResult)) + { + for(MapTargetList::const_iterator itTrg = _targets.begin(); + itTrg != _targets.end(); itTrg++) + { + for(MapTriggerList::const_iterator itTrigger = itTrg->getTriggerList().begin(); + itTrigger != itTrg->getTriggerList().end(); itTrigger++) + { + if(isFailed((*itTrigger)->checkTriggerReferences())) + { + nResult = ERR_INVALID_ARG; + } + } + for(MapAssignmentList::const_iterator itAssign = itTrg->getAssignmentList().begin(); + itAssign != itTrg->getAssignmentList().end(); itAssign++) + { + if(isFailed(checkAssignmentReferences(*itAssign))) + { + nResult = ERR_INVALID_ARG; + } + } + } + } + return nResult; +} + +a_util::result::Result MapConfiguration::checkDDLConsistency() +{ + a_util::result::Result nRes = a_util::result::SUCCESS; + // Sources + for (MapSourceList::iterator itSource = _sources.begin(); + itSource != _sources.end(); ++itSource) + { + if(isOk(checkSignalType(itSource->getType()))) + { + itSource->_is_valid = true; + } + else + { + itSource->_is_valid = false; + nRes = ERR_INVALID_TYPE; + } + } + + // Targets + for (MapTargetList::iterator itTarget = _targets.begin(); + itTarget != _targets.end(); ++itTarget) + { + if(isOk(checkSignalType(itTarget->getType()))) + { + itTarget->_is_valid = true; + + // Check Assignments type + const ddl::DDLComplex* pTargetStruct = + _ddl_ref->getStructByName(itTarget->getType()); + for (MapAssignmentList::iterator itAssign = itTarget->_assignments.begin(); + itAssign != itTarget->_assignments.end(); ++itAssign) + { + // Signal type was checked before, so pTargetStruct can be derefenrenced + if(isOk(checkAssignmentType(itTarget->getName(), *pTargetStruct, *itAssign))) + { + itAssign->_is_valid = true; + } + else + { + itAssign->_is_valid = false; + nRes = ERR_INVALID_TYPE; + } + } + + // Set overlapping assignments to invalid + a_util::result::Result nResDouble = itTarget->checkDoubleAssignments(); + if(isFailed(nResDouble)) + { + nRes = nResDouble; + } + + // Triggers + MapTriggerList& lstTrg = itTarget->_triggers; + for (MapTriggerList::iterator itTriggers = lstTrg.begin(); + itTriggers != lstTrg.end(); ++itTriggers) + { + if(isOk(checkTriggerType(*itTriggers))) + { + (*itTriggers)->_is_valid = true; + } + else + { + (*itTriggers)->_is_valid = false; + nRes = ERR_INVALID_TYPE; + } + } + } + else + { + itTarget->_is_valid = false; + nRes = ERR_INVALID_TYPE; + } + } + + // Transformations + for(MapTransformationList::iterator itTrf = _transforms.begin(); itTrf != _transforms.end(); itTrf++) + { + a_util::result::Result nResTrf = (*itTrf)->setTypeFromDDL(); + if(isOk(nResTrf)) + { + (*itTrf)->_is_valid = true; + } + else + { + (*itTrf)->_is_valid = false; + nRes = nResTrf; + } + } + if (isOk(nRes)) + { + _is_consistent = true; + } + _checked_for_consistency = true; + return nRes; +} + +a_util::result::Result MapConfiguration::findTypeObject(const std::string& strStruct, + const std::string& strPath, const ddl::IDDLDataType*& pType, + int& nArraySize) const +{ + const ddl::DDLComplex* pStruct = _ddl_ref->getStructByName(strStruct); + if (pStruct) + { + return findTypeObject(*pStruct, strPath, pType, nArraySize); + } + + return ERR_NOT_FOUND; +} + +a_util::result::Result MapConfiguration::findTypeObject(const ddl::DDLComplex& oStruct, + const std::string& strPath, const ddl::IDDLDataType*& pType, + int& nArraySize) const +{ + const ddl::DDLElement* pElem = NULL; + bool bIsArrayElement = false; + if (isFailed(DDLHelper::LookupElement(oStruct, strPath, pElem, bIsArrayElement))) + { + return ERR_NOT_FOUND; + } + if (pElem->isDynamic()) + { + return ERR_INVALID_TYPE; + } + + pType = pElem->getTypeObject(); + nArraySize = pElem->getArraysize(); + if (bIsArrayElement) + { + nArraySize = 1; + } + + return a_util::result::SUCCESS; +} + +bool MapConfiguration::checkTypeCompatibility(const ddl::IDDLDataType& oSource, + int nSourceArrSize, const ddl::IDDLDataType& oTarget, int nTargetArrSize) const +{ + const ddl::DDLComplex* pSourceStruct = dynamic_cast(&oSource); + const ddl::DDLComplex* pTargetStruct = dynamic_cast(&oTarget); + + if (pSourceStruct) + { + if (!pTargetStruct || pSourceStruct->getName() != pTargetStruct->getName()) + { + return false; + } + } + + if (pTargetStruct && !pSourceStruct) + { + return false; + } + + if (nSourceArrSize != nTargetArrSize) + { + return false; + } + + return true; +} + +a_util::result::Result MapConfiguration::checkSignalName(const std::string& name) const +{ + if(name.empty()) + { + return ERR_INVALID_ARG; + } + std::set lstSignalName; + for(MapSourceList::const_iterator it = _sources.begin(); it != _sources.end(); it++) + { + lstSignalName.insert(it->getName()); + } + for(MapTargetList::const_iterator it = _targets.begin(); it != _targets.end(); it++) + { + lstSignalName.insert(it->getName()); + } + if(lstSignalName.find(name) != lstSignalName.end()) + { + appendError(a_util::strings::format("A signal with the name '%s' already exists", + name.c_str())); + return ERR_INVALID_ARG; + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapConfiguration::checkSignalType(const std::string& strType) const +{ + a_util::result::Result nRes= a_util::result::SUCCESS; + // Is the type defined in DDL + if (!_ddl_ref||!_ddl_ref->getStructByName(strType)) + { + appendError( + a_util::strings::format("Unknown type '%s'", + strType.c_str())); + nRes = ERR_INVALID_TYPE; + } + return nRes; +} + +a_util::result::Result MapConfiguration::checkAssignmentReferences(const MapAssignment& oAssignment) const +{ + a_util::result::Result nRes = a_util::result::SUCCESS; + // Is the transformation known? + if (!oAssignment.getTransformation().empty() && + !getTransformation(oAssignment.getTransformation())) + + { + appendError(a_util::strings::format( + "Unknown '%s' in '%s'", + oAssignment.getTransformation().c_str(), oAssignment.getTo().c_str())); + nRes = ERR_INVALID_ARG; + } + // Is the source known? + if (!oAssignment.getSource().empty()&&!getSource(oAssignment.getSource())) + { + appendError( + a_util::strings::format("Unknown '%s' in '%s'", + oAssignment.getSource().c_str(), oAssignment.getTo().c_str())); + nRes = ERR_INVALID_ARG; + } + return nRes; +} + +a_util::result::Result MapConfiguration::checkAssignmentType(const std::string& strSignalName, const ddl::DDLComplex& oSignalStruct, const MapAssignment& oAssignment) const +{ + a_util::result::Result nRes= a_util::result::SUCCESS; + const std::string& strTo = oAssignment.getTo(); + + // Are From&To known in DDL and not dynamic? + int nArrSizeTo = 1; + const ddl::IDDLDataType* pTypeTo = NULL; + a_util::result::Result res = findTypeObject(oSignalStruct, strTo, pTypeTo, nArrSizeTo); + if (res == ERR_NOT_FOUND) + { + appendError( + a_util::strings::format("Target element '%s' unknown or invalid in '%s'", + strTo.c_str(), strSignalName.c_str())); + nRes = ERR_INVALID_TYPE; + } + if (res == ERR_INVALID_TYPE) + { + appendError( + a_util::strings::format("Dynamic target elements are not allowed: '%s' in '%s'", + strTo.c_str(), strSignalName.c_str())); + nRes = ERR_INVALID_TYPE; + } + + // find Type for assigned value + const ddl::IDDLDataType* pTypeFrom = NULL; + int nArrSizeFrom = 1; + // If it is a received function, type must be bool + if(oAssignment.getFunction() == "received") + { + pTypeFrom = _ddl_ref->getDataTypeByName("tBool"); + } + else if (!oAssignment.getSource().empty()) + { + const MapSource* pSrcInstance = getSource(oAssignment.getSource()); + const std::string& strFrom = oAssignment.getFrom(); + if (!strFrom.empty()) // its a regular field assignment + { + if (isFailed(findTypeObject(pSrcInstance->getType(), strFrom, + pTypeFrom, nArrSizeFrom))) + { + appendError(a_util::strings::format( + "Source element '%s' unknown or invalid for to '%s' in '%s'", + strFrom.c_str(), strTo.c_str(), strSignalName.c_str())); + nRes = ERR_INVALID_TYPE; + } + } + else // its a whole signal assignment + { + // use source type for whole signal assignment + pTypeFrom = _ddl_ref->getStructByName(pSrcInstance->getType()); + } + } + else // its a constant, a simulation_time or a trigger_counter + { + pTypeFrom = _ddl_ref->getDataTypeByName("tUInt64"); + } + + // Are From/Constant -> To type-compatible? + if (!checkTypeCompatibility(*pTypeFrom, nArrSizeFrom, *pTypeTo, nArrSizeTo)) + { + appendError(a_util::strings::format("Incompatible types for to '%s' in '%s'", + strTo.c_str(), strSignalName.c_str())); + nRes = ERR_INVALID_TYPE; + } + + return nRes; +} + + +a_util::result::Result MapConfiguration::checkTriggerType(const MapTriggerBase* pTrigger) const +{ + const oo::MapDataTrigger* pMapDTrigger = + dynamic_cast(pTrigger); + if(pMapDTrigger) + { + const MapSource* pSrcInstance = getSource(pMapDTrigger->getSource()); + const ddl::IDDLDataType* pTypeVar = NULL; + int nArrSizeVar = 1; + if (isFailed(findTypeObject(pSrcInstance->getType(), pMapDTrigger->getVariable(), + pTypeVar, nArrSizeVar))) + { + appendError(a_util::strings::format( + "Source element '%s' type unknown or invalid for data source '%s'", + pMapDTrigger->getVariable().c_str(), pMapDTrigger->getSource().c_str())); + return ERR_INVALID_TYPE; + } + + const ddl::IDDLDataType* pTypeFrom = _ddl_ref->getDataTypeByName("tFloat64"); + // Are Value -> Variable type-compatible? + if (!checkTypeCompatibility(*pTypeFrom, 1, *pTypeVar, nArrSizeVar)) + { + appendError(a_util::strings::format("Data variable '%s' in '%s' should be comparable to a float value", + pMapDTrigger->getVariable().c_str(), pMapDTrigger->getSource().c_str())); + return ERR_INVALID_TYPE; + } + } + return a_util::result::SUCCESS; +} + +void MapConfiguration::appendError(const std::string& m_strError) const +{ + _errors.push_back(m_strError); +} + +bool MapConfiguration::isConsistencyChecked() +{ + return _checked_for_consistency; +} + +bool MapConfiguration::isConsistent() +{ + return _is_consistent; +} diff --git a/mapping/configuration/map_configuration.h b/mapping/configuration/map_configuration.h new file mode 100644 index 0000000..730a417 --- /dev/null +++ b/mapping/configuration/map_configuration.h @@ -0,0 +1,577 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_CONFIGURATION_H +#define HEADER_MAP_CONFIGURATION_H + +#include +#include "a_util/result.h" + +#include "ddlrepresentation/ddldescription.h" +#include "ddlrepresentation/ddldatatype_intf.h" + +#include "map_header.h" +#include "map_source.h" +#include "map_transformation.h" +#include "map_assignment.h" +#include "map_trigger.h" +#include "map_target.h" + +namespace mapping +{ +namespace oo +{ + typedef std::vector MapErrorList; +/** + * MapConfiguration is the central class of the mapping::oo namespace. + * It represents a whole mapping configuration which can be imported from + * a mapping configuration file. + */ +class MapConfiguration +{ +public: // methods + /// Mapping import flags (\ref loadFromFile, \ref loadFromDOM) + enum MapConfigFlags + { + // replace the existing configuration + mc_load_mapping = 0x1 << 0, + + // merge any new configuration into the current one + // (error on conflicting configuration) + mc_merge_mapping = 0x1 << 1 + }; + + /** + * CTOR + */ + MapConfiguration(); + + /** + * CTOR + * @param [in] ddl The DDL information base used for type lookup + */ + MapConfiguration(const ddl::DDLDescription* ddl); + + /** + * DTOR + */ + ~MapConfiguration(); + + /** + * C-CTOR + */ + MapConfiguration(const MapConfiguration& other); + + /** + * Assignment operator + */ + MapConfiguration& operator=(const MapConfiguration& other); + + /** + * Set the reference ddl description + * + * @param [in] ddl The DDL information base used for type lookup + * @note This call implies an internal Reset call, the configuration is reset + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDescription(const ddl::DDLDescription* ddl); + + /** + * Set the reference ddl description without consistency check + * + * @param [in] ddl The DDL information base used for type lookup + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDescriptionWithoutConsistency(const ddl::DDLDescription* ddl); + + /** + * Modify the reference ddl description + * Set the new ddl description and check mapping consistency + * + * @param [in] ddl The DDL information base used for type lookup + * @note This call does not imply a internal Reset call + * @retval ERR_INVALID_TYPE Configuration is inconsistent with ddl, mapping validity updated + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result modifyDescription(const ddl::DDLDescription* ddl); + + /** + * Get the reference ddl description + */ + const ddl::DDLDescription* getDescription() const; + + /** + * Resets the entire map configuration to its initial, empty state + * \note The ddl description remains untouched by this + * @returns Nothing but doxygen won't shut up if I dont write anything here + */ + void reset(); + + /** + * Import mapping configuration from a file + * Load file in DOM and call loadFromDOM() + * + * @param [in] file_path The file path to the configuration file + * @param [in] flags Options for loading. See \ref MapConfigFlags + * + * @retval ERR_INVALID_FILE DOM Import from file failed + * (see error list for details) + * @retval see loadFromDOM() + */ + a_util::result::Result loadFromFile(const std::string& file_path, + uint32_t flags = mc_load_mapping); + + /** + * Import mapping configuration from a XML dom instance + * + * @param [in] dom The dom instance from which to import + * @param [in] flags Options for loading. See \ref MapConfigFlags + * + * @retval ERR_INVALID_FLAGS Invalid flag combination + * @retval ERR_INVALID_STATE No description found + * @retval ERR_FAILED Configuration file is invalid + * (see error list for details) + * @retval ERR_INVALID_TYPE Configuration uses unknown DDL types + * (see error list for details) + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOM(a_util::xml::DOM& dom, + uint32_t flags = mc_load_mapping); + + /** + * Import mapping configuration from a XML dom instance without checking for DDL consistency + * + * @param [in] dom The dom instance from which to import + * @param [in] flags Options for loading. See \ref MapConfigFlags + * + * @retval ERR_INVALID_FLAGS Invalid flag combination + * @retval ERR_FAILED Configuration file is invalid + * (see error list for details) + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOMWithoutDDLConsistency(a_util::xml::DOM& dom, + uint32_t flags = mc_load_mapping); + + /** + * Import mapping configuration from a file + * Load file in DOM and call loadPartiallyFromDOM() + * Modell is loaded even if it is not consistent with the DDL description + * Each element has a validity flag representing its consistency + * + * @param [in] file_path The file path to the configuration file + * @param [in] flags Options for loading. See \ref MapConfigFlags + * + * @retval ERR_INVALID_FILE DOM Import from file failed + * (see error list for details) + * @retval see loadPartiallyFromDOM() + */ + a_util::result::Result loadPartiallyFromFile(const std::string& file_path, + uint32_t flags = mc_load_mapping); + + /** + * Import mapping configuration from a XML dom instance + * Modell is laoding even if it is not consistent with the DDL description + * Each element has a validity flag representing its consistency + * + * @param [in] dom The dom instance from which to import + * @param [in] flags Options for loading. See \ref MapConfigFlags + * + * @retval ERR_INVALID_FLAGS Invalid flag combination + * @retval ERR_FAILED Configuration file is invalid + * (see error list for details) + * @retval ERR_INVALID_TYPE Configuration uses unknown DDL types + * (see error list for details) + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadPartiallyFromDOM(a_util::xml::DOM& dom, + uint32_t flags = mc_load_mapping); + + /** + * Export mapping configuration to a file + * Call writeToDOM() and wirte DOM to file + * + * @param [in] file_path The file path to the configuration file + * @retval ERR_INVALID_FILE Can not write in file + * (see error list for details) + * @retval see writeToDOM() + */ + a_util::result::Result writeToFile(const std::string& file_path); + + /** + * Export mapping configuration to a XML dom instance + * + * @param [in] dom The dom instance from which to import + * @retval ERR_INVALID_STATE No description found + * @retval ERR_FAILED Configuration is invalid + * (see error list for details) + * @retval ERR_INVALID_TYPE Configuration uses unknown DDL types + * (see error list for details) + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOM& dom); + + /** + * Returns the mapping header of the configuration + */ + const MapHeader& getHeader() const; + + /** + * Set the description in configuration header + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setHeaderDescription(const std::string& desc); + + /** + * Set the ddl paths attribute in configuration header + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setHeaderDdlPaths(const std::string& ddl_path); + + /** + * Get the ddl paths attribute from configuration header + */ + const std::string& getHeaderDdlPaths() const; + + /** + * Returns all transformations contained in the configuration + */ + const MapTransformationList& getTransformationList() const; + + /** + * Returns a specific transformation from the configuration + * + * @param [in] transformation_name The name of the transformation + * + * @retval The requested transformation base instance pointer + * @retval NULL if no transformation instance was found with that name + */ + const MapTransformationBase* getTransformation( + const std::string& transformation_name) const; + + /** + * Returns a specific transformation from the configuration + * + * @param [in] transformation_name The name of the transformation + * + * @retval The requested transformation base instance pointer + * @retval NULL if no transformation instance was found with that name + */ + MapTransformationBase* getTransformation( + const std::string& transformation_name); + + /** + * Add a transformation to use in mapping + * @param [in] transformation_name The transformation name + * @param [in] transformation_type The transformation type + * can be "Periodic", "Signal" or "Data" + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTransformation(const std::string& transformation_name, const std::string& transformation_type); + + /** + * Remove a transformation + * @param [in] transformation_name The transformation name + * @retval ERR_NOT_FOUND Transformation not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeTransformation(const std::string& transformation_name); + + /** + * Returns a specific mapping source from the configuration + * + * @param [in] source_name The name of the source + * + * @retval The requested source instance pointer + * @retval NULL if no source instance was found with that name + */ + const MapSource* getSource(const std::string& source_name) const; + + /** + * Returns a specific mapping source from the configuration + * + * @param [in] source_name The name of the source + * + * @retval The requested source instance pointer + * @retval NULL if no source instance was found with that name + */ + MapSource* getSource(const std::string& source_name); + + /** + * Returns all mapping sources contained in the configuration + */ + const MapSourceList& getSourceList() const; + + /** + * Add a source signal to use in mapping + * @param [in] name The name of the source + * @param [in] type The type of the source + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addSource(const std::string& name, const std::string& type); + + /** + * Remove a source signal from the configuration + * All connections using this source will be deleted + * @param [in] name The name of the target + * @retval ERR_NOT_FOUND Source not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeSource(const std::string& name); + + /** + * Returns a specific mapping target from the configuration + * + * @param [in] target_name The name of the target + * + * @retval The requested target instance pointer + * @retval NULL if no target instance was found with that name + */ + const MapTarget* getTarget(const std::string& target_name) const; + + /** + * Returns a specific mapping target from the configuration + * + * @param [in] target_name The name of the target + * + * @retval The requested target instance pointer + * @retval NULL if no target instance was found with that name + */ + MapTarget* getTarget(const std::string& target_name); + + /** + * Add a target signal to use in mapping + * @param [in] name The name of the target + * @param [in] type The type of the target + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTarget(const std::string& name, const std::string& type); + + /** + * Remove a target signal from the configuration + * All connections using this source will be deleted + * @param [in] name The name of the target + * @retval ERR_NOT_FOUND Target not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeTarget(const std::string& name); + + /** + * Returns all mapping targets contained in the configuration + */ + const MapTargetList& getTargetList() const; + + /** + * Returns the error list, containing human readable error messages. + * @note The error list is filled by \ref loadFromFile and \ref loadFromDOM + * and is reset on every call + * @returns Const reference to the error list + */ + const MapErrorList& getErrorList() const; + + /** + * Clear error list and verify DDL Description exists + * @retval ERR_INVALID_STATE No description found + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result resetErrors(); + + /** + * Append error to error list + **/ + void appendError(const std::string& error_string) const; + + /** + * Returns bool flag indicating whether consistency of mapping with its DDL was already checked + * @return Bool flag indicating whether consistency was checked + */ + bool isConsistencyChecked(); + + /** + * Returns bool flag indicating consistency of mapping with its DDL + * @return Bool flag indicating consistency + */ + bool isConsistent(); + + /** + * Checks the configuration for consistency with ddl representation + * (all types, transformations etc. are known and present & many other problems) + * @retval ERR_INVALID_TYPE Configuration is inconsistent with ddl, + * error list is populated and validity flags are set + * @retval a_util::result::SUCCESS Everything went fine, configuration is consistent + */ + a_util::result::Result checkDDLConsistency(); + +private: + /** + * swap implementation for use in the assignment op + */ + void swap(MapConfiguration& other); + + /** + * Set reference to new configuration + * @param [in] config The configuration to reference + */ + void repairConfigReferences(MapConfiguration& config); + + /** + * Import mapping configuration from a XML dom instance + * + * @param [in] dom The dom instance from which to import + * @param [out] tmp_config The temporary configuration to create + * @retval ERR_INVALID_ARG DOM does not contains a valid mapping + * @retval a_util::result::SUCCESS Everything went fine + **/ + static a_util::result::Result loadMappingFromDOM(a_util::xml::DOM& dom, MapConfiguration& tmp_config); + + /** + * Add a target signal to configuration + * @param [in] target The target signal + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTarget(const MapTarget& target); + + /** + * Add a source signal to configuration + * @param [in] source The source signal + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addSource(const MapSource& source); + + /** + * Checks the mapping for consistency + * All referenced Sources and Transformations must exist in Mapping + * @retval ERR_INVALID_ARG Unknown source or transformation is used + * @retval a_util::result::SUCCESS Everything went fine, configuration is consistent + */ + a_util::result::Result checkMappingConsistency(); + + /** + * merge another configuration into this one + * @param [in] other The other instance to be merged + * @retval ERR_INVALID_ARG Type conflict + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result merge(const MapConfiguration& other); + + /** + * find a DDL data type within a struct given a path to the element + * + * @param [in] struct_name Name of the struct type + * @param [in] path Path to be found + * @param [out] type Destination type parameter + * @param [out] array_size Destination array size parameter + * @retval ERR_NOT_FOUND The path is invalid or the type was not found + * @retval ERR_INVALID_TYPE Uses dynamic type + * @retval a_util::result::SUCCESS The type was found, type and array_size are filled + */ + a_util::result::Result findTypeObject(const std::string& struct_name, const std::string& + path, const ddl::IDDLDataType*& type, int& array_size) const; + + /** + * @overload + */ + a_util::result::Result findTypeObject(const ddl::DDLComplex& struct_name, const std::string& + path, const ddl::IDDLDataType*& type, int& array_size) const; + + /** + * Checks whether the target datatype is compatible with the source datatype + * @param [in] source Datatype 1 + * @param [in] source_array_size Arraysize 1 + * @param [in] target Datatype 2 + * @param [in] target_array_size Arraysize 2 + * @retval true or false + */ + bool checkTypeCompatibility(const ddl::IDDLDataType& source, int source_array_size, + const ddl::IDDLDataType& target, int target_array_size) const; + + /** + * Checks the configuration for consistency of a new signal + * @param [in] name The signal name + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkSignalName(const std::string& name) const; + + /** + * Checks the configuration for consistency of a new signal + * @param [in] type The type of the signal + * @retval ERR_INVALID_TYPE Type not found in DDL + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkSignalType(const std::string& type) const; + + /** + * Checks the configuration for consistency of a new assignment + * @param [in] assignment The assignment to check + * @retval ERR_INVALID_ARG Reference not found in Configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkAssignmentReferences(const MapAssignment& assignment) const; + + /** + * Checks the configuration for consistency of a new assignment + * @param [in] signal_name The name of the target signal (for error list) + * @param [in] signal_struct The ddl structure for the signal + * @param [in] assignment The assignment to check + * @retval ERR_INVALID_TYPE Definition is inconsistent with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkAssignmentType(const std::string& signal_name, + const ddl::DDLComplex& signal_struct, const MapAssignment& assignment) const; + + /** + * Checks the configuration for consistency of a new trigger + * @param [in] trigger The trigger to check + * @retval ERR_INVALID_TYPE Definition is inconsistent with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkTriggerType(const MapTriggerBase* trigger) const; + +private: + /// @cond nodoc + friend class MapSource; + friend class MapTarget; + friend class MapTriggerBase; + friend class MapDataTrigger; + MapHeader _header; + MapSourceList _sources; + MapTargetList _targets; + MapTransformationList _transforms; + // mutable because its not part of the object state + mutable MapErrorList _errors; + const ddl::DDLDescription* _ddl_ref; + bool _checked_for_consistency; + bool _is_consistent; + /// @endcond +}; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_CONFIGURATION_H diff --git a/mapping/configuration/map_header.cpp b/mapping/configuration/map_header.cpp new file mode 100644 index 0000000..85180d8 --- /dev/null +++ b/mapping/configuration/map_header.cpp @@ -0,0 +1,159 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_header.h" + +#include "map_configuration.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) +} +} + +using namespace mapping::oo; + +MapHeader::MapHeader() +{ + reset(); +} + +const std::string& MapHeader::getDescription() const +{ + return _desc; +} + +const std::string& MapHeader::getDllPaths() const +{ + return _ddl; +} + +const std::string& MapHeader::getLanguageVersion() const +{ + return _lang_version; +} + +const std::string& MapHeader::getAuthor() const +{ + return _author; +} + +const std::string& MapHeader::getCreationDate() const +{ + return _creation_date; +} + +const std::string& MapHeader::getModificationDate() const +{ + return _mod_date; +} + +void MapHeader::reset() +{ + _desc = "Auto-generated with Signal Mapping Editor"; + _ddl.clear(); + _lang_version = "1.00"; + _author = a_util::system::getCurrentUserName(); + _creation_date = a_util::datetime::getCurrentLocalDateTime().format("%c"); + _mod_date = _creation_date; +} + +a_util::result::Result MapHeader::setDescription(const std::string& strDescription) +{ + _desc = strDescription; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapHeader::setDdlPaths(const std::string& strDdlPaths) +{ + _ddl = strDdlPaths; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapHeader::loadFromDOM(const a_util::xml::DOMElement& oHeader, MapErrorList& lstErrors) +{ + const a_util::xml::DOMElement oLang = oHeader.getChild("language_version"); + const a_util::xml::DOMElement oAuthor = oHeader.getChild("author"); + const a_util::xml::DOMElement oCreated = oHeader.getChild("date_creation"); + const a_util::xml::DOMElement oModified = oHeader.getChild("date_change"); + const a_util::xml::DOMElement oDescription = oHeader.getChild("description"); + + if (oLang.isNull() || oAuthor.isNull() || oCreated.isNull() || + oModified.isNull() || oDescription.isNull()) + { + lstErrors.push_back("Missing , , , " + " or element in header"); + return ERR_INVALID_ARG; + } + + if(!a_util::strings::isDouble(oLang.getData()) || a_util::strings::toDouble(oLang.getData()) > 1) + { + lstErrors.push_back(" is not 1.00. No other language version exists."); + return ERR_INVALID_ARG; + } + + _lang_version = oLang.getData(); + _author = oAuthor.getData(); + _creation_date = oCreated.getData(); + _mod_date = oModified.getData(); + setDescription(oDescription.getData()); + + // optional + const a_util::xml::DOMElement oDdlPaths = oHeader.getChild("ddl"); + if (!oDdlPaths.isNull()) + { + setDdlPaths(oDdlPaths.getData()); + } + else + { + _ddl.clear(); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapHeader::writeToDOM(a_util::xml::DOMElement oDOMElement) +{ + oDOMElement.setName("header"); + + _mod_date = a_util::datetime::getCurrentLocalDateTime().format("%c"); + + a_util::xml::DOMElement oLang = oDOMElement.createChild("language_version"); + a_util::xml::DOMElement oAuthor = oDOMElement.createChild("author"); + a_util::xml::DOMElement oCreated = oDOMElement.createChild("date_creation"); + a_util::xml::DOMElement oModified = oDOMElement.createChild("date_change"); + a_util::xml::DOMElement oDescription = oDOMElement.createChild("description"); + + oLang.setData(_lang_version); + oAuthor.setData(_author); + oCreated.setData(_creation_date); + oDescription.setData(_desc); + oModified.setData(_mod_date); + + if(!_ddl.empty()) + { + a_util::xml::DOMElement oDdlPaths = oDOMElement.createChild("ddl"); + oDdlPaths.setData(_ddl); + } + + return a_util::result::SUCCESS; +} diff --git a/mapping/configuration/map_header.h b/mapping/configuration/map_header.h new file mode 100644 index 0000000..4a9edc4 --- /dev/null +++ b/mapping/configuration/map_header.h @@ -0,0 +1,127 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_HEADER_H +#define HEADER_MAP_HEADER_H + +#include "a_util/result.h" +#include "a_util/xml.h" + +namespace mapping +{ +namespace oo +{ + + typedef std::vector MapErrorList; + +/** + * MapHeader contains all information from the header-Tag of a mapping configuration + */ +class MapHeader +{ +public: + /** + * CTOR + */ + MapHeader(); + + /** + * Returns the description from the header tag or an empty string + */ + const std::string& getDescription() const; + + /** + * Returns the list of dll paths from the header tag or an empty string + */ + const std::string& getDllPaths() const; + + /** + * Returns the version from the language_version-header tag or an empty string + */ + const std::string& getLanguageVersion() const; + + /** + * Returns the author from the author-header tag or an empty string + */ + const std::string& getAuthor() const; + + /** + * Returns the date from the date_creation-header tag or an empty string + */ + const std::string& getCreationDate() const; + + /** + * Returns the date from the date_change-header tag or an empty string + */ + const std::string& getModificationDate() const; + +private: + /** + * Resets the instance to its initial state + */ + void reset(); + + /** + * Initializes the header from a header-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] errors The error list for debug + * @retval ERR_INVALID_ARG Field missing + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOM(const a_util::xml::DOMElement& header, MapErrorList& errors); + + /** + * Export header to a XML dom element + * + * @param [out] dom_element The dom element to be written + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement dom_element); + + /** + * Set description + * @param [in] description The description + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDescription(const std::string& description); + + /** + * Set ddl paths + * @param [in] ddl_paths The string containing ddl paths + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDdlPaths(const std::string& ddl_paths); + +private: + /// @cond nodoc + friend class MapConfiguration; + std::string _lang_version; + std::string _author; + std::string _desc; + std::string _ddl; + std::string _creation_date; + std::string _mod_date; + /// @endcond +}; + + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_HEADER_H diff --git a/mapping/configuration/map_source.cpp b/mapping/configuration/map_source.cpp new file mode 100644 index 0000000..24e3336 --- /dev/null +++ b/mapping/configuration/map_source.cpp @@ -0,0 +1,133 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_source.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "map_configuration.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-40, ERR_INVALID_STATE) +} +} + +using namespace mapping::oo; + +MapSource::MapSource(MapConfiguration* pConfig) : _is_valid(true), _config(pConfig) +{ +} + +MapSource::MapSource(MapConfiguration* pConfig, std::string name, std::string strType) : _config(pConfig), _is_valid(true) +{ + _name = name; + a_util::strings::trim(_name); + _type = strType; + a_util::strings::trim(_type); +} + +const std::string& MapSource::getName() const +{ + return _name; +} + +const std::string& MapSource::getType() const +{ + return _type; +} + +bool MapSource::isValid() const +{ + return _is_valid; +} + +a_util::result::Result MapSource::loadFromDOM(const a_util::xml::DOMElement& oSource) +{ + const a_util::xml::DOMAttributes mapAttrs = oSource.getAttributes(); + a_util::xml::DOMAttributes::const_iterator itName = mapAttrs.find("name"); + if (itName == mapAttrs.end() || itName->second.empty()) + { + _config->appendError("Missing or empty name attribute for a "); + return ERR_INVALID_ARG; + } + _name = itName->second; + a_util::strings::trim(_name); + + a_util::xml::DOMAttributes::const_iterator itType = mapAttrs.find("type"); + if (itType == mapAttrs.end() || itType->second.empty()) + { + _config->appendError(a_util::strings::format("Missing or empty type attribute for \ + '%s'", itName->second.c_str())); + return ERR_INVALID_ARG; + } + _type = itType->second; + a_util::strings::trim(_type); + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapSource::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("source"); + oDOMElement.setAttribute("name", _name); + oDOMElement.setAttribute("type", _type); + return a_util::result::SUCCESS; +} + + +a_util::result::Result MapSource::setName(const std::string& strNewName) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + RETURN_IF_FAILED(_config->checkSignalName(strNewName)); + + // modify references in Targets + for(MapTargetList::iterator itTrg = _config->_targets.begin(); itTrg != _config->_targets.end(); itTrg++) + { + if(itTrg->_sources.find(_name) != itTrg->_sources.end()) + { + itTrg->modifySourceName(_name, strNewName); + } + } + + _name = strNewName; + + return _config->checkMappingConsistency(); +} + +a_util::result::Result MapSource::setType(const std::string& strType) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + RETURN_IF_FAILED(_config->checkSignalType(strType)); + _type = strType; + return _config->checkDDLConsistency(); +} diff --git a/mapping/configuration/map_source.h b/mapping/configuration/map_source.h new file mode 100644 index 0000000..5556bf9 --- /dev/null +++ b/mapping/configuration/map_source.h @@ -0,0 +1,132 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_SOURCE_H +#define HEADER_MAP_SOURCE_H + +#include +#include + +#include "a_util/result.h" +#include "a_util/xml.h" + +namespace mapping +{ +namespace oo +{ + class MapConfiguration; + +/** + * MapSource represents a mapping source from the configuration file + */ +class MapSource +{ +public: + /** + * CTOR + */ + MapSource(MapConfiguration* config); + /** + * CTOR + * @param [in] name signal name + * @param [in] type signal type + */ + MapSource(MapConfiguration* config, std::string name, std::string type); + + /** + * Returns the name of the mapping source + */ + const std::string& getName() const; + + /** + * Set name + * @param [in] new_name The new name of the target + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setName(const std::string& new_name); + + /** + * Returns the DDL typename of the mapping source + */ + const std::string& getType() const; + + /** + * Set type + * @param [in] _type The type of the target + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setType(const std::string& type); + + /** + * Returns the validity for the current description + */ + bool isValid() const; + +private: + /** + * Initializes the source from a source-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing name or type + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOM(const a_util::xml::DOMElement& source); + + /** + * Export source to a XML dom element + * + * @param [in] dom_element The dom element to be written + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + +private: + /// @cond nodoc + friend class MapConfiguration; + friend class MapTarget; + MapConfiguration* _config; + std::string _name; + std::string _type; + bool _is_valid; + /// @endcond +}; + +inline bool operator==(const MapSource& a, const MapSource& b) +{ + return a.getName() == b.getName() && a.getType() == b.getType(); +} + +inline bool operator!=(const MapSource& a, const MapSource& b) +{ + return !(a == b); +} + +/// Public composite types used in the mapping::oo namespace +typedef std::vector MapSourceList; +typedef std::set MapSourceNameList; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_SOURCE_H diff --git a/mapping/configuration/map_target.cpp b/mapping/configuration/map_target.cpp new file mode 100644 index 0000000..d8b7e0b --- /dev/null +++ b/mapping/configuration/map_target.cpp @@ -0,0 +1,616 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_target.h" + +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "map_configuration.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-19, ERR_NOT_SUPPORTED) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-40, ERR_INVALID_STATE) +} +} + +using namespace mapping::oo; + +MapTarget::MapTarget(MapConfiguration* pConfig) : _config(pConfig), _is_valid(true) +{ +} + +MapTarget::MapTarget(MapConfiguration* pConfig, std::string name, std::string strType) : + _config(pConfig), _is_valid(true) +{ + _name = name; + _type = strType; +} + +MapTarget::MapTarget(const MapTarget& oOther) +{ + _name = oOther._name; + _type = oOther._type; + _assignments = oOther._assignments; + _sources = oOther._sources; + _is_valid = oOther._is_valid; + _config = oOther._config; + for (MapTriggerList::const_iterator it = oOther._triggers.begin(); + it != oOther._triggers.end(); ++it) + { + _triggers.push_back((*it)->clone()); + } +} + +MapTarget& MapTarget::operator=(const MapTarget& oOther) +{ + MapTarget oCopy(oOther); + oCopy.swap(*this); + return *this; +} + +MapTarget::~MapTarget() +{ + for (MapTriggerList::iterator it = _triggers.begin(); + it != _triggers.end(); ++it) + { + delete *it; + } + _triggers.clear(); +} + +const std::string& MapTarget::getName() const +{ + return _name; +} + +const std::string& MapTarget::getType() const +{ + return _type; +} + +bool MapTarget::isValid() const +{ + return _is_valid; +} + +const MapAssignmentList& MapTarget::getAssignmentList() const +{ + return _assignments; +} + + +a_util::result::Result MapTarget::addAssignment(const MapAssignment& oAssignment) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + + if(!_is_valid) + { + _config->appendError(a_util::strings::format("Target Signal %s is not valid, cannot add any assignment", _name.c_str())); + return ERR_INVALID_STATE; + } + + RETURN_IF_FAILED(_config->checkAssignmentReferences(oAssignment)); + RETURN_IF_FAILED(addAssignmentNoTypeCheck(oAssignment)); + + // Check new assignment with ddl + const ddl::DDLComplex* pTargetStruct = _config->_ddl_ref->getStructByName(_type); + // Target is valid, so the type is defined and can be dereferenced + a_util::result::Result nRes = _config->checkAssignmentType(_name, *pTargetStruct, oAssignment); + if(isOk(nRes)) + { + nRes = checkDoubleAssignments(); + } + // If assignment not consistent with DDL, remove assignment + if(isFailed(nRes)) + { + removeAssignmentWithoutClear(oAssignment.getTo()); + } + + return nRes; +} + +a_util::result::Result MapTarget::removeAssignment(const std::string& strElementName) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + _config->_errors.clear(); + return removeAssignmentWithoutClear(strElementName); +} + +a_util::result::Result MapTarget::addTrigger(MapTriggerBase* pTrigger) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + + if(!_is_valid) + { + _config->appendError(a_util::strings::format("Target Signal %s is not valid, cannot add any assignment", _name.c_str())); + return ERR_INVALID_STATE; + } + + if(pTrigger->_config != _config) + { + _config->appendError(a_util::strings::format("Trigger refers to another configuration")); + return ERR_INVALID_STATE; + } + + RETURN_IF_FAILED(pTrigger->checkTriggerReferences()); + RETURN_IF_FAILED(_config->checkTriggerType(pTrigger)); + return addTriggerNoTypeCheck(pTrigger); +} + +a_util::result::Result MapTarget::removeTrigger(MapTriggerBase* pTrigger) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + _config->_errors.clear(); + bool bIsRemoved = false; + std::string strSource; + for(MapTriggerList::iterator it = _triggers.begin(); it != _triggers.end(); it++) + { + if((*it)->isEqual(*pTrigger)) + { + strSource = (*it)->getSourceDependency(); + _triggers.erase(it); + bIsRemoved = true; + break; + } + } + if(!strSource.empty()) + { + bool bIsSourceUsed = false; + + for(MapAssignmentList::const_iterator it = _assignments.begin(); it != _assignments.end(); it++) + { + if(it->getSource() == strSource) + { + bIsSourceUsed = true; + } + } + for(MapTriggerList::const_iterator it = _triggers.begin(); it != _triggers.end(); it++) + { + if((*it)->getSourceDependency() == strSource) + { + bIsSourceUsed = true; + } + } + if(!bIsSourceUsed) + { + for (MapSourceNameList::iterator itSource = _sources.begin(); + itSource != _sources.end(); ++itSource) + { + if (*itSource == strSource) + { + _sources.erase(itSource); + break; + } + } + } + } + if(bIsRemoved) + { + return a_util::result::SUCCESS; + } + return ERR_NOT_FOUND; +} + +a_util::result::Result MapTarget::removeAssignmentWithoutClear(const std::string& strElementName) +{ + bool bIsRemoved = false; + std::string strSource; + for(MapAssignmentList::iterator it = _assignments.begin(); it != _assignments.end(); it++) + { + if(it->getTo() == strElementName) + { + strSource = it->getSource(); + _assignments.erase(it); + bIsRemoved = true; + break; + } + } + if(!strSource.empty()) + { + bool isSourceUsed = false; + + for(MapAssignmentList::const_iterator it = _assignments.begin(); it != _assignments.end(); it++) + { + if(it->getSource() == strSource) + { + isSourceUsed = true; + } + } + for(MapTriggerList::const_iterator it = _triggers.begin(); it != _triggers.end(); it++) + { + if((*it)->getSourceDependency() == strSource) + { + isSourceUsed = true; + } + } + if(!isSourceUsed) + { + for (MapSourceNameList::iterator itSource = _sources.begin(); + itSource != _sources.end(); ++itSource) + { + if (*itSource == strSource) + { + _sources.erase(itSource); + break; + } + } + } + } + if(bIsRemoved) + { + return a_util::result::SUCCESS; + } + return ERR_NOT_FOUND; +} + +a_util::result::Result MapTarget::addAssignmentNoTypeCheck(const MapAssignment& oAssignment) +{ + // Assignment is attributed to an element + const std::string& strTo = oAssignment.getTo(); + if(strTo.empty()) + { + _config->appendError(a_util::strings::format("Target element name is empty in '%s'", + _name.c_str())); + return ERR_INVALID_ARG; + } + + for(MapAssignmentList::iterator itAssign = _assignments.begin(); itAssign != _assignments.end(); itAssign++) + { + // Is To already assigned + if (itAssign->getTo() == strTo) + { + _config->appendError( + a_util::strings::format("Target element '%s' is already assigned in '%s'", + strTo.c_str(), getName().c_str())); + return ERR_INVALID_ARG; + } + } + + // Assignment is a constant, a connection or a function + if (oAssignment.getSource().empty() && oAssignment.getConstant().empty() && oAssignment.getFunction().empty()) + { + _config->appendError(a_util::strings::format("Missing , or attribute for to '%s' in '%s'", + strTo.c_str(), _name.c_str())); + return ERR_INVALID_ARG; + } + + // The constant is numeric + if (!oAssignment.getConstant().empty() && + !a_util::strings::isDouble(oAssignment.getConstant())) + { + _config->appendError( + a_util::strings::format("Empty or non-numeric constant for to '%s' in '%s'", + strTo.c_str(), _name.c_str())); + return ERR_INVALID_ARG; + } + + // The trigger_counter function modulo is numeric + if (!oAssignment.getModulo().empty()) + { + if (!a_util::strings::isInt64(oAssignment.getModulo()) || + oAssignment.getModulo().find('-') != std::string::npos || + oAssignment.getModulo().find('+') != std::string::npos || + a_util::strings::toUInt64(oAssignment.getModulo()) == 0) + { + _config->appendError( + a_util::strings::format("Non-integer or zero modulo in transmission_counter for to '%s' in '%s'", + strTo.c_str(), _name.c_str())); + return ERR_INVALID_ARG; + } + } + + _assignments.push_back(oAssignment); + if (!oAssignment.getSource().empty()) + { + for (MapSourceList::const_iterator itSource = _config->getSourceList().begin(); + itSource != _config->getSourceList().end(); ++itSource) + { + if (itSource->getName() == oAssignment.getSource()) + { + _sources.insert(itSource->getName()); + break; + } + } + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTarget::addTriggerNoTypeCheck(MapTriggerBase* pTrigger) +{ + _triggers.push_back(pTrigger); + + // append dependency to references sources + std::string strSourceDep = pTrigger->getSourceDependency(); + if (!strSourceDep.empty()) + { + for (MapSourceList::const_iterator itSource = _config->getSourceList().begin(); + itSource != _config->getSourceList().end(); ++itSource) + { + if (itSource->getName() == strSourceDep) + { + _sources.insert(itSource->getName()); + break; + } + } + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTarget::modifySourceName(const std::string& name, const std::string& strNewName) +{ + _sources.erase(name); + _sources.insert(strNewName); + for(MapAssignmentList::iterator itAssign = _assignments.begin(); + itAssign != _assignments.end(); itAssign++) + { + if(itAssign->_source == name) + { + itAssign->_source = strNewName; + } + } + for(MapTriggerList::iterator itTrigger = _triggers.begin(); + itTrigger != _triggers.end(); itTrigger++) + { + if((*itTrigger)->getSourceDependency() == name) + { + (*itTrigger)->setSourceDependency(strNewName); + } + } + return a_util::result::SUCCESS; +} + +const MapTriggerList& MapTarget::getTriggerList() const +{ + return _triggers; +} + +a_util::result::Result MapTarget::loadFromDOM(const a_util::xml::DOMElement& oTarget) +{ + _sources.clear(); + _assignments.clear(); + _triggers.clear(); + + // parse attributes + const a_util::xml::DOMAttributes mapAttrs = oTarget.getAttributes(); + a_util::xml::DOMAttributes::const_iterator itName = mapAttrs.find("name"); + if (itName == mapAttrs.end() || itName->second.empty()) + { + _config->appendError("Missing name attribute for a "); + return ERR_INVALID_ARG; + } + _name = itName->second; + a_util::strings::trim(_name); + + a_util::xml::DOMAttributes::const_iterator itType = mapAttrs.find("type"); + if (itType == mapAttrs.end() || itType->second.empty()) + { + _config->appendError(a_util::strings::format("Missing type attribute for '%s'", + itName->second.c_str())); + return ERR_INVALID_ARG; + } + _type = itType->second; + a_util::strings::trim(_type); + + // parse assignments and triggers + const a_util::xml::DOMElementList lstElements = oTarget.getChildren(); + a_util::result::Result nResult = a_util::result::SUCCESS; + for (a_util::xml::DOMElementList::const_iterator it = lstElements.begin(); + it != lstElements.end(); ++it) + { + const a_util::xml::DOMElement& oElem = *it; + const std::string& name = oElem.getName(); + + if (name == "assignment") + { + MapAssignment oAssign; + a_util::result::Result nRes = oAssign.loadFromDOM(oElem, _config->_errors); + if(isOk(nRes)) + { + nRes = addAssignmentNoTypeCheck(oAssign); + } + if (isFailed(nRes)) + { + nResult = nRes; + } + } + else if (name == "trigger") + { + MapTriggerBase* pTrigger = NULL; + a_util::result::Result nRes = MapTriggerBase::createFromDOM(_config, + oElem, pTrigger); + if(isOk(nRes)) + { + nRes = addTriggerNoTypeCheck(pTrigger); + } + if (isFailed(nRes)) + { + nResult = nRes; + } + } + else + { + _config->appendError(a_util::strings::format("Invalid element type in '%s': '%s'", + itName->second.c_str(), name.c_str())); + nResult = ERR_INVALID_ARG; + } + } + + return nResult; +} + +a_util::result::Result MapTarget::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("target"); + oDOMElement.setAttribute("name", _name); + oDOMElement.setAttribute("type", _type); + + for(MapAssignmentList::const_iterator itAssign = _assignments.begin(); + itAssign != _assignments.end(); itAssign++) + { + a_util::xml::DOMElement oDOMAssign = oDOMElement.createChild("assignment"); + itAssign->writeToDOM(oDOMAssign); + } + + for(MapTriggerList::const_iterator itTrigger = _triggers.begin(); + itTrigger != _triggers.end(); itTrigger++) + { + a_util::xml::DOMElement oDOMTrigger = oDOMElement.createChild("trigger"); + (*itTrigger)->writeToDOM(oDOMTrigger); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTarget::checkDoubleAssignments() +{ + a_util::result::Result nRes = a_util::result::SUCCESS; + std::set oAssignedElList; + for(MapAssignmentList::iterator itAssign = _assignments.begin(); itAssign != _assignments.end(); itAssign++) + { + oAssignedElList.insert(itAssign->getTo()); + } + for(MapAssignmentList::iterator itAssign = _assignments.begin(); itAssign != _assignments.end(); itAssign++) + { + for(std::set::iterator itParent = oAssignedElList.begin(); itParent != oAssignedElList.end(); itParent++) + { + std::string strEl = itAssign->getTo(); + if(strEl.find(*itParent) == 0) + { + size_t pos = 0; + while ((pos = strEl.find(*itParent, pos)) != std::string::npos) + { + strEl.replace(pos, itParent->length(), std::string()); + pos += 1; + } + + if(strEl.find('.') == 0 ||strEl.find('[') == 0) + { + _config->appendError(a_util::strings::format( + " to '%s' not possible because of to %s in '%s'", + strEl.c_str(), itParent->c_str(), getName().c_str())); + itAssign->_is_valid = false; + nRes = ERR_NOT_SUPPORTED; + } + } + } + } + return nRes; +} + +void MapTarget::swap(MapTarget& oOther) +{ + using std::swap; + swap(_config, oOther._config); + swap(_name, oOther._name); + swap(_type, oOther._type); + swap(_assignments, oOther._assignments); + swap(_sources, oOther._sources); + swap(_triggers, oOther._triggers); +} + +const MapSourceNameList& MapTarget::getReferencedSources() const +{ + return _sources; +} + +bool mapping::oo::operator==(const MapTarget& a, const MapTarget& b) +{ + if (a.getName() != b.getName() || + a.getType() != b.getType()) + { + return false; + } + + const MapAssignmentList& lstAssignA = a.getAssignmentList(); + const MapAssignmentList& lstAssignB = b.getAssignmentList(); + + if (lstAssignA.size() != lstAssignB.size() || + !std::equal(lstAssignA.begin(), lstAssignA.end(), lstAssignB.begin())) + { + return false; + } + + const MapTriggerList& lstTriggerA = a.getTriggerList(); + const MapTriggerList& lstTriggerB = b.getTriggerList(); + if (lstTriggerA.size() != lstTriggerB.size()) + { + return false; + } + + MapTriggerList::const_iterator itA = lstTriggerA.begin(); + MapTriggerList::const_iterator itB = lstTriggerB.begin(); + for (; itA != lstTriggerA.end() && itB != lstTriggerB.end(); + ++itA, ++itB) + { + if (!(*itA)->isEqual(*(*itB))) + { + return false; + } + } + + return true; +} + + +a_util::result::Result MapTarget::setName(const std::string& strNewName) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + RETURN_IF_FAILED(_config->checkSignalName(strNewName)); + _name = strNewName; + + return _config->checkMappingConsistency(); +} + +a_util::result::Result MapTarget::setType(const std::string& strType) +{ + if(!_config) + { + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + RETURN_IF_FAILED(_config->checkSignalType(strType)); + _type = strType; + return _config->checkDDLConsistency(); +} diff --git a/mapping/configuration/map_target.h b/mapping/configuration/map_target.h new file mode 100644 index 0000000..354a290 --- /dev/null +++ b/mapping/configuration/map_target.h @@ -0,0 +1,248 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_TARGET_H +#define HEADER_MAP_TARGET_H + +#include "a_util/result.h" +#include "a_util/xml.h" + +#include "map_assignment.h" +#include "map_trigger.h" +#include "map_source.h" + +namespace mapping +{ +namespace oo +{ + class MapConfiguration; + +/** + * MapTarget represents a mapped target from the mapping configuration + */ +class MapTarget +{ +public: + /** + * CTOR + */ + MapTarget(MapConfiguration* config); + + /** + * CTOR + * @param [in] name The signal name + * @param [in] type The signal type + */ + MapTarget(MapConfiguration* config, std::string name, std::string type); + + /** + * DTOR + */ + ~MapTarget(); + + /** + * CCTOR + */ + MapTarget(const MapTarget& other); + + /** + * Assignment operator + */ + MapTarget& operator=(const MapTarget& other); + + /** + * Returns the name of the mapped target + */ + const std::string& getName() const; + + /** + * Set name + * @param [in] new_name The new name of the target + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setName(const std::string& name); + + /** + * Returns the DDL typename of the mapped target + */ + const std::string& getType() const; + + /** + * Set type + * @param [in] _type The type of the target + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_ARG Signal name already used in configuration + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setType(const std::string& type); + + /** + * Returns the validity for the current description + */ + bool isValid() const; + + /** + * Add an assignment + * @param [in] assignment The assignment to add + * @retval ERR_INVALID_STATE No description found + * @retval ERR_INVALID_ARG Inconsistency with current configuration + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval ERR_NOT_SUPPORTED Assignment overlap with existing assignments + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addAssignment(const MapAssignment& assignment); + + /** + * Remove an assignment + * @param [in] element_name The name of the assigned element + * @retval ERR_NOT_FOUND Assignement not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeAssignment(const std::string& element_name); + + /** + * Returns all assignments configured for this target + */ + const MapAssignmentList& getAssignmentList() const; + + /** + * Add a trigger + * @param [in] trigger The trigger to add + * @retval ERR_INVALID_STATE No description found + * @retval ERR_NOT_FOUND Target not found + * @retval ERR_INVALID_ARG Inconsistency with current configuration + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTrigger(MapTriggerBase* trigger); + + /** + * Remove a trigger + * @param [in] trigger The trigger to remove + * @retval ERR_NOT_FOUND Trigger not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeTrigger(MapTriggerBase* trigger); + + /** + * Returns all triggers configured for this target + */ + const MapTriggerList& getTriggerList() const; + + /** + * Returns all referenced sources for this target. + */ + const MapSourceNameList& getReferencedSources() const; + +private: + /** + * Initializes the target from a target-dom element + * @param [in] dom_element The dom element from which to import + * @param [in] lstSources The list of existing sources in mapping + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing name or type + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDOM(const a_util::xml::DOMElement& target); + + /** + * Export target to a XML dom element + * + * @param [in] dom_element The dom element to be written + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Checks if the assignments overlap + * @retval ERR_NOT_SUPPORTED Assignments overlap + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkDoubleAssignments(); + + /** + * Add an assignment to this target + * @param [in] assignment The assignment to add + * @param [in] lstSources The list of existing sources in mapping + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing or erroneous attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addAssignmentNoTypeCheck(const MapAssignment& assignment); + + /** + * Remove an assignment from this target + * @param [in] strTo The name of the target element to unassign + * @retval ERR_NOT_FOUND Assignement not found + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeAssignmentWithoutClear(const std::string& element_name); + + /** + * Add a trigger to this target + * @param [in] trigger The trigger to add + * @param [in] lstSources The list of existing sources in mapping + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTriggerNoTypeCheck(MapTriggerBase* trigger); + + /** + * Modify a source signal name + * @param [in] _name The name of the target + * @param [in] new_name The new name of the target + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result modifySourceName(const std::string& name, const std::string& new_name); + + /** + * swap implementation + */ + void swap(MapTarget& other); + +private: + /// @cond nodoc + friend class MapConfiguration; + friend class MapSource; + MapConfiguration* _config; + std::string _name; + std::string _type; + MapSourceNameList _sources; + MapAssignmentList _assignments; + MapTriggerList _triggers; + bool _is_valid; + /// @endcond +}; + +bool operator==(const MapTarget& a, const MapTarget& b); + +inline bool operator!=(const MapTarget& a, const MapTarget& b) +{ + return !(a == b); +} + +/// Public composite types used in the mapping::oo namespace +typedef std::vector MapTargetList; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_TARGET_H diff --git a/mapping/configuration/map_transformation.cpp b/mapping/configuration/map_transformation.cpp new file mode 100644 index 0000000..d1e032e --- /dev/null +++ b/mapping/configuration/map_transformation.cpp @@ -0,0 +1,600 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_transformation.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "ddlrepresentation/ddlenum.h" + +#include "map_configuration.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-40, ERR_INVALID_STATE) + _MAKE_RESULT(-42, ERR_INVALID_TYPE) +} +} + +using namespace mapping::oo; + +MapTransformationBase::MapTransformationBase(MapConfiguration* pConfig, const std::string& name) + : _config(pConfig), _name(name), _is_valid(true) +{ +} + +MapTransformationBase::~MapTransformationBase() +{ +} + +a_util::result::Result MapTransformationBase::createFromDOM(MapConfiguration* pConfig, const a_util::xml::DOMElement& oTrans, + MapTransformationBase*& pDestination) +{ + const a_util::xml::DOMAttributes mapAttrs = oTrans.getAttributes(); + a_util::xml::DOMAttributes::const_iterator it = mapAttrs.find("name"); + if (it == mapAttrs.end() || it->second.empty()) + { + pConfig->appendError("Missing name attribute for a transformation element"); + return ERR_INVALID_ARG; + } + if(pConfig->getTransformation(it->second)) + { + pConfig->appendError("A transformation with this name already exists"); + return ERR_INVALID_ARG; + } + std::string name(it->second); + + if (oTrans.getName() == "polynomial") + { + MapPolynomTransformation* pPoly = new MapPolynomTransformation(pConfig, name); + if (isFailed(pPoly->loadFromDom(oTrans))) + { + delete pPoly; + return ERR_INVALID_ARG; + } + + pDestination = pPoly; + return a_util::result::SUCCESS; + } + + if (oTrans.getName() == "enum_table") + { + MapEnumTableTransformation* pPoly = new MapEnumTableTransformation(pConfig, name); + if (isFailed(pPoly->loadFromDom(oTrans))) + { + delete pPoly; + return ERR_INVALID_ARG; + } + + pDestination = pPoly; + return a_util::result::SUCCESS; + } + + pConfig->appendError("Invalid transformation element (expected )"); + + return ERR_INVALID_ARG; +} + +a_util::result::Result MapTransformationBase::create(MapConfiguration* pConfig, + const std::string& name, const std::string& strType, MapTransformationBase*& pDestination) +{ + if (strType == "polynomial") + { + MapPolynomTransformation* pPoly = new MapPolynomTransformation(pConfig, name); + pDestination = pPoly; + return a_util::result::SUCCESS; + } + + if (strType == "enum_table") + { + MapEnumTableTransformation* pPoly = new MapEnumTableTransformation(pConfig, name); + pDestination = pPoly; + return a_util::result::SUCCESS; + } + + pConfig->appendError("Invalid transformation type (expected or )"); + return ERR_INVALID_ARG; +} + +a_util::result::Result MapTransformationBase::setTypeFromDDL() +{ + MapEnumTableTransformation* pMapETransf = + dynamic_cast(this); + if(pMapETransf) + { + return pMapETransf->convertValuesWithDDL(); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTransformationBase::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + const MapPolynomTransformation* pMapPTransf = + dynamic_cast(this); + if(pMapPTransf) + { + return pMapPTransf->writeToDOM(oDOMElement); + } + const MapEnumTableTransformation* pMapETransf = + dynamic_cast(this); + if(pMapETransf) + { + return pMapETransf->writeToDOM(oDOMElement); + } + + return a_util::result::SUCCESS; +} + +const std::string& MapTransformationBase::getName() const +{ + return _name; +} + +bool MapTransformationBase::isValid() const +{ + return _is_valid; +} + +MapPolynomTransformation::MapPolynomTransformation(MapConfiguration* pConfig, const std::string& name) + : MapTransformationBase(pConfig, name), _a(0), _b(0), _c(0), _d(0), _e(0) +{ +} + +double MapPolynomTransformation::getA() const +{ + return _a; +} + +double MapPolynomTransformation::getB() const +{ + return _b; +} + +double MapPolynomTransformation::getC() const +{ + return _c; +} + +double MapPolynomTransformation::getD() const +{ + return _d; +} + +double MapPolynomTransformation::getE() const +{ + return _e; +} + +MapTransformationBase* MapPolynomTransformation::clone() const +{ + return new MapPolynomTransformation(*this); +} + +bool MapPolynomTransformation::isEqual(const MapTransformationBase& oOther) const +{ + if (oOther.getName() != getName()) + { + return false; + } + + const MapPolynomTransformation* p = + dynamic_cast(&oOther); + if (p) + { + return getA() == p->getA() && getB() == p->getB() && + getC() == p->getC() && getD() == p->getD() && getE() == p->getE(); + } + + return false; +} + +a_util::result::Result MapPolynomTransformation::loadFromDom(const a_util::xml::DOMElement& oTrans) +{ + const a_util::xml::DOMAttributes mapAttrs = oTrans.getAttributes(); + std::string strCoefs[5]; + char c = 'a'; + for (int i = 0; i < 5; ++i, ++c) + { + a_util::xml::DOMAttributes::const_iterator it = mapAttrs.find(std::string(1, c)); + if (it != mapAttrs.end()) + { + strCoefs[i] = it->second; + } + } + + return setCoefficients(strCoefs); +} + +a_util::result::Result MapPolynomTransformation::setCoefficients(const std::string strCoefs[5]) +{ + a_util::result::Result res = a_util::result::SUCCESS; + double p[5] = {0}; + char c = 'a'; + for (int i = 0; i < 5; ++i, c++) + { + if(!strCoefs[i].empty()) + { + if (!a_util::strings::isDouble(strCoefs[i])) + { + _config->appendError( + a_util::strings::format("Invalid coefficient attribute '%c' for polynomial transformation '%s' (expected number)", + c, this->getName().c_str())); + res = ERR_INVALID_ARG; + } + else + { + p[i] = a_util::strings::toDouble(strCoefs[i]); + } + } + } + _a = p[0]; + _b = p[1]; + _c = p[2]; + _d = p[3]; + _e = p[4]; + return res; +} + +a_util::result::Result MapPolynomTransformation::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("polynomial"); + oDOMElement.setAttribute("name", _name); + if(_a != 0) + { + oDOMElement.setAttribute("a", a_util::strings::format("%g",_a)); + } + if(_b != 0) + { + oDOMElement.setAttribute("b", a_util::strings::format("%g",_b)); + } + if(_c != 0) + { + oDOMElement.setAttribute("c", a_util::strings::format("%g",_c)); + } + if(_d != 0) + { + oDOMElement.setAttribute("d", a_util::strings::format("%g",_d)); + } + if(_e != 0) + { + oDOMElement.setAttribute("e", a_util::strings::format("%g",_e)); + } + return a_util::result::SUCCESS; +} + +double MapPolynomTransformation::evaluate(double value) const +{ + double f64Pow2 = value*value; + double f64Pow3 = f64Pow2*value; + return (_a + _b*value + _c*f64Pow2 + _d*f64Pow3 + _e*f64Pow3*value); +} + + +MapEnumTableTransformation::MapEnumTableTransformation(MapConfiguration* pConfig, const std::string& name) + : MapTransformationBase(pConfig, name), _default_int(0), _default_value("0") +{ +} + +MapTransformationBase* MapEnumTableTransformation::clone() const +{ + return new MapEnumTableTransformation(*this); +} + +bool MapEnumTableTransformation::isEqual(const MapTransformationBase& oOther) const +{ + if (oOther.getName() != getName()) + { + return false; + } + + const MapEnumTableTransformation* p = + dynamic_cast(&oOther); + if (p) + { + return getDefaultStr() == p->getDefaultStr() && getConversionsStr() == p->getConversionsStr(); + } + + return false; +} + +a_util::result::Result MapEnumTableTransformation::loadFromDom(const a_util::xml::DOMElement& oTrans) +{ + const a_util::xml::DOMAttributes mapAttrs = oTrans.getAttributes(); + a_util::result::Result nRes = a_util::result::SUCCESS; + // Read attribute + a_util::xml::DOMAttributes::const_iterator itAttrFrom = mapAttrs.find("from"); + if (itAttrFrom == mapAttrs.end() || itAttrFrom->second.empty()) + { + _config->appendError(a_util::strings::format("Missing attribute for '%s'", + getName().c_str())); + nRes = ERR_INVALID_ARG; + } + + // Read attribute + a_util::xml::DOMAttributes::const_iterator itAttrTo = mapAttrs.find("to"); + if (itAttrTo == mapAttrs.end() || itAttrTo->second.empty()) + { + _config->appendError(a_util::strings::format("Missing attribute for '%s'", + getName().c_str())); + nRes = ERR_INVALID_ARG; + } + + if(isOk(nRes)) + { + setEnumsStr(itAttrFrom->second, itAttrTo->second); + + // Read attribute + a_util::xml::DOMAttributes::const_iterator itAttrDefault = mapAttrs.find("default"); + if (itAttrDefault == mapAttrs.end() || itAttrDefault->second.empty()) + { + _config->appendError(a_util::strings::format("Missing attribute for '%s'", + getName().c_str())); + return ERR_INVALID_ARG; + } + setDefaultStr(itAttrDefault->second); + + // Search conversions in DDLEnums + const a_util::xml::DOMElementList lstConv = oTrans.getChildren(); + + for (a_util::xml::DOMElementList::const_iterator it = lstConv.begin(); it != lstConv.end(); ++it) + { + a_util::result::Result res = a_util::result::SUCCESS; + const a_util::xml::DOMAttributes mapConvAttrs = it->getAttributes(); + + a_util::xml::DOMAttributes::const_iterator itConvAttrFrom = mapConvAttrs.find("from"); + if (itConvAttrFrom == mapConvAttrs.end() || itConvAttrFrom->second.empty()) + { + _config->appendError(a_util::strings::format("Missing attribute for in '%s'", + getName().c_str())); + res = ERR_INVALID_ARG; + } + + a_util::xml::DOMAttributes::const_iterator itConvAttrTo = mapConvAttrs.find("to"); + if (itConvAttrTo == mapConvAttrs.end() || itConvAttrTo->second.empty()) + { + _config->appendError(a_util::strings::format("Missing attribute for in '%s'", + getName().c_str())); + res = ERR_INVALID_ARG; + } + + if(a_util::result::isOk(res)) + { + if(isFailed(addConversionStr(itConvAttrFrom->second, itConvAttrTo->second))) + { + _config->appendError(a_util::strings::format(" attribute '%s' appears more than once in '%s'", + itConvAttrFrom->second.c_str(), getName().c_str())); + res = ERR_INVALID_ARG; + } + } + + if(a_util::result::isFailed(res)) + { + nRes = res; + } + } + } + return nRes; +} + +a_util::result::Result MapEnumTableTransformation::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("enum_table"); + oDOMElement.setAttribute("name", _name); + oDOMElement.setAttribute("from", _enum_from); + oDOMElement.setAttribute("to", _enum_to); + oDOMElement.setAttribute("default", _default_value); + for(MapStrConversionList::const_iterator itConv = _conversions.begin(); itConv != _conversions.end(); itConv++) + { + a_util::xml::DOMElement oDOMConv = oDOMElement.createChild("conversion"); + oDOMConv.setAttribute("from", itConv->first); + oDOMConv.setAttribute("to", itConv->second); + } + return a_util::result::SUCCESS; +} + +const std::string& MapEnumTableTransformation::getEnumFrom() const +{ + return _enum_from; +} + +const std::string& MapEnumTableTransformation::getEnumTo() const +{ + return _enum_to; +} + +a_util::result::Result mapping::oo::MapEnumTableTransformation::setEnums(const std::string& strEnumFrom, const std::string& strEnumTo) +{ + RETURN_IF_FAILED(setEnumsStr(strEnumFrom, strEnumTo)); + a_util::result::Result nRes = convertValuesWithDDL(); + if(isFailed(nRes)) + { + _enum_from.clear(); + _enum_to.clear(); + } + return nRes; +} + +int64_t MapEnumTableTransformation::getDefault() const +{ + return _default_int; +} + +std::string MapEnumTableTransformation::getDefaultStr() const +{ + return _default_value; +} + +a_util::result::Result mapping::oo::MapEnumTableTransformation::setDefault(const std::string& strDefault) +{ + RETURN_IF_FAILED(setDefaultStr(strDefault)); + a_util::result::Result nRes = convertValuesWithDDL(); + if(isFailed(nRes)) + { + _default_value.clear(); + } + return nRes; +} + +const std::map& MapEnumTableTransformation::getConversions() const +{ + return _conversions_int; +} + +const std::map& MapEnumTableTransformation::getConversionsStr() const +{ + return _conversions; +} + +a_util::result::Result mapping::oo::MapEnumTableTransformation::addConversion(const std::string& strFrom, const std::string& strTo) +{ + RETURN_IF_FAILED(addConversionStr(strFrom, strTo)); + a_util::result::Result nRes = convertValuesWithDDL(); + if(isFailed(nRes)) + { + _conversions.erase(strFrom); + } + return nRes; +} + +a_util::result::Result MapEnumTableTransformation::removeConversion(const std::string& strFrom) +{ + _conversions.erase(strFrom); + return convertValuesWithDDL(); +} + +double MapEnumTableTransformation::evaluate(double f64Value) const +{ + std::map::const_iterator it = _conversions_int.find((int64_t)f64Value); + if(it != _conversions_int.end()) + { + return (double)it->second; + } + return (double)_default_int; +} + +a_util::result::Result MapEnumTableTransformation::setEnumsStr(const std::string& strEnumFrom, const std::string& strEnumTo) +{ + _enum_from = strEnumFrom; + _enum_to = strEnumTo; + + _conversions_int.clear(); + _conversions.clear(); + _default_value.clear(); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapEnumTableTransformation::setDefaultStr(const std::string& strDefault) +{ + _default_value = strDefault; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapEnumTableTransformation::addConversionStr(const std::string& strFrom, const std::string& strTo) +{ + if(_conversions.find(strFrom) != _conversions.end()) + { + return ERR_INVALID_ARG; + } + + _conversions[strFrom] = strTo; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapEnumTableTransformation::convertValuesWithDDL() +{ + if(!_config) + { + _is_valid = false; + return ERR_INVALID_STATE; + } + if(!_config->getDescription()) + { + _config->appendError(a_util::strings::format("No description found", + getName().c_str())); + _is_valid = false; + return ERR_INVALID_STATE; + } + // Search in DDL + const ddl::DDLEnum * pEnumFrom = _config->getDescription()->getEnumByName(_enum_from); + if(pEnumFrom == NULL) + { + _config->appendError(a_util::strings::format(" attribute for '%s' should be an enumeration", + getName().c_str())); + _is_valid = false; + return ERR_INVALID_TYPE; + } + // Search in DDL + const ddl::DDLEnum * pEnumTo = _config->getDescription()->getEnumByName(_enum_to); + if(pEnumTo == NULL) + { + _config->appendError(a_util::strings::format(" attribute for '%s' should be an enumeration", + getName().c_str())); + _is_valid = false; + return ERR_INVALID_TYPE; + } + + // Search in DDL + if(!_default_value.empty()) + { + std::string strValue; + if(isFailed(pEnumTo->getValue(_default_value, strValue)) || !a_util::strings::isInt64(strValue)) + { + _config->appendError(a_util::strings::format(" attribute for '%s' should be an element of '%s' ", + getName().c_str(), _enum_to.c_str())); + _is_valid = false; + return ERR_INVALID_TYPE; + } + + _default_int = a_util::strings::toInt64(strValue); + } + + a_util::result::Result res = a_util::result::SUCCESS; + _conversions_int.clear(); + for (std::map::iterator it = _conversions.begin(); it != _conversions.end(); ++it) + { + std::string strFromVal, strToVal; + + if(isFailed(pEnumFrom->getValue(it->first, strFromVal)) || !a_util::strings::isInt64(strFromVal)) + { + _config->appendError(a_util::strings::format(" attribute '%s' for in '%s' should be a element of '%s' ", + it->first.c_str(), getName().c_str(), pEnumFrom->getName().c_str())); + _is_valid = false; + res = ERR_INVALID_TYPE; + } + if(isFailed(pEnumTo->getValue(it->second, strToVal)) || !a_util::strings::isInt64(strToVal)) + { + _config->appendError(a_util::strings::format(" attribute '%s' for in '%s' should be a element of '%s' ", + it->second.c_str(), getName().c_str(), pEnumTo->getName().c_str())); + _is_valid = false; + res = ERR_INVALID_TYPE; + } + + if(isOk(res)) + { + _is_valid = true; + _conversions_int[a_util::strings::toInt64(strFromVal)] = a_util::strings::toInt64(strToVal); + } + } + return res; +} diff --git a/mapping/configuration/map_transformation.h b/mapping/configuration/map_transformation.h new file mode 100644 index 0000000..84ab8aa --- /dev/null +++ b/mapping/configuration/map_transformation.h @@ -0,0 +1,379 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + +#ifndef HEADER_MAP_TRANSFORMATION_H +#define HEADER_MAP_TRANSFORMATION_H + +#include "a_util/result.h" +#include "a_util/xml.h" +#include "a_util/strings.h" + +namespace mapping +{ +namespace oo +{ + + class MapConfiguration; + +/** + * cMapTransformation forms a base class for a single transformation + */ +class MapTransformationBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + * @param [in] name The transformation name + */ + MapTransformationBase(MapConfiguration* config, const std::string& name); + + /** + * DTOR + */ + virtual ~MapTransformationBase(); + + /** + * Returns the name of the transformation + */ + const std::string& getName() const; + + /** + * Returns the validity for the current description + */ + bool isValid() const; + + /** + * Polymorphic comparison method + */ + virtual bool isEqual(const MapTransformationBase& other) const = 0; + + /** + * Polymorphic clone method + */ + virtual MapTransformationBase* clone() const = 0; + + /** + * Polymorphic evaluation template method + * @param [in] value The value to evaluate + */ + virtual double evaluate(double value) const = 0; + +private: + /** + * creates a polymorphic transformation instance from a dom element + * @param [in] oConfig The configuration + * @param [in] dom_element The dom element from which to import + * @param [out] destination The Transformation object to fill + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing name or type + * @retval a_util::result::SUCCESS Everything went fine + */ + static a_util::result::Result createFromDOM(MapConfiguration* config, const a_util::xml::DOMElement& dom_element, + MapTransformationBase*& destination); + + /** + * creates a polymorphic transformation instance from a dom element + * @param [in] oConfig The configuration + * @param [in] dom_element The dom element from which to import + * @param [out] destination The Transformation object to fill + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing name or type + * @retval a_util::result::SUCCESS Everything went fine + */ + static a_util::result::Result create(MapConfiguration* config, const std::string& name, + const std::string& type, MapTransformationBase*& destination); + + /** + * Export transformation to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Set Float values from Enumeration definition in DDL-File + * @param [in] pDDLRef The ddl description + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setTypeFromDDL(); + +protected: + /// @cond nodoc + friend class MapConfiguration; + MapConfiguration* _config; + std::string _name; + bool _is_valid; + /// @endcond +}; + +/// MapPolynomTransformation represents a polynom transformation in the configuration api +/// as well as the actual implementation of the transformation in the evaluate method +class MapPolynomTransformation : public MapTransformationBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + * @param [in] name The transformation name + */ + MapPolynomTransformation(MapConfiguration* config, const std::string& name); + + /** + * Returns parameter A of the polynomial + */ + double getA() const; + + /** + * Returns parameter A of the polynomial + */ + double getB() const; + + /** + * Returns parameter A of the polynomial + */ + double getC() const; + + /** + * Returns parameter A of the polynomial + */ + double getD() const; + + /** + * Returns parameter A of the polynomial + */ + double getE() const; + + /** + * Set Polynom coefficients + * @param [in] coefs The list of coefficients + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG An attribute is not a float value + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setCoefficients(const std::string coefs[5]); + + /** + * @overload + */ + bool isEqual(const MapTransformationBase& other) const; + + /** + * @overload + */ + double evaluate(double value) const; + + /// nodoc + MapTransformationBase* clone() const; + +private: + /** + * Initializes the transformation from a target-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG An attribute is not a float value + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDom(const a_util::xml::DOMElement& dom_element); + + /** + * Export transformation to a XML dom element + * + * @param [in] dom_element The dom element to be written + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + +private: + /// @cond nodoc + friend class MapTransformationBase; + double _a, _b, _c, _d, _e; + /// @endcond +}; + +/// MapEnumTableTransformation represents a transformation between to enumerations +class MapEnumTableTransformation : public MapTransformationBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + * @param [in] name The transformation name + */ + MapEnumTableTransformation(MapConfiguration* config, const std::string& name); + + /** + * Returns the name of the source enumeration + */ + const std::string& getEnumFrom() const; + + /** + * Returns the name of the target enumeration + */ + const std::string& getEnumTo() const; + + /** + * Set the name of the target and source enumerations + * @param [in] enum_from input enumeration name + * @param [in] enum_to output enumeration name + * @retval ERR_INVALID_TYPE Enums not found in ddl + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setEnums(const std::string& enum_from, const std::string& enum_to); + + /** + * Returns default value + */ + int64_t getDefault() const; + + /** + * Returns default value as string + */ + std::string getDefaultStr() const; + + /** + * Set default value as string + * @param [in] default_value string for default value + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDefault(const std::string& default_value); + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic ignored "-Wattributes" // standard type attributes are ignored when used in templates +#endif + + /** + * Returns conversion list + */ + const std::map& getConversions() const; + + /** + * Returns conversion list as string + */ + const std::map& getConversionsStr() const; + + /** + * Add a conversion as string + * @param [in] from string for source value + * @param [in] to string for target value + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result addConversion(const std::string& from, const std::string& to); + + /** + * Remove a conversion as string + * @param [in] from string for source value + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result removeConversion(const std::string& from); + + /** + * @overload + */ + bool isEqual(const MapTransformationBase& other) const; + + /** + * @overload + */ + double evaluate(double value) const; + + /// nodoc + MapTransformationBase* clone() const; + +private: + /** + * Initializes the transformation from a target-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDom(const a_util::xml::DOMElement& dom_element); + + /** + * Export transformation to a XML dom element + * + * @param [in] dom_element The dom element to be written + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Convert string values to integer values + * before were the integer values not filled, as the ddl is necessary for this + * + * @param [in] pDDLRef The ddl description + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_TYPE Inconsistency with ddl + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result convertValuesWithDDL(); + + /** + * Set the name of the target and source enumerations + * @param [in] enum_from input enumeration name + * @param [in] enum_to output enumeration name + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setEnumsStr(const std::string& enum_from, const std::string& enum_to); + + /** + * Set default value as string + * @param [in] default_value string for default value + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setDefaultStr(const std::string& default_value); + + /** + * Add a conversion as string + * @param [in] from string for source value + * @param [in] to string for target value + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result addConversionStr(const std::string& from, const std::string& to); + +private: + /// @cond nodoc + friend class MapTransformationBase; + std::string _enum_from; + std::string _enum_to; + std::string _default_value; + typedef std::map MapStrConversionList; + MapStrConversionList _conversions; + int64_t _default_int; + std::map _conversions_int; + /// @endcond +}; + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic warning "-Wattributes" // standard type attributes are ignored when used in templates +#endif + +/// Public composite types used in the mapping::oo namespace +typedef std::vector MapTransformationList; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_TRANSFORMATION_H diff --git a/mapping/configuration/map_trigger.cpp b/mapping/configuration/map_trigger.cpp new file mode 100644 index 0000000..daca49d --- /dev/null +++ b/mapping/configuration/map_trigger.cpp @@ -0,0 +1,592 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "map_trigger.h" + +#include +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "map_configuration.h" + +namespace mapping +{ +namespace oo +{ + //define all needed error types and values locally + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-40, ERR_INVALID_STATE) +} +} + +using namespace mapping::oo; + +MapTriggerBase::MapTriggerBase(MapConfiguration* pConfig) : _config(pConfig), _is_valid(true) +{ +} + +MapTriggerBase::~MapTriggerBase() +{ +} + +bool MapTriggerBase::isValid() const +{ + return _is_valid; +} + +bool MapTriggerBase::checkValidity() +{ + if(isOk(_config->checkTriggerType(this))) + { + _is_valid = true; + } + else + { + _is_valid = false; + } + return _is_valid; +} + +std::string MapTriggerBase::getSourceDependency() const +{ + return std::string(); +} + +a_util::result::Result MapTriggerBase::setSourceDependency(const std::string& strNewName) +{ + MapSignalTrigger* pMapSTrigger = + dynamic_cast(this); + if(pMapSTrigger) + { + return pMapSTrigger->setVariableNoTypeCheck(strNewName); + } + oo::MapDataTrigger* pMapDTrigger = + dynamic_cast(this); + if(pMapDTrigger) + { + return pMapDTrigger->setSourceNoTypeCheck(strNewName); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTriggerBase::createFromDOM(MapConfiguration* pConfig, const a_util::xml::DOMElement& oTrigger, + MapTriggerBase*& pDestination) +{ + // parse attributes + const a_util::xml::DOMAttributes mapAttrs = oTrigger.getAttributes(); + a_util::xml::DOMAttributes::const_iterator it = mapAttrs.find("type"); + if (it == mapAttrs.end() || it->second.empty()) + { + pConfig->appendError("Missing type attribute"); + return ERR_INVALID_ARG; + } + + if (it->second == "periodic") + { + MapPeriodicTrigger* pTrig = new MapPeriodicTrigger(pConfig); + if (isFailed(pTrig->loadFromDom(oTrigger))) + { + delete pTrig; + return ERR_INVALID_ARG; + } + + pDestination = pTrig; + return a_util::result::SUCCESS; + } + + if (it->second == "signal") + { + MapSignalTrigger* pTrig = new MapSignalTrigger(pConfig); + if (isFailed(pTrig->loadFromDom(oTrigger))) + { + delete pTrig; + return ERR_INVALID_ARG; + } + + pDestination = pTrig; + return a_util::result::SUCCESS; + } + + if (it->second == "data") + { + MapDataTrigger* pTrig = new MapDataTrigger(pConfig); + if (isFailed(pTrig->loadFromDom(oTrigger))) + { + delete pTrig; + return ERR_INVALID_ARG; + } + + pDestination = pTrig; + return a_util::result::SUCCESS; + } + + pConfig->appendError(a_util::strings::format("Unknown type '%s'", + it->second.c_str())); + + return ERR_INVALID_ARG; +} + +a_util::result::Result MapTriggerBase::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setName("trigger"); + + const MapPeriodicTrigger* pMapPTrigger = + dynamic_cast(this); + if(pMapPTrigger) + { + return pMapPTrigger->writeToDOM(oDOMElement); + } + + const MapSignalTrigger* pMapSTrigger = + dynamic_cast(this); + if(pMapSTrigger) + { + return pMapSTrigger->writeToDOM(oDOMElement); + } + + const oo::MapDataTrigger* pMapDTrigger = + dynamic_cast(this); + if(pMapDTrigger) + { + return pMapDTrigger->writeToDOM(oDOMElement); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MapTriggerBase::checkTriggerReferences() const +{ + const MapSignalTrigger* pMapSTrigger = + dynamic_cast(this); + if(pMapSTrigger) + { + const MapSource* pSrcInstance = _config->getSource(pMapSTrigger->getVariable()); + if (!pSrcInstance) + { + _config->appendError( + a_util::strings::format("Trigger references unknown '%s'", + pMapSTrigger->getVariable().c_str())); + return ERR_INVALID_ARG; + } + } + const oo::MapDataTrigger* pMapDTrigger = + dynamic_cast(this); + if(pMapDTrigger) + { + const MapSource* pSrcInstance = _config->getSource(pMapDTrigger->getSource()); + if (!pSrcInstance) + { + _config->appendError( + a_util::strings::format("Assignment references unknown '%s'", + pMapDTrigger->getSource().c_str())); + return ERR_INVALID_ARG; + } + } + return a_util::result::SUCCESS; +} + +/** +* Periodic Trigger +**/ + +MapPeriodicTrigger::MapPeriodicTrigger(MapConfiguration* pConfig) : + MapTriggerBase(pConfig), _period(0) +{ +} + +double MapPeriodicTrigger::getPeriod() const +{ + return _period; +} + +a_util::result::Result MapPeriodicTrigger::setPeriod(const std::string& strPeriod, + const std::string& strUnit) +{ + a_util::result::Result res = a_util::result::SUCCESS; + if (!a_util::strings::isUInt32(strPeriod) || strPeriod.find('-') != std::string::npos || + strPeriod.find('+') != std::string::npos) + { + _config->appendError( + "Invalid period attribute for periodic trigger (expected positive integer)"); + res = ERR_INVALID_ARG; + } + + if(!(strUnit == "us" || strUnit == "ms" + || strUnit == "s")) + { + _config->appendError( + "Invalid unit attribute for periodic trigger (expected us, ms or s)"); + res = ERR_INVALID_ARG; + } + + if(isOk(res)) + { + uint32_t nPeriod = a_util::strings::toUInt32(strPeriod); + + if (strUnit == "us") + { + _period = double(nPeriod) / 1000.0; + } + else if (strUnit == "ms") + { + _period = nPeriod; + } + else if (strUnit == "s") + { + _period = double(nPeriod) * 1000.0; + } + } + return res; +} + +a_util::result::Result MapPeriodicTrigger::loadFromDom(const a_util::xml::DOMElement& oTrigger) +{ + a_util::result::Result res = a_util::result::SUCCESS; + const a_util::xml::DOMAttributes mapAttrs = oTrigger.getAttributes(); + a_util::xml::DOMAttributes::const_iterator itPeriod = mapAttrs.find("period"); + if (itPeriod == mapAttrs.end() || itPeriod->second.empty()) + { + _config->appendError("Missing period attribute for periodic trigger"); + res = ERR_INVALID_ARG; + } + + a_util::xml::DOMAttributes::const_iterator itUnit = mapAttrs.find("unit"); + if (itUnit == mapAttrs.end() || itUnit->second.empty()) + { + _config->appendError("Missing unit attribute for periodic trigger (expected us, ms or s)"); + res = ERR_INVALID_ARG; + } + + if(isOk(res)) + { + std::string strUnit = itUnit->second; + a_util::strings::trim(strUnit); + res = setPeriod(itPeriod->second, strUnit); + } + + return res; +} + +a_util::result::Result MapPeriodicTrigger::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setAttribute("type", "periodic"); + if(_period == ceil(_period)) + { + if((_period/1000) == ceil(_period/1000)) + { + oDOMElement.setAttribute("period", a_util::strings::format("%d", (uint32_t)floor(_period/1000))); + oDOMElement.setAttribute("unit", "s"); + } + else + { + oDOMElement.setAttribute("period", a_util::strings::format("%d", (uint32_t)floor(_period))); + oDOMElement.setAttribute("unit", "ms"); + } + } + else + { + oDOMElement.setAttribute("period", a_util::strings::format("%d", (uint32_t)floor(_period*1000))); + oDOMElement.setAttribute("unit", "us"); + } + return a_util::result::SUCCESS; +} + +MapTriggerBase* MapPeriodicTrigger::clone() const +{ + return new MapPeriodicTrigger(*this); +} + +bool MapPeriodicTrigger::isEqual(const MapTriggerBase& oOther) const +{ + const MapPeriodicTrigger* p = dynamic_cast(&oOther); + if (p) + { + return getPeriod() == p->getPeriod(); + } + + return false; +} + +/** +* Signal Trigger +**/ +MapSignalTrigger::MapSignalTrigger(MapConfiguration* pConfig) : MapTriggerBase(pConfig) +{ +} + +std::string MapSignalTrigger::getSourceDependency() const +{ + return _variable; +} + +const std::string& MapSignalTrigger::getVariable() const +{ + return _variable; +} + +a_util::result::Result MapSignalTrigger::setVariable(const std::string& strSignalName) +{ + if(!_config) + { + _is_valid = false; + return ERR_INVALID_STATE; + } + setVariableNoTypeCheck(strSignalName); + if(isFailed(_config->resetErrors())) + { + _is_valid = false; + return ERR_INVALID_STATE; + } + + const MapSource* pSrcInstance = _config->getSource(_variable); + if (!pSrcInstance) + { + _config->appendError( + a_util::strings::format("Trigger references unknown '%s'", + _variable.c_str())); + _variable.clear(); + _is_valid = false; + return ERR_INVALID_ARG; + } + _is_valid = true; + return a_util::result::SUCCESS; +} + +a_util::result::Result MapSignalTrigger::loadFromDom(const a_util::xml::DOMElement& oTrigger) +{ + const a_util::xml::DOMAttributes mapAttrs = oTrigger.getAttributes(); + a_util::xml::DOMAttributes::const_iterator it = mapAttrs.find("variable"); + if (it == mapAttrs.end() || it->second.empty()) + { + _config->appendError("Missing variable attribute for signal trigger"); + return ERR_INVALID_ARG; + } + return setVariableNoTypeCheck(it->second); +} + +a_util::result::Result MapSignalTrigger::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setAttribute("type", "signal"); + oDOMElement.setAttribute("variable", _variable); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapSignalTrigger::setVariableNoTypeCheck(const std::string& strSignalName) +{ + _variable = strSignalName; + return a_util::result::SUCCESS; +} + + +MapTriggerBase* MapSignalTrigger::clone() const +{ + return new MapSignalTrigger(*this); +} + +bool MapSignalTrigger::isEqual(const MapTriggerBase& oOther) const +{ + const MapSignalTrigger* p = dynamic_cast(&oOther); + if (p) + { + return getVariable() == p->getVariable(); + } + + return false; +} + +/** +* Data Trigger +**/ +MapDataTrigger::MapDataTrigger(MapConfiguration* pConfig) : MapTriggerBase(pConfig) +{ +} + +std::string MapDataTrigger::getSourceDependency() const +{ + return _source; +} + +const std::string& MapDataTrigger::getVariable() const +{ + return _variable; +} + +const std::string& MapDataTrigger::getSource() const +{ + return _source; +} + + + +a_util::result::Result MapDataTrigger::setSourceNoTypeCheck(const std::string& strSource) +{ + _source = strSource; + return a_util::result::SUCCESS; +} + +const std::string& MapDataTrigger::getOperator() const +{ + return _operator; +} + +double MapDataTrigger::getValue() const +{ + return _value; +} + +a_util::result::Result MapDataTrigger::loadFromDom(const a_util::xml::DOMElement& oTrigger) +{ + const a_util::xml::DOMAttributes mapAttrs = oTrigger.getAttributes(); + a_util::xml::DOMAttributes::const_iterator itVariable = mapAttrs.find("variable"); + a_util::result::Result res = a_util::result::SUCCESS; + if (itVariable == mapAttrs.end() || itVariable->second.empty()) + { + _config->appendError("Missing variable attribute for data trigger"); + res = ERR_INVALID_ARG; + } + + a_util::xml::DOMAttributes::const_iterator itOperator = mapAttrs.find("operator"); + if (itOperator == mapAttrs.end() || itOperator->second.empty()) + { + _config->appendError("Missing operator attribute for data trigger"); + res = ERR_INVALID_ARG; + } + + a_util::xml::DOMAttributes::const_iterator itValue = mapAttrs.find("value"); + if (itValue == mapAttrs.end() || itValue->second.empty()) + { + _config->appendError("Missing value attribute for data trigger (expected a source name)"); + res = ERR_INVALID_ARG; + } + + if(isOk(res)) + { + res = setComparisonNoTypeCheck(itVariable->second, itOperator->second, itValue->second); + } + + return res; +} + +a_util::result::Result MapDataTrigger::writeToDOM(a_util::xml::DOMElement& oDOMElement) const +{ + oDOMElement.setAttribute("type", "data"); + oDOMElement.setAttribute("variable", _source + "." + _variable); + oDOMElement.setAttribute("operator", _operator); + oDOMElement.setAttribute("value", a_util::strings::format("%g", _value)); + return a_util::result::SUCCESS; +} + +a_util::result::Result MapDataTrigger::setComparisonNoTypeCheck(const std::string& strSourceElementPath, + const std::string& strOperator, const std::string& strValue) +{ + a_util::result::Result res = a_util::result::SUCCESS; + + _variable = strSourceElementPath; + a_util::strings::trim(_variable); + _source.clear(); + + // parse source out of + size_t idx = _variable.find('.'); + if (idx != std::string::npos) + { + _source = _variable.substr(0, idx); + _variable = _variable.substr(idx + 1); + } + else + { + _variable.clear(); + _config->appendError("Variable attribute for data trigger should be a signal element (expected [Signal].[Element])"); + res = ERR_INVALID_ARG; + } + if (!(strOperator == "less_than" || strOperator == "greater_than" || + strOperator == "less_than_equal" || strOperator == "greater_than_equal" || + strOperator == "equal" || strOperator == "not_equal")) + { + _operator.clear(); + _config->appendError( + "Invalid operator attribute for data trigger (expected less_than, greater_than, " + "less_than_equal, greater_than_equal, equal or not_equal)"); + res = ERR_INVALID_ARG; + } + else + { + _operator = strOperator; + } + + if (!a_util::strings::isDouble(strValue)) + { + _value = 0; + _config->appendError( + "Invalid value attribute for data trigger (expected floating point value)"); + res = ERR_INVALID_ARG; + } + else + { + _value = a_util::strings::toDouble(strValue); + } + + return res; +} + +MapTriggerBase* MapDataTrigger::clone() const +{ + return new MapDataTrigger(*this); +} + +bool MapDataTrigger::isEqual(const MapTriggerBase& oOther) const +{ + const MapDataTrigger* p = dynamic_cast(&oOther); + if (p) + { + return getVariable() == p->getVariable() && getSource() == p->getSource() && + getOperator() == p->getOperator() && getValue() == p->getValue(); + } + + return false; +} + +a_util::result::Result MapDataTrigger::setComparison(const std::string& strSourceElementPath, + const std::string& strOperator, const std::string& strValue) +{ + if(!_config) + { + _is_valid = false; + return ERR_INVALID_STATE; + } + RETURN_IF_FAILED(_config->resetErrors()); + RETURN_IF_FAILED(setComparisonNoTypeCheck(strSourceElementPath, strOperator, strValue)); + const MapSource* pSrcInstance = _config->getSource(_source); + if (!pSrcInstance) + { + _config->appendError( + a_util::strings::format("Assignment references unknown '%s'", + _source.c_str())); + _is_valid = false; + return ERR_INVALID_ARG; + } + a_util::result::Result nRes = _config->checkTriggerType(this); + if(isFailed(nRes)) + { + _is_valid = false; + } + if(isOk(nRes)) + { + _is_valid = true; + } + return nRes; +} diff --git a/mapping/configuration/map_trigger.h b/mapping/configuration/map_trigger.h new file mode 100644 index 0000000..31f83f2 --- /dev/null +++ b/mapping/configuration/map_trigger.h @@ -0,0 +1,365 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef HEADER_MAP_TRIGGER_H +#define HEADER_MAP_TRIGGER_H + +#include "a_util/result.h" +#include "a_util/xml.h" + +namespace mapping +{ +namespace oo +{ + class MapConfiguration; +/** + * cMapTrigger forms a base class for a trigger contained in the configuration + */ +class MapTriggerBase +{ +public: + /** + * CTOR + */ + MapTriggerBase(MapConfiguration* config); + + /** + * DTOR + */ + virtual ~MapTriggerBase(); + + /** + * Returns the validity for the current description + */ + bool isValid() const; + + /** + * returns an optional dependency on a source name + */ + virtual std::string getSourceDependency() const; + + /** + * Polymorphic comparison method + */ + virtual bool isEqual(const MapTriggerBase& other) const = 0; + + /** + * Check Trigger validity and set validity flag + * @retval validity flag + **/ + bool checkValidity(); + + /** + * Checks the configuration for consistency of a new trigger + * @param [in] _name The name of the target + * @param [in] _type The type of the target + * @retval ERR_INVALID_ARG Reference not found in Configuration + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result checkTriggerReferences() const; + +protected: + /** + * Polymorphic clone method + */ + virtual MapTriggerBase* clone() const = 0; + +private: + /** + * creates a polymorphic trigger instance from a trigger-dom element + * @param [in] oConfig The configuration + * @param [in] dom_element The dom element from which to import + * @param [out] destination The Trigger object to fill + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + static a_util::result::Result createFromDOM(MapConfiguration* config, const a_util::xml::DOMElement& dom_element, + MapTriggerBase*& destination); + + /** + * Export trigger to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Change name for source signal + **/ + a_util::result::Result setSourceDependency(const std::string& new_name); + +protected: + /// @cond nodoc + friend class MapConfiguration; + friend class MapTarget; + MapConfiguration* _config; + bool _is_valid; + /// @endcond +}; + +/// implementation of a periodic trigger in the configuration api +class MapPeriodicTrigger : public MapTriggerBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + */ + MapPeriodicTrigger(MapConfiguration* config); + + /** + * Returns the period of the trigger in ms + */ + double getPeriod() const; + + /** + * Set the period + * @param [in] period The period as integer + * @param [in] unit The unit ("us", "ms" or "s") + **/ + a_util::result::Result setPeriod(const std::string& period, +const std::string& unit); + + /** + * Polymorphic comparison method (impl. from MapTriggerBase) + * @param [in] other The other instance + * @returns True if both are equal + */ + bool isEqual(const MapTriggerBase& other) const; + +protected: + // implements MapTriggerBase + MapTriggerBase* clone() const; + +private: + /** + * creates a trigger instance from a trigger-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDom(const a_util::xml::DOMElement& dom_element); + + /** + * Export trigger to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + +private: + /// @cond nodoc + friend class MapTriggerBase; + double _period; + /// @endcond +}; + +/// implementation of a signal trigger in the configuration api +class MapSignalTrigger : public MapTriggerBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + */ + MapSignalTrigger(MapConfiguration* config); + + /** + * Overrides MapTriggerBase + */ + virtual std::string getSourceDependency() const; + + /** + * Returns the source signal + */ + const std::string& getVariable() const; + + /** + * Set the source signal + * @param [in] signal_name The source signal name + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setVariable(const std::string& signal_name); + + /** + * Polymorphic comparison method (impl. from MapTriggerBase) + * @param [in] other The other instance + * @returns True if both are equal + */ + bool isEqual(const MapTriggerBase& other) const; + +protected: + // implements MapTriggerBase + MapTriggerBase* clone() const; + +private: + /** + * creates a trigger instance from a trigger-dom element + * @param [in] dom_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDom(const a_util::xml::DOMElement& dom_element); + + /** + * Export trigger to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Set the source signal + * @param [in] signal_name The source signal name + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setVariableNoTypeCheck(const std::string& signal_name); + +private: + /// @cond nodoc + friend class MapConfiguration; + friend class MapTriggerBase; + std::string _variable; + bool _is_valid; + /// @endcond +}; + +/// implementation of a data trigger in the configuration api +class MapDataTrigger : public MapTriggerBase +{ +public: + /** + * CTOR + * @param [in] oConfig The configuration + */ + MapDataTrigger(MapConfiguration* config); + + /** + * Overrides MapTriggerBase + */ + virtual std::string getSourceDependency() const; + + /** + * Returns the variable to compare + */ + const std::string& getVariable() const; + + /** + * Returns the source signal + */ + const std::string& getSource() const; + + /** + * Returns the operator for the comparison + */ + const std::string& getOperator() const; + + /** + * Returns the value to compare to + */ + double getValue() const; + + /** + * Set the comparison + * @param [in] source_element_path The path to the element ([SourceSignal].[Element]) + * @param [in] comp_operator The operator for the comparison + * @param [in] value The value to compare to + * @retval ERR_INVALID_ARG Missing attribute + * @retval ERR_INVALID_TYPE Definition is inconsistent with ddl + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setComparison(const std::string& source_element_path, + const std::string& comp_operator, + const std::string& value); + + + + /** + * Polymorphic comparison method (impl. from MapTriggerBase) + * @param [in] other The other instance + * @returns True if both are equal + */ + bool isEqual(const MapTriggerBase& other) const; + +protected: // implements MapTriggerBase + MapTriggerBase* clone() const; + +private: + /** + * creates a trigger instance from a trigger-dom element + * @param [in] trigger_element The dom element from which to import + * @param [out] lstErrors The error list for debug + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result loadFromDom(const a_util::xml::DOMElement& trigger_element); + + /** + * Export trigger to a XML dom element + * + * @param [in] dom_element The dom element from which to import + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result writeToDOM(a_util::xml::DOMElement& dom_element) const; + + /** + * Set the comparison + * @param [in] source_element_path The path to the element ([SourceSignal].[Element]) + * @param [in] comp_operator The operator for the comparison + * @param [in] value The value to compare to + * @retval ERR_INVALID_ARG Missing attribute + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setComparisonNoTypeCheck(const std::string& source_element_path, + const std::string& comp_operator, + const std::string& value); + + /** + * Set the source + * @param [in] source The source signal + * @retval a_util::result::SUCCESS Everything went fine + **/ + a_util::result::Result setSourceNoTypeCheck(const std::string& source); + +private: + /// @cond nodoc + friend class MapConfiguration; + friend class MapTriggerBase; + std::string _variable; + std::string _source; + std::string _operator; + double _value; + /// @endcond +}; + +/// Public composite types used in the mapping::oo namespace +typedef std::vector MapTriggerList; + +} // namespace oo +} // namespace mapping + +#endif // HEADER_MAP_TRIGGER_H diff --git a/mapping/ddl_helper.cpp b/mapping/ddl_helper.cpp new file mode 100644 index 0000000..c072975 --- /dev/null +++ b/mapping/ddl_helper.cpp @@ -0,0 +1,135 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ +#include "ddl_helper.h" + +#include +#include + +#include "a_util/strings.h" + +using namespace mapping; + +//define all needed error types and values locally +_MAKE_RESULT(-5, ERR_INVALID_ARG) + +namespace mapping +{ + _MAKE_RESULT(-20, ERR_NOT_FOUND) +} + +static a_util::result::Result ParseElementPath(const std::string& strPath, + std::vector >& vecPath) +{ + vecPath.clear(); + + std::vector lstPath = a_util::strings::split(strPath, "."); + + for (std::vector::const_iterator it = lstPath.begin(); it != lstPath.end(); ++it) + { + const std::string& strPathElem = *it; + + std::pair oPair; + size_t idxBegin = strPathElem.find('['); + if (idxBegin != std::string::npos) + { + size_t idxEnd = strPathElem.find(']', idxBegin); + if (idxEnd == std::string::npos || idxEnd != strPathElem.size() - 1) + { + return ERR_INVALID_ARG; + } + oPair.first = strPathElem.substr(0, idxBegin); + std::string strSubscript = strPathElem.substr(idxBegin + 1); + strSubscript.erase(strSubscript.size() - 1); + int nSubscript = a_util::strings::toInt32(strSubscript); + if (!a_util::strings::isInt64(strSubscript) || nSubscript < 0) + { + return ERR_INVALID_ARG; + } + oPair.second = nSubscript; + } + else + { + oPair.first = strPathElem; + oPair.second = -1; + } + + vecPath.push_back(oPair); + } + + return a_util::result::SUCCESS; +} + +static const ddl::DDLElement* GetNestedElement(const ddl::DDLElementVec& vecElements, + std::vector > vecPath) +{ + std::pair oPair = vecPath.front(); + vecPath.erase(vecPath.begin()); + + for (ddl::DDLElementItConst it = vecElements.begin(); it != vecElements.end(); ++it) + { + if ((*it)->getName() == oPair.first) + { + // check array size + if (oPair.second > -1) + { + if ((*it)->getArraysize() <= (unsigned int)oPair.second) + { + return NULL; + } + } + + if (vecPath.empty()) + { + return *it; + } + else + { + const ddl::DDLComplex* pCmplx = + dynamic_cast((*it)->getTypeObject()); + if (pCmplx) + { + return GetNestedElement(pCmplx->getElements(), vecPath); + } + } + break; + } + } + + return NULL; +} + +a_util::result::Result DDLHelper::LookupElement(const ddl::DDLComplex& oStruct, + const std::string& strPath, const ddl::DDLElement*& pElement, bool& bIsArrayElement) +{ + std::vector > vecPath; + if (isFailed(ParseElementPath(strPath, vecPath))) + { + return ERR_NOT_FOUND; + } + + const ddl::DDLElement* pElem = GetNestedElement(oStruct.getElements(), vecPath); + if (pElem) + { + pElement = pElem; + bIsArrayElement = vecPath.back().second > -1; + return a_util::result::SUCCESS; + } + + return ERR_NOT_FOUND; +} diff --git a/mapping/ddl_helper.h b/mapping/ddl_helper.h new file mode 100644 index 0000000..8aae551 --- /dev/null +++ b/mapping/ddl_helper.h @@ -0,0 +1,88 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + + +#ifndef HEADER_DDL_HELPER_H +#define HEADER_DDL_HELPER_H + +#include "a_util/result.h" + +#include "ddlrepresentation/ddlcomplex.h" +#include "ddlrepresentation/ddlelement.h" + +namespace mapping +{ + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic ignored "-Wattributes" // standard type attributes are ignored when used in templates +#endif + +/// String -> Datatype Enum Map +typedef std::map TypeMap; + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic warning "-Wattributes" // standard type attributes are ignored when used in templates +#endif + +/// Enum for all relevant data types +enum DataTypes +{ + e_uint8 = 1, + e_uint16, + e_uint32, + e_uint64, + e_int8, + e_int16, + e_int32, + e_int64, + e_float32, + e_float64, + e_bool, + e_char, +}; + +/** + * DDLHelper provides common DDL helper functionality needed + * by both the mapping configuration and runtime + */ +class DDLHelper +{ +public: + /** + * \c LookupElement finds a DDLElement located inside a DDLComplex + * by means of a path string. If the path represents an array element, + * the array itself is returned. + * + * @param [in] ddl_struct The base structure of the path + * @param [in] path The path to be looked up + * @param [out] element The destination target parameter + * @param [out] is_array_element Flag indicating whether the path referenced an array element + * + * @retval ERR_NOT_FOUND The element was not found or the path is invalid + * @retval a_util::result::SUCCESS The path was found and oElement contains the element + */ + static a_util::result::Result LookupElement(const ddl::DDLComplex& ddl_struct, + const std::string& path, const ddl::DDLElement*& element, bool& is_array_element); +}; + +} // namespace mapping + +#endif // HEADER_DDL_HELPER_H diff --git a/mapping/engine/data_trigger.cpp b/mapping/engine/data_trigger.cpp new file mode 100644 index 0000000..80582e9 --- /dev/null +++ b/mapping/engine/data_trigger.cpp @@ -0,0 +1,122 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "data_trigger.h" + +using namespace mapping::rt; + +DataTrigger::DataTrigger(IMappingEnvironment& oEnv, + const std::string& strTriggerName, + const std::string& strVariableName, + const std::string& strOperator, + const double& f64Value) : _env(oEnv), + _name(strTriggerName), _variable_name(strVariableName), + _value(f64Value), _is_running(false) +{ + if(strOperator == "equal") + { + _operator = e_equal; + } + else if(strOperator == "not_equal") + { + _operator = e_not_equal; + } + else if(strOperator == "less_than") + { + _operator = e_less_than; + } + else if(strOperator == "greater_than") + { + _operator = e_greater_than; + } + else if(strOperator == "less_than_equal") + { + _operator = e_less_than_equal; + } + else if(strOperator == "greater_than_equal") + { + _operator = e_greater_than_equal; + } +} + +DataTrigger::~DataTrigger() +{ + stop(); +} + +a_util::result::Result DataTrigger::start() +{ + _is_running = true; + return a_util::result::SUCCESS; +} + +a_util::result::Result DataTrigger::stop() +{ + _is_running = false; + return a_util::result::SUCCESS; +} + +bool DataTrigger::compare(double f64Val) +{ + switch(_operator) + { + case e_equal: + return f64Val == _value; + case e_not_equal: + return f64Val != _value; + case e_less_than: + return f64Val < _value; + case e_greater_than: + return f64Val > _value; + case e_less_than_equal: + return f64Val <= _value; + case e_greater_than_equal: + return f64Val >= _value; + default: + assert(false); + } + + return false; +} + +a_util::result::Result DataTrigger::transmit() +{ + if(_is_running) + { + for(TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it) + { + const void* pBuffer = NULL; + size_t szBuffer = 0; + (*it)->aquireReadLock(); + (*it)->updateTriggerFunctionValues(); + if (isOk((*it)->getBufferRef(pBuffer, szBuffer))) + { + _env.sendTarget((handle_t)*it, pBuffer, szBuffer, 0); + } + (*it)->releaseReadLock(); + } + } + + return a_util::result::SUCCESS; +} + +const std::string& DataTrigger::getVariable() const +{ + return _variable_name; +} diff --git a/mapping/engine/data_trigger.h b/mapping/engine/data_trigger.h new file mode 100644 index 0000000..fe16861 --- /dev/null +++ b/mapping/engine/data_trigger.h @@ -0,0 +1,109 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DATA_TRIGGER_HEADER +#define DATA_TRIGGER_HEADER + +#include "trigger.h" + +namespace mapping +{ +namespace rt +{ + +enum Operator +{ + e_equal = 1, + e_not_equal, + e_less_than, + e_greater_than, + e_less_than_equal, + e_greater_than_equal +}; + +/// DataTrigger implements a concrete periodic trigger in the runtime +class DataTrigger : public TriggerBase +{ +public: + /** + * CTOR + * @param [in] env The mapping environment + * @param [in] trigger_name The name of the trigger + * @param [in] fPeriod The period of the trigger + */ + DataTrigger(IMappingEnvironment& env, + const std::string& trigger_name, + const std::string& variable_name, + const std::string& comp_operator, + const double& value); + + /** + * DTOR + */ + ~DataTrigger(); + + /** + * Method to start trigger + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + a_util::result::Result start(); + + /** + * Method to stop trigger + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result stop(); + + /** + * Method to transmit targets + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result transmit(); + + /** + * Method to make the comparison + * + * @retval a_util::result::SUCCESS Everything went fine + */ + bool compare(double value); + + /** + * Returns the period of the trigger in ms + */ + const std::string& getVariable() const; + + + +private: + IMappingEnvironment& _env; + std::string _name; + std::string _variable_name; + Operator _operator; + double _value; + bool _is_running; + /// @endcond +}; + +} // namespace rt +} // namespace mapping +#endif //DATA_TRIGGER_HEADER diff --git a/mapping/engine/element.cpp b/mapping/engine/element.cpp new file mode 100644 index 0000000..1d48e46 --- /dev/null +++ b/mapping/engine/element.cpp @@ -0,0 +1,445 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "element.h" + +using namespace mapping; +using namespace mapping::rt; + +namespace mapping +{ +namespace rt +{ + //define all needed error types and values locally + _MAKE_RESULT(-3, ERR_UNEXPECTED) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-42, ERR_INVALID_TYPE) +} +} + +/// Helper method that sets a casted value in the coder +template +static void SetCastedValue(void* pDestination, unsigned int nArrayIndex, T* pData, + uint32_t type32) +{ + switch (type32) + { + case e_uint8: + { + uint8_t ui8Temp = static_cast(*pData); + a_util::memory::copy((uint8_t*)pDestination + nArrayIndex, sizeof(uint8_t), &ui8Temp, sizeof(uint8_t)); + } + break; + case e_uint16: + { + uint16_t ui16Temp = static_cast(*pData); + a_util::memory::copy((uint16_t*)pDestination + nArrayIndex, sizeof(uint16_t), &ui16Temp, sizeof(uint16_t)); + } + break; + case e_uint32: + { + uint32_t ui32Temp = static_cast(*pData); + a_util::memory::copy((uint32_t*)pDestination + nArrayIndex, sizeof(uint32_t), &ui32Temp, sizeof(uint32_t)); + } + break; + case e_uint64: + { + uint64_t ui64Temp = static_cast(*pData); + a_util::memory::copy((uint64_t*)pDestination + nArrayIndex, sizeof(uint64_t), &ui64Temp, sizeof(uint64_t)); + } + break; + case e_int8: + { + int8_t i8Temp = static_cast(*pData); + a_util::memory::copy((int8_t*)pDestination + nArrayIndex, sizeof(int8_t), &i8Temp, sizeof(int8_t)); + } + break; + case e_int16: + { + int16_t i16Temp = static_cast(*pData); + a_util::memory::copy((int16_t*)pDestination + nArrayIndex, sizeof(int16_t), &i16Temp, sizeof(int16_t)); + } + break; + case e_int32: + { + int32_t i32Temp = static_cast(*pData); + a_util::memory::copy((int32_t*)pDestination + nArrayIndex, sizeof(int32_t), &i32Temp, sizeof(int32_t)); + } + break; + case e_int64: + { + int64_t i64Temp = static_cast(*pData); + a_util::memory::copy((int64_t*)pDestination + nArrayIndex, sizeof(int64_t), &i64Temp, sizeof(int64_t)); + } + break; + case e_float32: + { + float f32Temp = static_cast(*pData); + a_util::memory::copy((float*)pDestination + nArrayIndex, sizeof(float), &f32Temp, sizeof(float)); + } + break; + case e_float64: + { + double f64Temp = static_cast(*pData); + a_util::memory::copy((double*)pDestination + nArrayIndex, sizeof(double), &f64Temp, sizeof(double)); + } + break; + case e_bool: + { + bool bTemp = *pData != 0 ? true : false; + a_util::memory::copy((bool*)pDestination + nArrayIndex, sizeof(bool), &bTemp, sizeof(bool)); + } + break; + case e_char: + { + char cTemp = static_cast(*pData); + a_util::memory::copy((char*)pDestination + nArrayIndex, sizeof(char), &cTemp, sizeof(char)); + } + break; + default: + assert(false); + break; + } +} + +template <> +void SetCastedValue(void* pDestination, unsigned int nArrayIndex, bool* pData, + uint32_t type32) +{ + int nBool = *pData ? 1 : 0; + switch (type32) + { + case e_uint8: + { + uint8_t ui8Temp = static_cast(nBool); + a_util::memory::copy((uint8_t*)pDestination + nArrayIndex, sizeof(uint8_t), &ui8Temp, sizeof(uint8_t)); + } + break; + case e_uint16: + { + uint16_t ui16Temp = static_cast(nBool); + a_util::memory::copy((uint16_t*)pDestination + nArrayIndex, sizeof(uint16_t), &ui16Temp, sizeof(uint16_t)); + } + break; + case e_uint32: + { + uint32_t ui32Temp = static_cast(nBool); + a_util::memory::copy((uint32_t*)pDestination + nArrayIndex, sizeof(uint32_t), &ui32Temp, sizeof(uint32_t)); + } + break; + case e_uint64: + { + uint64_t ui64Temp = static_cast(nBool); + a_util::memory::copy((uint64_t*)pDestination + nArrayIndex, sizeof(uint64_t), &ui64Temp, sizeof(uint64_t)); + } + break; + case e_int8: + { + int8_t i8Temp = static_cast(nBool); + a_util::memory::copy((int8_t*)pDestination + nArrayIndex, sizeof(int8_t), &i8Temp, sizeof(int8_t)); + } + break; + case e_int16: + { + int16_t i16Temp = static_cast(nBool); + a_util::memory::copy((int16_t*)pDestination + nArrayIndex, sizeof(int16_t), &i16Temp, sizeof(int16_t)); + } + break; + case e_int32: + { + int32_t i32Temp = static_cast(nBool); + a_util::memory::copy((int32_t*)pDestination + nArrayIndex, sizeof(int32_t), &i32Temp, sizeof(int32_t)); + } + break; + case e_int64: + { + int64_t i64Temp = static_cast(nBool); + a_util::memory::copy((int64_t*)pDestination + nArrayIndex, sizeof(int64_t), &i64Temp, sizeof(int64_t)); + } + break; + case e_float32: + { + float f32Temp = static_cast(nBool); + a_util::memory::copy((float*)pDestination + nArrayIndex, sizeof(float), &f32Temp, sizeof(float)); + } + break; + case e_float64: + { + double f64Temp = static_cast(nBool); + a_util::memory::copy((double*)pDestination + nArrayIndex, sizeof(double), &f64Temp, sizeof(double)); + } + break; + case e_bool: + a_util::memory::copy((bool*)pDestination + nArrayIndex, sizeof(bool), pData, sizeof(bool)); + break; + case e_char: + { + char cTemp = static_cast(nBool); + a_util::memory::copy((char*)pDestination + nArrayIndex, sizeof(char), &cTemp, sizeof(char)); + } + break; + default: + assert(false); + break; + } +} + +template +static inline void TransformAndSetValueImpl(const void* pData, void* pDestination, + unsigned int nArraySize, const oo::MapTransformationBase* pTrans, uint32_t type32) +{ + assert(pTrans); + assert(pData); + for(unsigned int i = 0; i < nArraySize; i++) + { + double fValue = pTrans->evaluate(static_cast(*((T*)pData + i))); + SetCastedValue(pDestination, i, &fValue, type32); + } +} + +template +static inline void SetValueImpl(const void* pData, void* pDestination, unsigned int nArraySize, + uint32_t type32) +{ + assert(pData); + for(unsigned int i = 0; i < nArraySize; i++) + { + SetCastedValue(pDestination, i, (T*)pData + i, type32); + } +} + +TargetElement::TargetElement(Target* pTarget) : + _target(pTarget), _element_ptr(NULL), _type_int(0), + _type(NULL), _struct(NULL), + _array_size(0), _transformation(NULL) +{ + _type_map["tUInt8"] = e_uint8; + _type_map["tUInt16"] = e_uint16; + _type_map["tUInt32"] = e_uint32; + _type_map["tUInt64"] = e_uint64; + _type_map["tInt8"] = e_int8; + _type_map["tInt16"] = e_int16; + _type_map["tInt32"] = e_int32; + _type_map["tInt64"] = e_int64; + _type_map["tFloat32"] = e_float32; + _type_map["tFloat64"] = e_float64; + _type_map["tBool"] = e_bool; + _type_map["tChar"] = e_char; +} + +TargetElement::~TargetElement() +{ + delete _transformation; + _transformation = NULL; +} + +a_util::result::Result TargetElement::create(void* pElementPtr, ddl::IDDLDataType* pDataType, + const unsigned int nArraySize, const std::string& strElementName) +{ + _element_ptr = pElementPtr; + _array_size = nArraySize; + _element_name = strElementName; + + _type = dynamic_cast(pDataType); + _struct = dynamic_cast(pDataType); + _enum = dynamic_cast(pDataType); + + if (_enum) + { + _type = dynamic_cast(_enum->getTypeObject()); + if (!_type) + { + return ERR_UNEXPECTED; + } + + _enum = NULL; + } + + if(_type) + { + TypeMap::const_iterator it = _type_map.find(_type->getName()); + if(it != _type_map.end()) + { + _type_int = it->second; + } + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result TargetElement::setTransformation(const oo::MapTransformationBase* pTransformation) +{ + if (_transformation) + { + delete _transformation; + _transformation = NULL; + } + + if (pTransformation) + { + _transformation = pTransformation->clone(); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result TargetElement::setValue(const void* pData, uint32_t ui32SrcType, size_t szMem) +{ + // Scalars (and enums converted to scalars) + if(_type) + { + if(_transformation) + { + switch(ui32SrcType) + { + case e_uint8: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_uint16: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_uint32: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_uint64: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_int8: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_int16: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_int32: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_int64: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_float32: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_float64: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_bool: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + case e_char: + TransformAndSetValueImpl(pData, _element_ptr, _array_size, _transformation, _type_int); + break; + default: + return ERR_INVALID_TYPE; + } + } + else if(_type_int == ui32SrcType) + { + // Source and target have the same type + a_util::memory::copy(_element_ptr, szMem, pData, szMem); + } + else + { + // Source and target have different types + switch(ui32SrcType) + { + case e_uint8: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_uint16: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_uint32: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_uint64: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_int8: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_int16: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_int32: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_int64: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_float32: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_float64: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_bool: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + case e_char: + SetValueImpl(pData, _element_ptr, _array_size, _type_int); + break; + default: + return ERR_INVALID_TYPE; + } + } + } + else if(_struct) // Structures + { + // Transformations are not allowed + a_util::memory::copy(_element_ptr, szMem, pData, szMem); + } + else + { + return ERR_INVALID_ARG; + } + + return a_util::result::SUCCESS; +} + +Target* TargetElement::getTarget() +{ + return _target; +} + +a_util::result::Result TargetElement::setDefaultValue(const std::string& strDefault) +{ + // Scalars and arrays + if(_type) + { + double fVal = 0; + if(!strDefault.empty() && a_util::strings::isDouble(strDefault)) + { + fVal = a_util::strings::toDouble(strDefault); + } + + for(unsigned int i = 0; i < _array_size; i++) + { + SetCastedValue(_element_ptr, i, &fVal, _type_int); + } + } + + //Structures + if(_struct) + { + //TODO: What is default value for a structure? + return ERR_INVALID_ARG; + } + + return a_util::result::SUCCESS; +} diff --git a/mapping/engine/element.h b/mapping/engine/element.h new file mode 100644 index 0000000..5676ab6 --- /dev/null +++ b/mapping/engine/element.h @@ -0,0 +1,116 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef ELEMENT_HEADER +#define ELEMENT_HEADER + +#include "a_util/result.h" + +#include "ddlrepresentation/ddldatatype_intf.h" +#include "ddlrepresentation/ddldatatype.h" +#include "ddlrepresentation/ddlcomplex.h" +#include "ddlrepresentation/ddlenum.h" + +#include "mapping/configuration/map_transformation.h" +#include "mapping/ddl_helper.h" + +namespace mapping +{ +namespace rt +{ + +class Target; + +/// TargetElement represents a single signal element in the target +class TargetElement +{ +public: + /** + * CTOR + * @param[in] target The target containing this element + */ + TargetElement(Target* target); + + /** + * DTOR + */ + ~TargetElement(); + + /** + * Creation method to initialize the object + * @param [in] element_ptr The Pointer referencing the element in target buffer + * @param [in] pDatatType The element datatype + * @param [in] array_size The array size of the element + * @param [in] element_name The name of the element in Assignment, for debug only + * @returns Standard result + */ + a_util::result::Result create(void* element_ptr, ddl::IDDLDataType* data_type, + const unsigned int array_size, const std::string& element_name); + + /** + * Setter for transformation + * Write constant from Mapping or default value from DDL or 0 + * @param [in] transformation The transformation to apply for to element + * @returns Standard result + */ + a_util::result::Result setTransformation(const oo::MapTransformationBase* transformation); + + /** + * Method to give a default value to the element + * @param [in] default_value The default value as a string + * @returns Standard result + */ + a_util::result::Result setDefaultValue(const std::string& default_value); + + /** + * Setter value to the element + * @param [in] data The pointer referencing the source buffer + * @param [in] src_type The datatype of the source element + * @param [in] mem_size The size of the source buffer + * @returns Standard result + */ + a_util::result::Result setValue(const void* data, uint32_t src_type, size_t mem_size); + + /** + * Getter for the parent target reference + * @returns The target + */ + Target* getTarget(); + +private: + /// @cond nodoc + Target* _target; + void* _element_ptr; + TypeMap _type_map; + uint32_t _type_int; + ddl::DDLDataType* _type; + ddl::DDLComplex* _struct; + ddl::DDLEnum* _enum; + unsigned int _array_size; + const oo::MapTransformationBase* _transformation; + // For Debug only + std::string _element_name; + /// @endcond +}; + +typedef std::vector TargetElementList; + +} // namespace rt +} // namespace mapping +#endif //ELEMENT_HEADER diff --git a/mapping/engine/mapping_engine.cpp b/mapping/engine/mapping_engine.cpp new file mode 100644 index 0000000..dbe0f4b --- /dev/null +++ b/mapping/engine/mapping_engine.cpp @@ -0,0 +1,423 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "mapping_engine.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +namespace mapping +{ +namespace rt +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-5, ERR_INVALID_ARG) + _MAKE_RESULT(-16, ERR_NOT_IMPL) + _MAKE_RESULT(-40, ERR_INVALID_STATE) + _MAKE_RESULT(-42, ERR_INVALID_TYPE) +} +} + +using namespace mapping; +using namespace mapping::rt; + +MappingEngine::MappingEngine(IMappingEnvironment& oEnv): + _env(oEnv), _map_config(NULL), _running(false) +{ +} + +MappingEngine::~MappingEngine() +{ + stop(); + unmapAll(); +} + +a_util::result::Result MappingEngine::setConfiguration(const oo::MapConfiguration& oConfig) +{ + _map_config = oConfig; + return a_util::result::SUCCESS; +} + +a_util::result::Result MappingEngine::Map(const std::string& strTargetName, handle_t& hMappedSignal) +{ + a_util::result::Result nRes = a_util::result::SUCCESS; + + // If the target is already in the List, return invalid error + if(_targets.find(strTargetName) != _targets.end()) + { + nRes = ERR_INVALID_ARG; + } + + const oo::MapTarget* pMapTarget = NULL; + std::string strTargetDesc; + if (isOk(nRes)) + { + pMapTarget = _map_config.getTarget(strTargetName); + // If the target is not found in the mapping configuration, return invalid error + if(pMapTarget == NULL) + { + nRes = ERR_INVALID_ARG; + } + else + { + const char* desc = 0; + if (isFailed(_env.resolveType(pMapTarget->getType().c_str(), desc))) + { + nRes = ERR_INVALID_TYPE; + } + // save a copy, never know how long the environment holds the memory + strTargetDesc = desc; + } + } + + // Backup storage for error cleanup + SourceMap oSourceCleanup; + TriggerMap oTriggerCleanup; + + if (isOk(nRes)) + { + // Create sources + const oo::MapSourceNameList& lstSources = pMapTarget->getReferencedSources(); + for (oo::MapSourceNameList::const_iterator it = lstSources.begin(); + it != lstSources.end(); ++it) + { + const oo::MapSource* pMapSource = _map_config.getSource(*it); + if (_sources.find(pMapSource->getName()) == _sources.end()) + { + const char* strSourceDesc = 0; + nRes = _env.resolveType(pMapSource->getType().c_str(), strSourceDesc); + if (isFailed(nRes)) + { + break; + } + + Source* pSrc = new Source(_env); + nRes = pSrc->create(*pMapSource, strSourceDesc); + if (isFailed(nRes)) + { + delete pSrc; + break; + } + + _sources[pMapSource->getName()] = pSrc; + oSourceCleanup[pMapSource->getName()] = pSrc; + } + } + } + + Target* pTarget = NULL; + if (isOk(nRes)) + { + // Create Target + pTarget = new Target(_env); + nRes = pTarget->create(_map_config, *pMapTarget, strTargetDesc, _sources); + if (isFailed(nRes)) + { + delete pTarget; + pTarget = NULL; + } + else + { + _targets[strTargetName] = pTarget; + } + } + + if (isOk(nRes)) + { + //Create Triggers + const oo::MapTriggerList& oTriggerList = pMapTarget->getTriggerList(); + for(oo::MapTriggerList::const_iterator it = oTriggerList.begin(); + it != oTriggerList.end(); it++) + { + const oo::MapPeriodicTrigger* pMapPTrigger = + dynamic_cast(*it); + const oo::MapSignalTrigger* pMapSigTrigger = + dynamic_cast(*it); + const oo::MapDataTrigger* pMapDataTrigger = + dynamic_cast(*it); + + if(!pMapPTrigger && !pMapSigTrigger && !pMapDataTrigger) + { + nRes = ERR_NOT_IMPL; + break; + } + + if (pMapPTrigger) + { + std::string strTrigName; + if(pMapPTrigger->getPeriod() == 0) + { + strTrigName = "ini"; + } + else + { + strTrigName = a_util::strings::toString(pMapPTrigger->getPeriod()) + "ms"; + } + + if(_triggers.find(strTrigName) == _triggers.end()) + { + PeriodicTrigger* pTrigger = new PeriodicTrigger(_env, strTrigName, + pMapPTrigger->getPeriod()); + nRes = pTrigger->create(); + if (isFailed(nRes)) + { + delete pTrigger; + break; + } + + _triggers[strTrigName] = pTrigger; + oTriggerCleanup[strTrigName] = pTrigger; + } + + _triggers[strTrigName]->addTarget(pTarget); + } + + if (pMapSigTrigger) + { + std::string strSourceName = pMapSigTrigger->getVariable(); + + TriggerMap::iterator iter = _triggers.find(strSourceName); + if(iter == _triggers.end()) + { + SignalTrigger* pTrigger = new SignalTrigger(_env, strSourceName); + std::pair oNewElem = + _triggers.insert(std::make_pair(strSourceName, pTrigger)); + iter = oNewElem.first; + + oTriggerCleanup[strSourceName] = pTrigger; + } + + iter->second->addTarget(pTarget); + _sources[strSourceName]->addTrigger(_map_config, iter->second); + } + + if (pMapDataTrigger) + { + std::string name = pMapDataTrigger->getSource() + "." + pMapDataTrigger->getVariable() + + pMapDataTrigger->getOperator(); + name.append(a_util::strings::format("%f", pMapDataTrigger->getValue())); + + TriggerMap::iterator iter = _triggers.find(name); + if(_triggers.find(name) == _triggers.end()) + { + DataTrigger* pTrigger = new DataTrigger(_env, name, + pMapDataTrigger->getVariable(), pMapDataTrigger->getOperator(), + pMapDataTrigger->getValue()); + std::pair oNewElem = + _triggers.insert(std::make_pair(name, pTrigger)); + iter = oNewElem.first; + + oTriggerCleanup[name] = pTrigger; + } + + iter->second->addTarget(pTarget); + _sources[pMapDataTrigger->getSource()]->addTrigger(_map_config, iter->second); + } + } + } + + // cleanup on error + if (isFailed(nRes)) + { + for (SourceMap::iterator it = oSourceCleanup.begin(); + it != oSourceCleanup.end(); ++it) + { + _sources.erase(it->first); + delete it->second; + } + + for (TriggerMap::iterator it = _triggers.begin(); + it != _triggers.end(); ++it) + { + it->second->removeTarget(pTarget); + } + + for (TriggerMap::iterator it = oTriggerCleanup.begin(); + it != oTriggerCleanup.end(); ++it) + { + _triggers.erase(it->first); + delete it->second; + } + + } + + if(isOk(nRes)) + { + hMappedSignal = reinterpret_cast(pTarget); + _env.targetMapped(strTargetName.c_str(), pTarget->getType().c_str(), hMappedSignal, pTarget->getSize()); + } + + return nRes; +} + +a_util::result::Result MappingEngine::reset() +{ + if (_running) + { + return ERR_INVALID_STATE; + } + + // Reset the target buffers + for(TargetMap::iterator it = _targets.begin(); it != _targets.end(); it++) + { + RETURN_IF_FAILED(it->second->reset(_map_config)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MappingEngine::start() +{ + if (_running) + { + return ERR_INVALID_STATE; + } + _running = true; + + // start the triggers in order to send targets + for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); it++) + { + it->second->start(); + } + + return a_util::result::SUCCESS; +} + +bool MappingEngine::hasTriggers(handle_t mapped_signal) const +{ + Target* target_signal = reinterpret_cast(mapped_signal); + if (!target_signal) + { + return false; + } + bool has_trigger = false; + for (const auto& trigga : _triggers) + { + if (has_trigger) + { + break; + } + const auto& target_list = trigga.second->getTargetList(); + for (const auto& target : target_list) + { + if (target == target_signal) + { + has_trigger = true; + break; + } + } + } + return has_trigger; +} + +a_util::result::Result MappingEngine::stop() +{ + if (!_running) + { + return ERR_INVALID_STATE; + } + _running = false; + + // stop the triggers in order to send targets + for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); it++) + { + it->second->stop(); + } + return a_util::result::SUCCESS; +} + +a_util::result::Result MappingEngine::unmap(handle_t hMappedSignal) +{ + if (_running) + { + return ERR_INVALID_STATE; + } + + Target* pTarget = reinterpret_cast(hMappedSignal); + if (!pTarget) { return ERR_POINTER; } + + std::vector vecEraseTrig; + for(TriggerMap::iterator it = _triggers.begin(); it != _triggers.end(); ++it) + { + it->second->removeTarget(pTarget); + if (it->second->getTargetList().empty()) + { + delete it->second; + vecEraseTrig.push_back(it); + } + } + for (std::vector::iterator it = vecEraseTrig.begin(); + it != vecEraseTrig.end(); ++it) + { + _triggers.erase(*it); + } + + std::vector vecEraseSrc; + for(SourceMap::iterator it = _sources.begin(); it != _sources.end(); ++it) + { + it->second->removeAssignmentsFor(pTarget); + if (it->second->getAssigmentList().empty()) + { + delete it->second; + vecEraseSrc.push_back(it); + } + } + for (std::vector::iterator it = vecEraseSrc.begin(); + it != vecEraseSrc.end(); ++it) + { + _sources.erase(*it); + } + + _env.targetUnmapped(pTarget->getName().c_str(), hMappedSignal); + _targets.erase(pTarget->getName()); + delete pTarget; + + return a_util::result::SUCCESS; +} + +a_util::result::Result MappingEngine::unmapAll() +{ + if (_running) + { + return ERR_INVALID_STATE; + } + + while (!_targets.empty()) + { + unmap(reinterpret_cast(_targets.begin()->second)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result MappingEngine::getCurrentData(handle_t hMappedSignal, + void* pTargetBuffer, size_t szTargetBuffer) const +{ + Target* pTarget = reinterpret_cast(hMappedSignal); + if (!pTarget) { return ERR_POINTER; } + if (!pTargetBuffer) { return ERR_POINTER; } + + return pTarget->getCurrentBuffer(pTargetBuffer, szTargetBuffer); +} + +// empty definitions of mapping environment destruktors +ISignalListener::~ISignalListener() {} +IPeriodicListener::~IPeriodicListener() {} +IMappingEnvironment::~IMappingEnvironment() {} diff --git a/mapping/engine/mapping_engine.h b/mapping/engine/mapping_engine.h new file mode 100644 index 0000000..73fd0c9 --- /dev/null +++ b/mapping/engine/mapping_engine.h @@ -0,0 +1,162 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +/*! Mapping Engine + * + * \section intro_sec Introduction + * + * This is the Mapping Engine documentation. + */ + +#ifndef MAPPINGENGINE_HEADER +#define MAPPINGENGINE_HEADER + +#include "mapping/configuration/map_configuration.h" + +#include "mapping_environment_intf.h" +#include "element.h" +#include "source.h" +#include "target.h" +#include "trigger.h" +#include "periodic_trigger.h" +#include "data_trigger.h" +#include "signal_trigger.h" + +namespace mapping +{ +namespace rt +{ + +class MappingEngine +{ +public: + /** + * CTOR + * @param[in] env - Mapping environment, used as interface + */ + MappingEngine(IMappingEnvironment& env); + + /** + * DTOR + */ + ~MappingEngine(); + + /** + * Setter for the current mapping configuration + * @param[in] config - The Configuration instance + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result setConfiguration(const oo::MapConfiguration& config); + + /** + * Method to instanciate or expand the mapping structure for one particular target + * @param [in] target_name The target name + * @param [out] mapped_signal - Destination parameter for the signal handle + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_INVALID_ARG Error target already mapped or not found in mapping configuration + * @retval ERR_FAILED Error during creation of the mapping + */ + a_util::result::Result Map(const std::string& target_name, handle_t& mapped_signal); + + /** + * Method to reset target buffers + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + a_util::result::Result reset(); + + /** + * Method to start mapping + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + a_util::result::Result start(); + + /** + * Method to stop mapping + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result stop(); + + /** + * Method to remove a target from the existing mapping structure + * @param [in] mapped_signal - Target handle + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_INVALID_ARG Error target not found in mapping structure + * @retval ERR_FAILED Error during removal + */ + a_util::result::Result unmap(handle_t mapped_signal); + + /** + * Method to know if signal has triggers or not + * + * @param [in] mapped_signal The target handle + * @retval true Signal has triggers + * @retval false Signal has no triggers + */ + bool hasTriggers(handle_t mapped_signal) const; + + /** + * Method to send current data + * + * @param [in] mapped_signal The target handle + * @param [in] target_buffer The pointer referencing the target buffer + * @param [in] target_buffer_size The size of the target buffer + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_INVALID_ARG Invalid target handle or target buffer is NULL + * @retval ERR_MEMORY Target buffer not large enough + */ + a_util::result::Result getCurrentData(handle_t mapped_signal, void* target_buffer, size_t target_buffer_size) const; + + /** + * Method to reinitialize the existing mapping structure + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during reinitialization + */ + a_util::result::Result unmapAll(); + +private: + /** + * Method to give an initial value to all targets + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during initialization + */ + a_util::result::Result initializeModel(); + +private: + IMappingEnvironment& _env; + bool _running; + + oo::MapConfiguration _map_config; + TargetMap _targets; + SourceMap _sources; + TriggerMap _triggers; +}; + +} // namespace rt +} // namespace mapping +#endif //MAPPINGENGINE_HEADER diff --git a/mapping/engine/mapping_environment_intf.h b/mapping/engine/mapping_environment_intf.h new file mode 100644 index 0000000..8868172 --- /dev/null +++ b/mapping/engine/mapping_environment_intf.h @@ -0,0 +1,167 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef MAPPINGENVIRONMENT_HEADER +#define MAPPINGENVIRONMENT_HEADER + +#include "a_util/result.h" + +namespace mapping +{ +namespace rt +{ + +/// Signal listener interface class +class ISignalListener +{ +public: + /// DTOR + virtual ~ISignalListener(); + + /** + * \c onSampleReceived is to be called by the mapping environment + * upon receiving a sample on a registered source signal. + * + * @param [in] data The data contained in the sample + * @param [in] size The size of the data + * @returns Standard result + */ + virtual a_util::result::Result onSampleReceived(const void* data, size_t size) = 0; +}; + +/// Timer interface class +class IPeriodicListener +{ +public: + /// DTOR + virtual ~IPeriodicListener(); + + /** + * \c onTimer is to be called by the mapping environment periodically. + * + * @param [in] now The current time + * @returns Nothing + */ + virtual void onTimer(timestamp_t now) = 0; +}; + +/// Mapping environment interface class +/// This in combination with ISignalListener forms the functionality that +/// the environment using the mapping package must provide. +class IMappingEnvironment +{ +public: + /// DTOR + virtual ~IMappingEnvironment(); + + /** + * Method to register a source signal. \c registerSource is called for all + * source signals inside a mapped target signal. + * + * @param [in] source_name The name of the source signal + * @param [in] type_name The type of the source signal + * @param [in] listener The signal listener instance + * @param [in] handle The output parameter for the source handle + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result registerSource(const char* source_name, + const char* type_name, ISignalListener* listener, handle_t& handle) = 0; + + /** + * Method to unregister a source signal. Used to unregister any source + * signals upon unmapping of a target signal. + * + * @param [in] handle The handle of the source signal + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result unregisterSource(handle_t handle) = 0; + + /** + * Method to send a target signal. It is called upon + * + * @param [in] target The target handle + * @param [in] data The pointer referencing the target buffer + * @param [in] size The size of the target buffer + * @param [in] time_stamp The timestamp of the target + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result sendTarget(handle_t target, const void* data, + size_t size, timestamp_t time_stamp) = 0; + + /** + * \c targetMapped is invoked by the mapping engine upon the creation of a mapping. + * The callback is supposed to give the mapping environment a chance to preallocate + * any sample buffers to be used during runtime. + * + * @param [in] target_name The target name + * @param [in] target_type The target type + * @param [in] target The handle under which the target is refered to in \c sendTarget + * @param [in] target_size The target type size (size of a sample in bytes) + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result targetMapped(const char* target_name, const char* target_type, + handle_t target, size_t target_size) = 0; + + /** + * \c targetUnmapped is invoked by the mapping engine upon the destruction of a mapping. + * The callback is supposed to give the mapping environment a chance to cleanup + * any sample buffers associated with that target. + * + * @param [in] target_name The target name + * @param [in] target The target handle + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result targetUnmapped(const char* target_name, handle_t target) = 0; + + /** + * Method to get the ddl description for a type + * @param [in] type_name The name of the type to be resolved + * @param [out] type_description Output paramter for the description for the type + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result resolveType(const char* type_name, const char*& type_description) = 0; + + /** + * \c getTime is used by the mapping engine to get the current time. Since only the + * application of mapping can now what time domain should be used, this method has to be + * implementied by the environment. + * @returns The current timestamp in microseconds + */ + virtual timestamp_t getTime() const = 0; + + /** + * \c registerPeriodicTimer is used by the mapping engine to register periodic timers + * @param [in] period_us The period + * @param [in] listener The listener to be called periodically + * @returns Standard result + */ + virtual a_util::result::Result registerPeriodicTimer(timestamp_t period_us, IPeriodicListener* listener) = 0; + + /** + * \c registerPeriodicTimer is used by the mapping engine to unregister periodic timers + * @param [in] period_us The period + * @param [in] listener The listener + * @returns Standard result + */ + virtual a_util::result::Result unregisterPeriodicTimer(timestamp_t period_us, IPeriodicListener* listener) = 0; +}; + +} // namespace rt +} // namespace mapping +#endif //MAPPINGENVIRONMENT_HEADER diff --git a/mapping/engine/periodic_trigger.cpp b/mapping/engine/periodic_trigger.cpp new file mode 100644 index 0000000..b18daec --- /dev/null +++ b/mapping/engine/periodic_trigger.cpp @@ -0,0 +1,69 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "periodic_trigger.h" + +using namespace mapping::rt; + +PeriodicTrigger::PeriodicTrigger(IMappingEnvironment& oEnv, + const std::string& strTriggerName, double fPeriod) : _env(oEnv), + _name(strTriggerName), _period(fPeriod), _running(false) +{ +} + +PeriodicTrigger::~PeriodicTrigger() +{ + _env.unregisterPeriodicTimer((timestamp_t)_period * 1000, this); +} + +a_util::result::Result PeriodicTrigger::create() +{ + return _env.registerPeriodicTimer((timestamp_t)_period * 1000, this); +} + +a_util::result::Result PeriodicTrigger::start() +{ + _running = true; + return a_util::result::SUCCESS; +} + +a_util::result::Result PeriodicTrigger::stop() +{ + _running = false; + return a_util::result::SUCCESS; +} + +void PeriodicTrigger::onTimer(timestamp_t tmNow) +{ + if (_running) + { + for(TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it) + { + const void* pBuffer = NULL; + size_t szBuffer = 0; + (*it)->aquireReadLock(); + (*it)->updateTriggerFunctionValues(); + if (isOk((*it)->getBufferRef(pBuffer, szBuffer))) + { + _env.sendTarget((handle_t)*it, pBuffer, szBuffer, tmNow); + } + (*it)->releaseReadLock(); + } + } +} diff --git a/mapping/engine/periodic_trigger.h b/mapping/engine/periodic_trigger.h new file mode 100644 index 0000000..70a4fc9 --- /dev/null +++ b/mapping/engine/periodic_trigger.h @@ -0,0 +1,83 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef PERIODIC_TRIGGER_HEADER +#define PERIODIC_TRIGGER_HEADER + +#include "a_util/result.h" + +#include "trigger.h" + +namespace mapping +{ +namespace rt +{ + +/// PeriodicTrigger implements a concrete periodic trigger in the runtime +class PeriodicTrigger : public TriggerBase, private IPeriodicListener +{ +public: + /** + * CTOR + * @param [in] env The mapping environment + * @param [in] trigger_name The name of the trigger + * @param [in] period The period of the trigger + */ + PeriodicTrigger(IMappingEnvironment& env, const std::string& trigger_name, double period); + + /** + * DTOR + */ + ~PeriodicTrigger(); + + /** + * Creates and initializes the periodic trigger + */ + a_util::result::Result create(); + + /** + * Method to start trigger + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + a_util::result::Result start(); + + /** + * Method to stop trigger + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result stop(); + +private: // IPeriodicListener + /// @cond nodoc + void onTimer(timestamp_t now); + +private: + IMappingEnvironment& _env; + std::string _name; + double _period; + bool _running; + /// @endcond +}; + +} // namespace rt +} // namespace mapping +#endif //PERIODIC_TRIGGER_HEADER diff --git a/mapping/engine/signal_trigger.cpp b/mapping/engine/signal_trigger.cpp new file mode 100644 index 0000000..1f7088c --- /dev/null +++ b/mapping/engine/signal_trigger.cpp @@ -0,0 +1,66 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "signal_trigger.h" + +using namespace mapping::rt; + +SignalTrigger::SignalTrigger(IMappingEnvironment& oEnv, + const std::string& strTriggerName) : _env(oEnv), + _name(strTriggerName), _is_running(false) +{ +} + +SignalTrigger::~SignalTrigger() +{ + stop(); +} + +a_util::result::Result SignalTrigger::start() +{ + _is_running = true; + return a_util::result::SUCCESS; +} + +a_util::result::Result SignalTrigger::stop() +{ + _is_running = false; + return a_util::result::SUCCESS; +} + +a_util::result::Result SignalTrigger::transmit() +{ + if(_is_running) + { + for(TargetSet::iterator it = _targets.begin(); it != _targets.end(); ++it) + { + const void* pBuffer = NULL; + size_t szBuffer = 0; + (*it)->aquireReadLock(); + (*it)->updateTriggerFunctionValues(); + if (isOk((*it)->getBufferRef(pBuffer, szBuffer))) + { + _env.sendTarget((handle_t)*it, pBuffer, szBuffer, 0); + } + (*it)->releaseReadLock(); + } + } + + return a_util::result::SUCCESS; +} diff --git a/mapping/engine/signal_trigger.h b/mapping/engine/signal_trigger.h new file mode 100644 index 0000000..5fdcdce --- /dev/null +++ b/mapping/engine/signal_trigger.h @@ -0,0 +1,81 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef SIGNAL_TRIGGER_HEADER +#define SIGNAL_TRIGGER_HEADER + +#include "a_util/result.h" +#include "trigger.h" + +namespace mapping +{ +namespace rt +{ + +/// SignalTrigger implements a concrete periodic trigger in the runtime +class SignalTrigger : public TriggerBase +{ +public: + /** + * CTOR + * @param [in] env The mapping environment + * @param [in] trigger_name The name of the trigger + * @param [in] fPeriod The period of the trigger + */ + SignalTrigger(IMappingEnvironment& env, + const std::string& trigger_name); + + /** + * DTOR + */ + ~SignalTrigger(); + + /** + * Method to start trigger + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + a_util::result::Result start(); + + /** + * Method to stop trigger + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result stop(); + + /** + * Method to transmit targets + * + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result transmit(); + +private: + /// @cond nodoc + IMappingEnvironment& _env; + std::string _name; + bool _is_running; + /// @endcond +}; + +} // namespace rt +} // namespace mapping +#endif //SIGNAL_TRIGGER_HEADER diff --git a/mapping/engine/source.cpp b/mapping/engine/source.cpp new file mode 100644 index 0000000..f46a3e8 --- /dev/null +++ b/mapping/engine/source.cpp @@ -0,0 +1,427 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "source.h" + +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "codec/access_element.h" + +#include "mapping/configuration/map_configuration.h" + +#include "data_trigger.h" +#include "signal_trigger.h" + +namespace mapping +{ +namespace rt +{ + //define all needed error types and values locally + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-42, ERR_INVALID_TYPE) +} +} + +using namespace mapping; +using namespace mapping::rt; + +Source::Source(IMappingEnvironment& oEnv) : _env(oEnv), _handle(0) +{ + _type_map["tUInt8"] = e_uint8; + _type_map["tUInt16"] = e_uint16; + _type_map["tUInt32"] = e_uint32; + _type_map["tUInt64"] = e_uint64; + _type_map["tInt8"] = e_int8; + _type_map["tInt16"] = e_int16; + _type_map["tInt32"] = e_int32; + _type_map["tInt64"] = e_int64; + _type_map["tFloat32"] = e_float32; + _type_map["tFloat64"] = e_float64; + _type_map["tBool"] = e_bool; + _type_map["tChar"] = e_char; +} + +Source::~Source() +{ + if (_handle) + { + _env.unregisterSource(_handle); + } +} + +a_util::result::Result Source::create(const oo::MapSource& oMapSource, const std::string& strTypeDescription) +{ + _name = oMapSource.getName(); + _type = oMapSource.getType(); + _type_description = strTypeDescription; + + _codec_factory.reset(new ddl::CodecFactory(_type.c_str(), _type_description.c_str())); + if (isOk(_codec_factory->isValid())) + { + return _env.registerSource(_name.c_str(), _type.c_str(), this, _handle); + } + + return ERR_INVALID_TYPE; +} + +a_util::result::Result Source::addTrigger(const oo::MapConfiguration& oMapConfig, TriggerBase* oTrigger) +{ + Triggers::iterator it = _triggers.begin(); + for(; it != _triggers.end(); ++it) + { + if (it->first == oTrigger) break; + } + + if(it == _triggers.end()) + { + AssignmentStruct oStruct; + DataTrigger* pDataTrigger = dynamic_cast(oTrigger); + + if(pDataTrigger) + { + // Get structure from DDL + const ddl::DDLDescription* pDescription = oMapConfig.getDescription(); + if (!pDescription) { return ERR_POINTER; } + const ddl::DDLComplex* pStruct = pDescription->getStructByName(_type); + if (!pStruct) { return ERR_POINTER; } + + const ddl::IDDLDataType* pDataType = NULL; + // Get Element from DDL Struct + const ddl::DDLElement* pElem = NULL; + bool bIsArrayElement = false; + RETURN_IF_FAILED(DDLHelper::LookupElement(*pStruct, pDataTrigger->getVariable(), + pElem, bIsArrayElement)); + + // Get ID in DDL + ddl::CodecFactory oFac(pStruct); + ddl::StaticDecoder oDecoder = _codec_factory->makeStaticDecoderFor(NULL, oFac.getStaticBufferSize()); + size_t nIdx = 0; + RETURN_IF_FAILED(ddl::access_element::find_index(oDecoder, pDataTrigger->getVariable(), nIdx)); + + // Get element pointer offset + oStruct.element_ptr_offset = (uintptr_t)oDecoder.getElementAddress(nIdx); + + pDataType = pElem->getTypeObject(); + // Get Type from TypeMap + TypeMap::const_iterator it = _type_map.find(pDataType->getName()); + if(it != _type_map.end()) + { + oStruct.type32 = it->second; + } + + // find element size + const ddl::DDLDataType* pSourceType = dynamic_cast(pDataType); + if(pSourceType) + { + oStruct.buffer_size = pSourceType->getNumBits()/8; + } + else + { + return ERR_INVALID_TYPE; + } + } + + _triggers.push_back(std::make_pair(oTrigger, oStruct)); + } + + return a_util::result::SUCCESS; +} + +const std::string& Source::getType() const +{ + return _type; +} + +const Source::Assignments& Source::getAssigmentList() const +{ + return _assignments; +} + +a_util::result::Result Source::addAssignment(const oo::MapConfiguration& oMapConfig, + const std::string& strSourceElement, TargetElement* pTargetElement) +{ + if(strSourceElement == "received()") + { + _received_elements.push_back(pTargetElement); + } + else + { + AssignmentStruct oStruct; + + // Get structure from DDL + const ddl::DDLDescription* pDescription = oMapConfig.getDescription(); + if (!pDescription) { return ERR_POINTER; } + const ddl::DDLComplex* pStruct = pDescription->getStructByName(_type); + if (!pStruct) { return ERR_POINTER; } + + unsigned int szArraySize = 1; + + // If strSourceElement is empty, the whole Structure will be copied + if(strSourceElement.empty()) + { + oStruct.buffer_size = _codec_factory->getStaticBufferSize(); + oStruct.element_ptr_offset = 0; + } + else + { + // Get Element from DDL Struct + const ddl::DDLElement* pElem = NULL; + bool bIsArrayElement = false; + + RETURN_IF_FAILED(DDLHelper::LookupElement(*pStruct, strSourceElement, + pElem, bIsArrayElement)); + + const ddl::IDDLDataType* pDataType = pElem->getTypeObject(); + + // Get ID in DDL Coder + if(!bIsArrayElement) + { + szArraySize = pElem->getArraysize(); + } + + // Get Type from TypeMap + TypeMap::const_iterator it = _type_map.find(pDataType->getName()); + if(it != _type_map.end()) + { + oStruct.type32 = it->second; + } + + // find element size + const ddl::DDLDataType* pSourceType = dynamic_cast(pDataType); + const ddl::DDLComplex* pSourceStruct = dynamic_cast(pDataType); + const ddl::DDLEnum* pSourceEnum = dynamic_cast(pDataType); + + if(pSourceType) + { + oStruct.buffer_size = pSourceType->getNumBits() * szArraySize/8; + } + else if(pSourceStruct) + { + // TODO: check if this struct can be a different one than the one in _codec_factory + ddl::CodecFactory oFactory(pSourceStruct->getName().c_str(), + _type_description.c_str()); + + oStruct.buffer_size = oFactory.getStaticBufferSize(); + } + else if(pSourceEnum) + { + const ddl::DDLDataType* pEnumType = dynamic_cast(pSourceEnum->getTypeObject()); + oStruct.buffer_size = pEnumType->getNumBits() * szArraySize/8; + + // we need to set the interpretation type to the underlying type here + it = _type_map.find(pEnumType->getName()); + if(it != _type_map.end()) + { + oStruct.type32 = it->second; + } + } + else + { + return ERR_INVALID_TYPE; + } + + std::string strPath = strSourceElement; + if (szArraySize > 1) + { + strPath.append("[0]"); + } + + ddl::CodecFactory oFac(pStruct); + ddl::StaticDecoder oDecoder = _codec_factory->makeStaticDecoderFor(NULL, oFac.getStaticBufferSize()); + size_t nIdx = 0; + RETURN_IF_FAILED(ddl::access_element::find_index(oDecoder, strPath, nIdx)); + + // Get element pointer offset + oStruct.element_ptr_offset = (uintptr_t)oDecoder.getElementAddress(nIdx); + } + + Assignments::iterator itAssigns = _assignments.end(); + for (itAssigns = _assignments.begin(); itAssigns != _assignments.end(); ++itAssigns) + { + if (itAssigns->first == oStruct) + { + break; + } + } + + if (itAssigns == _assignments.end()) + { + _assignments.push_back(std::make_pair(oStruct, TargetElementList())); + _assignments.back().second.push_back(pTargetElement); + } + else + { + itAssigns->second.push_back(pTargetElement); + } + } + + _targets.insert(pTargetElement->getTarget()); + + return a_util::result::SUCCESS; +} + +a_util::result::Result Source::removeAssignmentsFor(const Target* pTarget) +{ + for (Assignments::iterator itAssignments = _assignments.begin(); + itAssignments != _assignments.end();) + { + TargetElementList& oAssignedElements = itAssignments->second; + for (TargetElementList::iterator itElements = oAssignedElements.begin(); + itElements != oAssignedElements.end();) + { + if ((*itElements)->getTarget() == pTarget) + { + // element is owned and deleted by target + itElements = oAssignedElements.erase(itElements); + } + else + { + ++itElements; + } + } + + if (itAssignments->second.empty()) + { + itAssignments = _assignments.erase(itAssignments); + } + else + { + ++itAssignments; + } + } + + _targets.erase(pTarget); + + return a_util::result::SUCCESS; +} + +a_util::result::Result Source::onSampleReceived(const void* pData, size_t szSize) +{ + if (!pData) { return ERR_POINTER; } + + // lock all currently mapped target buffers + // note: theres some optimization potential here: + // -- rework the assignment container to be able to sort the assignments by target + // -- lock only the current target during iteration over all assignments + // for now it is fast enough since the number of mapped targets isn't to high + for (TargetRefList::const_iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + (*it)->aquireWriteLock(); + } + + // write true into all received() assignments + bool bValue = true; + for(TargetElementList::iterator it = _received_elements.begin(); it != _received_elements.end(); it++) + { + (*it)->setValue(&bValue, e_bool, sizeof(bValue)); + } + + // write all assignments that stem from this source + for (Assignments::iterator itAssign = _assignments.begin(); + itAssign != _assignments.end(); ++itAssign) + { + void* pValue = (void*)((uintptr_t)pData + itAssign->first.element_ptr_offset); + + const std::vector& vecElements = itAssign->second; + uint32_t type32 = itAssign->first.type32; + size_t buffer_size = itAssign->first.buffer_size; + + for (size_t idx = 0; idx < vecElements.size(); ++idx) + { + vecElements[idx]->setValue(pValue, type32, buffer_size); + } + } + + // unlock all currently mapped target buffers + for (TargetRefList::const_iterator it = _targets.begin(); + it != _targets.end(); ++it) + { + (*it)->releaseWriteLock(); + } + + // call signal triggers + for(Triggers::iterator it = _triggers.begin(); + it != _triggers.end(); it++) + { + SignalTrigger* pSigTrigger = dynamic_cast(it->first); + DataTrigger* pDataTrigger = dynamic_cast(it->first); + if(pSigTrigger) + { + pSigTrigger->transmit(); + } + else if(pDataTrigger) + { + // read the current value and cast it into a float64 + double f64Val = 0; + void* pValue = (void*)((uintptr_t)pData + it->second.element_ptr_offset); + switch (it->second.type32) + { + case e_uint8: + f64Val = *(static_cast(pValue)); + break; + case e_uint16: + f64Val = *(static_cast(pValue)); + break; + case e_uint32: + f64Val = *(static_cast(pValue)); + break; + case e_uint64: + f64Val = static_cast(*(static_cast(pValue))); + break; + case e_int8: + f64Val = *(static_cast(pValue)); + break; + case e_int16: + f64Val = *(static_cast(pValue)); + break; + case e_int32: + f64Val = *(static_cast(pValue)); + break; + case e_int64: + f64Val = static_cast(*(static_cast(pValue))); + break; + case e_float32: + f64Val = *(static_cast(pValue)); + break; + case e_float64: + f64Val = *(static_cast(pValue)); + break; + case e_bool: + f64Val = *(static_cast(pValue)); + break; + case e_char: + f64Val = *(static_cast(pValue)); + break; + default: + assert(false); + break; + } + + // compare/interpret the operator comparison + if(pDataTrigger->compare(f64Val)) + { + pDataTrigger->transmit(); + } + } + } + + return a_util::result::SUCCESS; +} diff --git a/mapping/engine/source.h b/mapping/engine/source.h new file mode 100644 index 0000000..a94aee0 --- /dev/null +++ b/mapping/engine/source.h @@ -0,0 +1,177 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + +#ifndef MAPPING_SOURCE_HEADER +#define MAPPING_SOURCE_HEADER + +#include "a_util/result.h" + +#include "mapping/configuration/map_source.h" +#include "codec/codec_factory.h" + +#include "mapping_environment_intf.h" +#include "element.h" + + +namespace mapping +{ +namespace rt +{ + +///@cond nodoc +struct AssignmentStruct +{ + size_t buffer_size; + uint32_t type32; + uintptr_t element_ptr_offset; + + AssignmentStruct() : + buffer_size(0), type32(0), element_ptr_offset(static_cast(-1)) {} + + bool operator==(const AssignmentStruct &other) const + { + return (element_ptr_offset == other.element_ptr_offset); + } +}; +///nodoc + +} +} + +namespace mapping +{ +namespace rt +{ + +class TriggerBase; +class Target; +class TargetElement; + +class Source : public ISignalListener +{ +public: // types + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic ignored "-Wattributes" // standard type attributes are ignored when used in templates +#endif + + // Map of source elements and a vector of target elements + typedef std::vector > Assignments; + typedef std::vector > Triggers; + typedef std::vector MemoryBuffer; + typedef std::set TargetRefList; + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic warning "-Wattributes" // standard type attributes are ignored when used in templates +#endif + +public: + /** + * CTOR + * @param [in] env The mapping environment + */ + Source(IMappingEnvironment& env); + + /** + * DTOR + */ + ~Source(); + + /** + * Creation method to fill the object with data. + * @param[in] oo::MapSource The soucre representation from mapping configuration + * @param[in] type_description The description for the source type + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error while filing the object + */ + a_util::result::Result create(const mapping::oo::MapSource& map_source, + const std::string& type_description); + + /** + * Method to add a new pair of source element and target element to the intern assignment list + * @param[in] oConfig The Configuration instance + * @param[in] source_element The name of the source element to map + * @param[in] target_element The target element instance + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addAssignment(const mapping::oo::MapConfiguration& map_config, + const std::string& source_element, TargetElement* target_element); + + /** + * Method to add a new trigger to the intern trigger list + * @param[in] trigger The trigger + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTrigger(const oo::MapConfiguration& map_config, TriggerBase* trigger); + + /** + * Method to remove all elements of a target from the intern assignment list + * @param[in] target The target to unmap + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeAssignmentsFor(const Target* target); + + /** + * Getter for the source type + * @return the source type + */ + const std::string& getType() const; + + /** + * Getter for the assignment list + * @return the assignment list + */ + const Assignments& getAssigmentList() const; + + /** + * Method to handle a sample when it is received. + * @param[in] data The memory location of the received buffer + * @param[in] size The memory size of the received buffer + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result onSampleReceived(const void* data, size_t size); + +private: + IMappingEnvironment& _env; + handle_t _handle; + std::string _name; + std::string _type; + std::string _type_description; + Assignments _assignments; + TargetRefList _targets; + a_util::memory::unique_ptr _codec_factory; + TypeMap _type_map; + TargetElementList _received_elements; + Triggers _triggers; + + Source(const Source&); // = delete; + Source& operator=(const Source&); // = delete; +}; + +/// Public composite types used in the mapping::rt namespace +typedef std::map SourceMap; + +} // namespace rt +} // namespace mapping + + + +#endif //MAPPING_SOURCE_HEADER diff --git a/mapping/engine/target.cpp b/mapping/engine/target.cpp new file mode 100644 index 0000000..fc336fe --- /dev/null +++ b/mapping/engine/target.cpp @@ -0,0 +1,379 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "target.h" + +#include //std::unique_ptr<> +#include "a_util/result/error_def.h" +#include "legacy_error_macros.h" + +#include "codec/access_element.h" + +#include "mapping/configuration/map_configuration.h" + +namespace mapping +{ +namespace rt +{ + //define all needed error types and values locally + _MAKE_RESULT(-3, ERR_UNEXPECTED) + _MAKE_RESULT(-4, ERR_POINTER) + _MAKE_RESULT(-12, ERR_MEMORY) +} +} + +using namespace mapping; +using namespace mapping::rt; + +Target::Target(IMappingEnvironment& oEnv) : + _counter(0), _env(oEnv) +{ +} + +Target::~Target() +{ + for (TargetElementList::iterator it = _target_elements.begin(); + it != _target_elements.end(); ++it) + { + delete *it; + } + _target_elements.clear(); + _simulation_time_elements.clear(); +} + +a_util::result::Result Target::create(const oo::MapConfiguration& oMapConfig, + const oo::MapTarget& oMapTarget, const std::string& strTargetDescription, + SourceMap& oSources) +{ + _name = oMapTarget.getName(); + _type = oMapTarget.getType(); + ddl::CodecFactory oFactory(_type.c_str(), strTargetDescription.c_str()); + RETURN_IF_FAILED(oFactory.isValid()); + + // Alloc and zero memory + _buffer.resize(oFactory.getStaticBufferSize(), 0); + + // Begin here, end when target is destroyed or after reset + _codec.reset(new ddl::StaticCodec(oFactory.makeStaticCodecFor(&_buffer[0], _buffer.size()))); + + // Get structure from DDL + const ddl::DDLDescription* pDescription = oMapConfig.getDescription(); + if (!pDescription) { return ERR_POINTER; } + const ddl::DDLComplex* pStruct = pDescription->getStructByName(_type); + if (!pStruct) { return ERR_POINTER; } + + // Create element for each assignment in mapping configuration + const oo::MapAssignmentList& oAssignmentList = oMapTarget.getAssignmentList(); + for(oo::MapAssignmentList::const_iterator itAssignment = oAssignmentList.begin(); + itAssignment != oAssignmentList.end(); ++itAssignment) + { + const ddl::DDLElement* pElem = NULL; + bool bIsArrayElement = false; + RETURN_IF_FAILED(DDLHelper::LookupElement(*pStruct, itAssignment->getTo(), + pElem, bIsArrayElement)); + + unsigned int szElement = pElem->getArraysize(); + if(bIsArrayElement) + { + szElement = 1; + } + + std::string strPath = itAssignment->getTo(); + if (szElement > 1) + { + strPath.append("[0]"); + } + + ddl::DDLComplex* pComplex = dynamic_cast(pElem->getTypeObject()); + if (pComplex) + { + // No StructElement is created for the actual struct, only for its elements. Therefore, if + // the assignment is a struct, we need to amend the path by the first element of the struct + if (pComplex->getElements().empty()) return ERR_UNEXPECTED; + strPath.push_back('.'); + strPath.append(pComplex->getElements()[0]->getName()); + } + + size_t nIdx = 0; + RETURN_IF_FAILED(ddl::access_element::find_index(*_codec, strPath, nIdx)); + void* pTargetElementPtr = _codec->getElementAddress(nIdx); + + // Create target element + std::unique_ptr pElement(new TargetElement(this)); + RETURN_IF_FAILED(pElement->create(pTargetElementPtr, pElem->getTypeObject(), + szElement, itAssignment->getTo())); + + // If a constant is given, there can be no transformation + if(!itAssignment->getConstant().empty()) + { + _constant_elements.push_back(make_pair(itAssignment->getConstant(), pElement.get())); + + } + else if(!itAssignment->getFunction().empty()) + { + if(itAssignment->getFunction() == "simulation_time") + { + _simulation_time_elements.push_back(pElement.get()); + } + else if(itAssignment->getFunction() == "trigger_counter") + { + uint64_t nMod = 0; + if (!itAssignment->getModulo().empty()) + { + nMod = a_util::strings::toUInt64(itAssignment->getModulo()); + } + _counter_elements.push_back(std::make_pair(nMod, pElement.get())); + } + else if(itAssignment->getFunction() == "received") + { + // Add assignments to source + SourceMap::iterator itSource = oSources.find(itAssignment->getSource()); + if (itSource == oSources.end()) + { + return ERR_UNEXPECTED; + } + + RETURN_IF_FAILED(itSource->second->addAssignment(oMapConfig, "received()", pElement.get())); + } + + } + else + { + // Add Transformation for Mapping configuration + const std::string& strTransformation = itAssignment->getTransformation(); + if(!strTransformation.empty()) + { + RETURN_IF_FAILED(pElement->setTransformation( + oMapConfig.getTransformation(strTransformation))); + } + + // Add assignments to source + SourceMap::iterator itSource = oSources.find(itAssignment->getSource()); + if (itSource == oSources.end()) + { + return ERR_UNEXPECTED; + } + + // getFrom() is empty when the source itself is referenced + RETURN_IF_FAILED(itSource->second->addAssignment(oMapConfig, itAssignment->getFrom(), pElement.get())); + } + + _target_elements.push_back(pElement.release()); + } + + // initialize memory + RETURN_IF_FAILED(reset(oMapConfig)); + + return a_util::result::SUCCESS; +} + +a_util::result::Result Target::reset(const oo::MapConfiguration& oMapConfig) +{ + a_util::result::Result nResult = a_util::result::SUCCESS; + // Reset Counter + _counter = 0; + + // Set default values from DDL + const ddl::DDLDescription* pDescription = oMapConfig.getDescription(); + if (!pDescription) { return ERR_POINTER; } + const ddl::DDLComplex* pStruct = pDescription->getStructByName(_type); + if (!pStruct) { return ERR_POINTER; } + + // Set default values from DDL in a newly created data sample + for (size_t nIdx = 0; nIdx < _codec->getElementCount(); ++nIdx) + { + const ddl::StructElement* pElement = NULL; + if (isFailed(_codec->getElement(nIdx, pElement))) + { + continue; + } + + const ddl::DDLElement* pElem = NULL; + bool bIsArrayElement = false; + a_util::result::Result nCurrentResult = DDLHelper::LookupElement(*pStruct, + pElement->name, pElem, bIsArrayElement); + + unsigned int nLastElementIndex = 1; + std::string strDefaultValue; + if (isOk(nCurrentResult)) + { + nLastElementIndex = pElem->getArraysize(); + // Element Description was found ... check for a default value + if (pElem->isDefaultValid()) + { + strDefaultValue = pElem->getDefaultValue(); + } + } + + // Set error if no error happend so far + if (isOk(nResult)) + { + nResult = nCurrentResult; + } + + if (strDefaultValue.empty()) + { + // No default detected, just reset this entry + ddl::access_element::reset(*_codec, pElement->name); + } + else + { + a_util::variant::Variant var; + switch (pElement->type) + { + case a_util::variant::VT_Bool: + var.reset(a_util::strings::toBool(strDefaultValue)); + break; + case a_util::variant::VT_Int8: + var.reset(a_util::strings::toInt8(strDefaultValue)); + break; + case a_util::variant::VT_UInt8: + var.reset(a_util::strings::toUInt8(strDefaultValue)); + break; + case a_util::variant::VT_Int16: + var.reset(a_util::strings::toInt16(strDefaultValue)); + break; + case a_util::variant::VT_UInt16: + var.reset(a_util::strings::toUInt16(strDefaultValue)); + break; + case a_util::variant::VT_Int32: + var.reset(a_util::strings::toInt32(strDefaultValue)); + break; + case a_util::variant::VT_UInt32: + var.reset(a_util::strings::toUInt32(strDefaultValue)); + break; + case a_util::variant::VT_Int64: + var.reset(a_util::strings::toInt64(strDefaultValue)); + break; + case a_util::variant::VT_UInt64: + var.reset(a_util::strings::toUInt64(strDefaultValue)); + break; + case a_util::variant::VT_Float: + var.reset(a_util::strings::toFloat(strDefaultValue)); + break; + case a_util::variant::VT_Double: + var.reset(a_util::strings::toDouble(strDefaultValue)); + break; + default: + ddl::access_element::reset(*_codec, pElement->name); + break; + } + + if (!var.isEmpty()) + { + nCurrentResult = _codec->setElementValue(nIdx, var); + } + + // Set error if no error happend so far + if (isOk(nResult)) + { + nResult = nCurrentResult; + } + } + } + + // Set constant elements + if (isOk(nResult)) + { + for(Constants::iterator it = _constant_elements.begin(); it != _constant_elements.end(); it++) + { + nResult = it->second->setDefaultValue(it->first); + } + } + return nResult; +} + +const std::string& Target::getName() const +{ + return _name; +} + +const std::string& Target::getType() const +{ + return _type; +} + +const TargetElementList& Target::getElementList() const +{ + return _target_elements; +} + +size_t Target::getSize() const +{ + return _buffer.size(); +} + +a_util::result::Result Target::updateAccessFunctionValues() +{ + // set simulation time for simulation_time assignments + timestamp_t tmTime = _env.getTime(); + for(std::vector::const_iterator it = _simulation_time_elements.begin(); + it != _simulation_time_elements.end(); it++) + { + (*it)->setValue(&tmTime, e_int64, sizeof(timestamp_t)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result Target::updateTriggerFunctionValues() +{ + // increment counter + _counter++; + + // write counter into trigger_counter assignments + for(TriggerCounters::const_iterator it = _counter_elements.begin(); it != _counter_elements.end(); it++) + { + uint64_t nValue = _counter; + if (it->first != 0) + { + nValue %= it->first; + } + it->second->setValue(&nValue, e_uint64, sizeof(nValue)); + } + + return a_util::result::SUCCESS; +} + +a_util::result::Result Target::getCurrentBuffer(void* pTargetBuffer, size_t szTargetBuffer) +{ + if(szTargetBuffer < _buffer.size()) + { + return ERR_MEMORY; + } + + updateAccessFunctionValues(); + + aquireReadLock(); + a_util::memory::copy(pTargetBuffer, szTargetBuffer, &_buffer[0], _buffer.size()); + releaseReadLock(); + return a_util::result::SUCCESS; +} + +a_util::result::Result Target::getBufferRef(const void*& pBuffer, size_t& szTargetBuffer) +{ + updateAccessFunctionValues(); + + // synchronization is done by the caller! + pBuffer = &_buffer[0]; + szTargetBuffer = _buffer.size(); + + return a_util::result::SUCCESS; +} + diff --git a/mapping/engine/target.h b/mapping/engine/target.h new file mode 100644 index 0000000..e8f0a59 --- /dev/null +++ b/mapping/engine/target.h @@ -0,0 +1,184 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + + +#ifndef TARGET_HEADER +#define TARGET_HEADER + +#include +#include "a_util/result.h" + +#include "codec/static_codec.h" + +#include "element.h" +#include "source.h" +#include "mapping_environment_intf.h" +#include "mapping/configuration/map_target.h" +#include "mapping/configuration/map_source.h" + +namespace mapping +{ +namespace rt +{ + +/// Target represents a mapped target signal in the runtime api +class Target +{ +public: // types + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic ignored "-Wattributes" // standard type attributes are ignored when used in templates +#endif + + /// Assignment container + typedef std::vector > Assignments; + /// Trigger counter container + typedef std::vector > TriggerCounters; + /// Constant container + typedef std::vector > Constants; + /// Generic byte-buffer + typedef std::vector MemoryBuffer; + +#if defined(__GNUC__) && (__GNUC__ == 5) && defined(__QNX__) +#pragma GCC diagnostic warning "-Wattributes" // standard type attributes are ignored when used in templates +#endif + +public: + /** + * CTOR + * @param [in] env The environment + */ + Target(IMappingEnvironment& env); + + /** + * DTOR + */ + ~Target(); + + /** + * Creation method to fill the object with data. + * @param[in] map_config - The Configuration instance + * @param[in] oo::MapTarget - target representation from mapping configuration + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error while filing the object + */ + a_util::result::Result create(const oo::MapConfiguration& map_config, const oo::MapTarget& map_target, + const std::string& target_description, SourceMap& sources); + + /** + * Reset target Buffers + * @param[in] map_config - The Configuration instance + * @return error code + */ + a_util::result::Result reset(const oo::MapConfiguration& map_config); + + /** + * Getter for the target name + * @return the target name + */ + const std::string& getName() const; + + /** + * Getter for the target type + * @return the target type + */ + const std::string& getType() const; + + /** + * Getter for the element list + * @return the element list + */ + const TargetElementList& getElementList() const; + + /** + * Method to get buffer size + * + * @retval buffer size + */ + size_t getSize() const; + + /** + * Method to get a copy of the current target buffer + * + * @param [in] target_buffer Pointer referencing the target buffer + * @param [in] target_buffer_size The size of the target buffer + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_MEMORY Target buffer size not large enough + */ + a_util::result::Result getCurrentBuffer(void* target_buffer, size_t target_buffer_size); + + + /** + * Method to get access to the current buffer without copying it + * + * @param [in] buffer Destination pointer + * @param [out] target_buffer_size Destination parameter for the size of the buffer + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result getBufferRef(const void*& buffer, size_t& target_buffer_size); + + /** + * Method to update all dynamic values that are to be updates during buffer access + * (i.e. simulation time) + */ + a_util::result::Result updateAccessFunctionValues(); + + /** + * Method to update all dynamic values that are to be updates during a trigger + * (i.e. trigger counters) + */ + a_util::result::Result updateTriggerFunctionValues(); + +private: + /// @cond nodoc + std::string _name; + std::string _type; + TargetElementList _target_elements; + std::vector _simulation_time_elements; + TriggerCounters _counter_elements; + Constants _constant_elements; + uint64_t _counter; + a_util::memory::unique_ptr _codec; + MemoryBuffer _buffer; + mutable a_util::concurrency::shared_mutex _buffer_mutex; + IMappingEnvironment& _env; + /// @nodoc +public: + /// Lock the buffer for a source update + inline void aquireWriteLock() const { _buffer_mutex.lock_shared(); } + + /// Unlock the buffer after a source update + inline void releaseWriteLock() const { _buffer_mutex.unlock_shared(); } + + /// Lock the buffer for a buffer read + inline void aquireReadLock() const { _buffer_mutex.lock(); } + + /// Unlock the buffer after a buffer read + inline void releaseReadLock() const { _buffer_mutex.unlock(); } +}; + +/// Public composite types used in the mapping::rt namespace +typedef std::map TargetMap; +typedef std::set TargetSet; + +} // namespace rt +} // namespace mapping +#endif //TARGET_HEADER diff --git a/mapping/engine/trigger.cpp b/mapping/engine/trigger.cpp new file mode 100644 index 0000000..c277828 --- /dev/null +++ b/mapping/engine/trigger.cpp @@ -0,0 +1,41 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ +#include "trigger.h" + + +using namespace mapping::rt; + +TriggerBase::~TriggerBase() {} + +TargetSet& TriggerBase::getTargetList() +{ + return _targets; +} + +a_util::result::Result TriggerBase::addTarget(Target* target) +{ + _targets.insert(target); + return a_util::result::SUCCESS; +} + +a_util::result::Result TriggerBase::removeTarget(Target* target) +{ + _targets.erase(target); + return a_util::result::SUCCESS; +} diff --git a/mapping/engine/trigger.h b/mapping/engine/trigger.h new file mode 100644 index 0000000..25fd17a --- /dev/null +++ b/mapping/engine/trigger.h @@ -0,0 +1,86 @@ +/** + * @file + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef TRIGGER_BASE_HEADER +#define TRIGGER_BASE_HEADER + +#include "a_util/result.h" + +#include "target.h" + +namespace mapping +{ +namespace rt +{ + +/// base class representing a trigger +class TriggerBase +{ +public: + /** + * Virtual DTOR + */ + virtual ~TriggerBase(); + + /** + * Method to start trigger + * + * @retval a_util::result::SUCCESS Everything went fine + * @retval ERR_FAILED Error during runtime + */ + virtual a_util::result::Result start() = 0; + + /** + * Method to stop trigger + * + * @retval a_util::result::SUCCESS Everything went fine + */ + virtual a_util::result::Result stop() = 0; + +public: // Base implementations + /** + * Getter for the list of registered targets + * @return the list of targets + */ + TargetSet& getTargetList(); + + /** + * Method to register a new target + * @param[in] target The target to add + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result addTarget(Target* target); + + /** + * Method to deregister a target + * @param[in] target The target to remove + * @retval a_util::result::SUCCESS Everything went fine + */ + a_util::result::Result removeTarget(Target* target); + +protected: + /// nodoc + TargetSet _targets; +}; + +typedef std::map TriggerMap; + +} // namespace rt +} // namespace mapping +#endif //TRIGGER_BASE_HEADER diff --git a/mapping/mapping.sources b/mapping/mapping.sources new file mode 100644 index 0000000..f9ef59e --- /dev/null +++ b/mapping/mapping.sources @@ -0,0 +1,53 @@ +set(MAPPING_DIR mapping) + +set(MAPPING_CONFIGURATION_H + ${MAPPING_DIR}/configuration/map_assignment.h + ${MAPPING_DIR}/configuration/map_configuration.h + ${MAPPING_DIR}/configuration/map_header.h + ${MAPPING_DIR}/configuration/map_source.h + ${MAPPING_DIR}/configuration/map_target.h + ${MAPPING_DIR}/configuration/map_transformation.h + ${MAPPING_DIR}/configuration/map_trigger.h +) + +set(MAPPING_ENGINE_H + ${MAPPING_DIR}/engine/data_trigger.h + ${MAPPING_DIR}/engine/element.h + ${MAPPING_DIR}/engine/mapping_engine.h + ${MAPPING_DIR}/engine/periodic_trigger.h + ${MAPPING_DIR}/engine/signal_trigger.h + ${MAPPING_DIR}/engine/source.h + ${MAPPING_DIR}/engine/target.h + ${MAPPING_DIR}/engine/trigger.h + ${MAPPING_DIR}/engine/mapping_environment_intf.h +) + + +set(MAPPING_H + ${MAPPING_DIR}/pkg_mapping.h + ${MAPPING_DIR}/ddl_helper.h +) + +set(MAPPING_CPP + ${MAPPING_DIR}/ddl_helper.cpp + ${MAPPING_DIR}/configuration/map_assignment.cpp + ${MAPPING_DIR}/configuration/map_configuration.cpp + ${MAPPING_DIR}/configuration/map_header.cpp + ${MAPPING_DIR}/configuration/map_source.cpp + ${MAPPING_DIR}/configuration/map_target.cpp + ${MAPPING_DIR}/configuration/map_transformation.cpp + ${MAPPING_DIR}/configuration/map_trigger.cpp + ${MAPPING_DIR}/engine/data_trigger.cpp + ${MAPPING_DIR}/engine/element.cpp + ${MAPPING_DIR}/engine/mapping_engine.cpp + ${MAPPING_DIR}/engine/periodic_trigger.cpp + ${MAPPING_DIR}/engine/signal_trigger.cpp + ${MAPPING_DIR}/engine/source.cpp + ${MAPPING_DIR}/engine/target.cpp + ${MAPPING_DIR}/engine/trigger.cpp +) + +set(MAPPING_CONFIGURATION_INSTALL ${MAPPING_CONFIGURATION_H}) +set(MAPPING_ENGINE_INSTALL ${MAPPING_ENGINE_H}) +set(MAPPING_INSTALL ${MAPPING_H}) +source_group(${MAPPING_DIR} FILES ${MAPPING_CONFIGURATION_H} ${MAPPING_ENGINE_H} ${MAPPING_H} ${MAPPING_CPP}) diff --git a/mapping/pkg_mapping.h b/mapping/pkg_mapping.h new file mode 100644 index 0000000..d18a3fd --- /dev/null +++ b/mapping/pkg_mapping.h @@ -0,0 +1,28 @@ +/** + * @file + * Description missing + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef MAPPING_MAPPING_HEADER_INCLUDED +#define MAPPING_MAPPING_HEADER_INCLUDED + +#include "ddl_helper.h" +#include "configuration/map_configuration.h" +#include "engine/mapping_engine.h" + +#endif //MAPPING_MAPPING_HEADER_INCLUDED diff --git a/serialization/pkg_serialization.h b/serialization/pkg_serialization.h new file mode 100644 index 0000000..777842a --- /dev/null +++ b/serialization/pkg_serialization.h @@ -0,0 +1,27 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _DDL_SERIALIZATION_PKG_HEADER_ +#define _DDL_SERIALIZATION_PKG_HEADER_ + +#include "serialization.h" + +#endif + diff --git a/serialization/serialization.cpp b/serialization/serialization.cpp new file mode 100644 index 0000000..e161451 --- /dev/null +++ b/serialization/serialization.cpp @@ -0,0 +1,55 @@ +/** + * @file + * Implementation of the ADTF default media description. + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include "serialization.h" +#include "a_util/result/error_def.h" + +namespace ddl +{ + +namespace serialization +{ +//define all needed error types and values locally +_MAKE_RESULT(-12, ERR_MEMORY) + +a_util::result::Result transform_to_buffer(const Decoder& decoder, a_util::memory::MemoryBuffer& buffer, bool zero) +{ + DataRepresentation target_rep = decoder.getRepresentation() == deserialized ? + serialized : + deserialized; + size_t needed_size = decoder.getBufferSize(target_rep); + if (buffer.getSize() < needed_size) + { + if (!buffer.allocate(needed_size)) + { + return ERR_MEMORY; + } + } + + if (zero) + { + a_util::memory::set(buffer.getPtr(), buffer.getSize(), 0, buffer.getSize()); + } + Codec codec = decoder.makeCodecFor(buffer.getPtr(), buffer.getSize(), target_rep); + return transform(decoder, codec); +} + +} + +} diff --git a/serialization/serialization.h b/serialization/serialization.h new file mode 100644 index 0000000..0a9f81f --- /dev/null +++ b/serialization/serialization.h @@ -0,0 +1,80 @@ +/** + * @file + * Implementation of the ADTF default media description. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_SERIALIZER_CLASS_HEADER +#define DDL_SERIALIZER_CLASS_HEADER + +#include + +#include "a_util/result.h" + +#include "codec/codec.h" + +namespace ddl +{ + +namespace serialization +{ + +/** + * Copies all elements from a decoder to a codec + * @param[in] decoder The source decoder. + * @param[out] encoder The destination codec. + * @return Standard result. + */ +template +a_util::result::Result transform(const DECODER& decoder, ENCODER& encoder) +{ + size_t element_count = decoder.getElementCount(); + assert(element_count == encoder.getElementCount()); + for (size_t element = 0; element < element_count; ++element) + { + uint64_t buffer = 0; + a_util::result::Result result = decoder.getElementValue(element, &buffer); + if (a_util::result::isFailed(result)) + { + return result; + } + + result = encoder.setElementValue(element, &buffer); + if (a_util::result::isFailed(result)) + { + return result; + } + } + + return a_util::result::SUCCESS; +} + +/** + * Tranforms the data from a given decoder into the opposite data representation. + * Allocates the buffer accordingly. + * @param[in] decoder The source decoder. + * @param[out] buffer The destination buffer object. + * @param[in] zero Whether or not to memzero the buffer before writing the elements to it. + * @return Standard result. + */ +a_util::result::Result transform_to_buffer(const Decoder& decoder, a_util::memory::MemoryBuffer& buffer, bool zero = false); + +} + +} + +#endif diff --git a/serialization/serialization.sources b/serialization/serialization.sources new file mode 100644 index 0000000..b1f80d8 --- /dev/null +++ b/serialization/serialization.sources @@ -0,0 +1,14 @@ +set(SERIALIZATION_DIR serialization) + +set(SERIALIZATION_H + ${SERIALIZATION_DIR}/pkg_serialization.h + ${SERIALIZATION_DIR}/serialization.h +) + +set(SERIALIZATION_CPP + ${SERIALIZATION_DIR}/serialization.cpp +) + +set(SERIALIZATION_INSTALL ${SERIALIZATION_H}) +source_group(${SERIALIZATION_DIR} FILES ${SERIALIZATION_H} ${SERIALIZATION_CPP}) + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..8e6ed0f --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,46 @@ +if (NOT ddl_cmake_integrated_tests) + project(ddl_tests) + # if Conan is used, we have to include the generated file and doing some basic setup + if(CONAN_COMPILER) + if ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo_multi.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/conanbuildinfo_multi.cmake) + elseif ( EXISTS ${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo_multi.cmake) + include(${CMAKE_CURRENT_BINARY_DIR}/../conanbuildinfo_multi.cmake) + else() + message(FATAL_ERROR "Conan build info can't be found.") + endif() + + if(CORTEX_WORKSPACE) + conan_basic_setup(TARGETS) + else() + conan_basic_setup(TARGETS NO_OUTPUT_DIRS) + endif() + endif() + + find_package(a_util REQUIRED) + find_package(ddl REQUIRED) + enable_testing() +endif () +find_package (Threads) +find_package(gtest REQUIRED CONFIG) +include(GoogleTest) + +if (WIN32 AND CMAKE_CL_64) + add_definitions(-DWIN64) +endif() + +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +add_subdirectory(_common) +add_subdirectory(codec/src) +add_subdirectory(ddlrepresentation/src) +add_subdirectory(ddlinspector/src) +add_subdirectory(mapping/src) +add_subdirectory(headerrepresentation/src) + +add_subdirectory(ddlgenerators/src) +add_subdirectory(function/api/src) \ No newline at end of file diff --git a/test/README.md b/test/README.md new file mode 100644 index 0000000..90d605f --- /dev/null +++ b/test/README.md @@ -0,0 +1,9 @@ +# DDL Library Tests{#mainpage} + + +# Description + +The Data Defintion Language (DDL) Package provides utilities to handle data descriptions and data defined by these descriptions. This documentation contains all the tests for this package + + + \ No newline at end of file diff --git a/test/_common/CMakeLists.txt b/test/_common/CMakeLists.txt new file mode 100644 index 0000000..f4bbb3b --- /dev/null +++ b/test/_common/CMakeLists.txt @@ -0,0 +1,4 @@ +# Add compat header files as projetc files when using with target_link_libraries(MyProject compat) +add_library(ddl_test_compat INTERFACE) +target_sources(ddl_test_compat INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/adtf_compat.h + ${CMAKE_CURRENT_SOURCE_DIR}/compat.h) \ No newline at end of file diff --git a/test/_common/adtf_compat.h b/test/_common/adtf_compat.h new file mode 100644 index 0000000..6ffaad6 --- /dev/null +++ b/test/_common/adtf_compat.h @@ -0,0 +1,142 @@ +/** + * @file + * Compat header containing structs and defines needed for the ddlcoder (mediacoder) test + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _ADTF_TEST_COMPAT_HEADER_ +#define _ADTF_TEST_COMPAT_HEADER_ + +/** +* This Macro is the type name of the tCanMessage to describe media samples submitted on a pin (@ref adtf::IPin). +* set these description on the Media Type (@ref adtf::IMediaTypeDescription of the IMediatype set on pin). +*/ +#define ADTF_MEDIA_DESC_CANMESSAGE "tCanMessage" + +/** +* This Macro defines the description of tCanMessage structure used within ADTF @ref adtf::cMediaSampleCan. +* used for @ref ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION in Version 1.0+. +*/ +#define ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION_DDL1 "" \ + " " \ + " " \ + " " \ + " " \ + "" + +/** +* This Macro defines the description of a tCanMessage structure used within ADTF @ref adtf::cMediaSampleCan. +* See @ref ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION_DDL1. +*/ +#define ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION_DDL1 + + +typedef struct +{ + /// id of can message + std::uint16_t ui16Id; + /// channel to send or transmit can data + std::uint8_t ui8Channel; + /// length of data + std::uint8_t ui8Length; + /// data field + std::uint8_t pui8Data[8]; +} tCanMessage; + +#define ADTF_MEDIA_DESC_MEDIA_TYPEINFO_DDL1 " " \ + " " \ + " " \ + " " \ + " " + +#define ADTF_MEDIA_DESC_MEDIATYPE_DDL1 "" \ + ADTF_MEDIA_DESC_MEDIA_TYPEINFO_DDL1 \ + " " \ + " " \ + " " \ + "" + +#define ADTF_MEDIA_DESC_MEDIA_TYPEINFO_DDL2 " " \ + " " \ + " " \ + " " \ + " " + + +#define ADTF_MEDIA_DESC_MEDIATYPE_DDL2 "" \ + ADTF_MEDIA_DESC_MEDIA_TYPEINFO_DDL2 \ + " " \ + " " \ + " " \ + "" + +#define ADTF_MEDIA_DESC_MEDIA_TYPEINFO ADTF_MEDIA_DESC_MEDIA_TYPEINFO_DDL2 +#define ADTF_MEDIA_DESC_MEDIATYPE ADTF_MEDIA_DESC_MEDIATYPE_DDL2 + +#pragma pack ( push, 1 ) +typedef struct +{ + ///The major type. + std::uint32_t ui32MajorType; + ///The minor sub type. + std::uint32_t ui32SubType; + ///Flags. + std::uint32_t ui32Flags; +} tMediaTypeInfo; + +typedef struct +{ + /// media type information + tMediaTypeInfo mediatype; +} tADTFCoreMediaType; + + +#pragma pack ( pop ) + + +class IMediaDescription +{ +public: + typedef enum + { + MDNT_FindOutSelf = 0x00, + MDNT_StreamType = 0x01, + MDNT_StructType = 0x02, + MDNT_DataType = 0x03, + MDNT_UnitType = 0x04, + MDNT_BaseUnitType = 0x05 + } tMediaNameType; + +}; + +class IMediaDescriptionManager +{ + public: + typedef enum + { + MDMF_ForceOverwrite = 0x0001000, + MDMF_FilenameRef = 0x0002000, + MDMF_StreamStructType = 0x0004000, + MDMF_StreamDataType = 0x0008000, + MDMF_ForceStreamDescription = 0x0010000, + MDMF_ForceStructDescription = 0x0020000, + MDMF_ForceDatatypeDescription = 0x0040000 + } tMediaDecriptionManagerFlags; + +}; + +#endif // _ADTF_TEST_COMPAT_HEADER_ diff --git a/test/_common/compat.h b/test/_common/compat.h new file mode 100644 index 0000000..9e3090a --- /dev/null +++ b/test/_common/compat.h @@ -0,0 +1,32 @@ +/** + * @file + * Compat header containing structs and defines needed for the ddlcoder (mediacoder) test + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef DDL_TEST_COMMON_COMPAT_HEADER_INCLUDED_ +#define DDL_TEST_COMMON_COMPAT_HEADER_INCLUDED_ + +#ifndef TEST_REQ +/** + * Porting AEV specific macro - only necessary for internal use + * @param[in] req_id Unused + */ +#define TEST_REQ(req_id) +#endif // TEST_REQ + +#endif // DDL_TEST_COMMON_COMPAT_HEADER_INCLUDED_ diff --git a/test/_doc/ddl_test.html b/test/_doc/ddl_test.html new file mode 100644 index 0000000..4889bf8 --- /dev/null +++ b/test/_doc/ddl_test.html @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/codec/files/hca.description b/test/codec/files/hca.description new file mode 100644 index 0000000..e80a4ea --- /dev/null +++ b/test/codec/files/hca.description @@ -0,0 +1,147 @@ + + +
+ 1.02 + fneumth + 28.09.2011 + 01.01.1900 + ADTF generated +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/codec/src/CMakeLists.txt b/test/codec/src/CMakeLists.txt new file mode 100644 index 0000000..ce077b2 --- /dev/null +++ b/test/codec/src/CMakeLists.txt @@ -0,0 +1,32 @@ +set(TEST_NAME codec) + +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp tester_bitserializer.cpp) + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/ddl) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 300) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl + a_util_result + GTest::Main + $<$:Threads::Threads> +) +add_test(tester_${TEST_NAME} tester_${TEST_NAME}) + +set(TEST_NAME mediacoder_regression) +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp) +add_test(NAME tester_${TEST_NAME} + COMMAND tester_${TEST_NAME} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../" + ) + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/ddl) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 300) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl_test_compat + ddl + a_util_result + GTest::Main + $<$:Threads::Threads> +) diff --git a/test/codec/src/tester_bitserializer.cpp b/test/codec/src/tester_bitserializer.cpp new file mode 100644 index 0000000..1a5b43e --- /dev/null +++ b/test/codec/src/tester_bitserializer.cpp @@ -0,0 +1,484 @@ +/** + * @file + * Bitserializer Test implementation. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" +#include "codec/bitserializer.h" + +using namespace a_util::memory; + +/** +* @detail Read values using the bit serializer +*/ +TEST(CodecTest, + BitSerializerTestReadValue) +{ + TEST_REQ(""); + + uint8_t aui8Buffer[10] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x80 }; + + BitSerializer *pBits = new BitSerializer(aui8Buffer, 10); + + uint64_t value = 0; + + + // Read complete aligned bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x7766554433221100ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 56, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x0066554433221100ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 32, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x33221100); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 24, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x00221100); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 16, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x1100); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 8, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x00); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x0011223344556677ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 56, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x0000112233445566ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 32, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x00112233); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 24, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x00001122); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 16, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x0011); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 8, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x00); + + + + // Read complete unaligned bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(16, 64, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x8088776655443322ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 16, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x2110); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(40, 16, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x6655); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(16, 16, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x3322); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(12, 64, &value, bit_little_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x0887766554433221ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 64, &value, bit_little_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x8776655443322110ULL); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 16, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x1021); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(40, 16, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x5566); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(16, 16, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x2233); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 64, &value, bit_big_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x1021324354657687ULL); + + + + // Read partial unaligned bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 13, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x0110); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(40, 17, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x00016655); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(11, 10, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x0042); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(1, 61, &value, bit_little_endian)); + + ASSERT_TRUE(value == 0x1BB32AA219910880ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 63, &value, bit_little_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x0776655443322110ULL); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(12, 61, &value, bit_little_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x0887766554433221ULL); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(4, 13, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x1008); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(40, 17, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x00012ab3); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(10, 10, &value, bit_big_endian)); + + ASSERT_TRUE(value == 0x0021); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(5, 61, &value, bit_big_endian)); // Read value from 9 buffer bytes + + ASSERT_TRUE(value == 0x0884C80C5195D91DULL); + + delete pBits; + +} + + +/** +* @detail Write values using the bit serializer +*/ +TEST(CodecTest, + BitSerializerTestWriteValue) +{ + TEST_REQ(""); + + uint8_t aui8Buffer[10] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x80 }; + + BitSerializer *pBits = new BitSerializer(&aui8Buffer, 10); + + + + // Test LE Signal Writing + + uint64_t value = 0x1101; + + uint64_t result = 0; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 10, value, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 10, &result, bit_little_endian)); + + ASSERT_TRUE(0x0101 == result); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(10, 10, value, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(10, 10, &result, bit_little_endian)); + + ASSERT_TRUE(0x0101 == result); + + + + // Write and then read adjacent values inside buffer + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 14, value, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(14, 16, value, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(30, 16, value, bit_little_endian)); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 14, &result, bit_little_endian)); + + ASSERT_TRUE(value == result); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(14, 16, &result, bit_little_endian)); + + ASSERT_TRUE(value == result); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(30, 16, &result, bit_little_endian)); + + ASSERT_TRUE(value == result); + + + + value = 0x1122334455667788ULL; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 64, value, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &result, bit_little_endian)); + + ASSERT_TRUE(0x1122334455667788ULL == result); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, value, bit_little_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &result, bit_little_endian)); + + ASSERT_TRUE(0x1122334455667788ULL == result); + + + + + + // Test BE Signal Writing + + value = 0x1101; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 10, value, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 10, &result, bit_big_endian)); + + ASSERT_TRUE(0x0101 == result); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(10, 10, value, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(10, 10, &result, bit_big_endian)); + + ASSERT_TRUE(0x0101 == result); + + + + // Write and then read adjacent values inside buffer + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 14, value, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(14, 16, value, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(30, 16, value, bit_big_endian)); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 14, &result, bit_big_endian)); + + ASSERT_TRUE(value == result); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(14, 16, &result, bit_big_endian)); + + ASSERT_TRUE(value == result); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(30, 16, &result, bit_big_endian)); + + ASSERT_TRUE(value == result); + + + + value = 0x1122334455667788ULL; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 64, value, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &result, bit_big_endian)); + + ASSERT_TRUE(0x1122334455667788ULL == result); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, value, bit_big_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &result, bit_big_endian)); + + ASSERT_TRUE(0x1122334455667788ULL == result); + + + + // Test Float values + + double valuef = 846.73648f; + + double resultf = 0.0f; + + double result_other_endianf = 0.0f; + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 64, valuef, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &resultf, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &result_other_endianf, bit_big_endian)); + + ASSERT_TRUE(valuef == resultf); + + ASSERT_TRUE(valuef != result_other_endianf); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, valuef, bit_little_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &resultf, bit_little_endian)); + + ASSERT_TRUE(valuef == resultf); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 64, valuef, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &resultf, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 64, &result_other_endianf, bit_little_endian)); + + ASSERT_TRUE(valuef == resultf); + + ASSERT_TRUE(valuef != result_other_endianf); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, valuef, bit_big_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &resultf, bit_big_endian)); + + ASSERT_TRUE(valuef == resultf); + + + + // Test Signed values + + int64_t sValue = -45872ll; + + int64_t sResult = 0; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 62, sValue, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 62, &sResult, bit_little_endian)); + + + ASSERT_TRUE(sValue == sResult); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, sValue, bit_little_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &sResult, bit_little_endian)); + + + ASSERT_TRUE(sValue == sResult); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 62, sValue, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 62, &sResult, bit_big_endian)); + + ASSERT_TRUE(sValue == sResult); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 64, sValue, bit_big_endian)); // Write value into 9 buffer bytes + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 64, &sResult, bit_big_endian)); + + ASSERT_TRUE(sValue == sResult); + + + + int16_t sValue2 = -358ll; + + int16_t sResult2 = 0; + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 10, sValue2, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 10, &sResult2, bit_little_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 10, sValue2, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 10, &sResult2, bit_little_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(0, 10, sValue2, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(0, 10, &sResult2, bit_big_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(15, 10, sValue2, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(15, 10, &sResult2, bit_big_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(17, 13, sValue2, bit_little_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(17, 13, &sResult2, bit_little_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + + + + ASSERT_EQ(a_util::result::SUCCESS, pBits->write(17, 13, sValue2, bit_big_endian)); + + ASSERT_EQ(a_util::result::SUCCESS, pBits->read(17, 13, &sResult2, bit_big_endian)); + + ASSERT_TRUE(sValue2 == sResult2); + +} \ No newline at end of file diff --git a/test/codec/src/tester_codec.cpp b/test/codec/src/tester_codec.cpp new file mode 100644 index 0000000..3a2b812 --- /dev/null +++ b/test/codec/src/tester_codec.cpp @@ -0,0 +1,992 @@ +/** + * @file + * Test implementation. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" + +using namespace ddl; + +void DumpElements(const StaticDecoder& oDecoder) +{ + const uint8_t* pFirstElement = static_cast(oDecoder.getElementAddress(0)); + for (size_t nElement = 0; nElement < oDecoder.getElementCount(); ++nElement) + { + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.getElement(nElement, pElement)); + std::cout << pElement->name.c_str() + << " @ " << static_cast(oDecoder.getElementAddress(nElement)) - pFirstElement + << ": " << access_element::get_value_as_string(oDecoder, nElement) << "\n"; + } +} + +namespace static_struct +{ + + struct tChildStruct + { + int8_t nValueDummy; + int32_t nValue[3]; + int8_t nAfter; + }; + + struct tTest + { + tChildStruct sChild[2]; + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tTest sTestData = + { + { + {0x01, {0x02, 0x03, 0x04}, 0x05}, + {0x06, {0x07, 0x08, 0x09}, 0x0A}, + } + }; + + namespace serialized + { +#pragma pack(push, 1) + + struct tChildStruct + { + int8_t nValueDummy; + int32_t nValue[3]; + int8_t nAfter; + }; + + struct tTest + { + tChildStruct sChild[2]; + }; + + const tTest sTestData = + { + { + {0x01, {0x02000000, 0x03000000, 0x04000000}, 0x05}, + {0x06, {0x07000000, 0x08000000, 0x09000000}, 0x0A}, + } + }; +#pragma pack(pop) + } + +} + +template +void test_static(CodecFactory& oFactory, const T& sTestData, DataRepresentation eRep) +{ + std::cout << a_util::strings::format("%d == %d", oFactory.getStaticBufferSize(eRep), sizeof(sTestData)).c_str(); + ASSERT_EQ(oFactory.getStaticBufferSize(eRep) , sizeof(sTestData)); + T sTest = sTestData; + StaticDecoder oDecoder = oFactory.makeStaticDecoderFor(&sTest, sizeof(sTest), eRep); + StaticCodec oCodec = oFactory.makeStaticCodecFor(&sTest, sizeof(sTest), eRep); + + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.isValid()); + ASSERT_EQ(a_util::result::SUCCESS, oCodec.isValid()); + + ASSERT_EQ(oDecoder.getElementCount() , 10); + DumpElements(oDecoder); + + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value_dummy").getInt8() , 1); + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value[0]").getInt32() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value[1]").getInt32() , 3); + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value[2]").getInt32() , 4); + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].after").getInt8() , 5); + ASSERT_EQ(access_element::get_value(oDecoder, "child[1].value_dummy").getInt8() , 6); + ASSERT_EQ(access_element::get_value(oDecoder, "child[1].value[0]").getInt32() , 7); + ASSERT_EQ(access_element::get_value(oDecoder, "child[1].value[1]").getInt32() , 8); + ASSERT_EQ(access_element::get_value(oDecoder, "child[1].value[2]").getInt32() , 9); + ASSERT_EQ(access_element::get_value(oDecoder, "child[1].after").getInt8() , 10); + + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value_dummy").getType() , a_util::variant::VT_Int8); + ASSERT_EQ(access_element::get_value(oDecoder, "child[0].value[0]").getType() , a_util::variant::VT_Int32); + + ASSERT_EQ(access_element::get_value(oDecoder, 300).getInt32() , 0); + ASSERT_EQ(access_element::get_value(oDecoder, 0).getInt8() , 1); + + int32_t nNewData = 0x10; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.setElementValue(1, &nNewData)); + ASSERT_TRUE(0x10 == sTest.sChild[0].nValue[0] || + 0x10000000 == sTest.sChild[0].nValue[0]); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "child[1].value[2]", (int32_t)0x20)); + ASSERT_TRUE(0x20 == sTest.sChild[1].nValue[2] || + 0x20000000 == sTest.sChild[1].nValue[2]); +} + +/** +* @detail Check deserialized codec static information +*/ +TEST(CodecTest, + TestSatic) +{ + TEST_REQ("ACORE-7704 ACORE-7997 CDPKGDDL-12"); + + CodecFactory oFactory("test", static_struct::strTestDesc); + + size_t nIndex = 200; + ASSERT_EQ(a_util::result::SUCCESS, access_element::find_index(oFactory, "child[0].after", nIndex)); + ASSERT_EQ(nIndex , 4); + ASSERT_EQ(a_util::result::SUCCESS, access_element::find_struct_index(oFactory, "child[1]", nIndex)); + ASSERT_EQ(nIndex , 5); + ASSERT_EQ(a_util::result::SUCCESS, access_element::find_array_index(oFactory, "child", nIndex)); + ASSERT_EQ(nIndex , 0); + + test_static(oFactory, static_struct::sTestData, deserialized); +} + +/** +* @detail Check serialized codec static information +*/ +TEST(CodecTest, + TestSaticSerialized) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-13"); + + CodecFactory oFactory("test", static_struct::strTestDesc); + test_static(oFactory, static_struct::serialized::sTestData, serialized); +} + +namespace simple +{ + struct tMain + { + int8_t nArraySize; + int32_t aArray[4]; + int16_t nAfter; + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + 4, + {1, 2, 3, 4}, + 8 + }; + + namespace serialized + { +#pragma pack(push, 1) + struct tMain + { + int8_t nArraySize; + int32_t aArray[4]; + int16_t nAfter; + }; + + const tMain sTestData = + { + 4, + {1, 2, 3, 4}, + 8 + }; +#pragma pack(pop) + } + +} + +template +void TestDynamicSimple(CodecFactory& oFactory, const T& sTestData, DataRepresentation eRep) +{ + Decoder oDecoder = oFactory.makeDecoderFor(&sTestData, sizeof(sTestData), eRep); + DumpElements(oDecoder); + + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.isValid()); + + ASSERT_EQ(sizeof(T) , oDecoder.getBufferSize(eRep)); + std::cout << a_util::strings::toString((uint64_t)oDecoder.getElementCount()).c_str(); + ASSERT_EQ(oDecoder.getElementCount() , 6); + + ASSERT_EQ(access_element::get_value(oDecoder, "array_size").getInt8() , 4); + ASSERT_EQ(access_element::get_value(oDecoder, "array[0]").getInt32() , 1); + ASSERT_EQ(access_element::get_value(oDecoder, "array[1]").getInt32() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "array[2]").getInt32() , 3); + ASSERT_EQ(access_element::get_value(oDecoder, "array[3]").getInt32() , 4); + ASSERT_EQ(access_element::get_value(oDecoder, "after").getInt16() , 8); +} + +/** +* @detail Check deserialized codec dynamic information +*/ +TEST(CodecTest, + TestDynamicSimple) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-12"); + + CodecFactory oFactory("main", simple::strTestDesc); + ::TestDynamicSimple(oFactory, simple::sTestData, deserialized); +} + +/** +* @detail Check serialized codec dynamic information +*/ +TEST(CodecTest, + TestDynamicSimpleSerialized) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-13"); + + CodecFactory oFactory("main", simple::strTestDesc); + ::TestDynamicSimple(oFactory, simple::serialized::sTestData, serialized); +} + +namespace complex +{ + + struct tArrayChildStruct + { + int8_t nChildSize; + int32_t aChildArray[3]; + int8_t nChildSize2; + int32_t aChildArray2[2]; + int16_t aFixedArray[3]; + }; + + struct tArrayTest + { + int8_t nArraySize; + tArrayChildStruct aArray[2]; + }; + + struct tMain + { + int8_t nBefore; + tArrayTest sTest; + int8_t nAfter; + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" // does not end at a multiple of 4 + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + 4, + { + 2, + { + { + 3, {1, 2, 3}, + 2, {10, 20}, + {40, 50, 60} + }, + { + 3, {11, 22, 33}, + 2, {110, 220}, + {400, 500, 600} + } + } + }, + 8 + }; + + namespace serialized + { +#pragma pack(push, 1) + struct tArrayChildStruct + { + int8_t nChildSize; + int32_t aChildArray[3]; + int8_t nChildSize2; + int32_t aChildArray2[2]; + int16_t aFixedArray[3]; + }; + + struct tArrayTest + { + int8_t nArraySize; + tArrayChildStruct aArray[2]; + }; + + struct tMain + { + int8_t nBefore; + tArrayTest sTest; + int8_t nAfter; + }; + + const tMain sTestData = + { + 4, + { + 2, + { + { + 3, {1, 2, 3}, + 2, {10, 20}, + {40, 50, 60} + }, + { + 3, {11, 22, 33}, + 2, {110, 220}, + {400, 500, 600} + } + } + }, + 8 + }; + +#pragma pack(pop) + } + +} + +template +void TestDynamicComplex(CodecFactory& oFactory, const T& sTestData, DataRepresentation eRep) +{ + Decoder oDecoder = oFactory.makeDecoderFor(&sTestData, sizeof(sTestData), eRep); + + DumpElements(oDecoder); + + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.isValid()); + + ASSERT_EQ(sizeof(T) , oDecoder.getBufferSize(eRep)); + std::cout << a_util::strings::toString((uint64_t)oDecoder.getElementCount()).c_str(); + ASSERT_EQ(oDecoder.getElementCount() , 23); + + ASSERT_EQ(access_element::get_value(oDecoder, "before").getInt8() , 4); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array_size").getInt8() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_size").getInt8() , 3); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_array[0]").getInt32() , 1); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_array[1]").getInt32() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_array[2]").getInt32() , 3); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_size2").getInt8() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_array2[0]").getInt32() , 10); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].child_array2[1]").getInt32() , 20); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].fixed_array[0]").getInt16() , 40); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].fixed_array[1]").getInt16() , 50); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[0].fixed_array[2]").getInt16() , 60); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_size").getInt8() , 3); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_array[0]").getInt32() , 11); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_array[1]").getInt32() , 22); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_array[2]").getInt32() , 33); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_size2").getInt8() , 2); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_array2[0]").getInt32() , 110); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].child_array2[1]").getInt32() , 220); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].fixed_array[0]").getInt16() , 400); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].fixed_array[1]").getInt16() , 500); + ASSERT_EQ(access_element::get_value(oDecoder, "test.array[1].fixed_array[2]").getInt16() , 600); + ASSERT_EQ(access_element::get_value(oDecoder, "after").getInt8() , 8); +} + +/** +* @detail Check deserialized codec dynamic information with complex data +*/ +TEST(CodecTest, + TestDynamicComplex) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-12"); + + CodecFactory oFactory("main", complex::strTestDesc); + ::TestDynamicComplex(oFactory, complex::sTestData, deserialized); +} + +/** +* @detail Check serialized codec dynamic information with complex data +*/ +TEST(CodecTest, + TestDynamicComplexSerialized) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-13"); + + CodecFactory oFactory("main", complex::strTestDesc); + ::TestDynamicComplex(oFactory, complex::serialized::sTestData, serialized); +} + +class cTestPerf +{ +public: + virtual inline ~cTestPerf() {}; + virtual const char* getName() = 0; + virtual void CreateCodec(const char* strStructName, const char* strDescription, void* pData, size_t nDataSize) = 0; + virtual timestamp_t TestAccessAllElements(size_t nRepeats, const char* strStructName, const char* strDescription, void* pData, size_t nDataSize) = 0; +}; + +class cTestNewPerf: public cTestPerf +{ +public: + const char* getName() + { + return "New"; + } + + void CreateCodec(const char* strStructName, const char* strDescription, void* pData, size_t nDataSize) + { + CodecFactory oFactory(strStructName, strDescription); + Decoder oCodec = oFactory.makeDecoderFor(pData, nDataSize); + } + + timestamp_t TestAccessAllElements(size_t nRepeats, const char* strStructName, const char* strDescription, void* pData, size_t nDataSize) + { + CodecFactory oFactory(strStructName, strDescription); + Decoder oCodec = oFactory.makeDecoderFor(pData, nDataSize); + + size_t nCount = oCodec.getElementCount(); + std::cout << a_util::strings::format("new elements: %d", nCount).c_str(); + timestamp_t now = a_util::system::getCurrentMicroseconds(); + for (size_t nRound = 0; nRound < nRepeats; ++nRound) + { + for (size_t nElement = 0; nElement < nCount; ++nElement) + { + uint64_t nBuffer; + oCodec.getElementValue(nElement, &nBuffer); + } + } + return a_util::system::getCurrentMicroseconds() - now; + } +}; + +void TestPerf(const char* strStructName, const char* strDescription, + void* pData, size_t nDataSize) +{ + size_t nRepeats = 10000; + + std::list oTesters; + oTesters.push_back(new cTestNewPerf()); +#ifdef DDL_ENABLE_DEPRECATED_CODER + oTesters.push_back(new cTestOldPerf()); +#endif + + for (std::list::iterator it = oTesters.begin(); it != oTesters.end(); ++it) + { + timestamp_t now = a_util::system::getCurrentMicroseconds(); + { + for (size_t nRound = 0; nRound < nRepeats; ++nRound) + { + (*it)->CreateCodec(strStructName, strDescription, pData, nDataSize); + } + } + timestamp_t nTime = a_util::system::getCurrentMicroseconds() - now; + std::cout << a_util::strings::format("%s: create %lld", (*it)->getName(), nTime).c_str(); + } + + for (std::list::iterator it = oTesters.begin(); it != oTesters.end(); ++it) + { + timestamp_t nTime = (*it)->TestAccessAllElements(nRepeats, strStructName, strDescription, pData, nDataSize); + std::cout << a_util::strings::format("%s: access %lld", (*it)->getName(), nTime).c_str(); + } + + while (!oTesters.empty()) + { + delete oTesters.front(); + oTesters.pop_front(); + } +} + +/** +* @detail Test codec performances for static information +*/ +TEST(CodecTest, + TestStaticPerf) +{ + TEST_REQ("ACORE-7704"); + + static_struct::tTest sTest = static_struct::sTestData; + TestPerf("test", static_struct::strTestDesc, &sTest, sizeof(sTest)); +} + +/** +* @detail Test codec performances for dynamic information +*/ +TEST(CodecTest, + TestDynamicPerf) +{ + TEST_REQ("ACORE-7704"); + +#if 1 + simple::tMain sTest = simple::sTestData; + TestPerf("main", simple::strTestDesc, &sTest, sizeof(sTest)); +#else + complex::tMain sTest = complex::sTestData; + TestPerf("main", complex::strTestDesc, &sTest, sizeof(sTest)); +#endif +} + +namespace enums +{ + + struct tMain + { + int32_t nStatic; + int8_t nArraySize; + int32_t aArray[3]; + int32_t nAfter; + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + 2, + 3, + {1, 2, 3}, + 3 + }; + +} + +/** +* @detail Check decoder functionalities for enums +*/ +TEST(CodecTest, + TestEnums) +{ + TEST_REQ("ACORE-7704"); + + CodecFactory oFactory("main", enums::strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + Decoder oDecoder = oFactory.makeDecoderFor(&enums::sTestData, sizeof(enums::sTestData)); + DumpElements(oDecoder); + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.isValid()); + + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "static") , "B"); + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "array_size") , "3"); + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "array[0]") , "D"); + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "array[1]") , "E"); + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "array[2]") , "F"); + ASSERT_EQ(access_element::get_value_as_string(oDecoder, "after") , "F"); +} + +namespace constants +{ + + struct tMain + { + int32_t nStatic; + int8_t nArraySize; + int32_t aArray[3]; + int32_t nAfter; + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + 0, + 3, + {0, 0, 0}, + 0 + }; + +} + +/** +* @detail Check decoder functionalities for constants +*/ +TEST(CodecTest, + TestConstants) +{ + TEST_REQ("ACORE-7704"); + + CodecFactory oFactory("main", constants::strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + constants::tMain sTestData = constants::sTestData; + Codec oCodec = oFactory.makeCodecFor(&sTestData, sizeof(sTestData)); + DumpElements(oCodec); + ASSERT_EQ(a_util::result::SUCCESS, oCodec.isValid()); + + ASSERT_EQ(access_element::get_value(oCodec, "static").asInt32() , 0); + ASSERT_EQ(access_element::get_value(oCodec, "array_size").asInt32() , 3); + ASSERT_EQ(access_element::get_value(oCodec, "array[0]").asInt32() , 0); + ASSERT_EQ(access_element::get_value(oCodec, "array[1]").asInt32() , 0); + ASSERT_EQ(access_element::get_value(oCodec, "array[2]").asInt32() , 0); + ASSERT_EQ(access_element::get_value(oCodec, "after").asInt32() , 0); + + ASSERT_EQ(a_util::result::SUCCESS, oCodec.setConstants()); + + ASSERT_EQ(access_element::get_value(oCodec, "static").asInt32() , 1); + ASSERT_EQ(access_element::get_value(oCodec, "array_size").asInt32() , 3); + ASSERT_EQ(access_element::get_value(oCodec, "array[0]").asInt32() , 1); + ASSERT_EQ(access_element::get_value(oCodec, "array[1]").asInt32() , 1); + ASSERT_EQ(access_element::get_value(oCodec, "array[2]").asInt32() , 1); + ASSERT_EQ(access_element::get_value(oCodec, "after").asInt32() , 2); +} + +namespace all_types +{ + +#ifdef WIN32 +#define ALIGNED_ELEM(__align, __def) \ + __declspec(align(__align)) __def; +#else +#define ALIGNED_ELEM(__align, __def)\ + __def __attribute__((aligned(__align))); +#endif + + struct tMain + { + ALIGNED_ELEM(1, bool bBool) + ALIGNED_ELEM(1, int8_t nInt8) + ALIGNED_ELEM(1, uint8_t nUInt8) + ALIGNED_ELEM(2, int16_t nInt16) + ALIGNED_ELEM(2, uint16_t nUInt16) + ALIGNED_ELEM(4, int32_t nInt32) + ALIGNED_ELEM(4, uint32_t nUInt32) + ALIGNED_ELEM(8, int64_t nInt64) + ALIGNED_ELEM(8, uint64_t nUInt64) + ALIGNED_ELEM(4, float fFloat32) + ALIGNED_ELEM(8, double fFloat64) + ALIGNED_ELEM(1, char nChar) + }; + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + true, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + (float)3.1415, + 2.7182, + 'x' + }; + +} + +/** +* @detail Check decoder functionalities for all types +*/ +TEST(CodecTest, + TestAllTypes) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-12 CDPKGDDL-13"); + + using namespace all_types; + + CodecFactory oFactory("main", strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + + Decoder oDecoder = oFactory.makeDecoderFor(&sTestData, sizeof(sTestData)); + a_util::memory::MemoryBuffer oSerializedBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oDecoder, oSerializedBuffer, true)); + + oDecoder = oFactory.makeDecoderFor(oSerializedBuffer.getPtr(), oSerializedBuffer.getSize(), + serialized); + a_util::memory::MemoryBuffer oBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oDecoder, oBuffer, true)); + + const tMain* pRes = reinterpret_cast(oBuffer.getPtr()); + ASSERT_EQ(pRes->bBool , sTestData.bBool); + ASSERT_EQ(pRes->nInt8 , sTestData.nInt8); + ASSERT_EQ(pRes->nUInt8 , sTestData.nUInt8); + ASSERT_EQ(pRes->nInt16 , sTestData.nInt16); + ASSERT_EQ(pRes->nUInt16 , sTestData.nUInt16); + ASSERT_EQ(pRes->nInt32 , sTestData.nInt32); + ASSERT_EQ(pRes->nUInt32 , sTestData.nUInt32); + ASSERT_EQ(pRes->nInt64 , sTestData.nInt64); + ASSERT_EQ(pRes->nUInt64 , sTestData.nUInt64); + ASSERT_EQ(pRes->fFloat32 , sTestData.fFloat32); + ASSERT_EQ(pRes->fFloat64 , sTestData.fFloat64); + ASSERT_EQ(pRes->nChar , sTestData.nChar); +} + +namespace alignment_of_substructs +{ + +#pragma pack(push, 2) + struct tSubStruct + { + int32_t nValue1; + int32_t nValue2; + }; + +#pragma pack(pop) + +#pragma pack(push, 1) + struct tMain + { + int8_t nPadding; + tSubStruct aSubStructs[4]; + }; +#pragma pack(pop) + + const char* strTestDesc = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + const tMain sTestData = + { + 0, + { + { 1, 2 }, + { 3, 4 }, + { 5, 6 }, + { 7, 8 } + } + }; + +} + +/** +* @detail Check alignment of substructures +*/ +TEST(CodecTest, + TestAlignmentOfSubstructs) +{ + TEST_REQ("CDDDL-54"); + + using namespace alignment_of_substructs; + + CodecFactory oFactory("tMain", strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticBufferSize(), sizeof(tMain)); + + Decoder oDecoder = oFactory.makeDecoderFor(&sTestData, sizeof(sTestData)); + DumpElements(oDecoder); + + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[0].nValue1").asInt8(), sTestData.aSubStructs[0].nValue1); + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[0].nValue2").asInt8(), sTestData.aSubStructs[0].nValue2); + + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[1].nValue1").asInt8(), sTestData.aSubStructs[1].nValue1); + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[1].nValue2").asInt8(), sTestData.aSubStructs[1].nValue2); + + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[2].nValue1").asInt8(), sTestData.aSubStructs[2].nValue1); + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[2].nValue2").asInt8(), sTestData.aSubStructs[2].nValue2); + + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[3].nValue1").asInt8(), sTestData.aSubStructs[3].nValue1); + ASSERT_EQ(access_element::get_value(oDecoder, "aSubStructs[3].nValue2").asInt8(), sTestData.aSubStructs[3].nValue2); +} + +void TestError(const CodecFactory& oFactory, void* pData, size_t nDataSize, size_t nIndex, bool bValid) +{ + { + StaticDecoder oTest = oFactory.makeStaticDecoderFor(pData, nDataSize); + if (bValid) + { + ASSERT_EQ(a_util::result::SUCCESS, oTest.isValid()); + } + else + { + ASSERT_NE(a_util::result::SUCCESS, oTest.isValid()); + } + uint64_t* nBuffer; + ASSERT_NE(a_util::result::SUCCESS, oTest.getElementValue(10, &nBuffer)); + a_util::variant::Variant oValue; + ASSERT_NE(a_util::result::SUCCESS, oTest.getElementValue(10, oValue)); + } + + { + Decoder oTest = oFactory.makeDecoderFor(pData, nDataSize); + if (bValid) + { + ASSERT_EQ(a_util::result::SUCCESS, oTest.isValid()); + } + else + { + ASSERT_NE(a_util::result::SUCCESS, oTest.isValid()); + } + uint64_t* nBuffer; + ASSERT_NE(a_util::result::SUCCESS, oTest.getElementValue(10, &nBuffer)); + a_util::variant::Variant oValue; + ASSERT_NE(a_util::result::SUCCESS, oTest.getElementValue(10, oValue)); + } + + { + StaticCodec oTest = oFactory.makeStaticCodecFor(pData, nDataSize); + if (bValid) + { + ASSERT_EQ(a_util::result::SUCCESS, oTest.isValid()); + } + else + { + ASSERT_NE(a_util::result::SUCCESS, oTest.isValid()); + } + uint64_t* nBuffer; + ASSERT_NE(a_util::result::SUCCESS, oTest.setElementValue(10, &nBuffer)); + a_util::variant::Variant oValue; + ASSERT_NE(a_util::result::SUCCESS, oTest.setElementValue(10, oValue)); + } + + { + Codec oTest = oFactory.makeCodecFor(pData, nDataSize); + if (bValid) + { + ASSERT_EQ(a_util::result::SUCCESS, oTest.isValid()); + } + else + { + ASSERT_NE(a_util::result::SUCCESS, oTest.isValid()); + } + uint64_t* nBuffer; + ASSERT_NE(a_util::result::SUCCESS, oTest.setElementValue(10, &nBuffer)); + a_util::variant::Variant oValue; + ASSERT_NE(a_util::result::SUCCESS, oTest.setElementValue(10, oValue)); + } +} + +/** +* @detail Test error handling in decoder +*/ +TEST(CodecTest, + TestErrorHandling) +{ + TEST_REQ("ACORE-7704 ACORE-8004"); + using namespace static_struct; + + // invalid index + { + CodecFactory oFactory = CodecFactory("test", strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + tTest sTest; + TestError(oFactory, &sTest, sizeof(sTest), 10, true); + } + + // invalid data + { + CodecFactory oFactory = CodecFactory("test", strTestDesc); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + TestError(oFactory, NULL, 0, 0, false); + } + + // invalid struct name + { + CodecFactory oFactory = CodecFactory("", strTestDesc); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + tTest sTest; + TestError(oFactory, &sTest, sizeof(sTest), 0, false); + } + + // invalid description + { + CodecFactory oFactory = CodecFactory("test", ""); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + tTest sTest; + TestError(oFactory, &sTest, sizeof(sTest), 0, false); + } +} + + diff --git a/test/codec/src/tester_mediacoder_regression.cpp b/test/codec/src/tester_mediacoder_regression.cpp new file mode 100644 index 0000000..3c3ce59 --- /dev/null +++ b/test/codec/src/tester_mediacoder_regression.cpp @@ -0,0 +1,2306 @@ +/** + * @file + * Description is missing. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" + +#define PLATFORM_BYTEORDER __get_platform_byteorder() + +_MAKE_RESULT(-20, ERR_NOT_FOUND) + + /** + * This function retrieves the platform dependent byte order. + * @return @ref platform_not_supported, @ref plattform_little_endian_8 or @ref platform_big_endian_8. + */ + static inline unsigned char __get_platform_byteorder() +{ + std::uint32_t ui32Value = 0x01020304; + if (((unsigned char*)&ui32Value)[0] == 0x04 && + ((unsigned char*)&ui32Value)[2] == 0x02) + { + return ddl::DDLByteorder::plattform_little_endian_8; + } + else if (((unsigned char*)&ui32Value)[0] == 0x01 && + ((unsigned char*)&ui32Value)[2] == 0x03) + { + return ddl::DDLByteorder::platform_big_endian_8; + } + else + { + return ddl::DDLByteorder::platform_not_supported; + } +} + +using namespace ddl; + +/** +* @detail Test that initializes a media coder by using Create and setValue +*/ +TEST(cTesterMediaCoder, + TestParseStructureSimple) +{ + TEST_REQ("ACORE-1265"); + + std::string strToParse = " "; + strToParse.append(ADTF_MEDIA_DESC_MEDIA_TYPEINFO); + strToParse.append(" "); + CodecFactory oFactory("tMediaTypeInfo", strToParse.c_str()); + + tMediaTypeInfo sInfo; + + Codec oCodec = oFactory.makeCodecFor(&sInfo, sizeof(sInfo)); + + uint32_t ui32MajorType = 1; + uint32_t ui32SubType = 2; + uint32_t ui32Flags = 3; + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui32MajorType", ui32MajorType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui32SubType", ui32SubType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui32Flags", ui32Flags)); + + ASSERT_EQ(sInfo.ui32Flags , 3); + ASSERT_EQ(sInfo.ui32SubType , 2); + ASSERT_EQ(sInfo.ui32MajorType , 1); + + + +} + +/** +* @detail Test that initializes a media coder by using Create and setValue with more complex values +*/ +TEST(cTesterMediaCoder, + TestParseNotSoVerySimple) +{ + TEST_REQ("ACORE-1265"); + + std::string strToParse = " "; + strToParse.append(ADTF_MEDIA_DESC_MEDIA_TYPEINFO); + strToParse.append(""); + strToParse.append(""); + strToParse.append(""); + strToParse.append(""); + strToParse.append(" "); + + CodecFactory oFactory("tMyType", strToParse.c_str()); + + typedef struct + { + tMediaTypeInfo sInfo1; + tMediaTypeInfo sInfo2; + } tMyType; + tMyType sMyType; + + Codec oCodec = oFactory.makeCodecFor(&sMyType, sizeof(sMyType)); + + uint32_t ui32MajorType = 1; + uint32_t ui32SubType = 2; + uint32_t ui32Flags = 3; + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32MajorType", ui32MajorType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32SubType", ui32SubType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32Flags", ui32Flags)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value2.ui32MajorType", ui32MajorType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value2.ui32SubType", ui32SubType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value2.ui32Flags", ui32Flags)); + + ASSERT_EQ(sMyType.sInfo1.ui32Flags , 3); + ASSERT_EQ(sMyType.sInfo1.ui32SubType , 2); + ASSERT_EQ(sMyType.sInfo1.ui32MajorType , 1); + + ASSERT_EQ(sMyType.sInfo2.ui32Flags , 3); + ASSERT_EQ(sMyType.sInfo2.ui32SubType , 2); + ASSERT_EQ(sMyType.sInfo2.ui32MajorType , 1); + + +} + +/** +* @detail Test that initializes a media coder by using Create and setValue with a union in the values +*/ +TEST(cTesterMediaCoder, + TestParseALittleBitDifficult) +{ + TEST_REQ("ACORE-1265"); + + std::string strToParse = " "; + strToParse.append(ADTF_MEDIA_DESC_MEDIA_TYPEINFO); + strToParse.append(""); + strToParse.append(""); + strToParse.append(""); + strToParse.append(""); + strToParse.append(" "); + + CodecFactory oFactory("tMyType", strToParse.c_str()); + + typedef struct + { + tMediaTypeInfo sInfo1; + tMediaTypeInfo sInfo2; + } tMyType; + tMyType sMyType; + + Codec oCodec = oFactory.makeCodecFor(&sMyType, sizeof(sMyType)); + + uint32_t ui32MajorType = 1; + uint32_t ui32SubType = 2; + uint32_t ui32Flags = 3; + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32MajorType", ui32MajorType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32SubType", ui32SubType)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1.ui32Flags", ui32Flags)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_struct_value(oCodec, "value2", &sMyType.sInfo1)); + + ASSERT_EQ(sMyType.sInfo1.ui32MajorType , 1); + ASSERT_EQ(sMyType.sInfo1.ui32SubType , 2); + ASSERT_EQ(sMyType.sInfo1.ui32Flags , 3); + + ASSERT_EQ(sMyType.sInfo2.ui32MajorType , 1); + ASSERT_EQ(sMyType.sInfo2.ui32SubType , 2); + ASSERT_EQ(sMyType.sInfo2.ui32Flags , 3); + + + +} + +/** +* @detail The parsing of data types will be tested with very different possibilities to add a type. +* A media coder is initialized using Create with dom string +*/ +TEST(cTesterMediaCoder, + TestParseOnlyDataTypes) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + { + std::string strDataTypeToParse = ""; + strDataTypeToParse.append(""); + CodecFactory oFactory("tMyType", strDataTypeToParse.c_str()); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + { + std::string strDataTypeToParse = ""; + strDataTypeToParse.append(""); + + CodecFactory oFactory("tMyType", strDataTypeToParse.c_str()); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + { + //error but nothing happen while datatype parsing + std::string strDataTypeToParse = ""; + strDataTypeToParse.append(""); + CodecFactory oFactory("tMyType", strDataTypeToParse.c_str()); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + { + //size is not valid + std::string strDataTypeToParse = ""; + strDataTypeToParse.append(""); + CodecFactory oFactory("tMyType", strDataTypeToParse.c_str()); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + +} + +/** +* @detail The parsing of struct will be tested with very different possibilities to add a struct +* A media coder is initialized using Create with dom string +*/ +TEST(cTesterMediaCoder, + TestParseOnlyStruct) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + { + //with no element + std::string strStructToParse = ""; + strStructToParse.append(""); + CodecFactory oFactory("mystruct", strStructToParse.c_str()); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + { + //with no element and forgotten aligment + std::string strStructToParse = ""; + strStructToParse.append(""); + CodecFactory oFactory("mystruct", strStructToParse.c_str()); + ASSERT_EQ(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + { + //test if root is the struct (it will work) + std::string strStructToParse = std::string(""); + strStructToParse.append(""); + strStructToParse.append(""); + strStructToParse.append(""); + CodecFactory oFactory("tMyType", strStructToParse.c_str()); + ASSERT_EQ(oFactory.getStaticElementCount() , 2); + } + + { + //test if root is structs and then the struct is in it (it will work) + std::string strStructToParse = std::string(""); + strStructToParse.append(""); + strStructToParse.append(""); + strStructToParse.append(""); + CodecFactory oFactory("tMyType", strStructToParse.c_str()); + ASSERT_EQ(oFactory.getStaticElementCount() , 2); + } + + { + //test if root is something else is the root and then the struct is in it (it will work) + std::string strStructToParse = std::string(""); + strStructToParse.append(""); + strStructToParse.append(""); + strStructToParse.append(""); + CodecFactory oFactory("tMyType", strStructToParse.c_str()); + ASSERT_EQ(oFactory.getStaticElementCount() , 2); + } + + { + //test if root is something else and there is ea forgotten struct + std::string strStructToParse = std::string(""); + strStructToParse.append(""); + strStructToParse.append(""); + strStructToParse.append(""); + CodecFactory oFactory("tMyType", strStructToParse.c_str()); + ASSERT_NE(a_util::result::SUCCESS, oFactory.isValid()); + ASSERT_EQ(oFactory.getStaticElementCount() , 0); + } + + +} + +#pragma pack ( push, 1 ) +// Test struct for DDL version < 3.0 +typedef struct +{ + uint16_t firstvalue; // aligned at position 0 (1 byte aligned) + uint8_t padding[6]; + uint8_t secondvalue; // aligned at position 8 (8 byte aligned) +} tAlignedStruct_v20; +// Test struct for DDL version >= 3.0 +typedef struct +{ + uint16_t firstvalue; // aligned at position 0 (1 byte aligned) + uint8_t padding1[6]; + uint8_t secondvalue; // aligned at position 8 (8 byte aligned) + uint8_t padding2[7]; // size of struct is 16 (for 8byte alignment) +} tAlignedStruct_v30; +#pragma pack ( pop ) + +/** +* Template method for filling an aligned struct +* Use this to fill tAlignedStruct_v20, tAlignedStruct_v30 and so on with number 1 and 2. +* @return A struct filled with value 1 and 2. +*/ +template +S FillAlignedStruct() +{ + S sAlignedStruct; + a_util::memory::set(&sAlignedStruct, sizeof(sAlignedStruct), 0, sizeof(sAlignedStruct)); + sAlignedStruct.firstvalue = 1; + sAlignedStruct.secondvalue = 2; + return sAlignedStruct; +} + +/** +* Template method for checking a struct if it has the same content as a struct filled with FillAlignedStruct(). +* Use this with tAlignedStruct_v20, tAlignedStruct_v30 and so on. +* @param [in] sAlignedStruct The struct to be checked. +* @param [in] pReference a pointer to the original memory block used with oCoder.Begin. +*/ +template +void CheckAlignedStruct(const S* sAlignedStruct, const S* sReference) +{ + // A bit redundant checking, but better save than sorry. + ASSERT_EQ(sAlignedStruct->firstvalue , sReference->firstvalue); + ASSERT_EQ(sAlignedStruct->secondvalue , sReference->secondvalue); + ASSERT_EQ(a_util::memory::compare(sAlignedStruct, sizeof(S), sReference, sizeof(S)) , 0); +} + +/** +* Checks if the decoded values from the media coder are the same as filled with FillAlignedStruct(). +* @param [in] pCoder The coder to use. Has to be fully initialized. +* @param [in] pReference a pointer to the original memory block used with oCoder.Begin. +* @param [in] strPrefix a prefix to used if the the member is within an array. +*/ +template +void CheckAlignedStructElementCoderAccess(Codec& oCodec, const S* pReference, const char* strPrefix = "") +{ + uint16_t ui16Value; + uint8_t ui8Value; + std::string strFmt = a_util::strings::format("%sfirstvalue", strPrefix); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, strFmt, (void*)&ui16Value)); + ASSERT_EQ(ui16Value , pReference->firstvalue); + strFmt = a_util::strings::format("%ssecondvalue", strPrefix); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, strFmt, (void*)&ui8Value)); + ASSERT_EQ(ui8Value , pReference->secondvalue); + + // Negative test: nonexisting element must not be found. + a_util::result::Result nResult = access_element::get_value(oCodec, a_util::strings::format("%sbla", strPrefix), &ui16Value); + ASSERT_EQ(nResult , ERR_NOT_FOUND); +} + +/** +* Template method for checking if if a whole struct can be accessed in a coder. +* Use this with tAlignedStruct_v20, tAlignedStruct_v30 and so on. +* @param [in] pCoder The coder to use. Has to be fully initialized. +* @param [in] pReference a pointer to the original memory block used with oCoder.Begin. +*/ +template +void CheckAlignedStructCoderAccess(Codec& oCodec, const S* pReference, bool bRefCheck) +{ + S* pValCheck = new S(); + a_util::memory::set((void*)pValCheck, sizeof(S), 0, sizeof(S)); + //access via Empty String + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "", pValCheck)); + CheckAlignedStruct(pValCheck, pReference); + + //Ref check + delete pValCheck; + + pValCheck = access_element::get_struct_address(oCodec, ""); + ASSERT_TRUE(pValCheck); + CheckAlignedStruct(pValCheck, pReference); + + if (bRefCheck) + { + ASSERT_EQ((void*)pValCheck, (void*)pReference); + } +} + +std::string g_strAlignedStructStructToParse = ""; + +std::string strDDLv20Header = "" + "
" + "2.00" + "AUDI Electronics Venture GmbH" + "20130703" + "" + "ADTF Common Description File" + "
"; +std::string strDDLv30Header = "" + "
" + "3.00" + "AUDI Electronics Venture GmbH" + "20130703" + "" + "ADTF Common Description File" + "
"; + +/** +* @detail The Structure will be represented without error in the memory +* This test initializes a media coder using create with dom string +* and access the members that are aligned +* Passed if: The function will resolve the right byte position to +* access the elements of the structure +*/ +TEST(cTesterMediaCoder, + TestAligmentSimpleAlsoVersion30) +{ + TEST_REQ("ACORE-1265 ACORE-2641 ACORE-6148"); + + std::string strStruct = "" + "" + " " + " " + "" + ""; + + std::string strDDLv20 = strDDLv20Header + strStruct + + "
"; + std::string strDDLv30 = strDDLv30Header + strStruct + + "
"; + + CodecFactory oFactory_v20("tAlignedStruct", strDDLv20.c_str()); + CodecFactory oFactory_v30("tAlignedStruct", strDDLv30.c_str()); + + tAlignedStruct_v20 sVal20 = FillAlignedStruct(); + tAlignedStruct_v30 sVal30 = FillAlignedStruct(); + + Codec oCodec_v20 = oFactory_v20.makeCodecFor(&sVal20, sizeof(sVal20)); + Codec oCodec_v30 = oFactory_v30.makeCodecFor(&sVal30, sizeof(sVal30)); + + CheckAlignedStructElementCoderAccess(oCodec_v20, &sVal20); + CheckAlignedStructElementCoderAccess(oCodec_v30, &sVal30); + + CheckAlignedStructCoderAccess(oCodec_v20, &sVal20, true); + CheckAlignedStructCoderAccess(oCodec_v30, &sVal30, true); +} + +#pragma pack ( push, 1 ) +// Test struct for DDL version < 3.0 +typedef struct +{ + tAlignedStruct_v20 s0; // 9 + uint8_t padding0[7]; // 16 + tAlignedStruct_v20 s1; // 25 + uint8_t padding1[7]; // 32 + tAlignedStruct_v20 s2; // 41 + uint8_t padding2[7]; // 48 + tAlignedStruct_v20 s3; // 57 + uint8_t padding3[7]; // 64 + tAlignedStruct_v20 s4; // 73 +} tAlignedStructArray_v20; +// Test struct for DDL version >= 3.0 +typedef struct +{ + tAlignedStruct_v30 s0; + tAlignedStruct_v30 s1; + tAlignedStruct_v30 s2; + tAlignedStruct_v30 s3; + tAlignedStruct_v30 s4; +} tAlignedStructArray_v30; +#pragma pack ( pop ) + +/** +* Template method for filling an aligned struct array +* Use this to fill tAlignedStructArray_v20, tAlignedStructArray_v30 and so on with values 1 to 10. +* @return A struct filled with values 1 to 10. +*/ +template +S FillAlignedStructArray() +{ + S sAlignedStructArray; + a_util::memory::set(&sAlignedStructArray, sizeof(S), 0, sizeof(S)); + sAlignedStructArray.s0.firstvalue = 1; + sAlignedStructArray.s0.secondvalue = 2; + sAlignedStructArray.s1.firstvalue = 3; + sAlignedStructArray.s1.secondvalue = 4; + sAlignedStructArray.s2.firstvalue = 5; + sAlignedStructArray.s2.secondvalue = 6; + sAlignedStructArray.s3.firstvalue = 7; + sAlignedStructArray.s3.secondvalue = 8; + sAlignedStructArray.s4.firstvalue = 9; + sAlignedStructArray.s4.secondvalue = 10; + return sAlignedStructArray; +} + +/** +* Template method for checking a struct if it has the same content as a struct filled with FillAlignedStruct(). +* Use this with tAlignedStructArray_v20, tAlignedStructArray_v30 and so on. +* @param [in] sAlignedStructArray The struct to be checked. +*/ +template +void CheckAlignedStructArray(const A* pAlignedStructArray, const A* pReference) +{ + // A bit redundant checking, but better save than sorry. + CheckAlignedStruct(&(pAlignedStructArray->s0), &(pReference->s0)); + CheckAlignedStruct(&(pAlignedStructArray->s1), &(pReference->s1)); + CheckAlignedStruct(&(pAlignedStructArray->s2), &(pReference->s2)); + CheckAlignedStruct(&(pAlignedStructArray->s3), &(pReference->s3)); + CheckAlignedStruct(&(pAlignedStructArray->s4), &(pReference->s4)); + ASSERT_EQ(a_util::memory::compare(pAlignedStructArray, sizeof(A), pReference, sizeof(A)) , 0); +} + +/** +* Template method for checking if a whole struct can be accessed with a coder. +* Use this with tAlignedStructArray_v20, tAlignedStructArray_v30 and so on. +* @param [in] pCoder The coder to use. Has to be fully initialized. +* @param [in] pReference a pointer to the original memory block used with oCoder.Begin. +*/ +template +void CheckAlignedStructArrayCoderAccess(Codec& oCodec, const A* pReference, bool bRefCheck) +{ + ASSERT_EQ(oCodec.getBufferSize(), sizeof(A)); + + A* pValCheck = new A(); + a_util::memory::set((void*)pValCheck, sizeof(A), 0, sizeof(A)); + //access via Empty String + a_util::memory::set((void*)pValCheck, sizeof(A), 0, sizeof(A)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "", pValCheck)); + CheckAlignedStructArray(pValCheck, pReference); + + //access via whole array element + a_util::memory::set((void*)pValCheck, sizeof(A), 0, sizeof(A)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_array_value(oCodec, "array", pValCheck)); + CheckAlignedStructArray(pValCheck, pReference); + + //Ref check + delete pValCheck; + + pValCheck = access_element::get_array_address(oCodec, ""); + ASSERT_TRUE(pValCheck); + CheckAlignedStructArray(pValCheck, pReference); + if (bRefCheck) + { + ASSERT_EQ((void*)pValCheck , (void*)pReference); + } + //Ref check via first element + pValCheck = NULL; + pValCheck = access_element::get_array_address(oCodec, "array"); + ASSERT_TRUE(pValCheck); + CheckAlignedStructArray(pValCheck, pReference); + if (bRefCheck) + { + ASSERT_EQ((void*)pValCheck , (void*)pReference); + } +} + +/** +* Template method for checking if single elements of and array and their children can be accessed with a coder. +* Use this with tAlignedStructArray_v20, tAlignedStructArray_v30 and so on. +* @param [in] pCoder The coder to use. Has to be fully initialized. +* @param [in] pReference a pointer to the original memory block used with oCoder.Begin. +*/ + +template +void CheckAlignedStructArrayCoderArrayAccess(Codec& oCodec, const A* pReference) +{ + S* pTestAlignedElement = new S(); + a_util::memory::set((void*)pTestAlignedElement, sizeof(S), 0, sizeof(S)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[0]", pTestAlignedElement)); + CheckAlignedStruct(pTestAlignedElement, &pReference->s0); + + a_util::memory::set((void*)pTestAlignedElement, sizeof(S), 0, sizeof(S)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[1]", pTestAlignedElement)); + CheckAlignedStruct(pTestAlignedElement, &pReference->s1); + + a_util::memory::set((void*)pTestAlignedElement, sizeof(S), 0, sizeof(S)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[2]", pTestAlignedElement)); + CheckAlignedStruct(pTestAlignedElement, &pReference->s2); + + a_util::memory::set((void*)pTestAlignedElement, sizeof(S), 0, sizeof(S)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[3]", pTestAlignedElement)); + CheckAlignedStruct(pTestAlignedElement, &pReference->s3); + + a_util::memory::set((void*)pTestAlignedElement, sizeof(S), 0, sizeof(S)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[4]", pTestAlignedElement)); + CheckAlignedStruct(pTestAlignedElement, &pReference->s4); + + CheckAlignedStructElementCoderAccess(oCodec, &pReference->s0, "array[0]."); + CheckAlignedStructElementCoderAccess(oCodec, &pReference->s1, "array[1]."); + CheckAlignedStructElementCoderAccess(oCodec, &pReference->s2, "array[2]."); + CheckAlignedStructElementCoderAccess(oCodec, &pReference->s3, "array[3]."); + CheckAlignedStructElementCoderAccess(oCodec, &pReference->s4, "array[4]."); + + // Negative test: nonexisting array element must not be found + ASSERT_NE(a_util::result::SUCCESS, access_element::get_struct_value(oCodec, "array[5]", pTestAlignedElement)); +} + + +std::string g_strAlignedStructArrayStructToParse = ""; + +/** +* @detail The Structure will be represented without error in the memory +* This test initializes a media coder using create with dom string and +* access the members of an array that are aligned +* Passed if: The function will resolve the right byte position to access the +* elements of the of the structure and array +*/ +TEST(cTesterMediaCoder, + TestAligmentArray) +{ + TEST_REQ("ACORE-1265 ACORE-2641 ACORE-6148"); + + std::string strStruct = "" + "" + " " + " " + "" + "" + " " + "" + ""; + + std::string strDDLv20 = strDDLv20Header + strStruct + + ""; + std::string strDDLv30 = strDDLv30Header + strStruct + + ""; + + //this is the description for the above Array structure with aligned access + + tAlignedStructArray_v20 sArray_v20 = FillAlignedStructArray(); + tAlignedStructArray_v30 sArray_v30 = FillAlignedStructArray(); + + CodecFactory oFactory_v20("tAlignedStructArray", strDDLv20.c_str()); + CodecFactory oFactory_v30("tAlignedStructArray", strDDLv30.c_str()); + Codec oCodec_v20 = oFactory_v20.makeCodecFor(&sArray_v20, sizeof(sArray_v20)); + Codec oCodec_v30 = oFactory_v30.makeCodecFor(&sArray_v30, sizeof(sArray_v30)); + + CheckAlignedStructArrayCoderAccess(oCodec_v20, &sArray_v20, true); + CheckAlignedStructArrayCoderAccess(oCodec_v30, &sArray_v30, true); + + CheckAlignedStructArrayCoderArrayAccess(oCodec_v20, &sArray_v20); + CheckAlignedStructArrayCoderArrayAccess(oCodec_v30, &sArray_v30); + +} + +#pragma pack ( push, 1 ) +typedef struct +{ + uint16_t firstvalue; + uint8_t secondvalue; +} tSerializedStruct; +typedef struct +{ + uint8_t gap[20]; + tSerializedStruct sValues[5]; +} tSerializedArray; +#pragma pack ( pop ) + +/** +* @detail The Structure will be serialized and deserialized with the description +* This test initializes a media coder using create with dom string and serializes +* and deserializes the content given. Test if the values are equal after +* deserialization. +* Passed if: The function will set the right byte and bit position in the stream given. +*/ +TEST(cTesterMediaCoder, + TestCoderSerializer) +{ + TEST_REQ("ACORE-1265 ACORE-2641 ACORE-6148"); + + std::string strStruct = "" + "" + " " + " " + "" + "" + " " + "" + ""; + + std::string strDDLv20 = strDDLv20Header + strStruct + + ""; + std::string strDDLv30 = strDDLv30Header + strStruct + + ""; + + //this is the description for the above Array structure with aligned access + + tAlignedStructArray_v20 sArray_v20 = FillAlignedStructArray(); + tAlignedStructArray_v30 sArray_v30 = FillAlignedStructArray(); + + CodecFactory oFactory_v20("tAlignedStructArray", strDDLv20.c_str()); + CodecFactory oFactory_v30("tAlignedStructArray", strDDLv30.c_str()); + Codec oCodec_v20 = oFactory_v20.makeCodecFor(&sArray_v20, sizeof(sArray_v20)); + Codec oCodec_v30 = oFactory_v30.makeCodecFor(&sArray_v30, sizeof(sArray_v30)); + + a_util::memory::MemoryBuffer oBuffer_v20; + a_util::memory::MemoryBuffer oBuffer_v30; + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec_v20, oBuffer_v20, true)); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec_v30, oBuffer_v30, true)); + + tSerializedArray* pSerArray_v20 = (tSerializedArray*)oBuffer_v20.getPtr(); + tSerializedArray* pSerArray_v30 = (tSerializedArray*)oBuffer_v30.getPtr(); + + // Check if serialization has the same result with both versions. + ASSERT_EQ(a_util::memory::compare(pSerArray_v20, sizeof(tSerializedArray), pSerArray_v30, sizeof(tSerializedArray)) , 0); + // Since both memory blocks are equal, only one has to be verified. + ASSERT_EQ(pSerArray_v20->sValues[0].secondvalue , 2); + ASSERT_EQ(pSerArray_v20->sValues[1].secondvalue , 4); + ASSERT_EQ(pSerArray_v20->sValues[2].secondvalue , 6); + ASSERT_EQ(pSerArray_v20->sValues[3].secondvalue , 8); + ASSERT_EQ(pSerArray_v20->sValues[4].secondvalue , 10); + + if (PLATFORM_BYTEORDER == ddl::DDLByteorder::plattform_little_endian_8) + { + ASSERT_EQ(pSerArray_v20->sValues[0].firstvalue , 256); + ASSERT_EQ(pSerArray_v20->sValues[1].firstvalue , 768); + ASSERT_EQ(pSerArray_v20->sValues[2].firstvalue , 1280); + ASSERT_EQ(pSerArray_v20->sValues[3].firstvalue , 1792); + ASSERT_EQ(pSerArray_v20->sValues[4].firstvalue , 2304); + } + else + { + ASSERT_EQ(pSerArray_v20->sValues[0].firstvalue , 1); + ASSERT_EQ(pSerArray_v20->sValues[1].firstvalue , 3); + ASSERT_EQ(pSerArray_v20->sValues[2].firstvalue , 5); + ASSERT_EQ(pSerArray_v20->sValues[3].firstvalue , 7); + ASSERT_EQ(pSerArray_v20->sValues[4].firstvalue , 9); + } + + + Decoder oSerDecoder_v20 = oFactory_v20.makeDecoderFor(oBuffer_v20.getPtr(), oBuffer_v20.getSize(), serialized); + Decoder oSerDecoder_v30 = oFactory_v30.makeDecoderFor(oBuffer_v30.getPtr(), oBuffer_v30.getSize(), serialized); + + tAlignedStructArray_v20 sArrayget_v20; + tAlignedStructArray_v30 sArrayget_v30; + a_util::memory::set(&sArrayget_v20, sizeof(sArrayget_v20), 0, sizeof(sArrayget_v20)); + a_util::memory::set(&sArrayget_v30, sizeof(sArrayget_v30), 0, sizeof(sArrayget_v30)); + oCodec_v20 = oSerDecoder_v20.makeCodecFor(&sArrayget_v20, sizeof(sArrayget_v20), deserialized); + oCodec_v30 = oSerDecoder_v30.makeCodecFor(&sArrayget_v30, sizeof(sArrayget_v30), deserialized); + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform(oSerDecoder_v20, oCodec_v20)); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform(oSerDecoder_v30, oCodec_v30)); + + // test if the content is still the same + CheckAlignedStructArrayCoderAccess(oCodec_v20, &sArray_v20, false); + CheckAlignedStructArrayCoderAccess(oCodec_v30, &sArray_v30, false); + + // test if accessing of the whole struct still works + CheckAlignedStructArrayCoderAccess(oCodec_v20, &sArrayget_v20, true); + CheckAlignedStructArrayCoderAccess(oCodec_v30, &sArrayget_v30, true); + + // test if array access still works + CheckAlignedStructArrayCoderArrayAccess(oCodec_v20, &sArrayget_v20); + CheckAlignedStructArrayCoderArrayAccess(oCodec_v30, &sArrayget_v30); + +} + +/** +* @detail The CAN Message will be serialized right. +* This test initializes a media coder using the definition of ADTF CAN Message +* Passed if: The function will resolve the right byte position to access the +* elements of the of the CAN structure +*/ +TEST(cTesterMediaCoder, + TestCoderSerializerCanMessage) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + tCanMessage sMessageToCompare; + tCanMessage sMessageToset; + + CodecFactory oFactory(ADTF_MEDIA_DESC_CANMESSAGE, ADTF_MEDIA_DESC_CANMESSAGE_DESCRIPTION); + + for (int nIdx = 1; nIdx < 200; nIdx++) + { + a_util::memory::set(&sMessageToset, sizeof(sMessageToset), 0, sizeof(sMessageToset)); + a_util::memory::set(&sMessageToCompare, sizeof(sMessageToCompare), 0, sizeof(sMessageToCompare)); + Codec oCodec = oFactory.makeCodecFor(&sMessageToset, sizeof(sMessageToset)); + + sMessageToCompare.ui16Id = nIdx; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui16Id", &sMessageToCompare.ui16Id)); + + sMessageToCompare.ui8Channel = nIdx % 5; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui8Channel", &sMessageToCompare.ui8Channel)); + + sMessageToCompare.ui8Length = nIdx % 7 + 1; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "ui8Length", &sMessageToCompare.ui8Length)); + + for (int nPayload = 0; + nPayload < sMessageToCompare.ui8Length; + nPayload++) + { + ASSERT_TRUE(nPayload < 8); + sMessageToCompare.pui8Data[nPayload] = nPayload; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, a_util::strings::format("pui8Data[%d]", nPayload), &sMessageToCompare.pui8Data[nPayload])); + } + ASSERT_EQ(a_util::memory::compare(&sMessageToset, sizeof(sMessageToset), &sMessageToCompare, sizeof(sMessageToset)) , 0); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + + if (PLATFORM_BYTEORDER == ddl::DDLByteorder::plattform_little_endian_8) + { + const tCanMessage* pCanMessageSerialized = (const tCanMessage*)oWriteBuffer.getPtr(); + ASSERT_EQ(a_util::memory::compare(pCanMessageSerialized, sizeof(sMessageToCompare), &sMessageToCompare, sizeof(sMessageToCompare)) , 0); + } + else + { + const tCanMessage* pCanMessageSerialized = (const tCanMessage*)oWriteBuffer.getPtr(); + ASSERT_NE(a_util::memory::compare(pCanMessageSerialized, sizeof(sMessageToCompare), &sMessageToCompare, sizeof(sMessageToCompare)) , 0); + ASSERT_EQ(pCanMessageSerialized->ui8Channel , sMessageToCompare.ui8Channel); + ASSERT_EQ(pCanMessageSerialized->ui8Length , sMessageToCompare.ui8Length); + ASSERT_EQ(a_util::memory::compare(pCanMessageSerialized->pui8Data, 8, sMessageToCompare.pui8Data, 8) , 0); + uint16_t ui16Id = pCanMessageSerialized->ui16Id; + ui16Id = a_util::memory::swapEndianess(ui16Id); + ASSERT_EQ(sMessageToCompare.ui16Id , ui16Id); + } + + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + a_util::memory::MemoryBuffer oReadBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oReadBuffer)); + ASSERT_EQ(a_util::memory::compare(oReadBuffer.getPtr(), sizeof(sMessageToCompare), &sMessageToCompare, sizeof(sMessageToCompare)) , 0); + } + +} + +/** +* @detail Media Coder Serialization for one bit values. +* This test serializes bit described values and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathOneBit) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[10]; + } tSerializedStructure10; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + size_t nSize = oFactory.getStaticBufferSize(); + a_util::memory::MemoryBuffer oBuffer(nSize); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + uint16_t ui16Value = 1; //one bit used + uint8_t ui8Value = 1; //one bit used + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitOnByteBorderInBeginning", &ui16Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning1", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning2", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning3", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning4", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning5", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning6", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "OneBitNotOnByteBorderInBeginning7", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + const tSerializedStructure10* psSerStructure = (const tSerializedStructure10*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0); + ASSERT_EQ(psSerStructure->ui8Value[2] , 1); + ASSERT_EQ(psSerStructure->ui8Value[3] , 2); + ASSERT_EQ(psSerStructure->ui8Value[4] , 4); + ASSERT_EQ(psSerStructure->ui8Value[5] , 8); + ASSERT_EQ(psSerStructure->ui8Value[6] , 16); + ASSERT_EQ(psSerStructure->ui8Value[7] , 32); + ASSERT_EQ(psSerStructure->ui8Value[8] , 64); + ASSERT_EQ(psSerStructure->ui8Value[9] , 128); + + +} + +/** +* @detail Media Coder Serialization for two bit values. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathTwoBits) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[11]; + } tSerializedStructure11; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + size_t nSize = oFactory.getStaticBufferSize(); + a_util::memory::MemoryBuffer oBuffer(nSize); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + uint16_t ui16Value = 1; //one bit used + uint8_t ui8Value = 1; //one bit used + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitOnByteBorderInBeginning", &ui16Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning3", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning4", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning5", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning6", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning7", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning8", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning9", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + const tSerializedStructure11* psSerStructure = (const tSerializedStructure11*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0); + ASSERT_EQ(psSerStructure->ui8Value[2] , 1); + ASSERT_EQ(psSerStructure->ui8Value[3] , 2); + ASSERT_EQ(psSerStructure->ui8Value[4] , 4); + ASSERT_EQ(psSerStructure->ui8Value[5] , 8); + ASSERT_EQ(psSerStructure->ui8Value[6] , 16); + ASSERT_EQ(psSerStructure->ui8Value[7] , 32); + ASSERT_EQ(psSerStructure->ui8Value[8] , 64); + ASSERT_EQ(psSerStructure->ui8Value[9] , 128); + ASSERT_EQ(psSerStructure->ui8Value[10] , 0); + + + //test two bits in it + ui16Value = 3; //two bit used + ui8Value = 3; //two bit used + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitOnByteBorderInBeginning", &ui16Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning3", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning4", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning5", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning6", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning7", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning8", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning9", &ui8Value)); + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + psSerStructure = (const tSerializedStructure11*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0); + ASSERT_EQ(psSerStructure->ui8Value[2] , 3); + ASSERT_EQ(psSerStructure->ui8Value[3] , 6); + ASSERT_EQ(psSerStructure->ui8Value[4] , 12); + ASSERT_EQ(psSerStructure->ui8Value[5] , 24); + ASSERT_EQ(psSerStructure->ui8Value[6] , 48); + ASSERT_EQ(psSerStructure->ui8Value[7] , 96); + ASSERT_EQ(psSerStructure->ui8Value[8] , 192); + ASSERT_EQ(psSerStructure->ui8Value[9] , 128); + ASSERT_EQ(psSerStructure->ui8Value[10] , 1); + + + //test two bits in it while all bits are set in memory, but only relvant for serialization will be copied + //to the data buffer + ui16Value = 0xFFFF; //all bits used + ui8Value = 0xFF; //all bits used + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitOnByteBorderInBeginning", &ui16Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning3", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning4", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning5", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning6", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning7", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning8", &ui8Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning9", &ui8Value)); + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + psSerStructure = (const tSerializedStructure11*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0); + ASSERT_EQ(psSerStructure->ui8Value[2] , 3); + ASSERT_EQ(psSerStructure->ui8Value[3] , 6); + ASSERT_EQ(psSerStructure->ui8Value[4] , 12); + ASSERT_EQ(psSerStructure->ui8Value[5] , 24); + ASSERT_EQ(psSerStructure->ui8Value[6] , 48); + ASSERT_EQ(psSerStructure->ui8Value[7] , 96); + ASSERT_EQ(psSerStructure->ui8Value[8] , 192); + ASSERT_EQ(psSerStructure->ui8Value[9] , 128); + ASSERT_EQ(psSerStructure->ui8Value[10] , 1); + + + //test two bits in it + //while sometimes only 1 bit is set + //to the data buffer + + uint8_t ui8NotAllset01 = 0xFD; //all bits used + uint8_t ui8NotAllset00 = 0xFC; //all bits used + uint8_t ui8NotAllset10 = 0xFE; //all bits used + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitOnByteBorderInBeginning", &ui16Value)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning3", &ui8NotAllset01)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning4", &ui8NotAllset00)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning5", &ui8NotAllset10)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning6", &ui8NotAllset01)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning7", &ui8NotAllset00)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning8", &ui8NotAllset10)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "TwoBitNotOnByteBorderInBeginning9", &ui8NotAllset10)); + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + psSerStructure = (const tSerializedStructure11*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0); + ASSERT_EQ(psSerStructure->ui8Value[2] , 3); + ASSERT_EQ(psSerStructure->ui8Value[3] , 2); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0); + ASSERT_EQ(psSerStructure->ui8Value[5] , 16); + ASSERT_EQ(psSerStructure->ui8Value[6] , 16); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0); + ASSERT_EQ(psSerStructure->ui8Value[8] , 128); + ASSERT_EQ(psSerStructure->ui8Value[9] , 0); + ASSERT_EQ(psSerStructure->ui8Value[10] , 1); + + //pSerializer = NULL; +} + +/** +* @detail Media Coder Serialization for bit values without byte gaps. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathDifferentPositionTogether) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[9]; + } tSerializedStructure9; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oBuffer(oFactory.getStaticBufferSize()); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + uint16_t ui16Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value10bits1", &ui16Value)); + uint32_t ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value11bits3", &ui32Value)); + ui32Value = 0x01FFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value45bits32", &ui32Value)); + uint8_t ui8Value = 0x07; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value85bits3", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + const tSerializedStructure9* psSerStructure = (const tSerializedStructure9*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0xF1); + ASSERT_EQ(psSerStructure->ui8Value[2] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[3] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0x1F); + ASSERT_EQ(psSerStructure->ui8Value[5] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[6] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[8] , 0xE0); + + // deserialize into oBuffer + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oBuffer, true)); + oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + ui16Value = 0; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value10bits1", &ui16Value)); + ASSERT_EQ(ui16Value , 0x01); + ui32Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value11bits3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25", &ui32Value)); + ASSERT_EQ(ui32Value , 0x01FFFFFF); + ui32Value = 0xFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value45bits32", &ui32Value)); + ASSERT_EQ(ui32Value , 0x0); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value85bits3", &ui8Value)); + ASSERT_EQ(ui8Value , 0x07); +} + +/** +* @detail Media Coder Serialization for bit values without byte gaps. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathDifferentPositionTogether2) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[9]; + } tSerializedStructure9; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oBuffer(oFactory.getStaticBufferSize()); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + uint16_t ui16Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value10bits1", &ui16Value)); + uint32_t ui32Value = 0x07; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value11bits3", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25", &ui32Value)); + ui32Value = 0xFFFFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value45bits32", &ui32Value)); + uint8_t ui8Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value85bits3", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + const tSerializedStructure9* psSerStructure = (const tSerializedStructure9*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0x0E); + ASSERT_EQ(psSerStructure->ui8Value[2] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[3] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0xE0); + ASSERT_EQ(psSerStructure->ui8Value[5] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[6] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[8] , 0x1F); + + // deserialize into oBuffer + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oBuffer, true)); + oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + ui16Value = 0xFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value10bits1", &ui16Value)); + ASSERT_EQ(ui16Value , 0x00); + ui32Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value11bits3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x07); + ui32Value = 0xFEFE; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + ui32Value = 0xFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value45bits32", &ui32Value)); + ASSERT_EQ(ui32Value , 0xFFFFFFFF); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value85bits3", &ui8Value)); + //this is because only 1 byte is changed by the get function + ASSERT_EQ(ui8Value , 0x00); +} + +/** +* @detail Media Coder Serialization for bit values without byte gaps in big endian representation. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathDifferentPositionTogetherInBigEndian) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[9]; + } tSerializedStructure9; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oBuffer(oFactory.getStaticBufferSize()); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + uint16_t ui16Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value10bits1", &ui16Value)); + uint32_t ui32Value = 0x07; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value11bits3", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25", &ui32Value)); + ui32Value = 0xFFFFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value45bits32", &ui32Value)); + uint8_t ui8Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value85bits3", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + const tSerializedStructure9* psSerStructure = (const tSerializedStructure9*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0x0E); + ASSERT_EQ(psSerStructure->ui8Value[2] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[3] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0xE0); + ASSERT_EQ(psSerStructure->ui8Value[5] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[6] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[8] , 0x1F); + + // deserialize into oBuffer + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oBuffer, true)); + oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + ui16Value = 0xFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value10bits1", &ui16Value)); + ASSERT_EQ(ui16Value , 0x00); + ui32Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value11bits3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x07); + ui32Value = 0xFEFE; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + ui32Value = 0xFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value45bits32", &ui32Value)); + ASSERT_EQ(ui32Value , 0xFFFFFFFF); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value85bits3", &ui8Value)); + //this is because only 1 byte is changed by the get function + ASSERT_EQ(ui8Value , 0x00); +} + +/** +* @detail Media Coder Serialization for bit values without byte gaps in big endian representation. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathDifferentPositionTogetherInBigEndian2) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[9]; + } tSerializedStructure9; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oBuffer(oFactory.getStaticBufferSize()); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + uint16_t ui16Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value10bits1", &ui16Value)); + uint32_t ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value11bits3", &ui32Value)); + ui32Value = 0x01FFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value45bits32", &ui32Value)); + uint8_t ui8Value = 0x07; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value85bits3", &ui8Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + const tSerializedStructure9* psSerStructure = (const tSerializedStructure9*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0xF1); + ASSERT_EQ(psSerStructure->ui8Value[2] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[3] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0x1F); + ASSERT_EQ(psSerStructure->ui8Value[5] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[6] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[8] , 0xE0); + + // deserialize into oBuffer + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oBuffer, true)); + oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + ui16Value = 0; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value10bits1", &ui16Value)); + ASSERT_EQ(ui16Value , 0x01); + ui32Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value11bits3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25", &ui32Value)); + ASSERT_EQ(ui32Value , 0x01FFFFFF); + ui32Value = 0xFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value45bits32", &ui32Value)); + ASSERT_EQ(ui32Value , 0x0); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value85bits3", &ui8Value)); + ASSERT_EQ(ui8Value , 0x07); +} + +/** +* @detail Media Coder Serialization for bit values without byte gaps in big endian representation and with an Array inside. +* This test serializes bits as described and check the serialized data buffer. +*/ +TEST(cTesterMediaCoder, + TestCoderForEverySerializationPathDifferentPositionTogetherInBigEndianWithArray) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + typedef struct + { + uint8_t ui8Value[18]; + } tSerializedStructure18; + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oBuffer(oFactory.getStaticBufferSize()); + Codec oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + uint16_t ui16Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value10bits1", &ui16Value)); + uint32_t ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value11bits3", &ui32Value)); + ui32Value = 0x01FFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25_0", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25_1", &ui32Value)); + ui32Value = 0x01FFFFFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25_2", &ui32Value)); + ui32Value = 0x00; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25_3", &ui32Value)); + ui32Value = 0x01FF0FFF; + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value14bits25_4", &ui32Value)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + const tSerializedStructure18* psSerStructure = (const tSerializedStructure18*)oWriteBuffer.getPtr(); + + ASSERT_EQ(psSerStructure->ui8Value[0] , 0); + ASSERT_EQ(psSerStructure->ui8Value[1] , 0xF1); // arrayelem 0 begins on bit 4 + ASSERT_EQ(psSerStructure->ui8Value[2] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[3] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[4] , 0x1F); // arrayelem 1 begins on bit 5 + ASSERT_EQ(psSerStructure->ui8Value[5] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[6] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[7] , 0xC0); // arrayelem 2 begins on bit 6 + ASSERT_EQ(psSerStructure->ui8Value[8] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[9] , 0xFF); + ASSERT_EQ(psSerStructure->ui8Value[10] , 0x7F); // arrayelem 3 begins on bit 7 + ASSERT_EQ(psSerStructure->ui8Value[11] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[12] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[13] , 0x00); + ASSERT_EQ(psSerStructure->ui8Value[14] , 0xFF); // arrayelem 4 begins on bit 0 + ASSERT_EQ(psSerStructure->ui8Value[15] , 0x1F); + ASSERT_EQ(psSerStructure->ui8Value[16] , 0xFE); + ASSERT_EQ(psSerStructure->ui8Value[17] , 0x01); + + // deserialize into oBuffer + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oBuffer, true)); + oCodec = oFactory.makeCodecFor(oBuffer.getPtr(), oBuffer.getSize()); + + ui16Value = 0; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value10bits1", &ui16Value)); + ASSERT_EQ(ui16Value , 0x01); + ui32Value = 0x01; + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value11bits3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25_0", &ui32Value)); + ASSERT_EQ(ui32Value , 0x01FFFFFF); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25_1", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25_2", &ui32Value)); + ASSERT_EQ(ui32Value , 0x01FFFFFF); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25_3", &ui32Value)); + ASSERT_EQ(ui32Value , 0x00); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value14bits25_4", &ui32Value)); + ASSERT_EQ(ui32Value , 0x01FF0FFF); +} + +/** +* @detail Media Coder Serialization with many random values. +* This test serializes and deserializes the given structure described. +* Passed if: The deserialized data is the same as before. +*/ +TEST(cTesterMediaCoder, + TestCoderForWithSeveralValuesForSerialization) +{ + TEST_REQ("ACORE-1265 ACORE-2641"); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + a_util::memory::MemoryBuffer oData(oFactory.getStaticBufferSize()); + a_util::memory::MemoryBuffer oDataRead(oFactory.getStaticBufferSize()); + a_util::memory::MemoryBuffer oWriteBuffer(oFactory.getStaticBufferSize()); + + for (uint64_t ui64Counter = 40000; + ui64Counter < 40100; + ui64Counter++) + { + uint16_t ui16TestValueWrite = uint16_t(ui64Counter); + uint32_t ui32TestValueWrite = uint32_t(ui64Counter); + uint64_t ui64TestValueWrite = ui64Counter; + double f64TestValueWrite = double(ui64Counter) * 0.1; + uint16_t ui16TestValueRead = 0; + uint32_t ui32TestValueRead = 0; + uint64_t ui64TestValueRead = 0; + double f64TestValueRead = 0.0; + + Codec oCodec = oFactory.makeCodecFor(oData.getPtr(), oData.getSize()); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value1", &ui16TestValueWrite)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value2", &ui32TestValueWrite)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "value3", &ui64TestValueWrite)); + for (int nIdx=0; + nIdx < 5; + nIdx++) + { + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, a_util::strings::format("array1[%d]",nIdx), &ui32TestValueWrite)); + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, a_util::strings::format("array2[%d]",nIdx), &f64TestValueWrite)); + } + + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + Codec oSerCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oSerCodec, oDataRead)); + + oCodec = oFactory.makeCodecFor(oDataRead.getPtr(), oDataRead.getSize()); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value1", &ui16TestValueRead)); + //one bit value only + if (true) + { + ASSERT_EQ(ui16TestValueRead , (ui16TestValueWrite & 0x0001)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value2", &ui32TestValueRead)); + //three bit value only + ASSERT_EQ(ui32TestValueRead , (ui32TestValueWrite & 0x00000007)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value3", &ui64TestValueRead)); + //three bit value only + ASSERT_EQ(ui64TestValueRead , (ui64TestValueWrite & 0x0000000000000007)); + } + else + { + ASSERT_EQ(ui16TestValueRead , (ui16TestValueWrite & 0x0100)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value2", &ui32TestValueRead)); + //three bit value only + ASSERT_EQ(ui32TestValueRead , (ui32TestValueWrite & 0x07000000)); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, "value3", &ui64TestValueRead)); + //three bit value only + ASSERT_EQ(ui64TestValueRead , (ui64TestValueWrite & 0x07000000000000000LL)); + } + for (int nIdx=0; + nIdx < 5; + nIdx++) + { + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, a_util::strings::format("array1[%d]",nIdx), &ui32TestValueRead)); + //twenty five bit value only + if (true) + { + ASSERT_EQ(ui32TestValueRead , (ui32TestValueWrite & 0x01FFFFFF)); + } + else + { + ASSERT_EQ(ui32TestValueRead , (ui32TestValueWrite & 0xFFFFFF01)); + } + ASSERT_EQ(a_util::result::SUCCESS, access_element::get_value(oCodec, a_util::strings::format("array2[%d]",nIdx), &f64TestValueRead)); + //all 64 Bit + ASSERT_EQ(f64TestValueRead , f64TestValueWrite); + } + } +} + +#pragma pack ( push, 1 ) +typedef struct +{ + int16_t i16Number; + int16_t i16DxV; + int16_t i16DyV; + int16_t i16VxV; + int16_t i16Width; + int8_t ui8Spare[6]; //padding +} tscHCAObjectData; + +typedef struct +{ + int32_t i32DistanceY; + int32_t i32YawAngleDiff; + int32_t i32HorizCurve; + int32_t i32HorizCurveChange; + int32_t i32Foresight; + int32_t i32Quality; + int32_t i32TrackID; + uint8_t ui8Spare[4]; //padding +} tscHCATrackData; + +typedef struct +{ + double f64TorqueFactor; + double f64KBIShownVelo; + double f64ESPVelo; + bool bBHIndicatorLeft; + bool bBHIndicatorRight; + bool bABBeltWarnVF; + uint8_t ui8MMIHCAIntrPoT; + bool bMMIHCAVibrActive; + bool bLDWActive; + uint8_t ui8Spare[2]; + double f64MUSteerWhAngle; + double f64ESPBrakePress; + double f64FDSteerWhTorque; + double f64SARAOmegaZb; + double f64SARAAccelYb; + double f64ESPVSignal; + tscHCAObjectData asObject[10]; + tscHCATrackData asTrack[8]; + int32_t i32LaneId; + int32_t i32LaneCount; +} tscHCAData; +#pragma pack ( pop ) + +#pragma pack ( push, 8 ) +typedef struct +{ + tscHCAData sElementOfCoder; +} tscHCADataAlignedSize; +#pragma pack ( pop ) + +/** +* @detail Test Media Coder Serialized Size and Deserialized Size. +* This test makes sure the coder follows the alignment and +* byteposition to evaluate sizes for serialized and deserialized data. +* Passed if: The expected sizes are equal to the evaluated sizes. +*/ +TEST(cTesterMediaCoder, + TestCheckRightSizeEvaluation) +{ + TEST_REQ("ACORE-5158"); + + std::string strDDL; + ASSERT_EQ(a_util::filesystem::readTextFile("files/hca.description", strDDL) , a_util::filesystem::OK); + CodecFactory oFactory("scHCAData", strDDL.c_str()); + + size_t nSerSize = oFactory.getStaticBufferSize(serialized); + size_t nDeSerSize = oFactory.getStaticBufferSize(deserialized); + size_t nDeserSizeFromStruct = sizeof(tscHCADataAlignedSize); + ASSERT_EQ(nDeserSizeFromStruct , 504); + ASSERT_EQ(nSerSize , nDeSerSize); + ASSERT_EQ(nDeSerSize , nDeserSizeFromStruct); +} + +#pragma pack ( push, 1 ) +struct tempStruct +{ + uint16_t value1; + uint8_t arraySize; + uint32_t dynamicArray[10]; + uint32_t value2; +}; + + +struct tempStruct2 +{ + uint16_t value1; + uint8_t arraySize; + tempStruct dynamicArray[2]; + uint32_t value2; +}; +#pragma pack ( pop ) + + +/** +* @detail Media Coder Dynamic Array Test +* Test the media coder and serialization for dynamic arrays. +*/ +TEST(cTesterMediaCoder, + TestCoderWithDynamicArrays) +{ + TEST_REQ(""); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + + std::vector vecCompare; + tempStruct2 temp; + temp.value1 = 996; + vecCompare.push_back(996); + temp.arraySize = 2; + vecCompare.push_back(2); + for (int i = 0; i < 2; ++i) + { + temp.dynamicArray[i].value1 = 997; + vecCompare.push_back(997); + temp.dynamicArray[i].arraySize = 10; + vecCompare.push_back(10); + for (int j = 0; j < 10; ++j) + { + temp.dynamicArray[i].dynamicArray[j] = (i + 1) * j; + vecCompare.push_back((i + 1) * j); + } + temp.dynamicArray[i].value2 = 998; + vecCompare.push_back(998); + } + temp.value2 = 999; + vecCompare.push_back(999); + + Codec oCodec = oFactory.makeCodecFor(&temp, sizeof(tempStruct2)); + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer, true)); + + oCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + a_util::memory::MemoryBuffer oDeserializedBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oDeserializedBuffer, true)); + + oCodec = oFactory.makeCodecFor(oDeserializedBuffer.getPtr(), oDeserializedBuffer.getSize()); + + for (size_t nElement = 0; nElement < oCodec.getElementCount(); ++nElement) + { + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElement(nElement, pElement)); + + switch (pElement->type) + { + case a_util::variant::VT_UInt16: + { + uint16_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + case a_util::variant::VT_UInt8: + { + uint8_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + + default: + { + uint32_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + } + } +} + +#pragma pack ( push, 1 ) +typedef enum +{ + TEN = 10, + FORTYTWO = 42, + FIFTYSIX = 56 +} tEnumTest; +typedef struct +{ + uint32_t enumElement; + uint32_t constantElement; + uint32_t enumElement2; +} tStructWithConstantAndEnum; + +#pragma pack ( pop ) + + +/** +* @detail Media Coder Enum Constant Test +* Tests the media coder and serialization for Enums and Constants. +*/ +TEST(cTesterMediaCoder, + TestCoderWithEnumAndConstant) +{ + TEST_REQ(""); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + + tStructWithConstantAndEnum oStruct; + oStruct.enumElement = FIFTYSIX; + oStruct.enumElement2 = FORTYTWO; + oStruct.constantElement = TEN; // this should be overwritten by the constant definition in the media description + + CodecFactory oFactory("tStructWithConstantAndEnum", strStructure.c_str()); + Codec oCodec = oFactory.makeCodecFor(&oStruct, sizeof(tStructWithConstantAndEnum)); + ASSERT_EQ(a_util::result::SUCCESS, oCodec.setConstants()); + + ASSERT_EQ(access_element::get_value(oCodec, "constantElement").getUInt32() , FORTYTWO); + ASSERT_EQ(access_element::get_value(oCodec, "enumElement").getUInt32() , FIFTYSIX); + ASSERT_EQ(access_element::get_value(oCodec, "enumElement2").getUInt32() , FORTYTWO); + + ASSERT_EQ(a_util::result::SUCCESS, access_element::set_value(oCodec, "enumElement", (uint32_t)TEN)); + + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + + oCodec = oCodec.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + + a_util::memory::MemoryBuffer oReadBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oReadBuffer)); + + oCodec = oCodec.makeCodecFor(oReadBuffer.getPtr(), oReadBuffer.getSize(), deserialized); + + ASSERT_EQ(access_element::get_value(oCodec, "constantElement").getUInt32() , FORTYTWO); + ASSERT_EQ(access_element::get_value(oCodec, "enumElement").getUInt32() , TEN); + ASSERT_EQ(access_element::get_value(oCodec, "enumElement2").getUInt32() , FORTYTWO); +} + +#pragma pack ( push, 1 ) +typedef struct +{ + uint16_t innerValue1; + uint8_t innerPadding1[6]; + uint8_t innerArraySize; + uint8_t innerPadding2[7]; + uint32_t innerDynamicArray[4]; + uint32_t innerValue2; +} tInnerStruct_v20; + +typedef struct +{ + uint16_t value1; + uint8_t padding1[14]; + uint8_t arraySize; + uint8_t padding2[15]; + // Begin unrolled array + tInnerStruct_v20 dynamicArray_0; + uint8_t innerpadding3_1[4]; + tInnerStruct_v20 dynamicArray_1; + uint8_t innerpadding3_2[4]; + tInnerStruct_v20 dynamicArray_2; + uint8_t innerpadding3_3[4]; + tInnerStruct_v20 dynamicArray_3; + // End unrolled array + uint8_t innerpadding3_4[4]; + uint32_t value2; +} tOuterStruct_v20; + +typedef struct +{ + uint16_t innerValue1; + uint8_t innerPadding1[6]; + uint8_t innerArraySize; + uint8_t innerPadding2[7]; + uint32_t innerDynamicArray[4]; + uint32_t innerValue2; + uint8_t innerPadding3[4]; +} tInnerStruct_v30; + +typedef struct +{ + uint16_t value1; + uint8_t padding1[14]; + uint8_t arraySize; + uint8_t padding2[15]; + tInnerStruct_v30 dynamicArray[4]; + uint32_t value2; + uint8_t padding3[12]; +} tOuterStruct_v30; + +#pragma pack ( pop ) + +/** +* Temnplate function for filling the inner structure. +* Use with tInnerStruct_v20, tInnerStruct_v30 and so on. +* @param [inout] pvecCompare An initialized vector. This vector will be filled with reference values. +* @param [inout] offset The number to start with filling the struct. Will be updated during filling. +* @return The initialized struct. +*/ +template +I FillInnerStruct(std::vector* pvecCompare, uint32_t* pui32Offset) +{ + I sInner; + a_util::memory::set(&sInner, sizeof(I), 0, sizeof(I)); + sInner.innerValue1 = static_cast(*pui32Offset); + pvecCompare->push_back(sInner.innerValue1); + (*pui32Offset)++; + sInner.innerArraySize = 4; + pvecCompare->push_back(sInner.innerArraySize); + for (unsigned int i = 0; i < sInner.innerArraySize; i++) + { + sInner.innerDynamicArray[i] = *pui32Offset; + pvecCompare->push_back(sInner.innerDynamicArray[i]); + (*pui32Offset)++; + } + sInner.innerValue2 = *pui32Offset; + pvecCompare->push_back(sInner.innerValue2); + (*pui32Offset)++; + return sInner; +} + +template +void ExecuteTest(S sReference, const std::vector &vecReference, ddl::DDLVersion eVersion); + +/** +* @detail Media Coder Dynamic Array Alignment Test +* Test the media coder and serialization for dynamic arrays with aligment != 1 +*/ +TEST(cTesterMediaCoder, + TestCoderWithDynamicArraysAlignmentNotOne) +{ + TEST_REQ("ACORE-6148"); + + // Build up the test data + std::vector vecCompare_v20; + std::vector vecCompare_v30; + tOuterStruct_v20 sReference_v20; + tOuterStruct_v30 sReference_v30; + a_util::memory::set(&sReference_v20, sizeof(sReference_v20), 0, sizeof(sReference_v20)); + a_util::memory::set(&sReference_v30, sizeof(sReference_v30), 0, sizeof(sReference_v30)); + uint32_t ui32Offset_v20 = 1; + uint32_t ui32Offset_v30 = 1; + sReference_v20.value1 = static_cast(ui32Offset_v20); + sReference_v30.value1 = static_cast(ui32Offset_v30); + vecCompare_v20.push_back(ui32Offset_v20); + vecCompare_v30.push_back(ui32Offset_v30); + ui32Offset_v20++; + ui32Offset_v30++; + sReference_v20.arraySize = 4; + sReference_v30.arraySize = 4; + vecCompare_v20.push_back(sReference_v20.arraySize); + vecCompare_v30.push_back(sReference_v30.arraySize); + sReference_v20.dynamicArray_0 = FillInnerStruct(&vecCompare_v20, &ui32Offset_v20); + sReference_v20.dynamicArray_1 = FillInnerStruct(&vecCompare_v20, &ui32Offset_v20); + sReference_v20.dynamicArray_2 = FillInnerStruct(&vecCompare_v20, &ui32Offset_v20); + sReference_v20.dynamicArray_3 = FillInnerStruct(&vecCompare_v20, &ui32Offset_v20); + for (size_t nIdx = 0; nIdx < sReference_v30.arraySize; nIdx++) + { + sReference_v30.dynamicArray[nIdx] = FillInnerStruct(&vecCompare_v30, &ui32Offset_v30); + } + sReference_v20.value2 = ui32Offset_v20; + sReference_v30.value2 = ui32Offset_v30; + vecCompare_v20.push_back(ui32Offset_v20); + vecCompare_v30.push_back(ui32Offset_v30); + + ExecuteTest(sReference_v20, vecCompare_v20, ddl::DDLVersion::ddl_version_20); + ExecuteTest(sReference_v30, vecCompare_v30, ddl::DDLVersion::ddl_version_30); + +} + +template +void ExecuteTest(S sReference, const std::vector &vecReference, ddl::DDLVersion eVersion) +{ + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + std::string strDDL; + if (eVersion == ddl::DDLVersion::ddl_version_20) + { + strDDL = strDDLv20Header + strStructure + + ""; + } + else + { + strDDL = strDDLv30Header + strStructure + + ""; + } + + CodecFactory oFactory("tOuterStruct", strStructure.c_str()); + + Decoder oDecoder = oFactory.makeDecoderFor(&sReference, sizeof(sReference)); + a_util::memory::MemoryBuffer oDestBuf; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oDecoder, oDestBuf, true)); + + // create a new coder to test deserialization + oDecoder = oFactory.makeDecoderFor(oDestBuf.getPtr(), oDestBuf.getSize(), serialized); + a_util::memory::MemoryBuffer oNewDestBuf; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oDecoder, oNewDestBuf, true)); + + oDecoder = oFactory.makeDecoderFor(oNewDestBuf.getPtr(), oNewDestBuf.getSize()); + + for (size_t nElement = 0; nElement < oDecoder.getElementCount(); ++nElement) + { + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.getElement(nElement, pElement)); + + switch (pElement->type) + { + case a_util::variant::VT_UInt16: + { + uint16_t value; + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.getElementValue(nElement, &value)); + ASSERT_EQ(vecReference.at(nElement) , value); + break; + } + case a_util::variant::VT_UInt8: + { + uint8_t value; + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.getElementValue(nElement, &value)); + ASSERT_EQ(vecReference.at(nElement) , value); + break; + } + + default: + { + uint32_t value; + ASSERT_EQ(a_util::result::SUCCESS, oDecoder.getElementValue(nElement, &value)); + ASSERT_EQ(vecReference.at(nElement) , value); + break; + } + } + } +} + + + +/** +* @detail Test the Path to an element in a MediaDescription +* Tests if the function getPathForID returns the correct path to an element referenced by its ID in a Media description +* Passed if: The values are set and retrieved correctly +*/ +TEST(cTesterMediaCoder, + TestgetFullPathToAnElement) +{ + TEST_REQ("ACORE-6631"); + + std::string strToParse; + + strToParse = " "; + strToParse.append(""); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(" "); + strToParse.append(""); + + + CodecFactory oFactory("tNestedStruct", strToParse.c_str()); + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oFactory.getStaticElement(0, pElement)); + std::cout << pElement->name.c_str(); + ASSERT_EQ(pElement->name , "sHeaderStruct.ui32HeaderVal"); + +} + +#pragma pack ( push, 1 ) +struct structWithZeroArraySize +{ + uint16_t value1; + uint8_t arraySize; + //uint32_t dynamicArray[0]; + uint32_t value2; +}; + + +struct structWithZeroInner +{ + uint16_t value1; + uint8_t arraySize; + structWithZeroArraySize dynamicArray[2]; + uint32_t value2; +}; +#pragma pack ( pop ) + +/** +* @detail Media Coder Dynamic Array Size Zero Test +* Tests the media coder and serialization for dynamic arrays with an array size of 0 +*/ +TEST(cTesterMediaCoder, + TestCoderWithDynamicArraysSizeZero) +{ + TEST_REQ(""); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + CodecFactory oFactory("tTest", strStructure.c_str()); + + std::vector vecCompare; + structWithZeroInner temp; + temp.value1 = 996; + vecCompare.push_back(996); + temp.arraySize = 2; + vecCompare.push_back(2); + for (int i = 0; i < 2; ++i) + { + temp.dynamicArray[i].value1 = 997; + vecCompare.push_back(997); + temp.dynamicArray[i].arraySize = 0; + vecCompare.push_back(0); + temp.dynamicArray[i].value2 = 998; + vecCompare.push_back(998); + } + temp.value2 = 999; + vecCompare.push_back(999); + + Codec oCodec = oFactory.makeCodecFor(&temp, sizeof(structWithZeroInner)); + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + + + oCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + a_util::memory::MemoryBuffer oReadBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oReadBuffer)); + + oCodec = oCodec.makeCodecFor(oReadBuffer.getPtr(), oReadBuffer.getSize(), deserialized); + + for (size_t nElement = 0; nElement < oCodec.getElementCount(); ++nElement) + { + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElement(nElement, pElement)); + + switch (pElement->type) + { + case a_util::variant::VT_UInt16: + { + uint16_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + case a_util::variant::VT_UInt8: + { + uint8_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + + default: + { + uint32_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + } + } +} + +#pragma pack ( push, 1 ) + + +struct structWithZeroInner2 +{ + uint16_t value1; + uint8_t arraySize; + // structWithZeroArraySize2 dynamicArray[2]; + uint32_t value2; +}; +#pragma pack ( pop ) + +/** +* @detail Media Coder Dynamic Array Size Zero Test 2 +* Tests the media coder and serialization for dynamic arrays with an array size of 0 +*/ +TEST(cTesterMediaCoder, + TestCoderWithDynamicArraysSizeZero2) +{ + TEST_REQ(""); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + std::vector vecCompare; + structWithZeroInner2 temp; + temp.value1 = 996; + vecCompare.push_back(996); + temp.arraySize = 0; + vecCompare.push_back(0); + temp.value2 = 999; + vecCompare.push_back(999); + + CodecFactory oFactory("tTest", strStructure.c_str()); + Codec oCodec = oFactory.makeCodecFor(&temp, sizeof(structWithZeroInner)); + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + + oCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + a_util::memory::MemoryBuffer oReadBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oReadBuffer)); + + oCodec = oCodec.makeCodecFor(oReadBuffer.getPtr(), oReadBuffer.getSize(), deserialized); + + for (size_t nElement = 0; nElement < oCodec.getElementCount(); ++nElement) + { + const StructElement* pElement; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElement(nElement, pElement)); + + switch (pElement->type) + { + case a_util::variant::VT_UInt16: + { + uint16_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + case a_util::variant::VT_UInt8: + { + uint8_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + + default: + { + uint32_t value; + ASSERT_EQ(a_util::result::SUCCESS, oCodec.getElementValue(nElement, &value)); + ASSERT_EQ(vecCompare.at(nElement) , value); + break; + } + } + } +} + +/** +* @detail Media Coder Dynamic Array Size Zero Test 3 +* Tests the media coder and serialization for dynamic arrays with an array size of 0 +*/ +TEST(cTesterMediaCoder, + TestCoderWithDynamicArraysSizeZero3) +{ + TEST_REQ(""); + + std::string strStructure = ""; + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + strStructure.append(""); + + uint8_t ui8ArraySize = 0; + int nRealSize = sizeof(uint8_t); + + CodecFactory oFactory("tTest", strStructure.c_str()); + Codec oCodec = oFactory.makeCodecFor(&ui8ArraySize, sizeof(nRealSize)); + a_util::memory::MemoryBuffer oWriteBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oWriteBuffer)); + + oCodec = oFactory.makeCodecFor(oWriteBuffer.getPtr(), oWriteBuffer.getSize(), serialized); + a_util::memory::MemoryBuffer oReadBuffer; + ASSERT_EQ(a_util::result::SUCCESS, serialization::transform_to_buffer(oCodec, oReadBuffer)); + + oCodec = oCodec.makeCodecFor(oReadBuffer.getPtr(), oReadBuffer.getSize(), deserialized); + + ASSERT_EQ(oReadBuffer.getSize() , 1); + ASSERT_EQ(((uint8_t*)oReadBuffer.getPtr())[0] , 0); +} diff --git a/test/ddlgenerators/files/expected_files/expected_result_datatype.h b/test/ddlgenerators/files/expected_files/expected_result_datatype.h new file mode 100644 index 0000000..c0204e4 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_datatype.h @@ -0,0 +1,27 @@ +/** + * @file + * This is a generated file, changes to it may be overwritten in the future. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +typedef tInt16 tPixelFormat; + +typedef int16_t tInt16; + +// The following type is assumed to be known: +// int16_t + diff --git a/test/ddlgenerators/files/expected_files/expected_result_existing_all.description b/test/ddlgenerators/files/expected_files/expected_result_existing_all.description new file mode 100644 index 0000000..281c7d9 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_existing_all.description @@ -0,0 +1,133 @@ + + +
+ 3.00 + WROTHFL + 09.10.2014 + 11.03.2016 + Generated by ADTF 2.13.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/expected_files/expected_result_existing_all.h b/test/ddlgenerators/files/expected_files/expected_result_existing_all.h new file mode 100644 index 0000000..028d551 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_existing_all.h @@ -0,0 +1,118 @@ +#ifndef RESULT_H +#define RESULT_H + +// This is a generated file, changes to it may be overwritten in the future. + +typedef enum { + PF_UNKNOWN=0, + PF_8BIT=10, + PF_GREYSCALE_8=11, + PF_RGB_8=12, + PF_16BIT=20, + PF_GREYSCALE_10=21, + PF_GREYSCALE_12=22, + PF_GREYSCALE_14=23, + PF_GREYSCALE_16=24, + PF_RGB_444=25, + PF_RGB_555=26, + PF_RGB_565=27, + PF_RGBA_4444=28, + PF_ABGR_4444=29, + PF_RIII_10=30, + PF_RIII_12=31, + PF_RIII_14=32, + PF_RIII_16=33, + PF_BGR_555=34, + PF_BGR_565=35, + PF_24BIT=40, + PF_GREYSCALE_18=41, + PF_GREYSCALE_20=42, + PF_GREYSCALE_22=43, + PF_GREYSCALE_24=44, + PF_RGB_888=45, + PF_BGR_888=46, + PF_32BIT=50, + PF_ARGB_8888=51, + PF_ABGR_8888=52, + PF_RGBA_8888=53, + PF_BGRA_8888=54, + PF_GREYSCALE_32=55, + PF_GREYSCALE_FLOAT32=56, + PF_YUV420P_888=60, + PF_CUSTOM=1000 +} tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tUInt32 ui32MajorType; + tUInt32 ui32SubType; + tUInt32 ui32Flags; +} tMediaTypeInfo; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo mediatype; +} adtf_core_media_type; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tWaveFormat sWaveFormat; +} adtf_type_audio; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nWidth; + tInt32 nHeight; + tInt16 nBitsPerPixel; + tInt16 nPixelFormat; + tInt32 nBytesPerLine; + tInt32 nSize; + tInt32 nPaletteSize; +} tBitmapFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tBitmapFormat sBitmapFormat; +} adtf_type_video; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef int32_t tInt32; + +typedef int16_t tInt16; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// int32_t + +// The following type is assumed to be known: +// int16_t + + +#endif //RESULT_H diff --git a/test/ddlgenerators/files/expected_files/expected_result_existing_struct.description b/test/ddlgenerators/files/expected_files/expected_result_existing_struct.description new file mode 100644 index 0000000..d4ab36b --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_existing_struct.description @@ -0,0 +1,137 @@ + + +
+ 3.00 + A8LD75D + 17.11.2017 + 17.11.2017 + Generated by DDL_Editor +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/expected_files/expected_result_existing_struct.h b/test/ddlgenerators/files/expected_files/expected_result_existing_struct.h new file mode 100644 index 0000000..028d551 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_existing_struct.h @@ -0,0 +1,118 @@ +#ifndef RESULT_H +#define RESULT_H + +// This is a generated file, changes to it may be overwritten in the future. + +typedef enum { + PF_UNKNOWN=0, + PF_8BIT=10, + PF_GREYSCALE_8=11, + PF_RGB_8=12, + PF_16BIT=20, + PF_GREYSCALE_10=21, + PF_GREYSCALE_12=22, + PF_GREYSCALE_14=23, + PF_GREYSCALE_16=24, + PF_RGB_444=25, + PF_RGB_555=26, + PF_RGB_565=27, + PF_RGBA_4444=28, + PF_ABGR_4444=29, + PF_RIII_10=30, + PF_RIII_12=31, + PF_RIII_14=32, + PF_RIII_16=33, + PF_BGR_555=34, + PF_BGR_565=35, + PF_24BIT=40, + PF_GREYSCALE_18=41, + PF_GREYSCALE_20=42, + PF_GREYSCALE_22=43, + PF_GREYSCALE_24=44, + PF_RGB_888=45, + PF_BGR_888=46, + PF_32BIT=50, + PF_ARGB_8888=51, + PF_ABGR_8888=52, + PF_RGBA_8888=53, + PF_BGRA_8888=54, + PF_GREYSCALE_32=55, + PF_GREYSCALE_FLOAT32=56, + PF_YUV420P_888=60, + PF_CUSTOM=1000 +} tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tUInt32 ui32MajorType; + tUInt32 ui32SubType; + tUInt32 ui32Flags; +} tMediaTypeInfo; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo mediatype; +} adtf_core_media_type; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tWaveFormat sWaveFormat; +} adtf_type_audio; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nWidth; + tInt32 nHeight; + tInt16 nBitsPerPixel; + tInt16 nPixelFormat; + tInt32 nBytesPerLine; + tInt32 nSize; + tInt32 nPaletteSize; +} tBitmapFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tBitmapFormat sBitmapFormat; +} adtf_type_video; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef int32_t tInt32; + +typedef int16_t tInt16; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// int32_t + +// The following type is assumed to be known: +// int16_t + + +#endif //RESULT_H diff --git a/test/ddlgenerators/files/expected_files/expected_result_newfile_all.description b/test/ddlgenerators/files/expected_files/expected_result_newfile_all.description new file mode 100644 index 0000000..6966ffa --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_newfile_all.description @@ -0,0 +1,133 @@ + + +
+ 3.00 + ANOAFR4 + 11.03.2016 + 11.03.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/expected_files/expected_result_newfile_all.h b/test/ddlgenerators/files/expected_files/expected_result_newfile_all.h new file mode 100644 index 0000000..adf012c --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_newfile_all.h @@ -0,0 +1,66 @@ +// This is a generated file, changes to it may be overwritten in the future. + +typedef tInt16 tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tUInt32 ui32MajorType; + tUInt32 ui32SubType; + tUInt32 ui32Flags; +} tMediaTypeInfo; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo mediatype; +} adtf_core_media_type; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tWaveFormat sWaveFormat; +} adtf_type_audio; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nWidth; + tInt32 nHeight; + tInt16 nBitsPerPixel; + tInt16 nPixelFormat; + tInt32 nBytesPerLine; + tInt32 nSize; + tInt32 nPaletteSize; +} tBitmapFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tBitmapFormat sBitmapFormat; +} adtf_type_video; +#pragma pack(pop) + +// The following types are assumed to be known: +// tInt16 +// tUInt32 +// tInt32 + diff --git a/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.description b/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.description new file mode 100644 index 0000000..5ad3dc0 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.description @@ -0,0 +1,110 @@ + + +
+ 3.00 + A8LD75D + 17.11.2017 + 17.11.2017 + Generated by DDL_Editor +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.h b/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.h new file mode 100644 index 0000000..60f9454 --- /dev/null +++ b/test/ddlgenerators/files/expected_files/expected_result_newfile_struct.h @@ -0,0 +1,63 @@ +#ifndef RESULT_H +#define RESULT_H + +// This is a generated file, changes to it may be overwritten in the future. + +typedef enum { + PF_UNKNOWN=0, + PF_8BIT=10, + PF_GREYSCALE_8=11, + PF_RGB_8=12, + PF_16BIT=20, + PF_GREYSCALE_10=21, + PF_GREYSCALE_12=22, + PF_GREYSCALE_14=23, + PF_GREYSCALE_16=24, + PF_RGB_444=25, + PF_RGB_555=26, + PF_RGB_565=27, + PF_RGBA_4444=28, + PF_ABGR_4444=29, + PF_RIII_10=30, + PF_RIII_12=31, + PF_RIII_14=32, + PF_RIII_16=33, + PF_BGR_555=34, + PF_BGR_565=35, + PF_24BIT=40, + PF_GREYSCALE_18=41, + PF_GREYSCALE_20=42, + PF_GREYSCALE_22=43, + PF_GREYSCALE_24=44, + PF_RGB_888=45, + PF_BGR_888=46, + PF_32BIT=50, + PF_ARGB_8888=51, + PF_ABGR_8888=52, + PF_RGBA_8888=53, + PF_BGRA_8888=54, + PF_GREYSCALE_32=55, + PF_GREYSCALE_FLOAT32=56, + PF_YUV420P_888=60, + PF_CUSTOM=1000 +} tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +typedef int32_t tInt32; + +// The following type is assumed to be known: +// int32_t + + +#endif //RESULT_H diff --git a/test/ddlgenerators/files/original_files/base_all.description b/test/ddlgenerators/files/original_files/base_all.description new file mode 100644 index 0000000..390bf85 --- /dev/null +++ b/test/ddlgenerators/files/original_files/base_all.description @@ -0,0 +1,133 @@ + + +
+ 3.00 + WROTHFL + 09.10.2014 + 09.10.2014 + Generated by ADTF 2.13.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/original_files/base_all.h b/test/ddlgenerators/files/original_files/base_all.h new file mode 100644 index 0000000..7b95664 --- /dev/null +++ b/test/ddlgenerators/files/original_files/base_all.h @@ -0,0 +1,84 @@ +/** + * @file + * This is a generated file, changes to it may be overwritten in the future. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +typedef tInt16 tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tUInt32 ui32MajorType; + tUInt32 ui32SubType; + tUInt32 ui32Flags; +} tMediaTypeInfo; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo mediatype; +} adtf_core_media_type; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tWaveFormat sWaveFormat; +} adtf_type_audio; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nWidth; + tInt32 nHeight; + tInt16 nBitsPerPixel; + tInt16 nPixelFormat; + tInt32 nBytesPerLine; + tInt32 nSize; + tInt32 nPaletteSize; +} tBitmapFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tBitmapFormat sBitmapFormat; +} adtf_type_video; +#pragma pack(pop) + +// The following types are assumed to be known: +// tInt16 +// tUInt32 +// tInt32 + diff --git a/test/ddlgenerators/files/original_files/enums.description b/test/ddlgenerators/files/original_files/enums.description new file mode 100644 index 0000000..c91a9f1 --- /dev/null +++ b/test/ddlgenerators/files/original_files/enums.description @@ -0,0 +1,56 @@ + + +
+ 4.00 + SVP5W4W + 08.02.2018 + 08.02.2018 + Generated by DDL_Editor +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlgenerators/files/original_files/enums.h b/test/ddlgenerators/files/original_files/enums.h new file mode 100644 index 0000000..3c9f204 --- /dev/null +++ b/test/ddlgenerators/files/original_files/enums.h @@ -0,0 +1,37 @@ +typedef enum { + C_UNKNOWN=0, + C_RED=1, + C_GREEN=2, + C_BLUE=50, + C_CYAN=2000 +} tColor; + + +typedef enum tTimber { + W_FIR=5, + W_PINE=1630, + W_OAK, + W_SPRUCE +} tWood; + +enum tAlphabet { +ABC, DEF, GHI}; + +typedef struct +{ + tColor col; + tTimber tim; + tWood wood; + tAlphabet alpha; +} tEnums; + +typedef bla blubb; + +typedef struct +{ + tBla bla; + tBlubb blubb; + kaka kaka; +} + + diff --git a/test/ddlgenerators/src/CMakeLists.txt b/test/ddlgenerators/src/CMakeLists.txt new file mode 100644 index 0000000..43fe256 --- /dev/null +++ b/test/ddlgenerators/src/CMakeLists.txt @@ -0,0 +1,23 @@ +set(TEST_NAME ddl_generators) + +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp) +if (NOT ddl_cmake_integrated_tests) + target_compile_definitions(tester_${TEST_NAME} PRIVATE TEST_INSTALL_DIR="${ddl_DIR}/..") +else() + target_compile_definitions(tester_${TEST_NAME} + PRIVATE TEST_INSTALL_DIR="${CMAKE_INSTALL_PREFIX}") +endif() + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/utils) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 120) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl_test_compat + ddl + a_util + GTest::Main + $<$:Threads::Threads> +) +add_test(NAME tester_${TEST_NAME} + COMMAND tester_${TEST_NAME} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../") diff --git a/test/ddlgenerators/src/tester_ddl_generators.cpp b/test/ddlgenerators/src/tester_ddl_generators.cpp new file mode 100644 index 0000000..5090ee4 --- /dev/null +++ b/test/ddlgenerators/src/tester_ddl_generators.cpp @@ -0,0 +1,419 @@ +/** + * @file + * Tester init. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + + +#include +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" + +class cCompareFile +{ +private: + std::vector _lines; + std::vector::iterator _pos; +public: + void Open(const std::string& filepath) + { + if (a_util::filesystem::OK == a_util::filesystem::readTextLines(filepath, _lines)) + { + _pos = _lines.begin(); + } + else + { + _lines.clear(); + _pos = _lines.end(); + } + } + bool isValid() const + { + return _pos != _lines.end(); + } + void ReadLine(std::string& line) + { + if (isValid()) + { + line = *_pos; + a_util::strings::replace(line, "\r", ""); + _pos++; + } + } +}; + +namespace ddl_generator +{ + namespace oo + { + //define all needed error types and values locally + _MAKE_RESULT(0, ERR_NOERROR) + _MAKE_RESULT(-11, ERR_INVALID_FILE) + _MAKE_RESULT(-20, ERR_NOT_FOUND) + _MAKE_RESULT(-24, ERR_PATH_NOT_FOUND) + _MAKE_RESULT(-38, ERR_FAILED) + } +} +using namespace ddl_generator::oo; + +#define __adtf_test_result(expr) ASSERT_TRUE(fep::isOk(expr)) + +#ifdef WIN32 +#pragma warning(disable : 4355) // 'this' used in initializer list +#endif + +#define LOG_POS LOG_INFO(a_util::strings::format("Starting Test '%s' (Line %d)", __FUNCTION__, __LINE__).c_str()); + //fprintf(stdout, "Starting Test '%s' (Line %d)\n", __FUNCTION__, __LINE__); + +static const std::string OPTION_HELP = " --help "; + +static const std::string PROPERTY_DESCRIPTIONFILE = " --descriptionfile="; +static const std::string PROPERTY_HEADERFILE = " --headerfile="; +static const std::string PROPERTY_STRUCT = " --struct="; + +static const std::string DIR_FILES = "./files/"; +static const std::string DIR_EXPECTED = DIR_FILES + "expected_files/"; +static const std::string DIR_ORIGINAL = DIR_FILES + "original_files/"; + +static const std::string PATH_RESULT_DESC = DIR_FILES + "result.description"; +static const std::string PATH_RESULT_HEADER = DIR_FILES + "result.h"; + +static const std::string PATH_DESC_BASE_ALL = DIR_ORIGINAL + "base_all.description"; +static const std::string PATH_HEADER_BASE_ALL = DIR_ORIGINAL + "base_all.h"; + +static const std::string PATH_DESC_ENUMS = DIR_ORIGINAL + "enums.description"; +static const std::string PATH_HEADER_ENUMS = DIR_ORIGINAL + "enums.h"; + + static const std::string PATH_EXPECTED_RES_DESC_EXIST_STRUCT = DIR_EXPECTED + "expected_result_existing_struct.description"; +static const std::string PATH_EXPECTED_RES_DESC_NEWFILE_ALL = DIR_EXPECTED + "expected_result_newfile_all.description"; + static const std::string PATH_EXPECTED_RES_DESC_NEWFILE_STRUCT = DIR_EXPECTED + "expected_result_newfile_struct.description"; +static const std::string PATH_EXPECTED_RES_HEADER_EXIST_ALL = DIR_EXPECTED + "expected_result_existing_all.h"; + static const std::string PATH_EXPECTED_RES_HEADER_EXIST_STRUCT = DIR_EXPECTED + "expected_result_existing_struct.h"; + static const std::string PATH_EXPECTED_RES_HEADER_NEWFILE_STRUCT = DIR_EXPECTED + "expected_result_newfile_struct.h"; + +a_util::filesystem::Path m_strDDL2HeaderExe; +a_util::filesystem::Path m_strHeader2DDLExe; + +static bool isSkippable(std::string strLine) +{ + return strLine.empty() || + strLine.find("): dump") != std::string::npos || + strLine.find("): info") != std::string::npos || + strLine.find("): warning") != std::string::npos || + strLine.find("): error") != std::string::npos || + strLine.find("leaving thread loop") != std::string::npos; +} + +static a_util::result::Result CompDDL(const ddl::DDLDescription* pddl1, const ddl::DDLDescription* pddl2) +{ + int flags = ddl::DDLCompare::dcf_data_types + ddl::DDLCompare::dcf_structs; + return ddl::DDLCompare::isEqual(pddl1, pddl2, flags); +} + +static a_util::result::Result CompOutput(const std::string& strFile1, const std::string& strFile2, int64_t nSkipLines = 0) +{ + cCompareFile oFile1; + cCompareFile oFile2; + oFile1.Open(strFile1); + oFile2.Open(strFile2); + + if (!oFile1.isValid() || !oFile2.isValid()) + { + return (ERR_FAILED); + } + + std::string strLine1; + std::string strLine2; + while (oFile1.isValid() && oFile2.isValid()) + { + oFile1.ReadLine(strLine1); + oFile2.ReadLine(strLine2); + if (strLine1 != strLine2) + { + printf("lines don't match:\n%s\n%s\n", strLine1.c_str(), strLine2.c_str()); + return (ERR_FAILED); + } + } + + if (oFile1.isValid() || oFile2.isValid()) + { + return (ERR_FAILED); + } + + return ERR_NOERROR; +} + +a_util::result::Result CompareDDLFiles(std::string strFile1, std::string strFile2) +{ + ddl::DDLImporter oImporter1; + oImporter1.setFile(strFile1); + oImporter1.createNew(); + + ddl::DDLImporter oImporter2; + oImporter2.setFile(strFile2); + oImporter2.createNew(); + + ddl::DDLDescription* pDesc1 = oImporter1.getDDL(); + + ddl::DDLDescription* pDesc2 = oImporter2.getDDL(); + + if(pDesc1->getStructs().size() == pDesc2->getStructs().size()) + { + return ERR_NOERROR; + } + else + { + return (ERR_FAILED); + } +} + +class cTesterddlgeneratorCmdLine : public ::testing::Test +{ +protected: + void SetUp() + { + if (m_strDDL2HeaderExe.isEmpty()) + { +#ifndef __QNX__ + m_strDDL2HeaderExe = TEST_INSTALL_DIR; +#else + // For QNX we have to cross compile and install tester_ddl_* manually by FTP in a test dir ".", then + // adding the binaries (ddl2header, header2ddl) in ./bin and the .description/.h files in ./files/... + m_strDDL2HeaderExe = "."; +#endif + /* Detect platform and switch to correct dummy application */ + m_strDDL2HeaderExe.append("bin"); + + +#if _DEBUG + m_strDDL2HeaderExe.append("debug"); +#endif +#if (defined(_MSC_VER)) + // WIN x86 vc90 || WIN x64 vc100 + m_strHeader2DDLExe = m_strDDL2HeaderExe; + m_strDDL2HeaderExe.append("ddl2header.exe"); + m_strHeader2DDLExe.append("header2ddl.exe"); + +#elif (defined(__linux) || defined(__QNX__)) + // LINUX x64 gcc46 + m_strHeader2DDLExe = m_strDDL2HeaderExe; + m_strDDL2HeaderExe.append("ddl2header"); + m_strHeader2DDLExe.append("header2ddl"); +#else + // this goes for vc120 or apple or arm or whatever. + assert("Platform currently not supported"); +#endif // Version check + m_strDDL2HeaderExe.makeCanonical(); + m_strHeader2DDLExe.makeCanonical(); + } + } + + void TearDown() + { + // nothing to do yet + } +}; + +/** +* @detail Test for using the FEP ddlgenerator core to import a structure from ddl to header. +*/ +TEST_F(cTesterddlgeneratorCmdLine, + TestImportStructInHeader) +{ + TEST_REQ(""); + + // basic generation + std::string strArgs; + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompOutput(PATH_RESULT_HEADER, PATH_EXPECTED_RES_HEADER_EXIST_ALL) == 0); + + + // with input struct + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER + PROPERTY_STRUCT + + "tWaveFormat"; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompOutput(PATH_RESULT_HEADER, PATH_EXPECTED_RES_HEADER_NEWFILE_STRUCT) == 0); + + // merge with existing file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompOutput(PATH_RESULT_HEADER, PATH_EXPECTED_RES_HEADER_EXIST_STRUCT) == 0); + + std::remove(PATH_RESULT_HEADER.c_str()); +} + +/** +* @detail Test for using the FEP ddlgenerator core to import a structure from header to ddl +*/ +TEST_F(cTesterddlgeneratorCmdLine, + TestImportStructInDdl) +{ + TEST_REQ(""); + + std::string strArgs; + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_RESULT_DESC + + PROPERTY_HEADERFILE + PATH_HEADER_BASE_ALL; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompareDDLFiles(PATH_EXPECTED_RES_DESC_NEWFILE_ALL, PATH_RESULT_DESC) == 0); + + // with input struct + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_RESULT_DESC + + PROPERTY_HEADERFILE + PATH_HEADER_BASE_ALL + PROPERTY_STRUCT + + "tWaveFormat"; + + std::remove(PATH_RESULT_DESC.c_str()); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompareDDLFiles(PATH_RESULT_DESC, PATH_EXPECTED_RES_DESC_NEWFILE_STRUCT) == 0); + + // merge with existing file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_RESULT_DESC + + PROPERTY_HEADERFILE + PATH_HEADER_BASE_ALL; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(CompareDDLFiles(PATH_RESULT_DESC, PATH_EXPECTED_RES_DESC_EXIST_STRUCT) == 0); + + std::remove(PATH_RESULT_DESC.c_str()); +} + +/** +* @detail Tests ddl generator with invalid options, properties and combinations. +*/ +TEST_F(cTesterddlgeneratorCmdLine, + TestUseConsole) +{ + TEST_REQ(""); + + std::string strArgs; + + // show help + strArgs = OPTION_HELP; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) == 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) == 0); + + // without option + strArgs = ""; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with undefined option + strArgs = "-wrongOption"; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with unknown options + strArgs = "-no_option"; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // without header file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with struct and without header file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL + + PROPERTY_STRUCT + "tMyStruct"; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with struct and without description file + strArgs = PROPERTY_HEADERFILE + + PATH_HEADER_BASE_ALL + PROPERTY_STRUCT + + PROPERTY_STRUCT + "tMyStruct"; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with header file as description file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_HEADER_BASE_ALL + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with non existing description file and header file + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_RESULT_DESC + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); + + // with unknown struct + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_BASE_ALL + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER + + PROPERTY_STRUCT + "tUnknownStruct"; + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) != 0); + ASSERT_TRUE(std::system((m_strHeader2DDLExe.toString() + " " + strArgs).c_str()) != 0); +} + +/** +* @detail Tests if enumerations are written correctly to header +*/ +TEST_F(cTesterddlgeneratorCmdLine, + TestEnumsDDL2Header) +{ + TEST_REQ(""); + + std::string strArgs; + strArgs = PROPERTY_DESCRIPTIONFILE + PATH_DESC_ENUMS + + PROPERTY_HEADERFILE + PATH_RESULT_HEADER; + + std::remove(PATH_RESULT_HEADER.c_str()); + ASSERT_TRUE(std::system((m_strDDL2HeaderExe.toString() + " " + strArgs).c_str()) == 0); + + std::string headerContent; + a_util::filesystem::readTextFile(PATH_RESULT_HEADER, headerContent); + + // check if types are present in header + ASSERT_TRUE(headerContent.find("tAlphabet") != std::string::npos); + ASSERT_TRUE(headerContent.find("tTimber") != std::string::npos); + ASSERT_TRUE(headerContent.find("tColor") != std::string::npos); + ASSERT_TRUE(headerContent.find("tEnums") != std::string::npos); + + // check if enum values are present in header + ASSERT_TRUE(headerContent.find("ABC") != std::string::npos); + ASSERT_TRUE(headerContent.find("DEF") != std::string::npos); + ASSERT_TRUE(headerContent.find("GHI") != std::string::npos); + ASSERT_TRUE(headerContent.find("W_FIR") != std::string::npos); + ASSERT_TRUE(headerContent.find("W_PINE") != std::string::npos); + ASSERT_TRUE(headerContent.find("W_OAK") != std::string::npos); + ASSERT_TRUE(headerContent.find("W_SPRUCE") != std::string::npos); + ASSERT_TRUE(headerContent.find("C_UNKNOWN") != std::string::npos); + ASSERT_TRUE(headerContent.find("C_RED") != std::string::npos); + ASSERT_TRUE(headerContent.find("C_CYAN") != std::string::npos); + + // check if comments are present in header + ASSERT_TRUE(headerContent.find("tEnumCommentary") != std::string::npos); + ASSERT_TRUE(headerContent.find("alpha-element-description") != std::string::npos); + ASSERT_TRUE(headerContent.find("alpha-element-comment") != std::string::npos); + + std::remove(PATH_RESULT_HEADER.c_str()); + +} diff --git a/test/ddlinspector/files/ArrayZero.description b/test/ddlinspector/files/ArrayZero.description new file mode 100644 index 0000000..e4805c6 --- /dev/null +++ b/test/ddlinspector/files/ArrayZero.description @@ -0,0 +1,116 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/DynArraySize.description b/test/ddlinspector/files/DynArraySize.description new file mode 100644 index 0000000..7d40e00 --- /dev/null +++ b/test/ddlinspector/files/DynArraySize.description @@ -0,0 +1,123 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/NestedCaps.description b/test/ddlinspector/files/NestedCaps.description new file mode 100644 index 0000000..c312f2d --- /dev/null +++ b/test/ddlinspector/files/NestedCaps.description @@ -0,0 +1,152 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/NestedNaming.description b/test/ddlinspector/files/NestedNaming.description new file mode 100644 index 0000000..78967e8 --- /dev/null +++ b/test/ddlinspector/files/NestedNaming.description @@ -0,0 +1,126 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/StructElementNaming.description b/test/ddlinspector/files/StructElementNaming.description new file mode 100644 index 0000000..7627142 --- /dev/null +++ b/test/ddlinspector/files/StructElementNaming.description @@ -0,0 +1,118 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/StructNaming.description b/test/ddlinspector/files/StructNaming.description new file mode 100644 index 0000000..78967e8 --- /dev/null +++ b/test/ddlinspector/files/StructNaming.description @@ -0,0 +1,126 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/UnitNaming.description b/test/ddlinspector/files/UnitNaming.description new file mode 100644 index 0000000..fbc1a46 --- /dev/null +++ b/test/ddlinspector/files/UnitNaming.description @@ -0,0 +1,120 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 24.04.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/base_all2.description b/test/ddlinspector/files/base_all2.description new file mode 100644 index 0000000..390bf85 --- /dev/null +++ b/test/ddlinspector/files/base_all2.description @@ -0,0 +1,133 @@ + + +
+ 3.00 + WROTHFL + 09.10.2014 + 09.10.2014 + Generated by ADTF 2.13.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/base_all_duplicates.description b/test/ddlinspector/files/base_all_duplicates.description new file mode 100644 index 0000000..cff2657 --- /dev/null +++ b/test/ddlinspector/files/base_all_duplicates.description @@ -0,0 +1,136 @@ + + +
+ 3.00 + WROTHFL + 09.10.2014 + 09.10.2014 + Generated by ADTF 2.13.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlinspector/files/invalid_duplicate.description b/test/ddlinspector/files/invalid_duplicate.description new file mode 100644 index 0000000..8d3f1d1 --- /dev/null +++ b/test/ddlinspector/files/invalid_duplicate.description @@ -0,0 +1,30 @@ + + +
+ 2.0 + TTTech TTX-Mwcodegenerator (Version 0.7.28, 02-Oct-2013) + 02-10-2013 + + All zFAS types used by any of the SW-Cs +
+ + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/test/ddlinspector/src/CMakeLists.txt b/test/ddlinspector/src/CMakeLists.txt new file mode 100644 index 0000000..7c641c8 --- /dev/null +++ b/test/ddlinspector/src/CMakeLists.txt @@ -0,0 +1,17 @@ +set(TEST_NAME ddlinspector) + +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp) + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/ddl) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 120) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl_test_compat + ddl + a_util + GTest::Main + $<$:Threads::Threads> +) +add_test(NAME tester_${TEST_NAME} + COMMAND tester_${TEST_NAME} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../") diff --git a/test/ddlinspector/src/tester_ddlinspector.cpp b/test/ddlinspector/src/tester_ddlinspector.cpp new file mode 100644 index 0000000..05b8034 --- /dev/null +++ b/test/ddlinspector/src/tester_ddlinspector.cpp @@ -0,0 +1,347 @@ +/** + * @file + * Implementation of the tester for the DDL inspector. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#include +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" + +using namespace ddl; + +#define DDL_TEST_STRING \ + "\n \ +\n \ +
\n \ +1.0+\n \ +AUDI Electronics Venture GmbH\n \ +20100407\n \ +\n \ +ADTF Common Description File\n \ +
\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +\n \ +
" + + +/** +* @detail Test for auto bytepos correction in nested structs by inspecting +* an ADTF description file for gaps/overlaps between elements +*/ +TEST(cTesterDDLInspector, + TestGapsAndPadding) +{ + TEST_REQ("ACORE-4637"); + + a_util::filesystem::Path strDescriptionFileName = "files/NestedCaps.description"; + + DDLImporter oImporter(strDescriptionFileName); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + + DDLInspector oInspector(true); + ASSERT_EQ(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); + + ASSERT_FALSE(oInspector.foundDynamicArrays()); + + ImporterMsgList lstMsgs = oInspector.getSuggestions(); + + DDLComplex *poComplex = poDDL->getStructByName("tBitmapFormat"); + DDLElementVec vecElement = poComplex->getElements(); + + ASSERT_TRUE((0 == vecElement[0]->getBytepos())) << "Excpected Bytepos == 0"; + ASSERT_TRUE((8 == vecElement[1]->getBytepos())) << "Excpected Bytepos == 8"; + ASSERT_TRUE((60 == vecElement[2]->getBytepos())) << "Excpected Bytepos == 92"; + + poComplex = poDDL->getStructByName("tNest1"); + vecElement = poComplex->getElements(); + ASSERT_TRUE((0 == vecElement[0]->getBytepos())) << "Excpected Bytepos == 0"; + ASSERT_TRUE((8 == vecElement[1]->getBytepos())) << "Excpected Bytepos == 8"; + ASSERT_TRUE((48 == vecElement[2]->getBytepos())) << "Excpected Bytepos == 80"; + + poComplex = poDDL->getStructByName("tNest2"); + vecElement = poComplex->getElements(); + ASSERT_TRUE((0 == vecElement[0]->getBytepos())) << "Excpected Bytepos == 0"; + ASSERT_TRUE((8 == vecElement[1]->getBytepos())) << "Excpected Bytepos == 8"; + ASSERT_TRUE((36 == vecElement[2]->getBytepos())) << "Excpected Bytepos == 68"; + + poComplex = poDDL->getStructByName("tNest3"); + vecElement = poComplex->getElements(); + ASSERT_TRUE((0 == vecElement[0]->getBytepos())) << "Excpected Bytepos == 0"; + ASSERT_TRUE((8 == vecElement[1]->getBytepos())) << "Excpected Bytepos == 8"; + ASSERT_TRUE((12 == vecElement[2]->getBytepos())) << "Excpected Bytepos == 56"; + + poComplex = poDDL->getStructByName("tNestTest"); + vecElement = poComplex->getElements(); + ASSERT_TRUE((0 == vecElement[0]->getBytepos())) << "Excpected Bytepos == 0"; + ASSERT_TRUE((8 == vecElement[1]->getBytepos())) << "Excpected Bytepos == 8"; +} + +/** +* @detail Test, that no Node name is duplicated by inspecting +* an ADTF description file for correct names +*/ +TEST(cTesterDDLInspector, + TestNaming) +{ + TEST_REQ("ACORE-4637"); + + a_util::filesystem::Path strDescriptionFileName = "files/StructNaming.description"; + + // Check in Duplicate Names - StructNaming + DDLImporter oImporter(strDescriptionFileName, false); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + + DDLInspector oInspector; + oInspector.visitDDL(poDDL); + ImporterMsgList lstMsgs = oInspector.getSuggestions(); + + ASSERT_TRUE(lstMsgs.size() == 1) << "One Error Expected"; + + for (ImporterMsgList::iterator itMsg = lstMsgs.begin(); itMsg != lstMsgs.end(); ++itMsg) + { + ASSERT_TRUE(((*itMsg).severity == importer_error)) << "An Error Expected"; + } + + // Check in Duplicate Names - StructElementNaming + strDescriptionFileName = "files/StructElementNaming.description"; + DDLImporter oImporterElementNaming(strDescriptionFileName, false); + ASSERT_EQ(a_util::result::SUCCESS, oImporterElementNaming.createNew()); + poDDL = oImporterElementNaming.getDDL(); + + DDLInspector oInspectorElementNaming(false); + oInspectorElementNaming.visitDDL(poDDL); + lstMsgs = oInspectorElementNaming.getSuggestions(); + + ASSERT_TRUE(lstMsgs.size() == 1) << "One Error Expected"; + + for (ImporterMsgList::iterator itMsg = lstMsgs.begin(); itMsg != lstMsgs.end(); ++itMsg) + { + ASSERT_TRUE(((*itMsg).severity == importer_error)) << "An Error Expected"; + } +} + +/** +* @detail Test that the user became a warning if he used a dynamic array +* or an element with array size [0] by inspecting an ADTF description file for dynamic Arrays. +*/ +TEST(cTesterDDLInspector, + TestDynArraySize) +{ + TEST_REQ("ACORE-4637"); + + a_util::filesystem::Path strDescriptionFileName = "files/DynArraySize.description"; + + DDLImporter oImporterDyn(strDescriptionFileName); + ASSERT_EQ(a_util::result::SUCCESS, oImporterDyn.createNew()); + DDLDescription *poDDLDyn = oImporterDyn.getDDL(); + + DDLInspector oInspectorDyn(false); + oInspectorDyn.visitDDL(poDDLDyn); + + ASSERT_TRUE(oInspectorDyn.foundDynamicArrays()) << "Dynamic array should be found"; + + ImporterMsgList lstMsgsDyn = oInspectorDyn.getSuggestions(); + + ASSERT_TRUE((lstMsgsDyn.size() == 1)) << "One Warning Expected"; + + for (ImporterMsgList::iterator itMsg = lstMsgsDyn.begin(); itMsg != lstMsgsDyn.end(); ++itMsg) + { + ASSERT_TRUE((*itMsg).severity == importer_warning) << "An Warning Expected"; + } + + ///// + //ARRAYSIZE == 0 + strDescriptionFileName = "files/DynArraySize.description"; + + DDLImporter oImporter(strDescriptionFileName); + + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + DDLComplex *poDDLStruct = poDDL->getStructByName("tDynStructTest"); + DDLElementVec vecElement = poDDLStruct->getElements(); + vecElement[0]->setArraysize(0); + + DDLInspector oInspector(false); + oInspector.visitDDL(poDDL); + ImporterMsgList lstMsgs = oInspector.getSuggestions(); + + ASSERT_TRUE((lstMsgs.size() == 2)) << "Two Warnings Expected"; + + for (ImporterMsgList::iterator itMsg = lstMsgs.begin(); itMsg != lstMsgs.end(); ++itMsg) + { + ASSERT_TRUE((*itMsg).severity == importer_warning) << "An Warning Expected"; + } +} + +/** +* @detail Test if the last byte position and last element size are correctly returned +* by inspecting an ADTF description file and returning a Byte position. +*/ +TEST(cTesterDDLInspector, + TestLastByteInclusiveElementSize) +{ + TEST_REQ("ACORE-6774"); + + a_util::filesystem::Path strDescriptionFileName = "files/NestedCaps.description"; + DDLImporter oImporter(strDescriptionFileName); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + + DDLInspector oInspector(false); + oInspector.visitDDL(poDDL); + + ASSERT_TRUE(7 == oInspector.getLastBytePosOfAStructReal("tBitmapFormat")) << "Excpected Bytepos == 7"; + ASSERT_TRUE(64 == oInspector.getLastBytePosOfAStructCorrected("tBitmapFormat")) << "Excpected Bytepos == 96"; + + ASSERT_TRUE(18 == oInspector.getLastBytePosOfAStructReal("tNestTest")) << "Excpected Bytepos == 18"; + ASSERT_TRUE(12 == oInspector.getLastBytePosOfAStructCorrected("tNestTest")) << "Excpected Bytepos == 12"; + + +} + +/** +* @detail Test that errors in referenced sub-struct do not trigger an endless loop +* by inspecting an ADTF description file. +*/ +TEST(cTesterDDLInspector, + TestNameDuplicate) +{ + TEST_REQ("ACORE-7178"); + + a_util::filesystem::Path strDescriptionFileName = "files/invalid_duplicate.description"; + DDLImporter oImporter(strDescriptionFileName, false); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + + DDLInspector oInspector(false); + ASSERT_NE(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); +} + +/** +* @detail Test that severity of warnings give output depending on the selected level +* by inspecting an ADTF description file. +*/ +TEST(cTesterDDLInspector, + TestWarningLevel) +{ + TEST_REQ("CDDDL-23"); + + a_util::filesystem::Path strDescriptionFileName = "files/base_all_duplicates.description"; + DDLImporter oImporter(strDescriptionFileName, false); + oImporter.setMergeDefaults(false); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + DDLInspector oInspector(false); + // test default is moderate + // get some warnings about duplicates + ASSERT_EQ(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); + ASSERT_EQ(oInspector.getSuggestions().size(), 3); + ASSERT_EQ(oInspector.getWarningLevel(), ddl::WarningLevel::moderate); + + // no suggestions anymore + oInspector.setWarningLevel(ddl::WarningLevel::silent); + ASSERT_EQ(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); + ASSERT_EQ(oInspector.getWarningLevel(), ddl::WarningLevel::silent); + ASSERT_EQ(oInspector.getSuggestions().size(), 0); + + // get 4 additional warnings about the biggest element/types first + oInspector.setWarningLevel(ddl::WarningLevel::verbose); + ASSERT_EQ(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); + ASSERT_EQ(oInspector.getWarningLevel(), ddl::WarningLevel::verbose); + auto lst = oInspector.getSuggestions(); + ASSERT_EQ(oInspector.getSuggestions().size(), 7); +} + diff --git a/test/ddlrepresentation/files/adtf.description b/test/ddlrepresentation/files/adtf.description new file mode 100644 index 0000000..d816194 --- /dev/null +++ b/test/ddlrepresentation/files/adtf.description @@ -0,0 +1,94 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 20130703 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf1.description b/test/ddlrepresentation/files/adtf1.description new file mode 100644 index 0000000..d191ed3 --- /dev/null +++ b/test/ddlrepresentation/files/adtf1.description @@ -0,0 +1,93 @@ + + +
+ 1.0+ + AUDI Electronics Venture GmbH + 20100407 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf2.xml b/test/ddlrepresentation/files/adtf2.xml new file mode 100644 index 0000000..cc2a0ea --- /dev/null +++ b/test/ddlrepresentation/files/adtf2.xml @@ -0,0 +1,94 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 20100407 + 20110301 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_1_02.description b/test/ddlrepresentation/files/adtf_1_02.description new file mode 100644 index 0000000..5b48ac0 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_1_02.description @@ -0,0 +1,94 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 20100407 + 20110301 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_1_0p.description b/test/ddlrepresentation/files/adtf_1_0p.description new file mode 100644 index 0000000..d191ed3 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_1_0p.description @@ -0,0 +1,93 @@ + + +
+ 1.0+ + AUDI Electronics Venture GmbH + 20100407 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_1_0p_out_expected.xml b/test/ddlrepresentation/files/adtf_1_0p_out_expected.xml new file mode 100644 index 0000000..ddd3cf6 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_1_0p_out_expected.xml @@ -0,0 +1,154 @@ + + +
+ 1.0+ + AUDI Electronics Venture GmbH + 07.04.2010 + 01.01.1900 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_1_0p_resolved_expected.xml b/test/ddlrepresentation/files/adtf_1_0p_resolved_expected.xml new file mode 100644 index 0000000..bb81551 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_1_0p_resolved_expected.xml @@ -0,0 +1,36 @@ + + +
+ 1.0+ + AUDI Electronics Venture GmbH + 07.04.2011 + 07.04.2011 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_changed_expected.xml b/test/ddlrepresentation/files/adtf_changed_expected.xml new file mode 100644 index 0000000..1ffed0f --- /dev/null +++ b/test/ddlrepresentation/files/adtf_changed_expected.xml @@ -0,0 +1,144 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 01.01.1900 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_dynamic.description b/test/ddlrepresentation/files/adtf_dynamic.description new file mode 100644 index 0000000..4a53fd2 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_dynamic.description @@ -0,0 +1,99 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 20130703 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_merged_expected.xml b/test/ddlrepresentation/files/adtf_merged_expected.xml new file mode 100644 index 0000000..b8361f2 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_merged_expected.xml @@ -0,0 +1,173 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 03.07.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_merged_ovrwrt_expected.xml b/test/ddlrepresentation/files/adtf_merged_ovrwrt_expected.xml new file mode 100644 index 0000000..0fd8da0 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_merged_ovrwrt_expected.xml @@ -0,0 +1,173 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 03.07.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_min_max_default.description b/test/ddlrepresentation/files/adtf_min_max_default.description new file mode 100644 index 0000000..103c684 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_min_max_default.description @@ -0,0 +1,59 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 20130701 + + ADTF Description File for test purposes +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_out_expected.xml b/test/ddlrepresentation/files/adtf_out_expected.xml new file mode 100644 index 0000000..866ee58 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_out_expected.xml @@ -0,0 +1,155 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 03.07.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_recursion.description b/test/ddlrepresentation/files/adtf_recursion.description new file mode 100644 index 0000000..f89bdf3 --- /dev/null +++ b/test/ddlrepresentation/files/adtf_recursion.description @@ -0,0 +1,96 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 20130703 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_resolved_expected.xml b/test/ddlrepresentation/files/adtf_resolved_expected.xml new file mode 100644 index 0000000..c6930da --- /dev/null +++ b/test/ddlrepresentation/files/adtf_resolved_expected.xml @@ -0,0 +1,37 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 03.07.2013 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/adtf_v40.description b/test/ddlrepresentation/files/adtf_v40.description new file mode 100644 index 0000000..6eeadbe --- /dev/null +++ b/test/ddlrepresentation/files/adtf_v40.description @@ -0,0 +1,44 @@ + + +
+ 4.00 + AUDI Electronics Venture GmbH + 20130703 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/fep_driver.description b/test/ddlrepresentation/files/fep_driver.description new file mode 100644 index 0000000..07395f3 --- /dev/null +++ b/test/ddlrepresentation/files/fep_driver.description @@ -0,0 +1,127 @@ + + +
+ 3.00 + KERNAND + 24.06.2014 + 31.03.2015 + FEP Driver standard interfaces +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/force_version_ddl-2.0.description b/test/ddlrepresentation/files/force_version_ddl-2.0.description new file mode 100644 index 0000000..d8ab62f --- /dev/null +++ b/test/ddlrepresentation/files/force_version_ddl-2.0.description @@ -0,0 +1,103 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 01.01.1900 + 01.01.1900 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/force_version_ddl-2.0_to_3.0_expected.description b/test/ddlrepresentation/files/force_version_ddl-2.0_to_3.0_expected.description new file mode 100644 index 0000000..3475f39 --- /dev/null +++ b/test/ddlrepresentation/files/force_version_ddl-2.0_to_3.0_expected.description @@ -0,0 +1,103 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 01.01.1900 + 01.01.1900 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/force_version_ddl-3.0.description b/test/ddlrepresentation/files/force_version_ddl-3.0.description new file mode 100644 index 0000000..82dcbf4 --- /dev/null +++ b/test/ddlrepresentation/files/force_version_ddl-3.0.description @@ -0,0 +1,103 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 01.01.1900 + 01.01.1900 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/invalid_numbits_attribute.description b/test/ddlrepresentation/files/invalid_numbits_attribute.description new file mode 100644 index 0000000..0f6d5c2 --- /dev/null +++ b/test/ddlrepresentation/files/invalid_numbits_attribute.description @@ -0,0 +1,25 @@ + + +
+ 2.0 + ANOAFR4 + 05-14-2013 + + Invalid numbits attribute TestDescription +
+ + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/test/ddlrepresentation/files/no_structs.description b/test/ddlrepresentation/files/no_structs.description new file mode 100644 index 0000000..877ec9c --- /dev/null +++ b/test/ddlrepresentation/files/no_structs.description @@ -0,0 +1,28 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 20120316 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/partial_expected.description b/test/ddlrepresentation/files/partial_expected.description new file mode 100644 index 0000000..910d170 --- /dev/null +++ b/test/ddlrepresentation/files/partial_expected.description @@ -0,0 +1,118 @@ + + +
+ 3.00 + FNEUMTH + 01.07.2013 + 01.07.2013 + ADTF generated +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/printer.description b/test/ddlrepresentation/files/printer.description new file mode 100644 index 0000000..94c71e8 --- /dev/null +++ b/test/ddlrepresentation/files/printer.description @@ -0,0 +1,96 @@ + + +
+ 3.00 + AUDI Electronics Venture GmbH + 20130703 + + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/test_insert.description b/test/ddlrepresentation/files/test_insert.description new file mode 100644 index 0000000..585d65f --- /dev/null +++ b/test/ddlrepresentation/files/test_insert.description @@ -0,0 +1,81 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 07.04.2010 + 06.05.2014 + ADTF Common Description File + + + + +
+ + + + + + + + + + + + 1 + 1 + 1.000000 + + + + + + + 2 + 2 + 2.000000 + + + 4 + 4 + 4.000000 + + + 5 + 5 + 5.000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/test_insert_results.description b/test/ddlrepresentation/files/test_insert_results.description new file mode 100644 index 0000000..1831960 --- /dev/null +++ b/test/ddlrepresentation/files/test_insert_results.description @@ -0,0 +1,136 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 07.04.2010 + 02.09.2016 + ADTF Common Description File + + + + + + + +
+ + + + + + + + + + + + + + + 1 + 1 + 1.000000 + + + + + + + + + + 1 + 1 + 1.000000 + + + + + + + + + + 2 + 2 + 2.000000 + + + 1 + 1 + 1.000000 + + + + + + + + + + 4 + 4 + 4.000000 + + + 5 + 5 + 5.000000 + + + 1 + 1 + 1.000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/test_insert_results_ref.description b/test/ddlrepresentation/files/test_insert_results_ref.description new file mode 100644 index 0000000..7d10f90 --- /dev/null +++ b/test/ddlrepresentation/files/test_insert_results_ref.description @@ -0,0 +1,135 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 07.04.2010 + 07.04.2010 + ADTF Common Description File + + + + + + + +
+ + + + + + + + + + + + + + + 1 + 1 + 1.000000 + + + + + + + + + + 1 + 1 + 1.000000 + + + + + + + + + + 2 + 2 + 2.000000 + + + 1 + 1 + 1.000000 + + + + + + + + + + 4 + 4 + 4.000000 + + + 5 + 5 + 5.000000 + + + 1 + 1 + 1.000000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/files/unresolved_datatype.description b/test/ddlrepresentation/files/unresolved_datatype.description new file mode 100644 index 0000000..528cf4b --- /dev/null +++ b/test/ddlrepresentation/files/unresolved_datatype.description @@ -0,0 +1,24 @@ + + +
+ 1.02 + AUDI Electronics Venture GmbH + 20100407 + + ADTF Common Description File +
+ + + + + + + + + + + + + + +
diff --git a/test/ddlrepresentation/src/CMakeLists.txt b/test/ddlrepresentation/src/CMakeLists.txt new file mode 100644 index 0000000..b01fea7 --- /dev/null +++ b/test/ddlrepresentation/src/CMakeLists.txt @@ -0,0 +1,17 @@ +set(TEST_NAME ddlrepresentation) + +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp ddl_definitions.h) + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/ddl) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 120) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl_test_compat + ddl + a_util_result + GTest::Main + $<$:Threads::Threads> +) +add_test(NAME tester_${TEST_NAME} + COMMAND tester_${TEST_NAME} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../") diff --git a/test/ddlrepresentation/src/ddl_definitions.h b/test/ddlrepresentation/src/ddl_definitions.h new file mode 100644 index 0000000..6524c7c --- /dev/null +++ b/test/ddlrepresentation/src/ddl_definitions.h @@ -0,0 +1,680 @@ +/** + * @file + * Headerfile for the tester for the DDL representation. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _TESTER_DDL_DEFINITIONS_HEADER_ +#define _TESTER_DDL_DEFINITIONS_HEADER_ + +static const std::string DDL_TEST_STRING = +"\n \ +\n \ +
\n \ + 1.0+\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +
"; + +// Test DDL that differs in the type of tBitmapFormat::nBytesPerLine +static const std::string DDL_TEST_STRING_DIFF = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + +// Test DDL that differs by names +static const std::string DDL_TEST_STRING_DIFF_NAMES = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + + +// Test DDL that differs by version +static const std::string DDL_TEST_STRING_DIFF_VERSION = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + +// Test DDL that differs by version +static const std::string DDL_TEST_STRING_DIFF_ARRAY = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + + +// Test DDL where tBitmapFormat is only a subset +static const std::string DDL_TEST_STRING_SUBSET = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + + +// Test DDL where tMediaTypInfo is one element short +static const std::string DDL_TEST_STRING_INVALID_SUBSET = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content +static const std::string DDL_TEST_STRING_DYNAMIC = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content but with different naming +static const std::string DDL_TEST_STRING_DYNAMIC_NAME_DIFF = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content that is not binary equal (tBitmapFormat::nPixelFormat2) +static const std::string DDL_TEST_STRING_DYNAMIC_BIN_DIFF = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content that is not binary equal in dynamic part (tMediaTypeInfo::ui32Flags has different type) +static const std::string DDL_TEST_STRING_DYNAMIC_BIN_DIFF_2 = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL to where the orignial struct layout is not the same (tTest1 vs tTest2) but the binary positions match +static const std::string DDL_TEST_STRING_LAYOUT_TEST = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL to where the array size element is different +static const std::string DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + + +static const std::string DDL_TEST_STRING_UNITS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + 1.0 \ + 1.0 \ + 1.0 \ + \ + \ + \ + 1.0 \ + 1.0 \ + 1.0 \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_ENUMS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_HEADER = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ + \ + \ +
\n \ + \ + \ + \ +
"; + + +static const std::string DDL_TEST_STRING_USER_BASE_UNITS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \ + \ + \ + \n \ + \n \ + \n \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_STREAM_TO_PREFIX = +"\ +\ +
\ + 1.02\ + AUDI Electronics Venture GmbH\ + 07.04.2010\ + 03.04.2014\ + ADTF Common Description File\ +
\ + \ + \ + \ + \ + 1\ + 1\ + 1.000000\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
\ +"; + +// Test DDL that has special characters in name +static const std::string DDL_TEST_STRING_SPECIAL_NAMES = +"\n \ +\n \ +
\ + 4.00\ + AUDI Electronics Venture GmbH\ + 07.04.2010\ + 03.04.2014\ + ADTF Common Description File\ +
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +\ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +
"; + +static const std::string DDL_TEST_STRING_STATIC_ARRAY = R"ESCAPE( + + +
+ 4.1.0 + AUDI Electronics Venture GmbH + 20120316 + + ADTF Common Description File +
+ + + + + + + + + + + + +
+ +)ESCAPE"; + +#endif diff --git a/test/ddlrepresentation/src/tester_ddlrepresentation.cpp b/test/ddlrepresentation/src/tester_ddlrepresentation.cpp new file mode 100644 index 0000000..7939c34 --- /dev/null +++ b/test/ddlrepresentation/src/tester_ddlrepresentation.cpp @@ -0,0 +1,1695 @@ +/** + * @file + * Implementation of the tester for the DDL representation. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim + * + * QNX support Copyright (c) 2019 by dSPACE GmbH, Paderborn, Germany. All Rights Reserved + */ + +#include +#include +#include "../../_common/adtf_compat.h" +#include "../../_common/compat.h" +#include "ddl_definitions.h" + +using namespace ddl; + +_MAKE_RESULT(-4, ERR_POINTER) +_MAKE_RESULT(-5, ERR_INVALID_ARG) +_MAKE_RESULT(-18, ERR_NO_CLASS) +_MAKE_RESULT(-36, ERR_UNKNOWN_FORMAT) +_MAKE_RESULT(-37, ERR_NOT_INITIALIZED) +_MAKE_RESULT(-38, ERR_FAILED) + +static a_util::result::Result CompOutput(const std::string& strFile1, const std::string& strFile2, int nSkip = 4) +{ + std::string strContent1; + std::string strContent2; + + if (a_util::filesystem::readTextFile(strFile1, strContent1) != a_util::filesystem::OK || + a_util::filesystem::readTextFile(strFile2, strContent2) != a_util::filesystem::OK) + { + return ::ERR_FAILED; + } + + a_util::result::Result res = DDLCompare::isEqual(strContent1, strContent2, + DDLCompare::dcf_all | DDLCompare::dcf_subset | DDLCompare::dcf_no_header_dates); +#ifdef __QNX__ + if (res != a_util::result::SUCCESS) + { + LOG_ERROR("CompOutput: LastDDLErrorCode=%d Label=%s Desc=%s", + DDLError::getLastDDLErrorCode().getErrorCode(), + DDLError::getLastDDLErrorCode().getErrorLabel(), + DDLError::getLastDDLErrorDescription()); + } +#endif + return res; +} + +/** +* @detail The building up of a DDL object representation. +* Read an adtf.description file and build up the object representation +*/ +TEST(cTesterDDLRep, + TestBuildUpFile) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oDDLImporter; + ASSERT_TRUE((ERR_NOT_INITIALIZED == oDDLImporter.createNew())) << + "Uninitialized status of the DDLImporter not detected."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setFile("files/adtf.description")) << + "Could not load adtf.description file."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.createNew()) << + "Creation of object hierarchy failed."; + DDLDescription * poDDL = oDDLImporter.getDDL(); + ASSERT_TRUE( (NULL !=poDDL)) << "Invalid DDL object retrieved."; + // free allocated resources + oDDLImporter.destroyDDL(); + poDDL = NULL; +} + +/** +* @detail The building up of a DDL object representation. +* Read string and build up the object representation +*/ +TEST(cTesterDDLRep, + TestBuildUpString) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oDDLImporter; + std::string strXML (DDL_TEST_STRING); + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setXML(strXML)) << + "Could not set XML string."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.createNew()) << "Creation of DDL failed."; + DDLPrinter oDDLPrinter; + ASSERT_TRUE( (NULL !=oDDLImporter.getDDL())) << "Invalid DDL object retrieved."; + // free allocated resources + oDDLImporter.destroyDDL(); +} + +/** +* @detail The building up of a default DDL object representation. +* Build up the object representation from the default description +*/ +TEST(cTesterDDLRep, + TestBuildDefault) +{ + TEST_REQ("ACORE-3904"); + + DDLDescription *poDDL = DDLDescription::createDefault(); + ASSERT_TRUE( (NULL !=poDDL)) << "Creation of default DDL failed."; + // free allocated resources + DDLImporter::destroyDDL(poDDL); +} + +/** +* @detail The printing of the XML file based on a DDL in object representation. +* Write an own adtf.xml file containing the XML representation of the DDL +*/ +TEST(cTesterDDLRep, + TestPrinter) +{ + TEST_REQ("ACORE-3904 ACORE-6050"); + + { + DDLImporter oDDLImporter("files/printer.description"); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLDescription * poDDL = oDDLImporter.getDDL(); + std::string const strTargetFile ("adtf_out.xml"); + DDLPrinter oDDLPrinter(true); + // tidy up before new file is created + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_EQ(a_util::result::SUCCESS,oDDLPrinter.visitDDL(poDDL)) << "Print process failed."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLPrinter.toFile(strTargetFile)) << + "Export to file failed."; + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/adtf_out_expected.xml", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + // free allocated resources + oDDLImporter.destroyDDL(); + poDDL = NULL; + } + { + // Test setting unknown Version + DDLPrinter oDDLPrinter; + ASSERT_NE(a_util::result::SUCCESS, oDDLPrinter.forceVersion(DDLVersion(99, 99))); + } + { + // Testing of setting explicitly version + // 2.0 on 2.0 file. + // 3.0 on 2.0 file. + // 3.0 on 3.0 file. + // 2.0 on 3.0 file. + // This test does not check if the printer is able to print DDL 2.0 and DDL 3.0 in general +#define __TESTER_DDL_REPRESENTATION_TEST_AMOUNT 4 + DDLVersion versions[__TESTER_DDL_REPRESENTATION_TEST_AMOUNT] = + { ddl::DDLVersion::ddl_version_30, + ddl::DDLVersion::ddl_version_40, + ddl::DDLVersion::ddl_version_40, + ddl::DDLVersion::ddl_version_30 }; + const char* strSourceFiles[__TESTER_DDL_REPRESENTATION_TEST_AMOUNT] = + {"files/force_version_ddl-2.0.description", + "files/force_version_ddl-2.0.description", + "files/force_version_ddl-3.0.description", + "files/force_version_ddl-3.0.description"}; + const char* strExpectedFiles[__TESTER_DDL_REPRESENTATION_TEST_AMOUNT] = + {"files/force_version_ddl-2.0.description", + "files/force_version_ddl-2.0_to_3.0_expected.description", + "files/force_version_ddl-3.0.description", + "files/force_version_ddl-2.0.description"}; + for (unsigned int nIdx = 0; nIdx < __TESTER_DDL_REPRESENTATION_TEST_AMOUNT; nIdx++) + { + std::string strResultFile = a_util::strings::format("%s_result.description", strExpectedFiles[nIdx]); + if (a_util::filesystem::exists(strResultFile.c_str())) + { + a_util::filesystem::remove(strResultFile); + } + DDLImporter oDDLImporter; + oDDLImporter.setFile(strSourceFiles[nIdx]); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLDescription* pDDL = oDDLImporter.getDDL(); + DDLPrinter oDDLPrinter; + oDDLPrinter.forceVersion(versions[nIdx]); + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.visitDDL(pDDL)); + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.toFile(strResultFile)); + ASSERT_TRUE(a_util::filesystem::exists(strResultFile)); + a_util::result::Result res = CompOutput(strResultFile, strExpectedFiles[nIdx], 0); + a_util::filesystem::remove(strResultFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + } + } + +} + +/** +* @detail The merging of 2 DDL descriptions in object-representation is tested. +* Import and merge 2 existing DDL descriptions and print the result to an own file +* Repeat the test with the overwrite flag +*/ +TEST(cTesterDDLRep, + TestMerge) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oDDLImporter("files/adtf1.description"); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLDescription *poDDL1 = oDDLImporter.getDDL(); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setFile("files/adtf2.xml")); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLDescription *poDDL2 = oDDLImporter.getDDL(); + ASSERT_EQ(a_util::result::SUCCESS,poDDL1->merge(*poDDL2)) << "Merge process failed."; + std::string strTargetFile = "adtf_merged.xml"; + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + DDLPrinter oDDLPrinter; + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.visitDDL(poDDL1)); + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.toFile(strTargetFile)); + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/adtf_merged_expected.xml", 9); + ASSERT_EQ(a_util::result::SUCCESS, res); + a_util::filesystem::remove(strTargetFile); + // free allocated resources + DDLImporter::destroyDDL(poDDL1); + DDLImporter::destroyDDL(poDDL2); + poDDL1 = NULL; + poDDL2 = NULL; + // merge with overwrite flag + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setFile("files/adtf.description")); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + poDDL1 = oDDLImporter.getDDL(); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setFile("files/adtf2.xml")); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + poDDL2 = oDDLImporter.getDDL(); + ASSERT_EQ(a_util::result::SUCCESS,poDDL1->merge( + *poDDL2, IMediaDescriptionManager::MDMF_ForceOverwrite)) << + "Merge with overwrite flag failed."; + strTargetFile = "adtf_merged_ovrwrt.xml"; + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.visitDDL(poDDL1)); + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.toFile(strTargetFile)); + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + res = CompOutput(strTargetFile, "files/adtf_merged_ovrwrt_expected.xml", 9); + ASSERT_EQ(a_util::result::SUCCESS, res); + a_util::filesystem::remove(strTargetFile); + // free allocated resources + DDLImporter::destroyDDL(poDDL1); + DDLImporter::destroyDDL(poDDL2); + +} + +/** +* @detail The resolving of a specific target inside a DDL is tested. +* Import an existing DDL description, resolve the target, +* and print the result to an own file +*/ +TEST(cTesterDDLRep, + TestResolver) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oDDLImporter("files/adtf.description"); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLResolver oResolver; + oResolver.setTargetName("extended_can_stream"); + ASSERT_EQ(a_util::result::SUCCESS,oResolver.visitDDL(oDDLImporter.getDDL())) << + "Could not resolve specified target."; + a_util::xml::DOM oDOM; + ASSERT_TRUE(oDOM.fromString(oResolver.getResolvedXML())) << + "Invalid XML string retrieved."; + std::string const strTargetFile ("adtf_resolved.xml"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_TRUE(oDOM.save(strTargetFile)) << + "Could not save resolved XML to file."; + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/adtf_resolved_expected.xml", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + // free allocated resources + oDDLImporter.destroyDDL(); + +} + +/** +* @detail The renaming of streams and the removal of types and streams are tested. +* Import an existing DDL description, rename and remove some elements, +* and print the result to an own file +*/ +TEST(cTesterDDLRep, + TestElementHandling) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oDDLImporter("files/adtf.description"); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + DDLDescription *poDDL = oDDLImporter.getDDL(); + ASSERT_TRUE(NULL !=poDDL); + ASSERT_EQ(a_util::result::SUCCESS,poDDL->renameStream("video_stream", "new_video")) << "Could not rename stream."; + ASSERT_EQ(a_util::result::SUCCESS,poDDL->removeStream("extended_can_stream")) << "Could not remove stream."; + ASSERT_EQ(a_util::result::SUCCESS,poDDL->removeType("tCanMessageExt")) << "Could not remove struct."; + ASSERT_EQ(a_util::result::SUCCESS,poDDL->removeType("tFloat32")) << "Could not remove primitive data type."; + DDLPrinter oDDLPrinter; + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.visitDDL(poDDL)); + std::string const strTargetFile ("adtf_changed.xml"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_EQ(a_util::result::SUCCESS, oDDLPrinter.toFile(strTargetFile)); + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/adtf_changed_expected.xml", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + // free allocated resources + DDLImporter::destroyDDL(poDDL); + poDDL = NULL; + +} + +/** +* @detail The creation of a partial DDL is tested. +* Import an existing DDL description, create a partial DDL, try to merge them together +*/ +TEST(cTesterDDLRep, + TestCreatePartial) +{ + TEST_REQ("ACORE-3904 ACORE-6148"); + + // import a wholly defined DDL + DDLImporter oImporter("files/adtf.description"); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poRefDDL = oImporter.getDDL(); + + // try to create a partial DDL with an undefined type + std::string strPartialDesc (""); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(strPartialDesc)); + ASSERT_TRUE((ERR_NO_CLASS == oImporter.createPartial(poRefDDL, ddl::DDLVersion::ddl_version_invalid))) << "Erroneous partial DDL not detected."; + oImporter.destroyDDL(); + strPartialDesc = std::string(""); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(strPartialDesc)); + ASSERT_TRUE((ERR_UNKNOWN_FORMAT == oImporter.createPartial(poRefDDL, ddl::DDLVersion::ddl_version_invalid))) << "Invalid partial DDL not detected."; + oImporter.destroyDDL(); + strPartialDesc = std::string(""); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(strPartialDesc)); + ASSERT_TRUE((ERR_POINTER == oImporter.createPartial(NULL, ddl::DDLVersion::ddl_version_invalid))) << "Null-pointer not detected."; + ASSERT_EQ(a_util::result::SUCCESS,oImporter.createPartial(poRefDDL, ddl::DDLVersion::ddl_version_invalid)) << "Could not create partial DDL"; + DDLDescription *poPartDDL = oImporter.getDDL(); + ASSERT_TRUE( (NULL !=poPartDDL)) << "Invalid DDL object retrieved."; + DDLPrinter oPrinter; + ASSERT_EQ(a_util::result::SUCCESS, oPrinter.visitDDL(poPartDDL)); + std::string const strTargetFile ("partial.description"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_EQ(a_util::result::SUCCESS, oPrinter.toFile(strTargetFile)); + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/partial_expected.description", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + + // free allocated resources + DDLImporter::destroyDDL(poPartDDL); + DDLImporter::destroyDDL(poRefDDL); + +} + +/** +* @detail The get-by-name methods of the DDL are tested. +* Import an existing DDL description and try to get some specific elements out by name +*/ +TEST(cTesterDDLRep, + TestgetXByName) +{ + TEST_REQ("ACORE-3904"); + + DDLImporter oImporter("files/adtf.description"); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poDDL = oImporter.getDDL(); + ASSERT_TRUE(NULL != poDDL); + // test exising items + ASSERT_TRUE((NULL != poDDL->getBaseunitByName("nou"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tFloat32"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tInt64"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("adtf.type.audio"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("tMediaTypeInfo"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStreamByName("video_stream"))) << "No object received"; + // test non-existing items + ASSERT_TRUE((NULL == poDDL->getStructByName("adtf.type.flexray"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getUnitByName("audio_stream"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getPrefixByName("tBitmapInfo"))) << "Invalid pointer received"; + // free allocated resources + oImporter.destroyDDL(); + +} + +/** +* @detail The switch between different creation levels is tested. +* Create a small DDL at level 0, add elements at some other levels, +* and test the existence of some elements at specific levels +*/ +TEST(cTesterDDLRep, + TestrestoreLevel) +{ + TEST_REQ("ACORE-3904"); + + // create DDL + DDLImporter oImporter("files/partial_expected.description"); + oImporter.setCreationLevel(0); // cMediaManager::DL_AlwaysThere + ASSERT_EQ(a_util::result::SUCCESS,oImporter.createNew()) << oImporter.getErrorDesc().c_str(); + DDLDescription *poDDL = oImporter.getDDL(); + // add some elements with different creation levels + // level: cMediaManager::DL_SystemGlobal + poDDL->addDatatype(new DDLDataType(std::string("tInt128"), (unsigned int)128, NULL, std::string("Type for very large numbers"), DDLAlignment::e1, 1, 1)); + DDLPrefix * poPrefix = new DDLPrefix("One", "", 1, 1); + poDDL->addPrefix(poPrefix); + // level: cMediaManager::DL_Config + DDLBaseunit * poBU = new DDLBaseunit("Bit", "b", "Smallest information unit", 2); + poDDL->addBaseunit(poBU); + DDLRefUnitVec vecRU; + vecRU.push_back(new DDLRefUnit(poBU, 1, poPrefix)); + poDDL->addUnit(new DDLUnit("Byte", "8", "1", 0.0, vecRU, 2)); + std::transform(vecRU.begin(), vecRU.end(), vecRU.begin(), DDLDescription::deleteChild); + // level: cMediaManager::DL_Running + poDDL->addDatatype(new DDLDataType("tFloat96", 96, NULL, + "Floating-point type for high demands", DDLAlignment::e1, 1, 3)); + // no changes to DDL expected through this level switch + ASSERT_EQ(a_util::result::SUCCESS,poDDL->restoreLevel(4)) << "Level switch failed"; + // test existence + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tBool"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tUInt16"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("tCanMessage"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tInt128"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getPrefixByName("One"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getBaseunitByName("Bit"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getUnitByName("Byte"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tFloat96"))) << "No object received"; + // decrease the level to DL_Running and test existence again + ASSERT_EQ(a_util::result::SUCCESS,poDDL->restoreLevel(3)) << "Level switch failed"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tBool"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tUInt16"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("tCanMessage"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tInt128"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getPrefixByName("One"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getBaseunitByName("Bit"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getUnitByName("Byte"))) << "No object received"; + ASSERT_TRUE((NULL == poDDL->getDataTypeByName("tFloat96"))) << "Invalid pointer received"; + // decrease the level to DL_Config and test existence again + ASSERT_EQ(a_util::result::SUCCESS,poDDL->restoreLevel(2)) << "Level switch failed"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tBool"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tUInt16"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("tCanMessage"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tInt128"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getPrefixByName("One"))) << "No object received"; + ASSERT_TRUE((NULL == poDDL->getBaseunitByName("Bit"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getUnitByName("Byte"))) << "Invalid received"; + ASSERT_TRUE((NULL == poDDL->getDataTypeByName("tFloat96"))) << "Invalid pointer received"; + // decrease the level to DL_SystemGlobal and test existence again + ASSERT_EQ(a_util::result::SUCCESS,poDDL->restoreLevel(1)) << "Level switch failed"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tBool"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getDataTypeByName("tUInt16"))) << "No object received"; + ASSERT_TRUE((NULL != poDDL->getStructByName("tCanMessage"))) << "No object received"; + ASSERT_TRUE((NULL == poDDL->getDataTypeByName("tInt128"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getPrefixByName("One"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getBaseunitByName("Bit"))) << "Invalid pointer received"; + ASSERT_TRUE((NULL == poDDL->getUnitByName("Byte"))) << "Invalid received"; + ASSERT_TRUE((NULL == poDDL->getDataTypeByName("tFloat96"))) << "Invalid pointer received"; + + // free allocated resources + DDLImporter::destroyDDL(poDDL); + +} + +/** +* @detail The compatibility to 'old' version 1.0+ gets tested. +* Read a DDL1.0+ from a file, test DDLPrinter and DDLResolver +*/ +TEST(cTesterDDLRep, + TestCompatibility) +{ + TEST_REQ("ACORE-3904"); + + // test import + DDLImporter oImporter("files/adtf_1_0p.description"); + ASSERT_EQ(a_util::result::SUCCESS,oImporter.createNew()) << "Import of DDL1.0+ failed."; + DDLDescription *poDDL = oImporter.getDDL(); + ASSERT_TRUE( (NULL !=poDDL)) << "Invalid pointer retrieved"; + // test printing + DDLPrinter oPrinter; + ASSERT_EQ(a_util::result::SUCCESS,oPrinter.visitDDL(poDDL)) << "Printing of DDL1.0+ failed."; + std::string strTargetFile ("adtf_1_0p_out.xml"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_EQ(a_util::result::SUCCESS,oPrinter.toFile(strTargetFile)) << "Export to file failed."; + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + a_util::result::Result res = CompOutput(strTargetFile, "files/adtf_1_0p_out_expected.xml", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + // test resolving + DDLResolver oResolver("extended_can_stream"); + ASSERT_EQ(a_util::result::SUCCESS,oResolver.visitDDL(poDDL)) << "Resolving of DDL1.0+ failed."; + a_util::xml::DOM oDOM; + ASSERT_TRUE(oDOM.fromString(oResolver.getResolvedXML())); + strTargetFile = std::string("adtf_1_0p_resolved.xml"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + ASSERT_TRUE(oDOM.save(strTargetFile)) << + "Export of resolved XML to file failed."; + ASSERT_TRUE(a_util::filesystem::exists(strTargetFile)); + res = CompOutput(strTargetFile, "files/adtf_1_0p_resolved_expected.xml", 9); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + + // free allocated resources + DDLImporter::destroyDDL(poDDL); + +} + +/** +* @detail Check if the DDLImporter correctly detects an illegal recursion. +* Load a DDL and check if an error message is returned. Passed if the +* DDLImporter announces the expected error messages and no program errors occur. +*/ +TEST(cTesterDDLRep, + TestRecursion) +{ + TEST_REQ("ACORE-5520"); + + DDLImporter oImporter; + + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setFile("files/adtf_recursion.description")); + + ASSERT_TRUE(a_util::result::isFailed(oImporter.createNew())); + + std::string strErrorDesc = oImporter.getErrorDesc(); + + std::cout << strErrorDesc.c_str(); +} + +/** +* @detail Test if the support for minimum, maximum, and default values works correctly. +* A DDL is loaded and the contained minimum, maximum and default values are validated. +* Passed if the validator announces the expected error messages and no program errors occur. +*/ +TEST(cTesterDDLRep, + TestMinMaxDefaultValues) +{ + TEST_REQ("ACORE-5212"); + + DDLImporter oImporter; + + ASSERT_EQ(a_util::result::SUCCESS,oImporter.setFile("files/adtf_min_max_default.description")) << + "Could not load DDL file with min, max, and default values"; + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + + DDLDescription *poDDL = oImporter.getDDL(); + ASSERT_TRUE(NULL !=poDDL); + + DDLInspector oInspector; + ASSERT_TRUE((a_util::result::SUCCESS != oInspector.visitDDL(poDDL))) << + "Validator did not detect erroneous default value."; + + auto suggestions = oInspector.getSuggestions(); + // Element (Complex_Datatypes Element Name) 'SomeStructU16WithBoolLimits.ui16Value1' maximum value is 'tTrue' but it should be a floating point value or tTrue if using type tBool. + // Element (Complex_Datatypes Element Name) 'SomeStructU16WithBoolLimits.ui16Value1' minimum value is 'tFalse' but it should be a floating point value or tFalse if using type tBool. + // Default value of element 'i16TooLow' is out of range. + // Default value of element 'tMinMaxDerived' is out of range. + ASSERT_EQ(suggestions.size(), 4); + + // tidy up + DDLImporter::destroyDDL(poDDL); + poDDL = NULL; + + +} + +class cWorker +{ + volatile bool exit; + a_util::concurrency::thread thread; + void LoopFunc() + { + while (!exit) + { + DDLImporter oDDLImporter; + std::string strXML (DDL_TEST_STRING); + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setXML(strXML)) << "Could not set XML string."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.createNew()) << "Creation of DDL failed."; + ASSERT_TRUE( (NULL !=oDDLImporter.getDDL())) << "Invalid DDL object retrieved."; + + DDLPrinter oDDLPrinter; + ASSERT_EQ(a_util::result::SUCCESS,oDDLPrinter.visitDDL(oDDLImporter.getDDL())) << "Print process failed."; + std::string strXMLRes = oDDLPrinter.getXML(); + ASSERT_FALSE(strXMLRes.empty()); + + // free allocated resources + oDDLImporter.destroyDDL(); + } + } + +public: + cWorker() : exit(false), thread(&cWorker::LoopFunc, this) + { + } + + ~cWorker() + { + exit = true; + thread.join(); + } +}; + +#define THREAD_COUNT 30 + +/** +* @detail Check if DDL objects are reenrant by creating multiple threads that perform OODDL operations +* Every thread should work without interfering the others. +*/ +TEST(cTesterDDLRep, + TestReentrant) +{ + TEST_REQ("ACORE-6945"); + + { + cWorker workers[THREAD_COUNT]; + a_util::system::sleepMilliseconds(1000); + } +} + +/** +* @detail Test DDLCloner by cloning DDL and compare if equal. +*/ +TEST(cTesterDDLRep, + TestCloner) +{ + TEST_REQ("ACORE-3904"); + + // test partial checker (good case) + DDLImporter oImporter ("files/adtf.description"); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + DDLDescription *poOrgDDL = oImporter.getDDL(); + ASSERT_TRUE(NULL !=poOrgDDL); + + DDLCloner oCloner; + ASSERT_EQ(a_util::result::SUCCESS, oCloner.setOriginal(poOrgDDL)); + ASSERT_EQ(a_util::result::SUCCESS, oCloner.createNew()); + + DDLDescription *pClonedDDL = oCloner.getDDL(); + ASSERT_TRUE(NULL !=pClonedDDL); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(poOrgDDL, pClonedDDL, DDLCompare::dcf_everything)); + + // reset original DDL + oCloner.destroyDDL(); + oImporter.destroyDDL(); + + oImporter.setFile("files/fep_driver.description"); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + poOrgDDL = oImporter.getDDL(); + + ASSERT_EQ(a_util::result::SUCCESS, oCloner.setOriginal(poOrgDDL)); + ASSERT_EQ(a_util::result::SUCCESS, oCloner.createNew()); + + pClonedDDL = oCloner.getDDL(); + ASSERT_TRUE(NULL != pClonedDDL); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(poOrgDDL, pClonedDDL, DDLCompare::dcf_everything)); + +} + +#define LOG_AND_RELEASE_EXCEPTION(__ex) LOG_EXCEPTION(__ex); __ex = NULL; + +/** +* @detail Test DDLCompare by cloning DDL and compare several DDL description. +*/ +TEST(cTesterDDLRep, + TestCompare) +{ + TEST_REQ("ACORE-7093"); + + // isBinaryEqual + { + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING, true)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING, false)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF, true)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF, false)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_SUBSET, "adtf.type.video", DDL_TEST_STRING, true)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_SUBSET, true)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_SUBSET, "adtf.type.video", DDL_TEST_STRING, false)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC, false)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_NAME_DIFF, false)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_BIN_DIFF, false)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_BIN_DIFF_2, false)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isBinaryEqual("tTest1", DDL_TEST_STRING_LAYOUT_TEST, "tTest2", DDL_TEST_STRING_LAYOUT_TEST, false)); + } + + // isEqual (types) + { + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING, + DDLCompare::icf_memory|DDLCompare::icf_serialized|DDLCompare::icf_names|DDLCompare::icf_versions)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF, + DDLCompare::icf_memory)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF_NAMES, + DDLCompare::icf_memory|DDLCompare::icf_names)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF_NAMES, + DDLCompare::icf_memory)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tTest1", DDL_TEST_STRING_LAYOUT_TEST, "tTest2", DDL_TEST_STRING_LAYOUT_TEST, + DDLCompare::icf_memory)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF_VERSION, + DDLCompare::icf_memory|DDLCompare::icf_versions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF_VERSION, + DDLCompare::icf_memory)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_DIFF_ARRAY, + DDLCompare::icf_memory)); + + // dynamic stuff + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC, DDLCompare::icf_memory)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_NAME_DIFF, DDLCompare::icf_memory)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_NAME_DIFF, DDLCompare::icf_memory|DDLCompare::icf_names)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_BIN_DIFF, DDLCompare::icf_memory)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_DYNAMIC, "adtf.type.video", DDL_TEST_STRING_DYNAMIC_BIN_DIFF_2, DDLCompare::icf_memory)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tTest1", DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC, "tTest1", DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC, DDLCompare::icf_memory)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tTest1", DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC, "tTest2", DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC, DDLCompare::icf_memory)); + + // subset + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_SUBSET, "adtf.type.video", DDL_TEST_STRING, DDLCompare::icf_memory|DDLCompare::icf_subset)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING, "adtf.type.video", DDL_TEST_STRING_SUBSET, DDLCompare::icf_memory|DDLCompare::icf_subset)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("adtf.type.video", DDL_TEST_STRING_INVALID_SUBSET, "adtf.type.video", DDL_TEST_STRING, DDLCompare::icf_memory|DDLCompare::icf_subset)); + + } + + // isEqual (descriptions) + { + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, DDL_TEST_STRING, + DDLCompare::dcf_everything)); + + // header + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_HEADER)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//header/language_version", oNode)); + oNode.setData("123"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header | DDLCompare::dcf_descriptions | DDLCompare::dcf_versions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header | DDLCompare::dcf_descriptions)); + + ASSERT_TRUE(oDom.findNode("//header/description", oNode)); + oNode.setData("blah blah"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header | DDLCompare::dcf_descriptions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header)); + + ASSERT_TRUE(oDom.findNode("//header/date_creation", oNode)); + std::string strOldData = oNode.getData().c_str(); + oNode.setData("20140213"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header)); + oNode.setData(strOldData); + + ASSERT_TRUE(oDom.findNode("//header/ext_declaration[@key='AnyKey']", oNode)); + oNode.setAttribute("value", "haha"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_header)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_HEADER, oDom.toString().c_str(), + DDLCompare::dcf_all & ~DDLCompare::dcf_header)); + } + + // datatypes + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//datatype[@name='tFloat64']", oNode)); + oNode.setAttribute("description", "foo"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types | DDLCompare::dcf_descriptions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types)); + + oNode.setAttribute("min", "2000"); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types | DDLCompare::dcf_visualization_attributes)); + + oNode.setAttribute("size", "16"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_data_types)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_data_types)); + } + + // structs + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//struct[@name='tBitmapFormat']", oNode)); + oNode.setAttribute("comment", "foo"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs | DDLCompare::dcf_comments | DDLCompare::dcf_versions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs | DDLCompare::dcf_versions)); + + oNode.setAttribute("version", "123"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs | DDLCompare::dcf_versions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs)); + + std::string strOldAlignment = oNode.getAttribute("alignment").c_str(); + oNode.setAttribute("alignment", "16"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs)); + + oNode.setAttribute("alignment", strOldAlignment); + + ASSERT_TRUE(oNode.findNode(".//element[@name='nPixelFormat']", oNode)); + + oNode.setAttribute("scale", "1000"); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs | DDLCompare::dcf_visualization_attributes)); + + oNode.setAttribute("name", "sepp"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_structs | DDLCompare::dcf_no_recursion)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_structs & ~DDLCompare::dcf_streams)); + } + + // streams + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//stream[@name='can_stream']", oNode)); + oNode.setAttribute("description", "foo"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams | DDLCompare::dcf_descriptions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams)); + + std::string strOldType = oNode.getAttribute("type").c_str(); + oNode.setAttribute("type", "tCanMessageExt"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams)); + oNode.setAttribute("type", strOldType); + + a_util::xml::DOMElement oStructNode; + ASSERT_TRUE(oNode.findNode(".//struct[@type='tCanMessage']", oStructNode)); + + oStructNode.setAttribute("bytepos", "500"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams | DDLCompare::dcf_no_recursion)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_streams)); + + // check differences in type as well + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + ASSERT_TRUE(oDom.findNode("//struct[@name='adtf.core.media_type']", oNode)); + oNode.setAttribute("alignment", "8"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING, oDom.toString().c_str(), DDLCompare::dcf_streams)); + } + + // base units + { + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, DDL_TEST_STRING_UNITS, DDLCompare::dcf_all)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//baseunit[@name='Candela']", oNode)); + oNode.setAttribute("description", "foo"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_base_units | DDLCompare::dcf_descriptions)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_base_units)); + + oNode.setAttribute("name", "foo_unit"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_base_units)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_base_units)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_base_units)); + } + + // prefix + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//prefixes[@name='deca']", oNode)); + + std::string strOldName = oNode.getAttribute("name").c_str(); + oNode.setAttribute("name", "deca2"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_prefixes)); + oNode.setAttribute("name", strOldName); + + std::string strOldSymbol = oNode.getAttribute("symbol").c_str(); + oNode.setAttribute("symbol", "XF"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_prefixes)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); //a unit that uses the prefix + oNode.setAttribute("symbol", strOldSymbol); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_all)); + } + + // units + { + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//unit[@name='bar_unit2']", oNode)); + + std::string strOldName = oNode.getAttribute("name").c_str(); + oNode.setAttribute("name", "foo_unit"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); + oNode.setAttribute("name", strOldName); + + a_util::xml::DOMElement oNumerator; + ASSERT_TRUE(oNode.findNode(".//numerator", oNumerator)); + + std::string strOldNumerator = oNumerator.getData().c_str(); + oNumerator.setData("200"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); + oNumerator.setData(strOldNumerator); + + a_util::xml::DOMElement oRef; + ASSERT_TRUE(oNode.findNode(".//refUnit", oRef)); + oRef.setAttribute("power", "100"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units | DDLCompare::dcf_no_recursion)); + + oRef.setAttribute("name", "Kelvin"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units | DDLCompare::dcf_no_recursion)); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_units)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_UNITS, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_units)); + } + + // enums + { + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, DDL_TEST_STRING_ENUMS, DDLCompare::dcf_all)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_ENUMS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//enum[@name='tValueDefinitions2']", oNode)); + + std::string strOldType = oNode.getAttribute("type").c_str(); + oNode.setAttribute("type", "tFloat64"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_enums)); + oNode.setAttribute("type", strOldType); + + a_util::xml::DOMElement oElement; + ASSERT_TRUE(oNode.findNode(".//element[@name='ELEMENT_TWO2']", oElement)); + oElement.setAttribute("value", "321"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_enums)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_enums | DDLCompare::dcf_no_enum_values_check)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_enums | DDLCompare::dcf_no_enum_values_check)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_enums)); + + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(DDL_TEST_STRING_ENUMS, oDom.toString().c_str(), DDLCompare::dcf_all & ~DDLCompare::dcf_enums)); + } + } + + { + //Item based string methods + + { + // enums + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tValueDefinitions2", DDL_TEST_STRING_ENUMS, "tValueDefinitions2", DDL_TEST_STRING_ENUMS)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_ENUMS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//enum[@name='tValueDefinitions2']", oNode)); + oNode.setAttribute("type", "tBool"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tValueDefinitions2", DDL_TEST_STRING_ENUMS, "tValueDefinitions2", oDom.toString().c_str(), DDLCompare::icf_none)); + } + + { + // prefixes + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualPrefix("deca", DDL_TEST_STRING_UNITS, "deca", DDL_TEST_STRING_UNITS)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//prefixes[@name='deca']", oNode)); + oNode.setAttribute("symbol", "XF"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualPrefix("deca", DDL_TEST_STRING_UNITS, "deca", oDom.toString().c_str(), DDLCompare::icf_none)); + } + + { + // units + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualUnit("bar_unit2", DDL_TEST_STRING_UNITS, "bar_unit2", DDL_TEST_STRING_UNITS)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//unit[@name='bar_unit2']", oNode)); + a_util::xml::DOMElement oNumerator; + ASSERT_TRUE(oNode.findNode(".//numerator", oNumerator)); + oNumerator.setData("200"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualUnit("bar_unit2", DDL_TEST_STRING_UNITS, "bar_unit2", oDom.toString().c_str(), DDLCompare::icf_none)); + } + + { + // structs + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tBitmapFormat", DDL_TEST_STRING, "tBitmapFormat", DDL_TEST_STRING)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//struct[@name='tBitmapFormat']", oNode)); + oNode.setAttribute("alignment", "2"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tBitmapFormat", DDL_TEST_STRING, "tBitmapFormat", oDom.toString().c_str(), DDLCompare::icf_memory)); + } + + { + // datatypes + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", DDL_TEST_STRING, "tUInt8", DDL_TEST_STRING)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//datatype[@name='tUInt8']", oNode)); + oNode.setAttribute("size", "9"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", DDL_TEST_STRING, "tUInt8", oDom.toString().c_str(), DDLCompare::icf_memory)); + + oNode.setAttribute("size", "8"); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", DDL_TEST_STRING, "tUInt8", oDom.toString().c_str(), DDLCompare::icf_memory)); + + oNode.setAttribute("max", "10"); //check attribute set only on one of the two + std::string strHelper = oDom.toString().c_str(); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", DDL_TEST_STRING, "tUInt8", strHelper, DDLCompare::icf_names | DDLCompare::icf_memory)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", DDL_TEST_STRING, "tUInt8", strHelper, DDLCompare::icf_names | DDLCompare::icf_visualizations_attributes)); + + // check set on both but different + oNode.setAttribute("max", "11"); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", oDom.toString().c_str(), "tUInt8", strHelper, DDLCompare::icf_names | DDLCompare::icf_memory)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualType("tUInt8", oDom.toString().c_str(), "tUInt8", strHelper, DDLCompare::icf_names | DDLCompare::icf_visualizations_attributes)); + } + + { + // streams + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualStream("video_stream", DDL_TEST_STRING, "video_stream", DDL_TEST_STRING)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//stream[@name='video_stream']", oNode)); + oNode.setAttribute("type", "adtf.type.audio"); + + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualStream("video_stream", DDL_TEST_STRING, "video_stream", oDom.toString().c_str(), DDLCompare::icf_memory)); + + // check recursion from stream to struct to unit to prefix. + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_STREAM_TO_PREFIX)); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqualStream("a", DDL_TEST_STRING_STREAM_TO_PREFIX, "a", oDom.toString().c_str(), DDLCompare::icf_units)); + ASSERT_TRUE(oDom.findNode("//prefixes[@name='TestPrefix']", oNode)); + oNode.setAttribute("symbol", "p2"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualStream("a", DDL_TEST_STRING_STREAM_TO_PREFIX, "a", oDom.toString().c_str(), DDLCompare::icf_units)); + + // check recursion from stream to struct to unit to baseunit. + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_STREAM_TO_PREFIX)); + ASSERT_TRUE(oDom.findNode("//baseunit[@name='nou']", oNode)); + oNode.setAttribute("symbol", "1"); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqualStream("a", DDL_TEST_STRING_STREAM_TO_PREFIX, "a", oDom.toString().c_str(), DDLCompare::icf_units)); + } + + { + DDLImporter oImporter1; + ASSERT_EQ(a_util::result::SUCCESS, oImporter1.setXML(DDL_TEST_STRING_UNITS)); + ASSERT_EQ(a_util::result::SUCCESS, oImporter1.createNew()); + + DDLRefUnit* pRefUnit1 = oImporter1.getDDL()->getUnitByName("bar_unit")->getRefUnits().front(); + ASSERT_EQ(a_util::result::SUCCESS, DDLCompare::isEqual(pRefUnit1, pRefUnit1)); + + a_util::xml::DOM oDom; + ASSERT_TRUE(oDom.fromString(DDL_TEST_STRING_UNITS)); + a_util::xml::DOMElement oNode; + ASSERT_TRUE(oDom.findNode("//refUnit", oNode)); + oNode.setAttribute("prefix", "giga"); + + DDLImporter oImporter2; + ASSERT_EQ(a_util::result::SUCCESS, oImporter2.setXML(oDom.toString().c_str())); + ASSERT_EQ(a_util::result::SUCCESS, oImporter2.createNew()); + + DDLRefUnit* pRefUnit2 = oImporter2.getDDL()->getUnitByName("bar_unit")->getRefUnits().front(); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(pRefUnit1, pRefUnit2, DDLCompare::icf_none)); + ASSERT_NE(a_util::result::SUCCESS, DDLCompare::isEqual(pRefUnit1, pRefUnit2, DDLCompare::icf_no_recursion | DDLCompare::icf_names)); + } + } +} + +/** +* @detail Test use defined base units by importing a ddl with user defined base units. +*/ +TEST(cTesterDDLRep, + TestUserBaseUnit) +{ + TEST_REQ("ACORE-7149"); + + { + DDLImporter oImporter; + oImporter.setMergeDefaults(false); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(DDL_TEST_STRING_USER_BASE_UNITS)); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + ASSERT_TRUE(oImporter.getDDL()->getStructByName("test_struct")); + } + + { + DDLImporter oImporter; + oImporter.setMergeDefaults(true); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(DDL_TEST_STRING_USER_BASE_UNITS)); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createNew()); + ASSERT_TRUE(oImporter.getDDL()->getStructByName("test_struct")); + auto uint8_item = oImporter.getDDL()->getDataTypeByName("tUInt8"); + ASSERT_TRUE(uint8_item->getMaxValue() == "255"); + ASSERT_TRUE(uint8_item->getMinValue() == "0"); + } + + { + DDLImporter oImporter; + oImporter.setMergeDefaults(false); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(DDL_TEST_STRING_USER_BASE_UNITS)); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createPartial(DDLDescription::createDefault(), ddl::DDLVersion::ddl_version_invalid)); + ASSERT_TRUE(oImporter.getDDL()->getStructByName("test_struct")); + } + + { + DDLImporter oImporter; + oImporter.setMergeDefaults(true); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.setXML(DDL_TEST_STRING_USER_BASE_UNITS)); + ASSERT_EQ(a_util::result::SUCCESS, oImporter.createPartial(DDLDescription::createDefault(), ddl::DDLVersion::ddl_version_invalid)); + ASSERT_TRUE(oImporter.getDDL()->getStructByName("test_struct")); + } +} + +void InsertHeaderExtDeclaration(DDLDescription* poDDL) +{ + { + // insert at the third position + DDLExtDeclaration* pExtDcl = new DDLExtDeclaration("c", "c"); + poDDL->getHeader()->addExtDeclaration(pExtDcl, 2); + } + { + // insert at the end + DDLExtDeclaration* pExtDcl = new DDLExtDeclaration("c2", "c2"); + poDDL->getHeader()->addExtDeclaration(pExtDcl, (int)poDDL->getHeader()->getExtDeclarations().size()); + } + { + // insert at the beginning + DDLExtDeclaration* pExtDcl = new DDLExtDeclaration("c3", "c3"); + poDDL->getHeader()->addExtDeclaration(pExtDcl, 0); + } +} + +void InsertBaseUnit(DDLDescription* poDDL) +{ + { + // insert at the third position + DDLBaseunit* poBaseunit = new DDLBaseunit("c", "c", "c"); + poDDL->addBaseunit(poBaseunit, 2); + } + { + // insert at the end + DDLBaseunit* poBaseunit = new DDLBaseunit("c2", "c2", "c2"); + poDDL->addBaseunit(poBaseunit, poDDL->getBaseunits().size()); + } + { + // insert at the beginning + DDLBaseunit* poBaseunit = new DDLBaseunit("c3", "c3", "c3"); + poDDL->addBaseunit(poBaseunit, 0); + } +} + +void InsertRefUnit(DDLDescription* poDDL) +{ + DDLUnit* poUnit = poDDL->getUnitByName("a"); + DDLPrefix* poPrefix = poDDL->getPrefixByName("a"); + + { + // insert at the third position + DDLBaseunit* poBaseUnit = poDDL->getBaseunitByName("c"); + DDLRefUnit* poRefUnit = new DDLRefUnit(poBaseUnit, 1, poPrefix); + poUnit->addRefUnit(poRefUnit, 2); + } + { + // insert at the end + DDLBaseunit* poBaseUnit = poDDL->getBaseunitByName("c2"); + DDLRefUnit* poRefUnit = new DDLRefUnit(poBaseUnit, 1, poPrefix); + poUnit->addRefUnit(poRefUnit, (int)poUnit->getRefUnits().size()); + } + { + // insert at the beginning + DDLBaseunit* poBaseUnit = poDDL->getBaseunitByName("c3"); + DDLRefUnit* poRefUnit = new DDLRefUnit(poBaseUnit, 1, poPrefix); + poUnit->addRefUnit(poRefUnit, 0); + } +} + +void InsertUnit(DDLDescription* poDDL) +{ + { + // insert at the third position + DDLUnit* poUnit = new DDLUnit(*poDDL->getUnitByName("a")); + poUnit->setName("c"); + poDDL->addUnit(poUnit, 2); + } + { + // insert at the end + DDLUnit* poUnit = new DDLUnit(*poDDL->getUnitByName("a")); + poUnit->setName("c2"); + poDDL->addUnit(poUnit, poDDL->getUnits().size()); + } + { + // insert at the beginning + DDLUnit* poUnit = new DDLUnit(*poDDL->getUnitByName("a")); + poUnit->setName("c3"); + poDDL->addUnit(poUnit, 0); + } +} + +void InserStructElement(const std::string& strComplexDT, + const std::string& strElementDT, + DDLDescription* poDDL) +{ + DDLComplex* pComplexDT = poDDL->getStructByName(strComplexDT); + + IDDLDataType* pElementDT = poDDL->getStructByName(strElementDT); + if (!pElementDT) + { + DDLDataType* pPrimitiveDT = poDDL->getDataTypeByName(strElementDT); + if (NULL == pPrimitiveDT) + { + DDLEnum* poEnum = poDDL->getEnumByName(strElementDT); + pPrimitiveDT = poDDL->getDataTypeByName(poEnum->getType()); + } + pElementDT = static_cast(pPrimitiveDT); + } + + // insert the element at the third, the last and the first position + unsigned int aPosition[] = { 2, 100, 0 }; + for (unsigned int nPos = 0; nPos < 3; ++nPos) + { + // byte position has to be passed by the DDLElement's constructor + unsigned int nBytePos; + if (aPosition[nPos] < pComplexDT->getElements().size()) + { + nBytePos = pComplexDT->getElements()[aPosition[nPos]]->getBytepos(); + } + else + { + DDLInspector oInspector(false); + ASSERT_EQ(a_util::result::SUCCESS, oInspector.visitDDL(poDDL)); + nBytePos = oInspector.getLastBytePosOfAStructReal(strComplexDT); + } + + DDLElement* pElement = new DDLElement(pElementDT, + a_util::strings::format("%s_%d", strElementDT.c_str(), nPos), + nBytePos, + 1, + DDLByteorder::e_le, + DDLAlignment::e1); + + pComplexDT->addElement(pElement, aPosition[nPos]); + } +} + +/** +* @detail Test the insert function by inserting DDL objects at different positions. +*/ +TEST(cTesterDDLRep, + TestInsert) +{ + TEST_REQ("ACORE-7238"); + + DDLImporter oDDLImporter("files/test_insert.description", false, false); + oDDLImporter.setMergeDefaults(false); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()); + + DDLDescription * poDDL = oDDLImporter.getDDL(); + ASSERT_TRUE(NULL !=poDDL); + + InsertHeaderExtDeclaration(poDDL); + InsertBaseUnit(poDDL); + InsertRefUnit(poDDL); + InsertUnit(poDDL); + + // It is not necessary to test the insert function for the prefixes, enums, + // primitive data types, complex data types and streams, + // because cDDLContainerNoClone::Insert is already tested by the base units. + + // There is no insert function for cDDLStreamStruct, because + // there is always only one cDDLStreamStruct. + + { + // test primitive data type + InserStructElement("test_complex_dt", "tUInt16", poDDL); + // test complex data type + InserStructElement("test_complex_dt", "tHeaderStruct", poDDL); + // test enum type + InserStructElement("test_complex_dt", "test_enum", poDDL); + + // calculate the byte positions + DDLComplex* pComplexDT = poDDL->getStructByName("test_complex_dt"); + DDLInspector oInspector(false); + oInspector.visitDDL(poDDL); + oInspector.InitNewCheck(); + oInspector.setAutoCorrect(true), + oInspector.visit(pComplexDT); + } + + a_util::filesystem::Path strTargetFile("test_insert_results.description"); + if (a_util::filesystem::exists(strTargetFile)) + { + a_util::filesystem::remove(strTargetFile); + } + + DDLPrinter oPrinter; + ASSERT_EQ(a_util::result::SUCCESS, oPrinter.visitDDL(poDDL)); + ASSERT_EQ(a_util::result::SUCCESS, oPrinter.toFile(strTargetFile.toString())); + a_util::result::Result res = CompOutput(strTargetFile.toString(), "files/test_insert_results_ref.description"); + a_util::filesystem::remove(strTargetFile); + ASSERT_EQ(a_util::result::SUCCESS, res); + + oDDLImporter.destroyDDL(); + poDDL = NULL; + +} + +/** +* @detail Test import from invalid description file. +* Read an invalid_numbits_attribute.description file and build up the object representation. +*/ +TEST(cTesterDDLRep, + TestImportInvalidNumbitsAttributeWithArray) +{ + TEST_REQ("ACORE-6472"); + + DDLImporter oDDLImporter; + ASSERT_TRUE((ERR_NOT_INITIALIZED == oDDLImporter.createNew())) << + "Uninitialized status of the DDLImporter not detected."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setFile("files/invalid_numbits_attribute.description")) << + "Could not load invalid_numbits_attribute.description file."; + ASSERT_EQ(ERR_INVALID_ARG , oDDLImporter.createNew()); + // free allocated resources + oDDLImporter.destroyDDL(); + +} + +/** +* @detail Test inspection of an invalid description file. +* Try to inspect a complex structure which is invalid due to a misplaced numbits attribute. +* Passed if an error occurs on visiting a complex structure which is invalid and thus not existing. +*/ +TEST(cTesterDDLRep, + TestInspectInvalidNumbitsAttributeWithArray) +{ + TEST_REQ("ACORE-6472"); + + DDLImporter oDDLImporter; + ASSERT_TRUE((ERR_NOT_INITIALIZED == oDDLImporter.createNew())) << + "Uninitialized status of the DDLImporter not detected."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setFile("files/invalid_numbits_attribute.description")) << + "Could not load invalid_numbits_attribute.description file."; + ASSERT_EQ(ERR_INVALID_ARG , oDDLImporter.createNew()); + + DDLInspector oInspector; + DDLDescription *pDDLDesc = oDDLImporter.getDDL(); + ASSERT_TRUE(NULL !=pDDLDesc); + + ASSERT_EQ(ERR_POINTER , oInspector.visit(pDDLDesc->getStructByName("ObjectFusiontAssociation"))); + + // free allocated resources + oDDLImporter.destroyDDL(); + +} + +void TestDDL40(const DDLDescription* pDDL) +{ + const DDLComplex* pStruct = pDDL->getStructByName("tTest"); + ASSERT_TRUE(pStruct); + ASSERT_EQ(pStruct->getDDLVersion() , ddl::DDLVersion::ddl_version_20); + const DDLElementVec& oElements = pStruct->getElements(); + ASSERT_EQ(oElements.size() , 4); + + ASSERT_EQ(oElements[0]->getName() , "bBool"); + ASSERT_EQ(oElements[0]->getByteorder() , DDLByteorder::plattform_little_endian_8); + ASSERT_EQ(oElements[0]->getBytepos() , 0); + ASSERT_EQ(oElements[0]->getBitpos() , 0); + ASSERT_EQ(oElements[0]->getNumBits() , 8); + ASSERT_EQ(oElements[0]->getAlignment() , 1); + + ASSERT_EQ(oElements[3]->getName() , "fFloat32"); + ASSERT_EQ(oElements[3]->getByteorder() , DDLByteorder::plattform_little_endian_8); + ASSERT_EQ(oElements[3]->getBytepos() , 6); + ASSERT_EQ(oElements[3]->getBitpos() , 0); + ASSERT_EQ(oElements[3]->getNumBits() , 32); + ASSERT_EQ(oElements[3]->getAlignment() , 4); + + const DDLStreamMetaType* pStreamMetaType = pDDL->getStreamMetaTypeByName("adtf/default"); + ASSERT_TRUE(pStreamMetaType); + ASSERT_EQ(pStreamMetaType->getVersion() , "1"); + ASSERT_EQ(pStreamMetaType->getParent() , ""); + ASSERT_TRUE(pStreamMetaType->getParentObject() == NULL); + ASSERT_EQ(pStreamMetaType->getProperties().size() , 2); + ASSERT_EQ(pStreamMetaType->getProperties()[0]->getName() , "md_struct"); + ASSERT_EQ(pStreamMetaType->getProperties()[0]->getType() , "string"); + ASSERT_EQ(pStreamMetaType->getProperties()[1]->getName() , "md_definitions"); + ASSERT_EQ(pStreamMetaType->getProperties()[1]->getType() , "string"); + const DDLStreamMetaType* pADTFDefault = pStreamMetaType; + + pStreamMetaType = pDDL->getStreamMetaTypeByName("test_parent_not_yet_defined"); + ASSERT_TRUE(pStreamMetaType); + ASSERT_EQ(pStreamMetaType->getVersion() , "1"); + ASSERT_EQ(pStreamMetaType->getParent() , "adtf/default"); + ASSERT_EQ(pStreamMetaType->getParentObject() , pADTFDefault); + ASSERT_TRUE(pStreamMetaType->getProperties().empty()); + + pStreamMetaType = pDDL->getStreamMetaTypeByName("test"); + ASSERT_TRUE(pStreamMetaType); + ASSERT_EQ(pStreamMetaType->getVersion() , "1"); + ASSERT_EQ(pStreamMetaType->getParent() , "adtf/default"); + ASSERT_EQ(pStreamMetaType->getParentObject() , pADTFDefault); + ASSERT_EQ(pStreamMetaType->getProperties().size() , 1); + ASSERT_EQ(pStreamMetaType->getProperties()[0]->getName() , "test_prop"); + ASSERT_EQ(pStreamMetaType->getProperties()[0]->getType() , "tInt32"); +} + +/** +* @detail Test the building up of a DDL object representation in Version 4.0 +* Read an adtf.description file and build up the object representation +*/ +TEST(cTesterDDLRep, + TestVersion40) +{ + TEST_REQ("ACORE-7704 CDPKGDDL-14"); + + a_util::memory::unique_ptr pDDL; + + { + DDLImporter oDDLImporter; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setFile("files/adtf_v40.description")) << + "Could not load adtf_v40.description file."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.createNew()) << + "Creation of object hierarchy failed."; + pDDL.reset(oDDLImporter.getDDL()); + ASSERT_TRUE( (NULL !=pDDL.get())) << "Invalid DDL object retrieved."; + TestDDL40(pDDL.get()); + } + + DDLPrinter oPrinter; + ASSERT_EQ(a_util::result::SUCCESS, oPrinter.visitDDL(pDDL.get())); + + { + DDLImporter oDDLImporter; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.setXML(oPrinter.getXML())) << + "Could not load adtf_v40.description file."; + ASSERT_EQ(a_util::result::SUCCESS,oDDLImporter.createNew()) << + "Creation of object hierarchy failed."; + pDDL.reset(oDDLImporter.getDDL()); + ASSERT_TRUE( (NULL !=pDDL.get())) << "Invalid DDL object retrieved."; + TestDDL40(pDDL.get()); + } +} + +/** +* @detail Test the building up of a DDL object representation from manually set information +*/ +TEST(cTesterDDLRep, + TestManualCreation) +{ + TEST_REQ("CDPKGDDL-63"); + + std::unique_ptr pDescription(DDLDescription::createDefault(ddl::DDLVersion::ddl_version_invalid)); + auto pTestStruct = new DDLComplex("test", 1); + ASSERT_EQ(pTestStruct->getDDLVersion(), DDLVersion::getDefaultVersion()); + pDescription->addStruct(pTestStruct); + + pTestStruct = new DDLComplex("test_version", 1, "", DDLAlignment::e1, DDLElementVec(), 1, ddl::DDLVersion::ddl_version_30); + ASSERT_EQ(pTestStruct->getDDLVersion(), ddl::DDLVersion::ddl_version_30); + pDescription->addStruct(pTestStruct); + + DDLPrinter oPrinter; + oPrinter.visitDDL(pDescription.get()); + a_util::xml::DOM oDom; + ASSERT_EQ(a_util::result::SUCCESS, oDom.fromString(oPrinter.getXML())); + + a_util::xml::DOMElement oStructNode; + ASSERT_EQ(a_util::result::SUCCESS, oDom.findNode("//struct[@name='test']", oStructNode)); + ASSERT_EQ(oStructNode.getAttribute("ddlversion"), DDLVersion::getDefaultVersion().toString()); + ASSERT_EQ(a_util::result::SUCCESS, oDom.findNode("//struct[@name='test_version']", oStructNode)); + ASSERT_EQ(ddl::DDLVersion::fromString(oStructNode.getAttribute("ddlversion")), + ddl::DDLVersion::ddl_version_30); +} + +/** +* @detail Test DDL with special chars in names, special characters + _ . / should be supported. +*/ +TEST(cTesterDDLRep, + TestSpecialChars) +{ + TEST_REQ("CDDDL-43"); + + DDLImporter oDDLImporter; + std::string strXML(DDL_TEST_STRING_SPECIAL_NAMES); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setXML(strXML)) << + "Could not set XML string."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()) << "Creation of DDL failed."; + auto ddl = oDDLImporter.getDDL(); + ASSERT_TRUE((NULL != oDDLImporter.getDDL())) << "Invalid DDL object retrieved."; + + auto special_struct = ddl->getStructByName("name_with+special/characters"); + ASSERT_TRUE(NULL != special_struct); + + + ASSERT_EQ(special_struct->getName(), "name_with+special/characters"); + + for (auto element : special_struct->getElements()) + { + if (a_util::strings::compare("ui32/MajorType", element->getName().c_str()) == 0) + { + continue; + } + else if (a_util::strings::compare("ui32_Sub+Type", element->getName().c_str()) == 0) + { + continue; + } + else if (a_util::strings::compare("ui32.Flags", element->getName().c_str()) == 0) + { + continue; + } + else + { + auto err_msg = a_util::strings::format("Unexpected element name: '%s'", element->getName().c_str()); + ASSERT_TRUE(false) << err_msg.c_str(); + } + } + + DDLInspector oInspector; + ASSERT_TRUE(a_util::result::SUCCESS == oInspector.visitDDL(ddl)); + + // free allocated resources + oDDLImporter.destroyDDL(); + +} + +/** +* @detail Test if changing the size of static size arrays works. +* Strategy: - Load DDL with static sized array +* - Change size of array. +* - Print DDL description as xml +* - import generated description +* - Check if DDL has updated array size +*/ +TEST(cTesterDDLRep, + TestChangeStaticArraySize) +{ + TEST_REQ("CDDDL-35"); + + std::string updatedDDL; + { + DDLImporter oDDLImporter; + std::string strXML(DDL_TEST_STRING_STATIC_ARRAY); + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setXML(strXML)) << + "Could not set XML string."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()) << "Creation of DDL failed."; + auto ddl = oDDLImporter.getDDL(); + ASSERT_TRUE((NULL != oDDLImporter.getDDL())) << "Invalid DDL object retrieved."; + + auto array_struct = ddl->getStructByName("tStaticArray"); + ASSERT_TRUE(NULL != array_struct); + + auto array_element = array_struct->getElements()[0]; + + ASSERT_TRUE(NULL != array_element); + + ASSERT_EQ(8, array_element->getArraysize()); + + // change arraysize + array_element->setArraysize(16); + + ASSERT_EQ(16, array_element->getArraysize()); + + DDLPrinter oPrinter; + oPrinter.visitDDL(ddl); + + updatedDDL = oPrinter.getXML(); + + oDDLImporter.destroyDDL(); + } + + // import the exported description + { + DDLImporter oDDLImporter; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setXML(updatedDDL)) << + "Could not set XML string."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()) << "Creation of DDL failed."; + auto ddl = oDDLImporter.getDDL(); + ASSERT_TRUE((NULL != oDDLImporter.getDDL())) << "Invalid DDL object retrieved."; + + auto array_struct = ddl->getStructByName("tStaticArray"); + ASSERT_TRUE(NULL != array_struct); + + auto array_element = array_struct->getElements()[0]; + + ASSERT_TRUE(NULL != array_element); + + ASSERT_EQ(16, array_element->getArraysize()); + } + +} + +/** +* @detail Test the identification of dynamic objects in a DDL object representation +* by reading strings and build up object representations. +*/ +TEST(cTesterDDLRep, + TestHasDynamicArrays) +{ + TEST_REQ("ACORE-3904"); + + /* Import DDL without dynamic structures*/ + DDLImporter oDDLImporter; + ASSERT_TRUE((ERR_NOT_INITIALIZED == oDDLImporter.createNew())) << + "Uninitialized status of the DDLImporter not detected."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.setFile("files/adtf.description")) << + "Could not load adtf.description file."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporter.createNew()) << + "Creation of object hierarchy failed."; + DDLDescription * poDDL = oDDLImporter.getDDL(); + + ASSERT_FALSE(poDDL->hasDynamicStructs()); + + // free allocated resources + oDDLImporter.destroyDDL(); + + /* Import DDL with dynamic structures*/ + DDLImporter oDDLImporterDyn; + ASSERT_TRUE((ERR_NOT_INITIALIZED == oDDLImporterDyn.createNew())) << + "Uninitialized status of the DDLImporter not detected."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporterDyn.setFile("files/adtf_dynamic.description")) << + "Could not load adtf_dynamic.description file."; + ASSERT_EQ(a_util::result::SUCCESS, oDDLImporterDyn.createNew()) << + "Creation of object hierarchy failed."; + DDLDescription * poDDLDyn = oDDLImporterDyn.getDDL(); + + ASSERT_TRUE(poDDLDyn->hasDynamicStructs()) << "DDL should contain dynamic structs"; + + // free allocated resources + oDDLImporterDyn.destroyDDL(); +} diff --git a/test/function/api/src/CMakeLists.txt b/test/function/api/src/CMakeLists.txt new file mode 100644 index 0000000..bcad26e --- /dev/null +++ b/test/function/api/src/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable(tester_ddl_type_api test_fixture_ddl_types.h tester_ddl_types.cpp) +set_target_properties(tester_ddl_type_api PROPERTIES FOLDER test/ddl/api) +target_link_libraries(tester_ddl_type_api PRIVATE ddl_test_compat + ddl + GTest::Main) + +add_test(tester_ddl_type_api tester_ddl_type_api) +set_target_properties(tester_ddl_type_api PROPERTIES TIMEOUT 10) \ No newline at end of file diff --git a/test/function/api/src/test_fixture_ddl_types.h b/test/function/api/src/test_fixture_ddl_types.h new file mode 100644 index 0000000..6545d3c --- /dev/null +++ b/test/function/api/src/test_fixture_ddl_types.h @@ -0,0 +1,54 @@ +#ifndef DDL_LIBRARY_TEST_FUNCTION_API_TEST_FIXTURE_DDL_TYPES_HEADER_INCLUDED_ +#define DDL_LIBRARY_TEST_FUNCTION_API_TEST_FIXTURE_DDL_TYPES_HEADER_INCLUDED_ + +#include +#include + +class DDLTypesTestFixture : public ::testing::Test +{ +public: + template + bool isCopyable(Args&&... args) const noexcept + { + // copyable compile time check + static_assert(std::is_copy_constructible::value, "Not copy constructible"); + static_assert(std::is_copy_assignable::value, "Not copy assignable"); + + // copyable runtime functionality + const DDLType copy_source(std::forward(args)...); + DDLType copy_sink(copy_source); + copy_sink = copy_sink.operator=(copy_source); + return true; + } + + template + bool isMovable(Args&&...) const noexcept + { + static_assert(std::is_move_constructible::value, "Not move constructible"); + static_assert(std::is_move_assignable::value, "Not move assignable"); + + // TODO: Add check for valid move during runtime + return true; + } + + template + bool isNotCopyable(Args&&... args) const noexcept + { + // copyable compile time check + static_assert(!std::is_copy_constructible::value, "Copy constructible"); + static_assert(!std::is_copy_assignable::value, "Copy assignable"); + return true; + } + + template + bool isNotMovable(Args&&...) const noexcept + { + static_assert(!std::is_move_constructible::value, "Move constructible"); + static_assert(!std::is_move_assignable::value, "Move assignable"); + + // TODO: Add check for valid move during runtime + return true; + } +}; + +#endif // DDL_LIBRARY_TEST_FUNCTION_API_TEST_FIXTURE_DDL_TYPES_HEADER_INCLUDED_ \ No newline at end of file diff --git a/test/function/api/src/tester_ddl_types.cpp b/test/function/api/src/tester_ddl_types.cpp new file mode 100644 index 0000000..358623e --- /dev/null +++ b/test/function/api/src/tester_ddl_types.cpp @@ -0,0 +1,283 @@ +#include "ddl.h" +#include "test_fixture_ddl_types.h" + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDL) +{ + TEST_REQ("CDDDL-89"); + struct DDLMOC : public ddl::DDL + { + using Result = a_util::result::Result; + Result accept(ddl::IDDLChangeVisitor*) override { return a_util::result::SUCCESS; } + Result accept(ddl::IDDLVisitor*) const override { return a_util::result::SUCCESS; } + const std::string& getName() const override { return _name; } + + private: + std::string _name; + }; + + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLAlignment) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLBaseunit) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLByteorder) +{ + TEST_REQ("CDDDL-89"); + struct DDLByteOrderMOC : public ddl::DDLByteorder + { + using Result = a_util::result::Result; + Result accept(ddl::IDDLChangeVisitor*) override { return a_util::result::SUCCESS; } + Result accept(ddl::IDDLVisitor*) const override { return a_util::result::SUCCESS; } + const std::string& getName() const override { return _name; } + + private: + std::string _name; + }; + + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLComplex) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLDataType) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLAutoVec) +{ + TEST_REQ("CDDDL-89"); + struct DeleteTester : public ddl::DDLElement + { + DeleteTester() { ++DeleteTester::not_deleted(); } + ~DeleteTester() { --DeleteTester::not_deleted(); } + static int& not_deleted() { static int count{}; return count; } + }; + + { + std::vector elements(10, nullptr); + std::for_each(elements.begin(), elements.end(), [](DeleteTester*& element) { + element = new DeleteTester(); + }); + EXPECT_TRUE(isCopyable>(&elements)); + EXPECT_TRUE(isMovable>(&elements)); + } + EXPECT_EQ(DeleteTester::not_deleted(), 0); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLCloner) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLCompare) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLContainerNoClone) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable>()); + EXPECT_TRUE(isMovable>()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLContainer) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable>()); + EXPECT_TRUE(isMovable>()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLDescription) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isNotCopyable(nullptr)); + EXPECT_TRUE(isMovable(nullptr)); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLElement) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLEnum) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLError) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLExtDeclaration) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLHeader) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLImporter) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLInspector) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLPrefix) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLPrinter) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLProperty) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLRefUnit) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLRepair) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLResolver) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLStream) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLStreamMetaType) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLStreamStruct) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLUnit) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDDLVersion) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsStaticDecoder) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isNotCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsDecoder) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isNotCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsCodec) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isNotCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsStaticCodec) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isNotCopyable()); + EXPECT_TRUE(isMovable()); +} + +TEST_F(DDLTypesTestFixture, testCopyAndMoveSemanticsCodecFactory) +{ + TEST_REQ("CDDDL-89"); + EXPECT_TRUE(isCopyable()); + EXPECT_TRUE(isMovable()); +} diff --git a/test/headerrepresentation/files/adtf2.description b/test/headerrepresentation/files/adtf2.description new file mode 100644 index 0000000..54e16b5 --- /dev/null +++ b/test/headerrepresentation/files/adtf2.description @@ -0,0 +1,137 @@ + + +
+ 2.00 + AUDI Electronics Venture GmbH + 07.04.2010 + 07.04.2010 + ADTF Common Description File +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/adtf_expected.h b/test/headerrepresentation/files/adtf_expected.h new file mode 100644 index 0000000..7910bec --- /dev/null +++ b/test/headerrepresentation/files/adtf_expected.h @@ -0,0 +1,113 @@ +// This is a generated file, changes to it may be overwritten in the future. + +typedef enum { + PF_UNKNOWN=0, + PF_8BIT=10, + PF_GREYSCALE_8=11, + PF_RGB_8=12, + PF_16BIT=20, + PF_GREYSCALE_10=21, + PF_GREYSCALE_12=22, + PF_GREYSCALE_14=23, + PF_GREYSCALE_16=24, + PF_RGB_444=25, + PF_RGB_555=26, + PF_RGB_565=27, + PF_RGBA_4444=28, + PF_ABGR_4444=29, + PF_RIII_10=30, + PF_RIII_12=31, + PF_RIII_14=32, + PF_RIII_16=33, + PF_BGR_555=34, + PF_BGR_565=35, + PF_24BIT=40, + PF_GREYSCALE_18=41, + PF_GREYSCALE_20=42, + PF_GREYSCALE_22=43, + PF_GREYSCALE_24=44, + PF_RGB_888=45, + PF_BGR_888=46, + PF_32BIT=50, + PF_ARGB_8888=51, + PF_ABGR_8888=52, + PF_RGBA_8888=53, + PF_BGRA_8888=54, + PF_GREYSCALE_32=55, + PF_GREYSCALE_FLOAT32=56, + PF_YUV420P_888=60, + PF_CUSTOM=1000 +} tPixelFormat; + +#pragma pack(push,1) +typedef struct +{ + tUInt32 ui32MajorType; + tUInt32 ui32SubType; + tUInt32 ui32Flags; +} tMediaTypeInfo; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo mediatype; +} adtf_core_media_type; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nWidth; + tInt32 nHeight; + tInt16 nBitsPerPixel; + tPixelFormat nPixelFormat; + tInt32 nBytesPerLine; + tInt32 nSize; + tInt32 nPaletteSize; +} tBitmapFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tInt32 nFormatType; + tInt32 nChannels; + tInt32 nSamplesPerSec; + tInt32 nBitsPerSample; + tInt32 nNumSamples; + tInt32 nSize; +} tWaveFormat; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tBitmapFormat sBitmapFormat; +} adtf_type_video; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tMediaTypeInfo sMediatype; + tWaveFormat sWaveFormat; +} adtf_type_audio; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef int32_t tInt32; + +typedef int16_t tInt16; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// int32_t + +// The following type is assumed to be known: +// int16_t + diff --git a/test/headerrepresentation/files/array_header.h b/test/headerrepresentation/files/array_header.h new file mode 100644 index 0000000..8d94341 --- /dev/null +++ b/test/headerrepresentation/files/array_header.h @@ -0,0 +1,31 @@ +struct simple_array_struct +{ + tUInt8 a[5]; +}; + +struct simple_struct1 +{ + tUInt8 b; +}; + +struct complex_array_struct1 +{ + tUInt8 c; + simple_struct1 d; + simple_array_struct f; + simple_struct1 g[6]; + simple_array_struct h[7]; +}; + +#define count1 8 +const tUInt8 count2 = 9; + +struct complex_array_struct2 +{ + tUInt8 i[count1]; + simple_struct1 j; + simple_array_struct k; + simple_struct1 l[count2]; + simple_array_struct m[10]; +}; + diff --git a/test/headerrepresentation/files/array_header_expected.description b/test/headerrepresentation/files/array_header_expected.description new file mode 100644 index 0000000..35cfcc3 --- /dev/null +++ b/test/headerrepresentation/files/array_header_expected.description @@ -0,0 +1,110 @@ + + +
+ 3.00 + ANOAFR4 + 11.04.2016 + 11.04.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/array_header_expected.h b/test/headerrepresentation/files/array_header_expected.h new file mode 100644 index 0000000..a9afc89 --- /dev/null +++ b/test/headerrepresentation/files/array_header_expected.h @@ -0,0 +1,52 @@ +// This is a generated file, changes to it may be overwritten in the future. + +#pragma pack(push,1) +typedef struct +{ + tUInt8 a[5]; +} simple_array_struct; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tUInt8 b; +} simple_struct1; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tUInt8 c; + simple_struct1 d; + simple_array_struct f; + simple_struct1 g[6]; + simple_array_struct h[7]; +} complex_array_struct1; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tUInt8 i[8]; + simple_struct1 j; + simple_array_struct k; + simple_struct1 l[9]; + simple_array_struct m[10]; +} complex_array_struct2; +#pragma pack(pop) + +const tUInt64 count1 = 8; + +const tUInt8 count2 = 9; + +typedef uint8_t tUInt8; + +typedef uint64_t tUInt64; + +// The following type is assumed to be known: +// uint8_t + +// The following type is assumed to be known: +// uint64_t + diff --git a/test/headerrepresentation/files/commented_header.h b/test/headerrepresentation/files/commented_header.h new file mode 100644 index 0000000..2367384 --- /dev/null +++ b/test/headerrepresentation/files/commented_header.h @@ -0,0 +1,38 @@ +// struct simple_struct0 +struct /*oh my god, a comment*/ simple_struct1 +// struct simple_struct5 +{ + /*oh my god, a comment*/ tUInt8 /*oh my god, a comment*/ a /*oh my god, a comment*/;/*oh my god, a comment// dammit*/ //; tUInt b; + /*oh my god, a comment* tUInt8 ***** / *oh my god, a comment/ a *oh my god, a comment*;*oh my god, a comment// dammit*/ //; tUInt c; +}/*Comments!!!!!*/; + + +typedef/*oh my god, a comment*/ struct +{/*oh my god, a comment*//*oh my god, a comment*/ + /*oh my god, a comment*/tUInt16/*oh my god, a comment*/ b;/*oh my god, a comment*/ +} /*oh my god, a comment*/simple_struct2/*oh my god, a comment*/;/*oh my god, a comment*/ + + +typedef /*oh my god, a comment*//*oh my god, a comment*/struct/*oh my god, a comment*//*oh my god, a comment*/ simple_struct3/*oh my god, a comment*//*oh my god, a comment*//*oh my god, a comment*/ +{/*oh my god, a comment*/ + /*oh my god, a comment*/ tUInt32 /*oh my god, a comment*/c; +} /*oh my god, a comment*/simple_struct4;/*oh my god, a comment*/ + +/* +typedef struct +{ + tUInt16 b; +} simple_struct5; +*/ + +//const tInt16 f = 42; +/*const tInt16 g = 42;*/ +/*oh my god, a comment*/const/*oh my god, a comment*/tInt16/*oh my god, a comment*//*oh my god, a comment*/d/*oh my god, a comment*/=/*oh my god, a comment*/42/*oh my god, a comment*/;/*oh my god, a comment*//*oh my god, a comment*/ +const/*oh my god, a comment*/tInt32 e/*oh my god, a comment*/=/*oh my god, a comment*/43;/*oh my god, a comment*/ + +/*oh my god, a comment*/#define constant1 /*This will compile*/ 6 /*...maybe*/ + +/*oh my god, a comment*/typedef/*oh my god, a comment*/tUInt32/*oh my god, a comment*/UINT_32/*oh my god, a comment*/; +/*oh my god, a comment*/typedef tUInt16 /*oh my god, a comment*/UINT_16; //Hello World +//typedef uint64 supergross2; +/*typedef uint64 supergross3;*/ \ No newline at end of file diff --git a/test/headerrepresentation/files/complex_header.h b/test/headerrepresentation/files/complex_header.h new file mode 100644 index 0000000..51e4801 --- /dev/null +++ b/test/headerrepresentation/files/complex_header.h @@ -0,0 +1,28 @@ +struct simple_struct1 +{ + tUInt8 a; +}; + +typedef struct +{ + tUInt16 b; +} simple_struct2; + +typedef struct simple_struct3 +{ + tUInt32 c; +} simple_struct4; + +typedef struct +{ + tUInt16 a; + simple_struct1 b; + simple_struct3 c; +} complex_struct1; + +typedef struct +{ + simple_struct1 d; + simple_struct3 e; + complex_struct1 f; +} complex_struct2; \ No newline at end of file diff --git a/test/headerrepresentation/files/complex_header_expected.description b/test/headerrepresentation/files/complex_header_expected.description new file mode 100644 index 0000000..2981138 --- /dev/null +++ b/test/headerrepresentation/files/complex_header_expected.description @@ -0,0 +1,119 @@ + + +
+ 3.00 + ANOAFR4 + 11.04.2016 + 11.04.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/complex_header_expected.h b/test/headerrepresentation/files/complex_header_expected.h new file mode 100644 index 0000000..6d2176c --- /dev/null +++ b/test/headerrepresentation/files/complex_header_expected.h @@ -0,0 +1,58 @@ +// This is a generated file, changes to it may be overwritten in the future. + +#pragma pack(push,4) +typedef struct +{ + tUInt32 c; +} simple_struct3; +#pragma pack(pop) + +typedef simple_struct3 simple_struct4; + +#pragma pack(push,1) +typedef struct +{ + tUInt8 a; +} simple_struct1; +#pragma pack(pop) + +#pragma pack(push,2) +typedef struct +{ + tUInt16 b; +} simple_struct2; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 a; + simple_struct1 b; + simple_struct3 c; +} complex_struct1; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + simple_struct1 d; + simple_struct3 e; + complex_struct1 f; +} complex_struct2; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef uint8_t tUInt8; + +typedef uint16_t tUInt16; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// uint8_t + +// The following type is assumed to be known: +// uint16_t + diff --git a/test/headerrepresentation/files/complex_struct2_expected.description b/test/headerrepresentation/files/complex_struct2_expected.description new file mode 100644 index 0000000..2a7aaa5 --- /dev/null +++ b/test/headerrepresentation/files/complex_struct2_expected.description @@ -0,0 +1,116 @@ + + +
+ 3.00 + ANOAFR4 + 11.04.2016 + 11.04.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/constants_header.h b/test/headerrepresentation/files/constants_header.h new file mode 100644 index 0000000..4214da0 --- /dev/null +++ b/test/headerrepresentation/files/constants_header.h @@ -0,0 +1,7 @@ + + +const tInt16 d = 42; + + + +const tInt32 e = 43; \ No newline at end of file diff --git a/test/headerrepresentation/files/default_types_header.h b/test/headerrepresentation/files/default_types_header.h new file mode 100644 index 0000000..758f1ea --- /dev/null +++ b/test/headerrepresentation/files/default_types_header.h @@ -0,0 +1,5 @@ +struct doubles +{ + tUInt8 a; + tFloat64 b; +}; \ No newline at end of file diff --git a/test/headerrepresentation/files/defines_header.h b/test/headerrepresentation/files/defines_header.h new file mode 100644 index 0000000..c9a1345 --- /dev/null +++ b/test/headerrepresentation/files/defines_header.h @@ -0,0 +1,26 @@ +// inclusion protection should not be a problem since #22594 +#ifndef DEFINES_HEADER_H__ +#define DEFINES_HEADER_H__ + +// empty macro followed by another one shouldn't be a problem either since #22594 +#define SOME_MACRO_WITHOUT_VALUE1 +#define SOME_MACRO_WITHOUT_VALUE2 +#define SOME_MACRO_WITHOUT_VALUE3 +#define FIRST_CONSTANT 5 +#define OTHER_CONSTANT 6 +#define SOME_MACRO_WITHOUT_VALUE4 +#define SOME_MACRO_WITHOUT_VALUE5 +#define LAST_CONSTANT 7 + +// This was copied from RDB header +/** @addtogroup ARRAY_SIZES + * ------ array sizes ------ + * @{ + */ +#define RDB_SIZE_OBJECT_NAME 32 /**< m */ +#define RDB_SIZE_SCP_NAME 64 /**< maximum length of an SCP sender / receiver @version 0x010C */ +#define RDB_SIZE_FILENAME 1024 /**< number of bytes in a filename (may include path) @version 0x0100 */ +#define RDB_SIZE_TRLIGHT_PHASES 8 /**< maximum number of phases for a traffic light @version 0x0100 */ +/** @} */ + +#endif /* DEFINES_HEADER_H__ */ diff --git a/test/headerrepresentation/files/faulty_header1.h b/test/headerrepresentation/files/faulty_header1.h new file mode 100644 index 0000000..0c0cd8e --- /dev/null +++ b/test/headerrepresentation/files/faulty_header1.h @@ -0,0 +1,5 @@ +#define constant1 5 or better 6, i am not sure +#define constant2 5+4 +#define constant3 +#define constant4 \ +5 \ No newline at end of file diff --git a/test/headerrepresentation/files/faulty_header2.h b/test/headerrepresentation/files/faulty_header2.h new file mode 100644 index 0000000..8138f3b --- /dev/null +++ b/test/headerrepresentation/files/faulty_header2.h @@ -0,0 +1,4 @@ +// Unnamed struct +struct { + tInt8 a; +}; \ No newline at end of file diff --git a/test/headerrepresentation/files/faulty_header3.h b/test/headerrepresentation/files/faulty_header3.h new file mode 100644 index 0000000..084b52d --- /dev/null +++ b/test/headerrepresentation/files/faulty_header3.h @@ -0,0 +1,4 @@ +// Wrong type of member +struct wrong_member { + tInt9 a; +}; diff --git a/test/headerrepresentation/files/faulty_header4.h b/test/headerrepresentation/files/faulty_header4.h new file mode 100644 index 0000000..9a1eb69 --- /dev/null +++ b/test/headerrepresentation/files/faulty_header4.h @@ -0,0 +1,4 @@ +// Unnamed struct +struct { + tInt8 a; +} unnamed_struct_var; diff --git a/test/headerrepresentation/files/faulty_header5.h b/test/headerrepresentation/files/faulty_header5.h new file mode 100644 index 0000000..269931c --- /dev/null +++ b/test/headerrepresentation/files/faulty_header5.h @@ -0,0 +1,9 @@ +typedef a; + +// Unknown type +typedef tUInt9 who_the_fuck_is_tUInt9; + +// Weird typedef +typedef struct not_ok{ + tInt8 a; +}; \ No newline at end of file diff --git a/test/headerrepresentation/files/packing_header.h b/test/headerrepresentation/files/packing_header.h new file mode 100644 index 0000000..9970d9b --- /dev/null +++ b/test/headerrepresentation/files/packing_header.h @@ -0,0 +1,31 @@ +#pragma pack(push, 4) +struct simple_struct1 +{ + tUInt8 a; +}; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + tUInt16 b; +} simple_struct2; +#pragma pack(pop) + +#pragma pack(push, 2) +typedef struct simple_struct3 +{ + tUInt32 c; +} simple_struct4; + +typedef struct +{ + tUInt64 d; +} simple_struct5; +#pragma pack(pop) + +#pragma pack(1) +typedef struct +{ + tUInt64 e; +} simple_struct6; diff --git a/test/headerrepresentation/files/packing_header_expected.description b/test/headerrepresentation/files/packing_header_expected.description new file mode 100644 index 0000000..7731531 --- /dev/null +++ b/test/headerrepresentation/files/packing_header_expected.description @@ -0,0 +1,34 @@ + + +
+ 3.00 + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/test/headerrepresentation/files/packing_header_expected.h b/test/headerrepresentation/files/packing_header_expected.h new file mode 100644 index 0000000..c57c291 --- /dev/null +++ b/test/headerrepresentation/files/packing_header_expected.h @@ -0,0 +1,59 @@ +// This is a generated file, changes to it may be overwritten in the future. + +#pragma pack(push,2) +typedef struct +{ + tUInt32 c; +} simple_struct3; +#pragma pack(pop) + +typedef simple_struct3 simple_struct4; + +#pragma pack(push,1) +typedef struct +{ + tUInt8 a; +} simple_struct1; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tUInt16 b; +} simple_struct2; +#pragma pack(pop) + +#pragma pack(push,2) +typedef struct +{ + tUInt64 d; +} simple_struct5; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ + tUInt64 e; +} simple_struct6; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef uint8_t tUInt8; + +typedef uint16_t tUInt16; + +typedef uint64_t tUInt64; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// uint8_t + +// The following type is assumed to be known: +// uint16_t + +// The following type is assumed to be known: +// uint64_t + diff --git a/test/headerrepresentation/files/simple_header.h b/test/headerrepresentation/files/simple_header.h new file mode 100644 index 0000000..e614435 --- /dev/null +++ b/test/headerrepresentation/files/simple_header.h @@ -0,0 +1,19 @@ +// For type # see implementation of cHeaderImporter::BuildStructs() + +// Type #1 +struct simple_struct1 +{ + uint8_t a; +}; + +// Type #2 +typedef struct +{ + tUInt16 b; +} simple_struct2; + +// Type #3 +typedef struct simple_struct3 +{ + unsigned int c; +} simple_struct4; \ No newline at end of file diff --git a/test/headerrepresentation/files/simple_header_expected.description b/test/headerrepresentation/files/simple_header_expected.description new file mode 100644 index 0000000..53757a5 --- /dev/null +++ b/test/headerrepresentation/files/simple_header_expected.description @@ -0,0 +1,40 @@ + + +
+ 3.00 + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/simple_header_expected.h b/test/headerrepresentation/files/simple_header_expected.h new file mode 100644 index 0000000..fc8661f --- /dev/null +++ b/test/headerrepresentation/files/simple_header_expected.h @@ -0,0 +1,38 @@ +// This is a generated file, changes to it may be overwritten in the future. + +#pragma pack(push,4) +typedef struct +{ + unsigned int c; +} simple_struct3; +#pragma pack(pop) + +typedef simple_struct3 simple_struct4; + +#pragma pack(push,1) +typedef struct +{ + uint8_t a; +} simple_struct1; +#pragma pack(pop) + +#pragma pack(push,2) +typedef struct +{ + tUInt16 b; +} simple_struct2; +#pragma pack(pop) + +typedef uint32_t unsigned int; + +// The following type is assumed to be known: +// uint8_t + +typedef uint16_t tUInt16; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// uint16_t + diff --git a/test/headerrepresentation/files/simple_header_result.description b/test/headerrepresentation/files/simple_header_result.description new file mode 100644 index 0000000..c65f2fc --- /dev/null +++ b/test/headerrepresentation/files/simple_header_result.description @@ -0,0 +1,109 @@ + + +
+ 3.00 + titm724 + 06.09.2013 + 06.09.2013 + Generated by ADTF 2.10.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/typedef_header.h b/test/headerrepresentation/files/typedef_header.h new file mode 100644 index 0000000..89e3e4a --- /dev/null +++ b/test/headerrepresentation/files/typedef_header.h @@ -0,0 +1,5 @@ +typedef tUInt32 UINT_32; +typedef tUInt16 UINT_16; +typedef tUInt64 UINT_64; +typedef UINT_64 uint64; +typedef uint64 supergross; \ No newline at end of file diff --git a/test/headerrepresentation/files/typedef_header_expected.h b/test/headerrepresentation/files/typedef_header_expected.h new file mode 100644 index 0000000..79d4ffa --- /dev/null +++ b/test/headerrepresentation/files/typedef_header_expected.h @@ -0,0 +1,27 @@ +// This is a generated file, changes to it may be overwritten in the future. + +typedef tUInt32 UINT_32; + +typedef tUInt16 UINT_16; + +typedef tUInt64 UINT_64; + +typedef UINT_64 uint64; + +typedef uint64 supergross; + +typedef uint32_t tUInt32; + +typedef uint16_t tUInt16; + +typedef uint64_t tUInt64; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// uint16_t + +// The following type is assumed to be known: +// uint64_t + diff --git a/test/headerrepresentation/files/viRDBIcd.description b/test/headerrepresentation/files/viRDBIcd.description new file mode 100644 index 0000000..0c4e8eb --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd.description @@ -0,0 +1,551 @@ + + +
+ 3.00 + titm724 + 17.09.2013 + 17.09.2013 + Generated by ADTF 2.10.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/test/headerrepresentation/files/viRDBIcd.h b/test/headerrepresentation/files/viRDBIcd.h new file mode 100644 index 0000000..a6da8e0 --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd.h @@ -0,0 +1,1737 @@ +/*****************************************************//** + * @file + * ICD of the Runtime Data Bus (RDB) + * + * (c) VIRES GmbH + * @author Marius Dupuis + ********************************************************/ + +/*****************************************************/ +/** + @page RDB_CHANGE_LOG RDB Change Log +- 10.07.2013 version still 0x0110 + added RDB_PKG_ID_TRAJECTORY and accompanying definitions +- 08.07.2013 version 0x0110 + added OpenGL conform RDB image pix formats + old formats now deprecated +- 02.07.2013 version 0x0110 + added RDB_OBJECT_VIS_FLAG_RECORDER + added RDB_COORD_TYPE_RELATIVE_START + added empty or cast definitions for + RDB_END_OF_FRAME_t + RDB_START_OF_FRAME_t + added RDB_OBJECT_CATEGORY_OPENDRIVE +- 22.04.2013 version 0x010F + added RDB_DRIVER_SOURCE definitions + added RDB_SHM_ID_TC_IN + added RDB_SHM_ID_TC_OUT + added RDB_SHM_SIZE_TC +- 13.02.2013 version still 0x010E + added shared memory identifier RDB_SHM_ID_CONTROL_GENERATOR_IN + added control commands for sync message (RDB_SYNC_CMD_xxx) + used a spare of RDB_SYNC_t +- 22.01.2013 version 0x010E + added path s-coordinate to RDB_ROAD_POS_t + added RDB_PKG_FLAG_HIDDEN +- 27.12.2012 version 0x010D + converted spare variable to "type" in structure RDB_LANE_INFO_t + extended range of road mark IDs +- 18.12.2012 version still 0x010C (by H.H.) + added message type RDB_PKG_ID_OPTIX_BUFFER ( RDBInterface plugin ) +- 03.12.2012: version 0x010C +- added package type RDB_PKG_ID_SCP and associated structure +- 15.11.2012: version still 0x010B +- improved description of occlusion +- 10.10.2012: version still 0x010B +- added RDB_ROAD_TYPE definitions and member "type" in RDB_ROAD_POS_t +- 02.10.2012: version still 0x010B +- introduced RDB_LIGHT_SOURCE_FLAG_STENCIL +- introduced RDB_COORD_TYPE_TEXTURE +- 01.10.2012: version set to 0x010B +- activated one spare parameter in RDB_VEHICLE_SYSTEMS_t +- 18.09.2012: version set to 0x010A +- added further gearbox positions +- added flags for mockup inputs: RDB_MOCKUP_INPUT0_, RDB_MOCKUP_INPUT1_, RDB_MOCKUP_INPUT2_ +- introduced mockup input flags in RDB_DRIVER_CTRL_t +- 06.09.2012: version set to 0x0109 +- corrected frameNo type mismatch +- 27.08.2012: version set to 0x0108 +- added RDB_OBJECT_TYPE_PLAYER_TRAILER +- added "spare0" in RDB_LANE_INFO_t between "status" and "width" +- to comply with 4-byte alignment. The space has been there before +- due to the compiler and is now adressable. So, don't panic! Your +- "old" code should still work. +- 06.08.2012: version set to 0x0107 +- added RDB_PKG_ID_ROAD_QUERY and associated structures +- 04.07.2012: added definition RDB_PIX_FORMAT_BW_32 + added definition RDB_PIX_FORMAT_RGB_32 + added definition RDB_PIX_FORMAT_RGBA_32 +- version set to 0x0106 +- 01.05.2012: added some driver control flags (headlight etc.) +- version set to 0x0105 +- 17.04.2012: corrected comment in RDB_OBJECT_CFG_t +- 12.04.2012: introduced RDB_DRIVER_INPUT_VALIDITY_ADD_ON +- 26.03.2012: set version to 0x0104 +- added sourceId in structure RDB_DRIVER_CTRL_t (converted one spare uint8 for this) +- 28.02.2012: set version to 0x0103 +- set occlusion in SENSOR_OBJECT_t to type int8_t instead of uint8_t +- introduced RDB_OBJECT_CATEGORY_COMMON +- introduced RDB_OBJECT_TYPE_NONE +- 09.02.2012: introduced RDB_ENV_FLAG_STREET_LAMPS +- 31.01.2012: introduced RDB_LIGHT_SOURCE_FLAG_PERSISTENT +- 22.01.2012: set version to 0x0102 +- introduced RDB_CONTACT_POINT_FLAG_... +- 10.12.2011: set version to 0x0101 +- modified definition of co-ordinate systems +- RDB_COORD_TYPE_DEFAULT has become RDB_COORD_TYPE_INERTIAL +- RDB_COORD_TYPE_INERTIAL has become RDB_COORD_TYPE_RESERVED_1 +- 17.11.2011: introduced RDB_COORD_TYPE_WINDOW +- 03.11.2011: converted two spares in RDB_ENGINE_EXT_t into variables +- for current and average fuel consumptions +- 10.10.2011: inserted RDB_GEAR_BOX_POS_5 +- 15.09.2011: added definition RDB_PIX_FORMAT_DEPTH_32 +- 16.08.2011: introduced "parent" as member in OBJECT_STATE_BASE_t +- introduced RDB_OBJECT_CATEGORY_LIGHT_POINT +- 02.08.2011: added flags for direction info to RDB_ROAD_POS_t +- 14.07.2011: added playerId to LANE_INFO +- 10.07.2011: added steeringWheelTorque to VEHICLE_SYSTEMS +- 08.07.2011: introduced RDB_DRIVER_INPUT_VALIDITY_INFO_ONLY +- 07.07.2011: introduced visMask in RDB_OBJECT_STATE_t +- 28.06.2011: introduced structure RDB_FUNCTION_t +- introduced packages RDB_PKG_ID_LIGHT_MAP and +- RDB_PKG_ID_TONE_MAPPING +- 30.05.2011: introduced member "material" in RDB_LANE_INFO_t +- introduced member "addOnId" in RDB_TRAFFIC_SIGN_t; this shall +- point to a sign which extends the original sign; 0 for no extension +- 20.05.2011: fixed a GSI typo, added RDB_PIX_FORMAT_CUSTOM_01 +- 17.05.2011: added some picture formats +- 18.04.2011: introduced RDB_PKG_ID_DRIVER_PERCEPTION +- 31.03.2011: introduced RDB_PKG_ID_SYNC +- introduced RDB_OBJECT_CFG_FLAG +- 14.03.2011: updated comment fields of @unit +- added shared memory header +- 07.03.2011: deleted "throttlePos" from RDB_ENGINE_EXT_t since +- "load" is already in BASE package +- introduced "RDB_DRIVER_INPUT_VALIDITY_CURVATURE" and +- curvatureTgt in "RDB_DRIVER_CTRL_t" +- introduced "RDB_DRIVER_INPUT_VALIDITY_STEERING_TORQUE" and +- steeringTorque in "RDB_DRIVER_CTRL_t" +- introduced "RDB_DRIVER_INPUT_VALIDITY_ENGINE_TORQUE" and +- engineTorqueTgt in "RDB_DRIVER_CTRL_t" +- introduced "RDB_DRIVER_INPUT_VALIDITY_SPEED" and +- speedTgt in "RDB_DRIVER_CTRL_t" +- increased "validityFlags" in "RDB_DRIVER_CTRL_t" from +- 16 to 32 bit. +- RDB_WHEEL_BASE_t: replaced "deflZ" with "springCompression" +- RDB_WHEEL_EXT_t: deleted "springCompression" +- 09.02.2011: initial version will be 0x0100 +- 01 = major version +- 00 = minor version +- major version will change when binary +- incompatibility is imminent, otherwise +- minor version will change +- 08.02.2011: fixed minor bug in wheel structure +- set initial revision to 0x000E +- 14.01.2011: replaced "class" with "category" +- 18.11.2010: added feedback from review +- modified general remarks +- 28.10.2010: added feedback from review +- added general remarks +- 17.08.2010: draft version 0x0100 +- 03.08.2010: derived from GSI version 0x000D++ +*********************************************************/ + +/** +*

General Remarks:

+* +*

Introduction:

+* +* RDB contains a wide variety of packages, most of which +* are (potentially) well suited for most applications. +* Nevertheless, several things have to be noted: +* - not all applications will use or provide +* all sorts of packages +* - when a package is provided all of its elements must +* be filled with valid data (in case of doubt, initialize +* the packages with 0 before filling the respective data) +* - some packages are specialized so that they work +* well only in certain environments; these packages +* bear the string "CUSTOM" in their name and have +* IDs in the range 10000-19999 +* +* +*

Packages with Trailing Data:

+* +* Some packages may be followed by trailing data of flexible size. +* In this case, a package itself contains information about the +* number of bytes that will follow the original package. The +* type and content of the trailing data depend on the package +* type. +* +* +*

Extended Information:

+* +* Packages are defined for maximum flexibility. This means +* that for the complete description of a complex object more +* data may be required than for a simple object of comparable +* type. +* +* Therefore, the information about an object may be contained +* in a basic structure followed immediately - within the same +* package - by an additional information block (so-called extension). +* In the respective package's header (of type RDB_MSG_ENTRY_HDR_t) +* the member "flags" will have the flag RDB_PKG_FLAG_EXTENDED set +* in case of an extended package. +* +* Note that if multiple elements of the same package type are +* packed in a package vector, all of these elements must be +* either of basic type or of extended type. Mixing these types +* is not allowed. +* +* For easier casting of basic and extended packages, containers +* are provided which provide one member of the basic information +* followed by one member holding the extended information. +* +* The following package extensions are possible: +* +*

A) OBJECTS (PKG ID = RDB_PKG_ID_OBJECT_STATE)

+* +* information about a static object (e.g. obstacle): +* package contains only +* RDB_OBJECT_STATE_BASE_t +* +* information about a dynamic object (e.g. vehicle) +* package contains +* RDB_OBJECT_STATE_BASE_t +* followed by +* RDB_OBJECT_STATE_EXT_t +* +* casting structure: +* @code +* { +* RDB_OBJECT_STATE_BASE_t base; +* RDB_OBJECT_STATE_EXT_t ext; +* } RDB_OBJECT_STATE_t; +* @endcode +* +*

B) WHEELS (PKG ID = RDB_PKG_ID_WHEEL)

+* +* basic information about a wheel: +* package contains only +* RDB_WHEEL_BASE_t +* +* extended information about a wheel +* package contains +* RDB_WHEEL_BASE_t +* followed by +* RDB_WHEEL_EXT_t +* +* casting structure: +* @code +* { +* RDB_WHEEL_BASE_t base; +* RDB_WHEEL_EXT_t ext; +* } RDB_WHEEL_t; +* @endcode +* +* +*

C) ENGINE (PKG ID = RDB_PKG_ID_ENGINE)

+* +* basic information about an engine: +* package contains only +* RDB_ENGINE_BASE_t +* +* extended information about an engine +* package contains +* RDB_ENGINE_BASE_t +* followed by +* RDB_ENGINE_EXT_t +* +* casting structure: +* @code +* { +* RDB_ENGINE_BASE_t base; +* RDB_ENGINE_EXT_t ext; +* } RDB_ENGINE_t; +* @endcode +* +* +*

D) DRIVETRAIN (PKG ID = RDB_PKG_ID_DRIVETRAIN)

+* +* basic information about a drivetrain: +* package contains only +* RDB_DRIVETRAIN_BASE_t +* +* extended information about a drivetrain +* package contains +* RDB_DRIVETRAIN_BASE_t +* followed by +* RDB_DRIVETRAIN_EXT_t +* +* casting structure: +* @code +* { +* RDB_DRIVETRAIN_BASE_t base; +* RDB_DRIVETRAIN_EXT_t ext; +* } RDB_DRIVETRAIN_t; +* @endcode +* +* +*

E) TRAFFIC LIGHT (PKG ID = RDB_PKG_ID_TRAFFIC_LIGHT)

+* +* basic information about a traffic light: +* package contains only +* RDB_TRAFFIC_LIGHT_BASE_t +* +* extended information about a traffic light +* package contains +* RDB_TRAFFIC_LIGHT_BASE_t +* followed by +* RDB_TRAFFIC_LIGHT_EXT_t +* +* casting structure: +* @code +* { +* RDB_TRAFFIC_LIGHT_BASE_t base; +* RDB_TRAFFIC_LIGHT_EXT_t ext; +* } RDB_TRAFFIC_LIGHT_t; +* @endcode +*/ + +#pragma pack (push, 4) + +#ifndef _VIRES_RDB_ICD_H +#define _VIRES_RDB_ICD_H + +// includes for 64bit compatibility +#include +#include + + +/** @addtogroup GENERAL_DEFINITIONS + * @{ + */ +#define RDB_DEFAULT_PORT 48190 /**< default port for RDB communication @version 0x0100 */ +#define RDB_FEEDBACK_PORT 48191 /**< port for RDB feedback to taskControl @version 0x0100 */ +#define RDB_IMAGE_PORT 48192 /**< port for RDB image data @version 0x0100 */ +#define RDB_MAGIC_NO 35712 /**< magic number @version 0x0100 */ +#define RDB_VERSION 0x0110 /**< upper byte = major, lower byte = minor @version 0x010C */ +/** @} */ + +/** @addtogroup ARRAY_SIZES + * ------ array sizes ------ + * @{ + */ +#define RDB_SIZE_OBJECT_NAME 32 /**< maximum length of an object's name @version 0x0100 */ +#define RDB_SIZE_SCP_NAME 64 /**< maximum length of an SCP sender / receiver @version 0x010C */ +#define RDB_SIZE_FILENAME 1024 /**< number of bytes in a filename (may include path) @version 0x0100 */ +#define RDB_SIZE_TRLIGHT_PHASES 8 /**< maximum number of phases for a traffic light @version 0x0100 */ +/** @} */ + + +/** @addtogroup ENUM_DEFINITIONS + * ------ Enum Definitions ------ + * @{ + */ +/** @addtogroup RDB_PKG_ID + * ------ message types ------ + * @{ + */ +#define RDB_PKG_ID_START_OF_FRAME 1 /**< sent as first package of a simulation frame @version 0x0100 */ +#define RDB_PKG_ID_END_OF_FRAME 2 /**< sent as last package of a simulation frame @version 0x0100 */ +#define RDB_PKG_ID_COORD_SYSTEM 3 /**< defines a (custom) co-ordinate system @version 0x0100 */ +#define RDB_PKG_ID_COORD 4 /**< single co-ordinate extending previous object information @version 0x0100 */ +#define RDB_PKG_ID_ROAD_POS 5 /**< detailed road position of a given entity @version 0x0100 */ +#define RDB_PKG_ID_LANE_INFO 6 /**< lane information for a given entity @version 0x0100 */ +#define RDB_PKG_ID_ROADMARK 7 /**< road mark information of a player (typically EGO) @version 0x0100 */ +#define RDB_PKG_ID_OBJECT_CFG 8 /**< object configuration information @version 0x0100 */ +#define RDB_PKG_ID_OBJECT_STATE 9 /**< state of a standard (static) object @version 0x0100 */ +#define RDB_PKG_ID_VEHICLE_SYSTEMS 10 /**< vehicle systems' states (lights etc.) @version 0x0100 */ +#define RDB_PKG_ID_VEHICLE_SETUP 11 /**< basic information about a vehicle (mass etc.) @version 0x0100 */ +#define RDB_PKG_ID_ENGINE 12 /**< info about a vehicle's engine @version 0x0100 */ +#define RDB_PKG_ID_DRIVETRAIN 13 /**< info about a vehicle's drivetrain @version 0x0100 */ +#define RDB_PKG_ID_WHEEL 14 /**< info about a wheel of a player @version 0x0100 */ +#define RDB_PKG_ID_PED_ANIMATION 15 /**< pedestrian animation details (joint angles etc.) @version 0x0100 */ +#define RDB_PKG_ID_SENSOR_STATE 16 /**< state (position etc.) of a sensor @version 0x0100 */ +#define RDB_PKG_ID_SENSOR_OBJECT 17 /**< information about an object registered within a sensor @version 0x0100 */ +#define RDB_PKG_ID_CAMERA 18 /**< camera parameters corresponding to video image @version 0x0100 */ +#define RDB_PKG_ID_CONTACT_POINT 19 /**< road data at a given contact point @version 0x0100 */ +#define RDB_PKG_ID_TRAFFIC_SIGN 20 /**< info about traffic signs objects @version 0x0100 */ +#define RDB_PKG_ID_ROAD_STATE 21 /**< road state information for a given player @version 0x0100 */ +#define RDB_PKG_ID_IMAGE 22 /**< video image @version 0x0100 */ +#define RDB_PKG_ID_LIGHT_SOURCE 23 /**< light source information @version 0x0100 */ +#define RDB_PKG_ID_ENVIRONMENT 24 /**< environment information @version 0x0100 */ +#define RDB_PKG_ID_TRIGGER 25 /**< trigger info for next simulation frame @version 0x0100 */ +#define RDB_PKG_ID_DRIVER_CTRL 26 /**< info about mockup or from driver module as input for dynamics @version 0x0100 */ +#define RDB_PKG_ID_TRAFFIC_LIGHT 27 /**< information about a traffic lights and their states @version 0x0100 */ +#define RDB_PKG_ID_SYNC 28 /**< synchronization with external RDB client @version 0x0100 */ +#define RDB_PKG_ID_DRIVER_PERCEPTION 29 /**< driver perception @version 0x0100 */ +#define RDB_PKG_ID_LIGHT_MAP 30 /**< light map for a headlight @version 0x0100 */ +#define RDB_PKG_ID_TONE_MAPPING 31 /**< tone mapping function @version 0x0100 */ +#define RDB_PKG_ID_ROAD_QUERY 32 /**< co-ordinates of an explicit ODR road query @version 0x0107 */ +#define RDB_PKG_ID_SCP 33 /**< SCP package via RDB @version 0x010C */ +#define RDB_PKG_ID_TRAJECTORY 34 /**< trajectory for path planning @version 0x0110 */ + + + +/** @} */ + +/** @addtogroup RDB_PKG_ID_CUSTOM + * ------ custom message types, not to be expected in "standard" simulations ------ + * @{ + */ +#define RDB_PKG_ID_CUSTOM_SCORING 10000 /**< parameters for driver scoring (efficiency, safety, race etc.) @version 0x0100 */ +#define RDB_PKG_ID_CUSTOM_AUDI_FORUM 12000 /**< parameters for AUDI Forum @version 0x0100 */ +#define RDB_PKG_ID_CUSTOM_OPTIX_START 12100 /**< start of custom packages for OPTIX applications @version 0x0100 */ +#define RDB_PKG_ID_OPTIX_BUFFER 12101 /**< custom optix buffer for RDBInterface Plugin @version 0x010C */ +#define RDB_PKG_ID_CUSTOM_OPTIX_END 12149 /**< end of custom packages for OPTIX applications @version 0x0100 */ +#define RDB_PKG_ID_CUSTOM_USER_A_START 12150 /**< start of custom packages for user A @version 0x0106 */ +#define RDB_PKG_ID_CUSTOM_USER_A_END 12174 /**< end of custom packages for user A @version 0x0106 */ +/** @} */ + +/** @addtogroup RDB_OBJECT_CATEGORY + * ------ object types ------ + * @{ + */ +#define RDB_OBJECT_CATEGORY_NONE 0 /**< no category defined @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_PLAYER 1 /**< category is player @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_SENSOR 2 /**< category is sensor @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_CAMERA 3 /**< category is camera @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_LIGHT_POINT 4 /**< category is light point @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_COMMON 5 /**< category is common object @version 0x0100 */ +#define RDB_OBJECT_CATEGORY_OPENDRIVE 6 /**< category is OpenDRIVE object @version 0x0110 */ +/** @} */ + +/** @addtogroup RDB_OBJECT_TYPE + * ------ object types ------ + * @{ + */ +#define RDB_OBJECT_TYPE_NONE 0 /**< undefined object type for categories other than player @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_NONE 0 /**< undefined player type @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_CAR 1 /**< player of type car @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_TRUCK 2 /**< player of type truck @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_VAN 3 /**< player of type van @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_BIKE 4 /**< player of type bicycle @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_PEDESTRIAN 5 /**< player of type pedestrian @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_PED_GROUP 6 /**< player of type pedestrian group @version 0x0100 */ +#define RDB_OBJECT_TYPE_POLE 7 /**< pole @version 0x0100 */ +#define RDB_OBJECT_TYPE_TREE 8 /**< tree @version 0x0100 */ +#define RDB_OBJECT_TYPE_BARRIER 9 /**< barrier @version 0x0100 */ +#define RDB_OBJECT_TYPE_OPT1 10 /**< optional user type 1 @version 0x0100 */ +#define RDB_OBJECT_TYPE_OPT2 11 /**< optional user type 2 @version 0x0100 */ +#define RDB_OBJECT_TYPE_OPT3 12 /**< optional user type 3 @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_MOTORBIKE 13 /**< player of type motorbike @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_BUS 14 /**< player of type bus @version 0x0100 */ +#define RDB_OBJECT_TYPE_STREET_LAMP 15 /**< street lamp @version 0x0100 */ +#define RDB_OBJECT_TYPE_TRAFFIC_SIGN 16 /**< traffic sign @version 0x0100 */ +#define RDB_OBJECT_TYPE_HEADLIGHT 17 /**< headlights @version 0x0100 */ +#define RDB_OBJECT_TYPE_PLAYER_TRAILER 18 /**< player of type trailer @version 0x0108 */ + +/** @} */ + +/** @addtogroup RDB_LANE_BORDER + * ------ lane border types ------ + * @{ + */ +#define RDB_LANE_BORDER_UNKNOWN 0 /**< unknown border type @version 0x0100 */ +#define RDB_LANE_BORDER_NONE 1 /**< no border @version 0x0100 */ +#define RDB_LANE_BORDER_POLE 2 /**< pole border @version 0x0100 */ +#define RDB_LANE_BORDER_BARRIER 3 /**< barrier border @version 0x0100 */ +#define RDB_LANE_BORDER_SOFT_SHOULDER 4 /**< soft shoulder border @version 0x0100 */ +#define RDB_LANE_BORDER_HARD_SHOULDER 5 /**< hard shoulder border @version 0x0100 */ +#define RDB_LANE_BORDER_CURB 6 /**< curb border */ +/** @} */ + +/** @addtogroup RDB_ROADMARK_TYPE + * ------ road mark types ------ + * @{ + */ +#define RDB_ROADMARK_TYPE_NONE 0 /**< no roadmark defined @version 0x0100 */ +#define RDB_ROADMARK_TYPE_SOLID 1 /**< solid marks @version 0x0100 */ +#define RDB_ROADMARK_TYPE_BROKEN 2 /**< broken marks @version 0x0100 */ +#define RDB_ROADMARK_TYPE_CURB 3 /**< curb @version 0x0100 */ +#define RDB_ROADMARK_TYPE_GRASS 4 /**< grass @version 0x0100 */ +#define RDB_ROADMARK_TYPE_BOTDOT 5 /**< Botts' dots @version 0x0100 */ +#define RDB_ROADMARK_TYPE_OTHER 6 /**< something else @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_ROADMARK_COLOR + * ------ road mark colors ------ + * @{ + */ +#define RDB_ROADMARK_COLOR_NONE 0 /**< no color defined @version 0x0100 */ +#define RDB_ROADMARK_COLOR_WHITE 1 /**< white color @version 0x0100 */ +#define RDB_ROADMARK_COLOR_RED 2 /**< red color @version 0x0100 */ +#define RDB_ROADMARK_COLOR_YELLOW 3 /**< yellow color @version 0x0100 */ +#define RDB_ROADMARK_COLOR_OTHER 4 /**< other color @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_WHEEL_ID + * ------ wheel indices ------ + * @{ + */ +#define RDB_WHEEL_ID_FRONT_LEFT 0 /**< increase ID clockwise; next one is front right wheel (not on trikes) @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_GEAR_BOX_TYPE + * ------ gear box types ------ + * @{ + */ +#define RDB_GEAR_BOX_TYPE_AUTOMATIC 0 /**< automatic gear shift @version 0x0100 */ +#define RDB_GEAR_BOX_TYPE_MANUAL 1 /**< manual gear shift @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_GEAR_BOX_POS + * ------ gear box positions ------ + * @{ + */ +#define RDB_GEAR_BOX_POS_AUTO 0 /**< gear set to automatic @version 0x0100 */ +#define RDB_GEAR_BOX_POS_P 1 /**< park @version 0x0100 */ +#define RDB_GEAR_BOX_POS_R 2 /**< reverse @version 0x0100 */ +#define RDB_GEAR_BOX_POS_N 3 /**< neutral @version 0x0100 */ +#define RDB_GEAR_BOX_POS_D 4 /**< drive @version 0x0100 */ +#define RDB_GEAR_BOX_POS_1 5 /**< 1st gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_2 6 /**< 2nd gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_3 7 /**< 3rd gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_4 8 /**< 4th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_5 9 /**< 5th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_6 10 /**< 6th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_7 11 /**< 7th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_8 12 /**< 8th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_9 13 /**< 9th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_10 14 /**< 10th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_11 15 /**< 11th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_12 16 /**< 12th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_13 17 /**< 13th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_14 18 /**< 14th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_15 19 /**< 15th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_16 20 /**< 16th gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_R1 21 /**< 1st reverse gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_R2 22 /**< 2nd reverse gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_R3 23 /**< 3rd reverse gear @version 0x0100 */ +#define RDB_GEAR_BOX_POS_M 24 /**< manual shift position (tiptronic) @version 0x010A */ +#define RDB_GEAR_BOX_POS_M_UP 25 /**< manual shift up @version 0x010A */ +#define RDB_GEAR_BOX_POS_M_DOWN 26 /**< manual shift down @version 0x010A */ +/** @} */ + +/** @addtogroup RDB_DRIVETRAIN_TYPE + * ------ drivetrain types ------ + * @{ + */ +#define RDB_DRIVETRAIN_TYPE_FRONT 0 /**< front-wheel drive @version 0x0100 */ +#define RDB_DRIVETRAIN_TYPE_REAR 1 /**< rear-wheel drive @version 0x0100 */ +#define RDB_DRIVETRAIN_TYPE_AWD 2 /**< all-wheel drive @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_PIX_FORMAT + * ------ image pixel formats ------ + * @{ + */ +#define RDB_PIX_FORMAT_RGB 0 /**< deprecated: use RDB_PIX_FORMAT_R3_G2_B2 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGB_16 1 /**< deprecated: use RDB_PIX_FORMAT_R5_G6_B5 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGB_24 2 /**< deprecated: use RDB_PIX_FORMAT_RGB8 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGBA 3 /**< deprecated: use RDB_PIX_FORMAT_R3_G2_B2_A8 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGBA_16 4 /**< deprecated: use RDB_PIX_FORMAT_R5_G6_B5_A16 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGBA_24 5 /**< deprecated: use RDB_PIX_FORMAT_RGB8_A24 @version 0x0100 */ +#define RDB_PIX_FORMAT_BW_8 6 /**< deprecated: use RDB_PIX_FORMAT_RED8 @version 0x0100 */ +#define RDB_PIX_FORMAT_BW_16 7 /**< deprecated: use RDB_PIX_FORMAT_RED16 @version 0x0100 */ +#define RDB_PIX_FORMAT_BW_24 8 /**< deprecated: use RDB_PIX_FORMAT_RED24 @version 0x0100 */ +#define RDB_PIX_FORMAT_DEPTH_8 9 /**< deprecated: use RDB_PIX_FORMAT_DEPTH8 @version 0x0100 */ +#define RDB_PIX_FORMAT_DEPTH_16 10 /**< deprecated: use RDB_PIX_FORMAT_DEPTH16 @version 0x0100 */ +#define RDB_PIX_FORMAT_DEPTH_24 11 /**< deprecated: use RDB_PIX_FORMAT_DEPTH24 @version 0x0100 */ +#define RDB_PIX_FORMAT_RGB_32_F 12 /**< deprecated: use RDB_PIX_FORMAT_RGB32F @version 0x0100 */ +#define RDB_PIX_FORMAT_RGBA_32_F 13 /**< deprecated: use RDB_PIX_FORMAT_RGBA32F @version 0x0100 */ +#define RDB_PIX_FORMAT_LUM_32_F 14 /**< deprecated: use RDB_PIX_FORMAT_RED32F @version 0x0100 */ +#define RDB_PIX_FORMAT_LUMA_32_F 15 /**< deprecated: use RDB_PIX_FORMAT_RG32F @version 0x0100 */ +#define RDB_PIX_FORMAT_RGB_16_F 16 /**< deprecated: use RDB_PIX_FORMAT_RGB16F @version 0x0100 */ +#define RDB_PIX_FORMAT_RGBA_16_F 17 /**< deprecated: use RDB_PIX_FORMAT_RGBA16F @version 0x0100 */ +#define RDB_PIX_FORMAT_LUM_16_F 18 /**< deprecated: use RDB_PIX_FORMAT_RED16F @version 0x0100 */ +#define RDB_PIX_FORMAT_LUMA_16_F 19 /**< deprecated: use RDB_PIX_FORMAT_RG16F @version 0x0100 */ +#define RDB_PIX_FORMAT_DEPTH_32 20 /**< deprecated: use RDB_PIX_FORMAT_DEPTH32 @version 0x0101 */ +#define RDB_PIX_FORMAT_BW_32 21 /**< deprecated: use RDB_PIX_FORMAT_RED32 @version 0x0106 */ +#define RDB_PIX_FORMAT_RGB_32 22 /**< 32 bit RGB data @version 0x0106 */ +#define RDB_PIX_FORMAT_RGBA_32 23 /**< 32 bit RGB data + 32 bit alpha @version 0x0106 */ + +#define RDB_PIX_FORMAT_R3_G2_B2 24 /**< 8 bit RGB data @version 0x010F */ +#define RDB_PIX_FORMAT_R3_G2_B2_A8 25 /**< 8 bit RGB data + 8 bit alpha @version 0x010F */ +#define RDB_PIX_FORMAT_R5_G6_B5 26 /**< 16 bit RGB data @version 0x010F */ +#define RDB_PIX_FORMAT_R5_G6_B5_A16 27 /**< 16 bit RGB data + 16 bit alpha @version 0x010F */ +#define RDB_PIX_FORMAT_RED8 28 /**< 8 bit RED data @version 0x010F */ +#define RDB_PIX_FORMAT_RED16 29 /**< 16 bit RED data @version 0x010F */ +#define RDB_PIX_FORMAT_RED16F 30 /**< 16 bit RED floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RED24 31 /**< 24 bit RED data @version 0x010F */ +#define RDB_PIX_FORMAT_RED32 32 /**< 32 bit RED data @version 0x010F */ +#define RDB_PIX_FORMAT_RED32F 33 /**< 32 bit RED floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RG8 34 /**< 16 bit RED+GREEN data @version 0x010F */ +#define RDB_PIX_FORMAT_RG16 35 /**< 32 bit RED+GREEN data @version 0x010F */ +#define RDB_PIX_FORMAT_RG16F 36 /**< 32 bit RED+GREEN floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RG32 37 /**< 64 bit RED+GREEN floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RG32F 38 /**< 64 bit RED+GREEN floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RGB8 39 /**< 24 bit RGB data @version 0x010F */ +#define RDB_PIX_FORMAT_RGBA8 40 /**< 24 bit RGB data + 8 bit alpha @version 0x010F */ +#define RDB_PIX_FORMAT_RGB8_A24 41 /**< 24 bit RGB data + 24 bit alpha @version 0x010F */ +#define RDB_PIX_FORMAT_RGB16 42 /**< 48 bit RGB data @version 0x010F */ +#define RDB_PIX_FORMAT_RGB16F 43 /**< 48 bit RGB floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RGBA16 44 /**< 64 bit RGBA data @version 0x010F */ +#define RDB_PIX_FORMAT_RGBA16F 45 /**< 64 bit RGBA floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RGB32 46 /**< 96 bit RGB data @version 0x010F */ +#define RDB_PIX_FORMAT_RGB32F 47 /**< 96 bit RGB floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_RGBA32 48 /**< 128 bit RGBA data @version 0x010F */ +#define RDB_PIX_FORMAT_RGBA32F 49 /**< 128 bit RGBA floating point data @version 0x010F */ +#define RDB_PIX_FORMAT_DEPTH8 50 /**< 8 bit DEPTH data @version 0x010F */ +#define RDB_PIX_FORMAT_DEPTH16 51 /**< 16 bit DEPTH data @version 0x010F */ +#define RDB_PIX_FORMAT_DEPTH24 52 /**< 24 bit DEPTH data @version 0x010F */ +#define RDB_PIX_FORMAT_DEPTH32 53 /**< 32 bit DEPTH data @version 0x010F */ + +/** @} */ + +/** @addtogroup RDB_PIX_FORMAT_CUSTOM + * ------ custom pixel formats (any ID above 150 up to 255) may be used ------ + * @{ + */ +#define RDB_PIX_FORMAT_CUSTOM_01 151 /**< custom image format 01 @version 0x0100 */ +#define RDB_PIX_FORMAT_CUSTOM_02 152 /**< custom image format 02 @version 0x0100 */ +#define RDB_PIX_FORMAT_CUSTOM_03 153 /**< custom image format 03 @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_SENSOR_TYPE + * ------ sensor types ------ + * @{ + */ +#define RDB_SENSOR_TYPE_NONE 0 /**< unknown sensor type @version 0x0100 */ +#define RDB_SENSOR_TYPE_RADAR 1 /**< radar sensor @version 0x0100 */ +#define RDB_SENSOR_TYPE_VIDEO 2 /**< video sensor @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_TRLIGHT_PHASE + * ------ traffic light phases ------ + * @{ + */ +#define RDB_TRLIGHT_PHASE_OFF 0 /**< traffic light is off @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_STOP 1 /**< traffic indicates STOP @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_STOP_ATTN 2 /**< traffic indicates STOP/ATTENTION @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_GO 3 /**< traffic indicates GO @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_GO_EXCL 4 /**< traffic indicates GO EXCLUSIVELY @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_ATTN 5 /**< traffic indicates ATTENTION @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_BLINK 6 /**< traffic indicates BLINK @version 0x0100 */ +#define RDB_TRLIGHT_PHASE_UNKNOWN 7 /**< traffic indicates an unknown state @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_COORD_TYPE + * ------ co-ordinate type identifiers ------ + * @{ + */ +#define RDB_COORD_TYPE_INERTIAL 0 /**< inertial co-ordinate system @version 0x0101 */ +#define RDB_COORD_TYPE_RESERVED_1 1 /**< reserved for future use @version 0x0101 */ +#define RDB_COORD_TYPE_PLAYER 2 /**< player co-ordinate system @version 0x0100 */ +#define RDB_COORD_TYPE_SENSOR 3 /**< sensor-specific co-ordinate system @version 0x0100 */ +#define RDB_COORD_TYPE_USK 4 /**< universal sensor co-ordinate system @version 0x0100 */ +#define RDB_COORD_TYPE_USER 5 /**< relative to a user co-ordinate system @version 0x0100 */ +#define RDB_COORD_TYPE_WINDOW 6 /**< window co-ordinates [pixel] @version 0x0100 */ +#define RDB_COORD_TYPE_TEXTURE 7 /**< texture co-ordinates [normalized] @version 0x010C */ +#define RDB_COORD_TYPE_RELATIVE_START 8 /**< co-ordinate relative to start pos. @version 0x0110 */ +/** @} */ + +/** @addtogroup RDB_ENV_CLOUD_STATE + * ------ cloud states ------ + * @{ + */ +#define RDB_ENV_CLOUD_STATE_OFF 0 /**< sky is disabled @version 0x0100 */ +#define RDB_ENV_CLOUD_STATE_0_8 1 /**< blue sky @version 0x0100 */ +#define RDB_ENV_CLOUD_STATE_4_8 2 /**< cloudy sky @version 0x0100 */ +#define RDB_ENV_CLOUD_STATE_6_8 3 /**< overcast sky @version 0x0100 */ +#define RDB_ENV_CLOUD_STATE_8_8 4 /**< rainy sky @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_FUNCTION_TYPE + * ------ function types ------ + * @{ + */ +#define RDB_FUNCTION_TYPE_NONE 0 /**< unknown @version 0x0100 */ +#define RDB_FUNCTION_TYPE_TONE_MAPPING 1 /**< tone mapping function @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_ROAD_TYPE + * ------ road types ------ + * @{ + */ +#define RDB_ROAD_TYPE_UNKNOWN 0 /**< unknown @version 0x010A */ +#define RDB_ROAD_TYPE_RURAL 1 /**< rural road (100km/h in Germany) @version 0x010A */ +#define RDB_ROAD_TYPE_MOTORWAY 2 /**< motorway (no limit in Germany) @version 0x010A */ +#define RDB_ROAD_TYPE_TOWN 3 /**< town (50km/h in Germany) @version 0x010A */ +#define RDB_ROAD_TYPE_LOW_SPEED 4 /**< low speed zone (30km/h in Germany) @version 0x010A */ +#define RDB_ROAD_TYPE_PEDESTRIAN 5 /**< sidewalk (slow, worldwide) @version 0x010A */ +/** @} */ + +/** @addtogroup RDB_DRIVER_SOURCE + * ------ sources of driver commands ------ + * @{ + */ +#define RDB_DRIVER_SOURCE_UNKNOWN 0 /**< unknown @version 0x010F */ +#define RDB_DRIVER_SOURCE_GHOSTDRIVER 1 /**< ghostdriver @version 0x010F */ +/** @} */ + +/** @addtogroup RDB_SHM_SIZE + * ------ shared memory sizes ------ + * @{ + */ +#define RDB_SHM_SIZE_TC 5242880 /**< total SHM size for TC I/O (5 MB) @version 0x010F */ +/** @} */ + +/** @} --END GROUP ENUM_DEFINITIONS--*/ + + +/** @addtogroup BITMASK_DEFINITIONS + * ------ Bitmask Definitions ------ + * @{ + */ +/** @addtogroup RDB_PKG_FLAG + * ------ basic package flags ------ + * @{ + */ +#define RDB_PKG_FLAG_NONE 0x0000 /**< no flags @version 0x0100 */ +#define RDB_PKG_FLAG_EXTENDED 0x0001 /**< package contains extended information @version 0x0100 */ +#define RDB_PKG_FLAG_HIDDEN 0x0002 /**< package contains hidden information (not for public) @version 0x010E */ +/** @} */ + +/** @addtogroup RDB_OBJECT_VIS_FLAG + * ------ object visibility flags ------ + * @{ + */ +#define RDB_OBJECT_VIS_FLAG_ALL 0xffff /**< all visibility flags set @version 0x0100 */ +#define RDB_OBJECT_VIS_FLAG_NONE 0x0000 /**< no visibility flags set @version 0x0100 */ +#define RDB_OBJECT_VIS_FLAG_GFX 0x0001 /**< object is visible in graphics @version 0x0100 */ +#define RDB_OBJECT_VIS_FLAG_TRAFFIC 0x0002 /**< object is visible for traffic @version 0x0100 */ +#define RDB_OBJECT_VIS_FLAG_RECORDER 0x0004 /**< object is visible on data recorder @version 0x0110 */ +/** @} */ + +/** @addtogroup RDB_VEHICLE_LIGHT + * ------ light states ------ + * @{ + */ +#define RDB_VEHICLE_LIGHT_OFF 0x00000000 /**< all lights OFF @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_PARK 0x00000001 /**< front and rear lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_LOW_BEAM 0x00000002 /**< front and rear lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_HIGH_BEAM 0x00000004 /**< front lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_REAR_BRAKE 0x00000008 /**< only rear lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_REAR_DRIVE 0x00000010 /**< only rear lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_INDICATOR_L 0x00000020 /**< left indicator lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_INDICATOR_R 0x00000040 /**< right indicator lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_FLASH 0x00000080 /**< special light for police forces etc. @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_FRONT_FOG 0x00000100 /**< only front lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_REAR_FOG 0x00000200 /**< only rear lights are ON @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_VIRES1 0x00000400 /**< used internally by VIRES @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_DRL 0x00000800 /**< daytime running light @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_DRL_LEFT_LOW 0x00001000 /**< dimmed state of left front DRLs @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_DRL_RIGHT_LOW 0x00002000 /**< dimmed state of right front DRLs @version 0x0100 */ +#define RDB_VEHICLE_LIGHT_EMERGENCY 0x00004000 /**< emergency indicator lights @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_VEHICLE_ACC_FLAG + * ------ acc states, 1 byte ------ + * @{ + */ +#define RDB_VEHICLE_ACC_FLAG_OFF 0x00 /**< ACC is OFF @version 0x010A */ +#define RDB_VEHICLE_ACC_FLAG_DIST_1 0x01 /**< ACC distance setting 1 @version 0x010A */ +#define RDB_VEHICLE_ACC_FLAG_DIST_2 0x02 /**< ACC distance setting 2 @version 0x010A */ +#define RDB_VEHICLE_ACC_FLAG_DIST_3 0x03 /**< ACC distance setting 3 @version 0x010A */ +#define RDB_VEHICLE_ACC_FLAG_TARGET 0x04 /**< show ACC target vehicle @version 0x010A */ +#define RDB_VEHICLE_ACC_FLAG_SPEED 0x08 /**< show ACC speed @version 0x010A */ +/** @} */ + +/** @addtogroup RDB_VEHICLE_DISPLAY_LIGHT + * ------ display lights, 2 bytes ------ + * @{ + */ +#define RDB_VEHICLE_DISPLAY_LIGHT_OFF 0x0000 /**< all lights OFF in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_01 0x0001 /**< light 01 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_02 0x0002 /**< light 02 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_03 0x0004 /**< light 03 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_04 0x0008 /**< light 04 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_05 0x0010 /**< light 05 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_06 0x0020 /**< light 06 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_07 0x0040 /**< light 07 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_08 0x0080 /**< light 08 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_09 0x0100 /**< light 09 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_10 0x0200 /**< light 10 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_11 0x0400 /**< light 11 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_12 0x0800 /**< light 12 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_13 0x1000 /**< light 13 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_14 0x2000 /**< light 14 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_15 0x4000 /**< light 15 ON in driver display @version 0x010A */ +#define RDB_VEHICLE_DISPLAY_LIGHT_16 0x8000 /**< light 16 ON in driver display @version 0x010A */ +/** @} */ + + +/** @addtogroup RDB_LANE_EXISTS + * ------ lane existence masks ------ + * @{ + */ +#define RDB_LANE_EXISTS_OWN 0x01 /**< own lane exists @version 0x0100 */ +#define RDB_LANE_EXISTS_LEFT 0x02 /**< left lane exists @version 0x0100 */ +#define RDB_LANE_EXISTS_RIGHT 0x04 /**< right lane exists @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_LANE_STATUS + * ------ lane status masks ------ + * @{ + */ +#define RDB_LANE_STATUS_NONE 0x0000 /**< nothing special @version 0x0100 */ +#define RDB_LANE_STATUS_ROADWORKS 0x0001 /**< road works @version 0x0100 */ +#define RDB_LANE_STATUS_EXIT 0x0002 /**< motorway exit @version 0x0100 */ +#define RDB_LANE_STATUS_ENTRY 0x0004 /**< motorway entry @version 0x0100 */ +#define RDB_LANE_STATUS_LINKED 0x0008 /**< linked lanes @version 0x0100 */ +#define RDB_LANE_STATUS_WET 0x0010 /**< wet lane (from rain) @version 0x0100 */ +#define RDB_LANE_STATUS_SNOW 0x0020 /**< snow-covered lane @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_DRIVER_FLAG + * ------ dynamics input flags ------ + * @{ + */ +#define RDB_DRIVER_FLAG_NONE 0x00000000 /**< default @version 0x0100 */ +#define RDB_DRIVER_FLAG_INDICATOR_L 0x00000001 /**< driver activated left indicator @version 0x0100 */ +#define RDB_DRIVER_FLAG_INDICATOR_R 0x00000002 /**< driver activated right indicator @version 0x0100 */ +#define RDB_DRIVER_FLAG_PARKING_BRAKE 0x00000004 /**< driver activated parking brake @version 0x0100 */ +#define RDB_DRIVER_FLAG_LIGHT_LOW_BEAM 0x00000008 /**< driver activated low beam headlights @version 0x0105 */ +#define RDB_DRIVER_FLAG_LIGHT_HIGH_BEAM 0x00000010 /**< driver activated high beam headlights @version 0x0105 */ +#define RDB_DRIVER_FLAG_LIGHT_FOG_FRONT 0x00000020 /**< driver activated front fog light @version 0x0105 */ +#define RDB_DRIVER_FLAG_LIGHT_FOG_REAR 0x00000040 /**< driver activated rear fog light @version 0x0105 */ +#define RDB_DRIVER_FLAG_LIGHT_EMERGENCY 0x00000080 /**< driver activated emergency light (indic. L&R) @version 0x0105 */ +#define RDB_DRIVER_FLAG_LIGHT_PRIORITY 0x00000100 /**< driver activated priority light (blue flashlight) @version 0x0105 */ +/** @} */ + +/** @addtogroup RDB_MOCKUP_INPUT0 + * ------ mockup input flags, part 1 ------ + * @{ + */ +// INPUT: MFL and SZL bits +#define RDB_MOCKUP_INPUT0_MFL_PLUS 0x00000001 /**< input no. 0 for MFL_PLUS @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_MINUS 0x00000002 /**< input no. 0 for MFL_MINUS @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_PHONE 0x00000004 /**< input no. 0 for MFL_PHONE @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_VOICE 0x00000008 /**< input no. 0 for MFL_VOICE @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_UP 0x00000010 /**< input no. 0 for MFL_UP @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_DOWN 0x00000020 /**< input no. 0 for MFL_DOWN @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_DIAMOND 0x00000040 /**< input no. 0 for MFL_DIAMOND @version 0x010B */ +#define RDB_MOCKUP_INPUT0_MFL_STAR 0x00000080 /**< input no. 0 for MFL_STAR @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_UP 0x00000100 /**< input no. 0 for TURN_UP @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_UP_2 0x00000200 /**< input no. 0 for TURN_UP_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_DOWN 0x00000400 /**< input no. 0 for TURN_DOWN @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_DOWN_2 0x00000800 /**< input no. 0 for TURN_DOWN_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_FLASHER 0x00001000 /**< input no. 0 for TURN_FLASHER @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_HIGHBEAM 0x00002000 /**< input no. 0 for TURN_HIGHBEAM @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_CHECK 0x00004000 /**< input no. 0 for TURN_CHECK @version 0x010B */ +#define RDB_MOCKUP_INPUT0_TURN_BC 0x00008000 /**< input no. 0 for TURN_BC @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_BACK 0x00010000 /**< input no. 0 for ACC_BACK @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_BACK_2 0x00020000 /**< input no. 0 for ACC_BACK_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_FWD 0x00040000 /**< input no. 0 for ACC_FWD @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_FWD_2 0x00080000 /**< input no. 0 for ACC_FWD_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_UP 0x00100000 /**< input no. 0 for ACC_UP @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_DOWN 0x00200000 /**< input no. 0 for ACC_DOWN @version 0x010B */ +#define RDB_MOCKUP_INPUT0_ACC_SET 0x00400000 /**< input no. 0 for ACC_SET @version 0x010B */ +#define RDB_MOCKUP_INPUT0_HORN 0x00800000 /**< input no. 0 for HORN @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_INTERVAL 0x03000000 /**< input no. 0 for WIPER_INTERVAL @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_INTERVAL_1 0x01000000 /**< input no. 0 for WIPER_INTERVAL_1 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_INTERVAL_2 0x02000000 /**< input no. 0 for WIPER_INTERVAL_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_INTERVAL_3 0x03000000 /**< input no. 0 for WIPER_INTERVAL_3 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_AUTO 0x04000000 /**< input no. 0 for WIPER_AUTO @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_BACK 0x08000000 /**< input no. 0 for WIPER_BACK @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_UP 0x10000000 /**< input no. 0 for WIPER_UP @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_UP_2 0x20000000 /**< input no. 0 for WIPER_UP_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT0_WIPER_DOWN 0x40000000 /**< input no. 0 for WIPER_DOWN @version 0x010B */ +/** @} */ + +/** @addtogroup RDB_MOCKUP_INPUT1 + * ------ mockup input flags, part 2 ------ + * @{ + */ +// INPUT: ZBE and GWS bits +#define RDB_MOCKUP_INPUT1_ZBE_COUNTER 0x0000FFFF /**< input no. 1 for ZBE_COUNTER @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_FWD 0x00010000 /**< input no. 1 for ZBE_FWD @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_BACK 0x00020000 /**< input no. 1 for ZBE_BACK @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_LEFT 0x00040000 /**< input no. 1 for ZBE_LEFT @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_RIGHT 0x00080000 /**< input no. 1 for ZBE_RIGHT @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_PRESS 0x00100000 /**< input no. 1 for ZBE_PRESS @version 0x010B */ +#define RDB_MOCKUP_INPUT1_ZBE_MENU 0x00200000 /**< input no. 1 for ZBE_MENU @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_P 0x00400000 /**< input no. 1 for GWS_P @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_LOCK 0x00800000 /**< input no. 1 for GWS_LOCK @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_FWD 0x01000000 /**< input no. 1 for GWS_FWD @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_FWD_2 0x02000000 /**< input no. 1 for GWS_FWD_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_BACK 0x04000000 /**< input no. 1 for GWS_BACK @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_BACK_2 0x08000000 /**< input no. 1 for GWS_BACK_2 @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_AUTO_N 0x10000000 /**< input no. 1 for GWS_AUTO_N @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_MAN_N 0x20000000 /**< input no. 1 for GWS_MAN_N @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_MAN_PLUS 0x40000000 /**< input no. 1 for GWS_MAN_PLUS @version 0x010B */ +#define RDB_MOCKUP_INPUT1_GWS_MAN_MINUS 0x80000000 /**< input no. 1 for GWS_MAN_MINUS @version 0x010B */ +/** @} */ + +/** @addtogroup RDB_MOCKUP_INPUT2 + * ------ mockup input flags, part 3 ------ + * @{ + */ +#define RDB_MOCKUP_INPUT2_LSZ_POTI 0x000000FF /**< input no. 2 for LSZ_POTI @version 0x010B */ +#define RDB_MOCKUP_INPUT2_LSZ_PARKING 0x00000100 /**< input no. 2 for LSZ_PARKING @version 0x010B */ +#define RDB_MOCKUP_INPUT2_LSZ_DRIVING 0x00000200 /**< input no. 2 for LSZ_DRIVING @version 0x010B */ +#define RDB_MOCKUP_INPUT2_LSZ_AUTO 0x00000300 /**< input no. 2 for LSZ_AUTO @version 0x010B */ +#define RDB_MOCKUP_INPUT2_LSZ_FOG_FRONT 0x00000400 /**< input no. 2 for LSZ_FOG_FRONT @version 0x010B */ +#define RDB_MOCKUP_INPUT2_LSZ_FOG_REAR 0x00000800 /**< input no. 2 for LSZ_FOG_REAR @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_DTC 0x00001000 /**< input no. 2 for DB_DTC @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_PDC 0x00002000 /**< input no. 2 for DB_PDC @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_SEAT_HEAT_L 0x00004000 /**< input no. 2 for DB_SEAT_HEAT_L @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_SEAT_HEAT_R 0x00008000 /**< input no. 2 for DB_SEAT_HEAT_R @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_STARTER 0x00010000 /**< input no. 2 for DB_STARTER @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_HAZARD_LIGHTS 0x00020000 /**< input no. 2 for DB_HAZARD_LIGHTS @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_LOCK 0x00040000 /**< input no. 2 for DB_LOCK @version 0x010B */ + +#define RDB_MOCKUP_INPUT2_DB_STEER_ADJUST_FWD 0x00100000 /**< input no. 2 for DB_STEER_ADJUST_FWD @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_STEER_ADJUST_BACK 0x00200000 /**< input no. 2 for DB_STEER_ADJUST_BACK @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_STEER_ADJUST_UP 0x00400000 /**< input no. 2 for DB_STEER_ADJUST_UP @version 0x010B */ +#define RDB_MOCKUP_INPUT2_DB_STEER_ADJUST_DOWN 0x00800000 /**< input no. 2 for DB_STEER_ADJUST_DOWN @version 0x010B */ +/** @} */ + +/** @addtogroup RDB_DRIVER_PERCEPTION_FLAG + * ------ driver persecption flags ------ + * @{ + */ +#define RDB_DRIVER_PERCEPTION_FLAG_NONE 0x00000000 /**< default @version 0x0100 */ +#define RDB_DRIVER_PERCEPTION_FLAG_TURN_L 0x00000001 /**< turn left at next intersection @version 0x0100 */ +#define RDB_DRIVER_PERCEPTION_FLAG_TURN_R 0x00000002 /**< turn right at next intersection @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_DRIVER_INPUT_VALIDITY + * ------ dynamics input flags ------ + * @{ + */ +#define RDB_DRIVER_INPUT_VALIDITY_NONE 0x00000000 /**< default @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_STEERING_WHEEL 0x00000001 /**< steering wheel is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_STEERING_SPEED 0x00000002 /**< steering speed is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_THROTTLE 0x00000004 /**< throttle is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_BRAKE 0x00000008 /**< brake is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_CLUTCH 0x00000010 /**< clutch is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_TGT_ACCEL 0x00000020 /**< target acceleration is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_TGT_STEERING 0x00000040 /**< target steering is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_GEAR 0x00000080 /**< gear selection is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_CURVATURE 0x00000100 /**< curvature is valid for lateral control @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_STEERING_TORQUE 0x00000200 /**< torque at steering wheel is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_ENGINE_TORQUE 0x00000400 /**< target torque of engine is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_TGT_SPEED 0x00000800 /**< target speed is valid @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_INFO_ONLY 0x00001000 /**< consider the values for info only @version 0x0100 */ +#define RDB_DRIVER_INPUT_VALIDITY_ADD_ON 0x00002000 /**< consider the values as an addOn for existing values @version 0x0104 */ +#define RDB_DRIVER_INPUT_VALIDITY_FLAGS 0x00004000 /**< member "flags" of RDB_DRIVER_CTRL_t is valid @version 0x0107 */ +#define RDB_DRIVER_INPUT_VALIDITY_MOCKUP_INPUT0 0x00008000 /**< member "mockupInput0" of RDB_DRIVER_CTRL_t is valid @version 0x010A */ +#define RDB_DRIVER_INPUT_VALIDITY_MOCKUP_INPUT1 0x00010000 /**< member "mockupInput1" of RDB_DRIVER_CTRL_t is valid @version 0x010A */ +#define RDB_DRIVER_INPUT_VALIDITY_MOCKUP_INPUT2 0x00020000 /**< member "mockupInput2" of RDB_DRIVER_CTRL_t is valid @version 0x010A */ +/** @} */ + + +/** @addtogroup RDB_SCORING_FLAG + * ------ arbitrary flags influencing the scoring ------ + * @{ + */ +#define RDB_SCORING_FLAG_NONE 0x00000000 /**< default @version 0x0100 */ +#define RDB_SCORING_FLAG_COLLISION 0x00000001 /**< driver caused collision @version 0x0100 */ +#define RDB_SCORING_FLAG_OFF_ROAD 0x00000002 /**< driver went off road @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_COORD_FLAG + * ------ co-ordinate flags ------ + * @{ + */ +#define RDB_COORD_FLAG_NONE 0x00 /**< co-ordinate has no flags (state unknown or invalid) @version 0x0100 */ +#define RDB_COORD_FLAG_POINT_VALID 0x01 /**< point co-ordinate is valid @version 0x0100 */ +#define RDB_COORD_FLAG_ANGLES_VALID 0x02 /**< angles are valid @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_LIGHT_SOURCE_FLAG + * ------ light source flags ------ + * @{ + */ +#define RDB_LIGHT_SOURCE_FLAG_NONE 0x0000 /**< light source has no flags (state unknown) @version 0x0100 */ +#define RDB_LIGHT_SOURCE_FLAG_USE_FRUSTUM 0x0001 /**< use frustum information of light source @version 0x0100 */ +#define RDB_LIGHT_SOURCE_FLAG_PERSISTENT 0x0002 /**< keep the light source even after initialization @version 0x0100 */ +#define RDB_LIGHT_SOURCE_FLAG_STENCIL 0x0004 /**< use this definition for the stencil mask of a light source @version 0x010C */ +/** @} */ + +/** @addtogroup RDB_SENSOR_OBJECT_FLAG + * ------ sensor object flags ------ + * @{ + */ +#define RDB_SENSOR_OBJECT_FLAG_NONE 0x0000 /**< object has no flags @version 0x0100 */ +#define RDB_SENSOR_OBJECT_FLAG_CRITICALITY_LOW 0x0001 /**< criticality of object is low @version 0x0100 */ +#define RDB_SENSOR_OBJECT_FLAG_CRITICALITY_MEDIUM 0x0002 /**< criticality of object is medium @version 0x0100 */ +#define RDB_SENSOR_OBJECT_FLAG_CRITICALITY_HIGH 0x0003 /**< criticality of object is high @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_ROAD_EVENT + * ------ road events ------ + * @{ + */ +#define RDB_ROAD_EVENT_NONE 0x00000000 /**< no event is triggered @version 0x0100 */ +#define RDB_ROAD_EVENT_POTHOLE 0x00000001 /**< contact point is in a pothole @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_ENV_FLAG + * ------ road events ------ + * @{ + */ +#define RDB_ENV_FLAG_NONE 0x0000 /**< no environment flag is set @version 0x0100 */ +#define RDB_ENV_FLAG_PRECIPITATION_SNOW 0x0001 /**< precipitation is snow, not rain @version 0x0100 */ +#define RDB_ENV_FLAG_PRECIPITATION_HAIL 0x0002 /**< precipitation is hail, not rain @version 0x0100 */ +#define RDB_ENV_FLAG_ROAD_SURFACE_WET 0x0004 /**< wet road surface @version 0x0100 */ +#define RDB_ENV_FLAG_STREET_LAMPS 0x0008 /**< street lamps are ON @version 0x0102 */ +/** @} */ + +/** @addtogroup RDB_SHM_ID + * ------ shared memory identifiers ------ + * @{ + */ +#define RDB_SHM_ID_IMG_GENERATOR_OUT 0x0816a /**< shared memory key of image generator @version 0x0100 */ +#define RDB_SHM_ID_IMG_GENERATOR_IN 0x0817a /**< shared memory key for light maps @version 0x0100 */ +#define RDB_SHM_ID_CONTROL_GENERATOR_IN 0x0817b /**< shared memory key commands @version 0x010E */ +#define RDB_SHM_ID_CUSTOM_01 0x0818a /**< shared memory key of custom data block @version 0x0100 */ +#define RDB_SHM_ID_TC_IN 0x08200 /**< shared memory key of taskControl input @version 0x010F */ +#define RDB_SHM_ID_TC_OUT 0x08201 /**< shared memory key of taskControl output @version 0x010F */ +/** @} */ + +/** @addtogroup RDB_SHM_BUFFER_FLAG + * ------ shared memory identifiers ------ + * @{ + */ +#define RDB_SHM_BUFFER_FLAG_NONE 0x00000000 /**< no bits set, buffer may be overwritten @version 0x0100 */ +#define RDB_SHM_BUFFER_FLAG_LOCK 0x00000001 /**< buffer is locked by producer @version 0x0100 */ +#define RDB_SHM_BUFFER_FLAG_TC 0x00000002 /**< buffer is to be processed by TC @version 0x0100 */ +#define RDB_SHM_BUFFER_FLAG_IG 0x00000004 /**< buffer is to be processed by IG @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_OBJECT_CFG_FLAG + * ------ object configuration flags ------ + * @{ + */ +#define RDB_OBJECT_CFG_FLAG_NONE 0x0000 /**< no configuration flag set @version 0x0100 */ +#define RDB_OBJECT_CFG_FLAG_CTRL_EXTERN 0x0001 /**< object is controlled externally @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_ROAD_POS_FLAG + * ------ road position flags ------ + * @{ + */ +#define RDB_ROAD_POS_FLAG_NONE 0x00 /**< no flag set @version 0x0100 */ +#define RDB_ROAD_POS_FLAG_DIR_FWD 0x01 /**< player orientation is in forward road direction @version 0x0100 */ +#define RDB_ROAD_POS_FLAG_DIR_REAR 0x02 /**< player orientation is in rearward road direction @version 0x0100 */ +/** @} */ + +/** @addtogroup RDB_CONTACT_POINT_FLAG + * ------ contact point flags ------ + * @{ + */ +#define RDB_CONTACT_POINT_FLAG_NONE 0x0000 /**< contact point has no flags (state unknown) @version 0x0102 */ +#define RDB_CONTACT_POINT_FLAG_PLAYER_VALID 0x0001 /**< player ID within CP structure is valid @version 0x0102 */ +/** @} */ + +/** @addtogroup RDB_SYNC_CMD + * ------ commands distributed with sync messages ------ + * @{ + */ +#define RDB_SYNC_CMD_RENDER_CONTINUOUS 0x00000080 /**< target will render as usual @version 0x010E */ +#define RDB_SYNC_CMD_RENDER_PAUSE 0x00000100 /**< target will pause rendering completely @version 0x010E */ +#define RDB_SYNC_CMD_RENDER_SINGLE_FRAME 0x00000200 /**< target will render a single frame and pause then @version 0x010E */ +/** @} */ + +/** @addtogroup RDB_TRAJECTORY_FLAG + * ------ commands distributed with sync messages ------ + * @{ + */ +#define RDB_TRAJECTORY_FLAG_NONE 0x0000 /**< no special settings @version 0x0110 */ +#define RDB_TRAJECTORY_FLAG_TIME_DOMAIN 0x0001 /**< trajectory is in time domain @version 0x0110 */ +/** @} */ + + +/** @} --END GROUP BITMASK_DEFINITIONS-- */ + +/** ------ generic point structure --- */ +typedef struct +{ + double x; /**< x position @unit m @version 0x0100 */ + double y; /**< y position @unit m @version 0x0100 */ + double z; /**< z position @unit m @version 0x0100 */ + uint8_t flags; /**< co-ordinate flags @unit @link RDB_COORD_FLAG @endlink @version 0x0100 */ + uint8_t type; /**< co-ordinate system type identifier @unit @link RDB_COORD_TYPE @endlink @version 0x0100 */ + uint16_t system; /**< unique ID of the corresponding (user) co-ordinate system @unit _ @version 0x0100 */ +} RDB_POINT_t; + +/** ------ generic co-ordinate structure --- */ +typedef struct +{ + double x; /**< x position @unit m @version 0x0100 */ + double y; /**< y position @unit m @version 0x0100 */ + double z; /**< z position @unit m @version 0x0100 */ + float h; /**< heading angle @unit rad @version 0x0100 */ + float p; /**< pitch angle @unit rad @version 0x0100 */ + float r; /**< roll angle @unit rad @version 0x0100 */ + uint8_t flags; /**< co-ordinate flags @unit @link RDB_COORD_FLAG @endlink @version 0x0100 */ + uint8_t type; /**< co-ordinate system type identifier @unit @link RDB_COORD_TYPE @endlink @version 0x0100 */ + uint16_t system; /**< unique ID of the corresponding (user) co-ordinate system @unit _ @version 0x0100 */ +} RDB_COORD_t; + +/** ------ definition / position of a user co-ordinate system --- */ +typedef struct +{ + uint16_t id; /**< unique ID of the co-ordinate system @unit _ @version 0x0100 */ + uint16_t spare; /**< spare for future use @unit _ @version 0x0100 */ + RDB_COORD_t pos; /**< origin and orientation of x axis of the co-ordinate system @unit m,m,m,rad,rad,rad @version 0x0100 */ +} RDB_COORD_SYSTEM_t; + +/** ------ road position and associated properties ------ */ +typedef struct +{ + uint32_t playerId; /**< id of the player to which road position belongs @unit _ @version 0x0100 */ + uint16_t roadId; /**< unique road ID @unit _ @version 0x0100 */ + int8_t laneId; /**< lane ID @unit _ @version 0x0100 */ + uint8_t flags; /**< road position flags, further info @unit @link RDB_ROAD_POS_FLAG @endlink @version 0x0100 */ + float roadS; /**< s-coordinate along road's reference line @unit m @version 0x0100 */ + float roadT; /**< t-coordinate perpendicular to road's reference line @unit m @version 0x0100 */ + float laneOffset; /**< offset from lane center in road co-ordinates @unit m @version 0x0100 */ + float hdgRel; /**< heading angle relative to lane tangent dir @unit rad @version 0x0100 */ + float pitchRel; /**< pitch angle relative to road tangent plane @unit rad @version 0x0100 */ + float rollRel; /**< roll angle relative to road tangent plane @unit rad @version 0x0100 */ + uint8_t roadType; /**< type of the road, corresponding to OpenDRIVE @unit @link RDB_ROAD_TYPE @endlink @version 0x010A */ + uint8_t spare1; /**< for future use @unit _ @version 0x010A */ + uint16_t spare2; /**< for future use @unit _ @version 0x010A */ + float pathS; /**< longitudinal path co-ordinate @unit _ @version 0x010E */ +} RDB_ROAD_POS_t; + +/** ------ road mark information ------ + * @note this package is immediately followed by "noDataPoints" entries of type RDB_POINT_t + */ +typedef struct +{ + uint32_t playerId; /**< id of the player to which roadmark belongs @unit _ @version 0x0100 */ + int8_t id; /**< id of this road mark @unit [0..127] @version 0x010D */ + int8_t prevId; /**< id of predecessor @unit [-1, 0..127] @version 0x010D */ + int8_t nextId; /**< id of successor @unit [-1, 0..127] @version 0x010D */ + uint8_t spare0; /**< for future use @unit _ @version 0x0100 */ + float lateralDist; /**< lateral distance to vehicle ref. point and dir @unit m @version 0x0100 */ + float yawRel; /**< yaw angle relative to vehicle dir @unit rad @version 0x0100 */ + double curvHor; /**< horizontal curvature @unit 1/m @version 0x0100 */ + double curvHorDot; /**< change of horizontal curvature @unit 1/m2 @version 0x0100 */ + float startDx; /**< start of road mark in driving dir @unit m @version 0x0100 */ + float previewDx; /**< distance of last valid measurement @unit m @version 0x0100 */ + float width; /**< width of road mark @unit m @version 0x0100 */ + float height; /**< height of road mark @unit m @version 0x0100 */ + double curvVert; /**< vertical curvature @unit 1/m @version 0x0100 */ + double curvVertDot; /**< change of vertical curvature @unit 1/m2 @version 0x0100 */ + uint8_t type; /**< type of road mark @unit @link RDB_ROADMARK_TYPE @endlink @version 0x0100 */ + uint8_t color; /**< color of road mark @unit @link RDB_ROADMARK_COLOR @endlink @version 0x0100 */ + uint16_t noDataPoints; /**< number of tesselation points following this package @unit _ @version 0x0100 */ + uint32_t spare1[2]; /**< for future use @unit _ @version 0x0100 */ +} RDB_ROADMARK_t; + +/** ------ lane information ------ */ +typedef struct +{ + uint16_t roadId; /**< unique road ID @unit _ @version 0x0100 */ + int8_t id; /**< lane ID according to OpenDRIVE @unit [-127..127] @version 0x0100 */ + uint8_t neighborMask; /**< existence mask for adjacent lanes @unit @link RDB_LANE_EXISTS @endlink @version 0x0100 */ + int8_t leftLaneId; /**< ID of lane left of current lane @unit [-127..127] @version 0x0100 */ + int8_t rightLaneId; /**< ID of lane right of current lane @unit [-127..127] @version 0x0100 */ + uint8_t borderType; /**< type of lane border @unit @link RDB_LANE_BORDER @endlink @version 0x0100 */ + uint8_t material; /**< type of lane material @unit [0..255] @version 0x0100 */ + uint16_t status; /**< status mask of lane @unit @link RDB_LANE_STATUS @endlink @version 0x0100 */ + uint16_t type; /**< lane type according to OpenDRIVE @unit _ @version 0x010D */ + float width; /**< lane width @unit m @version 0x0100 */ + double curvVert; /**< vertical curvature in lane center @unit 1/m @version 0x0100 */ + double curvVertDot; /**< change of vertical curvature in lane center @unit 1/m2 @version 0x0100 */ + double curvHor; /**< horizontal curvature in lane center @unit 1/m @version 0x0100 */ + double curvHorDot; /**< change of horizontal curvature in lane center @unit 1/m2 @version 0x0100 */ + uint32_t playerId; /**< id of the player to which this info belongs @unit _ @version 0x0100 */ + uint32_t spare1; /**< for future use @unit _ @version 0x0100 */ +} RDB_LANE_INFO_t; + +/** ------ configuration of an object (sent at start of sim and when triggered via SCP) ------ */ +typedef struct +{ + uint32_t id; /**< unique object ID @unit _ @version 0x0100 */ + uint8_t category; /**< object category @unit @link RDB_OBJECT_CATEGORY @endlink @version 0x0100 */ + uint8_t type; /**< object type @unit @link RDB_OBJECT_TYPE @endlink @version 0x0100 */ + int16_t modelId; /**< visual model ID @unit _ @version 0x0100 */ + char name[RDB_SIZE_OBJECT_NAME]; /**< symbolic name @unit _ @version 0x0100 */ + char modelName[RDB_SIZE_OBJECT_NAME]; /**< model name associated to an object @unit _ @version 0x0100 */ + char fileName[RDB_SIZE_FILENAME]; /**< filename associated to an object @unit _ @version 0x0100 */ + uint16_t flags; /**< object configuration flags @unit @link RDB_OBJECT_CFG_FLAG @endlink @version 0x0100 */ + uint16_t spare0; /**< reserved for future use @unit _ @version 0x0100 */ + uint32_t spare1; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_OBJECT_CFG_t; + +/** ------ geometry information for an object --- */ +typedef struct +{ + float dimX; /**< x dimension in object co-ordinates (length) @unit m @version 0x0100 */ + float dimY; /**< y dimension in object co-ordinates (width) @unit m @version 0x0100 */ + float dimZ; /**< z dimension in object co-ordinates (height) @unit m @version 0x0100 */ + float offX; /**< x distance from ref. point to center of geometry, object co-ordinate system @unit m @version 0x0100 */ + float offY; /**< y distance from ref. point to center of geometry, object co-ordinate system @unit m @version 0x0100 */ + float offZ; /**< z distance from ref. point to center of geometry, object co-ordinate system @unit m @version 0x0100 */ +} RDB_GEOMETRY_t; + +/** ------ state of an object (may be extended by the next structure) ------- */ +typedef struct +{ + uint32_t id; /**< unique object ID @unit _ @version 0x0100 */ + uint8_t category; /**< object category @unit @link RDB_OBJECT_CATEGORY @endlink @version 0x0100 */ + uint8_t type; /**< object type @unit @link RDB_OBJECT_TYPE @endlink @version 0x0100 */ + uint16_t visMask; /**< visibility mask @unit @link RDB_OBJECT_VIS_FLAG @endlink @version 0x0100 */ + char name[RDB_SIZE_OBJECT_NAME]; /**< symbolic name @unit _ @version 0x0100 */ + RDB_GEOMETRY_t geo; /**< info about object's geometry @unit m,m,m,m,m,m @version 0x0100 */ + RDB_COORD_t pos; /**< position and orientation of object's reference point @unit m,m,m,rad,rad,rad @version 0x0100 */ + uint32_t parent; /**< unique ID of parent object @unit _ @version 0x0100 */ + uint32_t spare1; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_OBJECT_STATE_BASE_t; + +/** ------ extended object data (e.g. for dynamic objects) ------- */ +typedef struct +{ + RDB_COORD_t speed; /**< speed and rates @unit m/s,m/s,m/s,rad/s,rad/s,rad/s @version 0x0100 */ + RDB_COORD_t accel; /**< acceleration @unit m/s2,m/s2,m/s2,rad/s2,rad/s2/rad/s2 @version 0x0100 */ + uint32_t spare[4]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_OBJECT_STATE_EXT_t; + +/** ------ complete object data (basic and extended info) ------- */ +typedef struct +{ + RDB_OBJECT_STATE_BASE_t base; /**< state of an object @unit RDB_OBJECT_STATE_BASE_t @version 0x0100 */ + RDB_OBJECT_STATE_EXT_t ext; /**< extended object data @unit RDB_OBJECT_STATE_EXT_t @version 0x0100 */ +} RDB_OBJECT_STATE_t; + +/** ------ standard engine information ------ */ +typedef struct +{ + uint32_t playerId; /**< unique ID of the player @unit _ @version 0x0100 */ + float rps; /**< current rotation speed @unit 1/s @version 0x0100 */ + float load; /**< engine load (throttle position) @unit [0.0..1.0] @version 0x0100 */ + uint32_t spare1[2]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_ENGINE_BASE_t; + +/** ------ extension of standard engine information ------ */ +typedef struct +{ + float rpsStart; /**< start speed @unit 1/s @version 0x0100 */ + float torque; /**< torque @unit Nm @version 0x0100 */ + float torqueInner; /**< inner torque @unit Nm @version 0x0100 */ + float torqueMax; /**< maximum torque @unit Nm @version 0x0100 */ + float torqueFriction; /**< friction torque @unit Nm @version 0x0100 */ + float fuelCurrent; /**< current fuel consumption @unit l/100km @version 0x0100 */ + float fuelAverage; /**< average fuel consumption @unit l/100km @version 0x0100 */ + uint32_t spare[2]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_ENGINE_EXT_t; + +/** ------ complete engine data (basic and extended info) ------- */ +typedef struct +{ + RDB_ENGINE_BASE_t base; /**< standard engine information @unit RDB_ENGINE_BASE_t @version 0x0100 */ + RDB_ENGINE_EXT_t ext; /**< extension of standard engine information @unit RDB_ENGINE_EXT_t @version 0x0100 */ +} RDB_ENGINE_t; + +/** ------ standard drivetrain information ------ */ +typedef struct +{ + uint32_t playerId; /**< unique ID of the player @unit _ @version 0x0100 */ + uint8_t gearBoxType; /**< type of gear box @unit @link RDB_GEAR_BOX_TYPE @endlink @version 0x0100 */ + uint8_t driveTrainType; /**< type of drivetrain @unit @link RDB_DRIVETRAIN_TYPE @endlink @version 0x0100 */ + uint8_t gear; /**< current gear position @unit @link RDB_GEAR_BOX_POS @endlink @version 0x0100 */ + uint8_t spare0; /**< reserved for future use @unit _ @version 0x0100 */ + uint32_t spare1[2]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_DRIVETRAIN_BASE_t; + +/** ------ extension of standard drivetrain information ------ */ +typedef struct +{ + float torqueGearBoxIn; /**< torque at entry of gearbox @unit Nm @version 0x0100 */ + float torqueCenterDiffOut; /**< torque at exit of center differential @unit Nm @version 0x0100 */ + float torqueShaft; /**< torque at shaft @unit Nm @version 0x0100 */ + uint32_t spare1[2]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_DRIVETRAIN_EXT_t; + +/** ------ complete engine data (basic and extended info) ------- */ +typedef struct +{ + RDB_DRIVETRAIN_BASE_t base; /**< standard drivetrain information @unit RDB_DRIVETRAIN_BASE_t @version 0x0100 */ + RDB_DRIVETRAIN_EXT_t ext; /**< extension of standard drivetrain information @unit RDB_DRIVETRAIN_EXT_t @version 0x0100 */ +} RDB_DRIVETRAIN_t; + +/** ------ standard wheel information ------ */ +typedef struct +{ + uint32_t playerId; /**< ID of the player to which the wheel belongs @unit _ @version 0x0100 */ + uint8_t id; /**< ID of the wheel within the player @unit @link RDB_WHEEL_ID @endlink @version 0x0100 */ + uint8_t spare0[3]; /**< reserved for future use @unit _ @version 0x0100 */ + float radiusStatic; /**< static tire radius @unit m @version 0x0100 */ + float springCompression; /**< compression of spring @unit m @version 0x0100 */ + float rotAngle; /**< angle of rotation @unit rad @version 0x0100 */ + float slip; /**< slip factor [0.0..1.0] @unit _ @version 0x0100 */ + float steeringAngle; /**< steering angle @unit rad @version 0x0100 */ + uint32_t spare1[4]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_WHEEL_BASE_t; + +/** ------ extension of standard wheel information ------ */ +typedef struct +{ + float vAngular; /**< angular velocity @unit rad/s @version 0x0100 */ + float forceZ; /**< wheel contact force @unit N @version 0x0100 */ + float forceLat; /**< lateral force @unit N @version 0x0100 */ + float forceLong; /**< longitudinal force @unit N @version 0x0100 */ + float forceTireWheelXYZ[3]; /**< force of tire on wheel @unit N @version 0x0100 */ + float radiusDynamic; /**< dynamic tire radius @unit m @version 0x0100 */ + float brakePressure; /**< brake pressure at wheel @unit Pa @version 0x0100 */ + float torqueDriveShaft; /**< torque at drive shaft @unit Nm @version 0x0100 */ + float damperSpeed; /**< speed of damper @unit m/s @version 0x0100 */ + uint32_t spare2[4]; /**< reserved for future use @unit _ @version 0x0100 */ +} RDB_WHEEL_EXT_t; + +/** ------ complete wheel data (basic and extended info) ------- */ +typedef struct +{ + RDB_WHEEL_BASE_t base; /**< standard wheel information @unit RDB_WHEEL_BASE_t @version 0x0100 */ + RDB_WHEEL_EXT_t ext; /**< extension of standard wheel information @unit RDB_WHEEL_EXT_t @version 0x0100 */ +} RDB_WHEEL_t; + +/** ------ vehicle system information ------ */ +typedef struct +{ + uint32_t playerId; /**< ID of the player to which the data belongs @unit _ @version 0x0100 */ + uint32_t lightMask; /**< mask of active light systems @unit @link RDB_VEHICLE_LIGHT @endlink @version 0x0100 */ + float steering; /**< front wheel steering angle (NOT: steering wheel angle) @unit rad @version 0x0100 */ + float steeringWheelTorque; /**< torque at the steering wheel @unit Nm @version 0x0100 */ + uint8_t accMask; /**< acc state mask @unit @link RDB_VEHICLE_ACC_FLAG @endlink @version 0x010A */ + uint8_t accSpeed; /**< acc speed indication @unit km/h [0..255] @version 0x010A */ + uint8_t batteryState; /**< battery charge state @unit [0..255] @version 0x010A */ + int8_t batteryRate; /**< battery discharge / charge rate @unit [-127..127] @version 0x010A */ + uint16_t displayLightMask; /**< lightmask for driver display (16 lights) @unit @link RDB_VEHICLE_DISPLAY_LIGHT @endlink @version 0x010A */ + uint16_t spare0; /**< spare for future use @unit _ @version 0x010A */ + uint32_t spare[5]; /**< spares for future use @unit _ @version 0x0100 */ +} RDB_VEHICLE_SYSTEMS_t; + +/** ------ vehicle setup information ------ */ +typedef struct +{ + uint32_t playerId; /**< ID of the player to which the data belongs @unit _ @version 0x0100 */ + float mass; /**< vehicle mass @unit kg @version 0x0100 */ + float wheelBase; /**< wheel base @unit m @version 0x0100 */ + int32_t spare[4]; /**< for future use @unit _ @version 0x0100 */ +} RDB_VEHICLE_SETUP_t; + +/** ------ image information ------ +* @note to be followed by actual image data +*/ +typedef struct +{ + uint32_t id; /**< unique ID of the image (e.g. frame count) @unit _ @version 0x0100 */ + uint16_t width; /**< width of the image @unit pixel @version 0x0100 */ + uint16_t height; /**< height of the image @unit pixel @version 0x0100 */ + uint8_t pixelSize; /**< memory size of a pixel @unit bit @version 0x0100 */ + uint8_t pixelFormat; /**< format of a pixel @unit @link RDB_PIX_FORMAT @endlink @version 0x0100 */ + uint16_t spare0; /**< for future use @unit _ @version 0x0100 */ + uint32_t imgSize; /**< total size of image @unit byte @version 0x0100 */ + uint8_t color[4]; /**< color for additional colorizing, if required @unit _ @version 0x0100 */ + uint32_t spare1[3]; /**< for future use @unit _ @version 0x0100 */ +} RDB_IMAGE_t; + +/** ------ arbitrary x/y function ------ +* @note to be followed by actual function points (each 2 or 3 doubles) +*/ +typedef struct +{ + uint32_t id; /**< unique ID of the function @unit _ @version 0x0100 */ + uint8_t type; /**< type of the function @unit @link RDB_FUNCTION_TYPE @endlink @version 0x0100 */ + uint8_t dimension; /**< dimension of the function (xy=2, xyz=3) @unit _ @version 0x0100 */ + uint16_t spare; /**< for future use @unit _ @version 0x0100 */ + uint32_t dataSize; /**< total size of following data @unit byte @version 0x0100 */ + uint32_t spare1[4]; /**< for future use @unit _ @version 0x0100 */ +} RDB_FUNCTION_t; + +/** ------ sensor definition and state ------ */ +typedef struct +{ + uint32_t id; /**< id of the sensor @unit _ @version 0x0100 */ + uint8_t type; /**< type of the sensor @unit @link RDB_SENSOR_TYPE @endlink @version 0x0100 */ + uint8_t hostCategory; /**< category of the object hosting the sensor @unit @link RDB_OBJECT_CATEGORY @endlink @version 0x0100 */ + uint16_t spare0; /**< for future use @unit _ @version 0x0100 */ + uint32_t hostId; /**< unique id of the sensor's host @unit _ @version 0x0100 */ + char name[RDB_SIZE_OBJECT_NAME]; /**< name of the sensor @unit _ @version 0x0100 */ + float fovHV[2]; /**< field-of-view (horizontal/vertical) @unit rad,rad @version 0x0100 */ + float clipNF[2]; /**< clipping ranges (near/far) @unit m,m @version 0x0100 */ + RDB_COORD_t pos; /**< position and orientation of sensor's reference point @unit m,m,m,rad,rad,rad @version 0x0100 */ + RDB_COORD_t originCoordSys; /**< position and orientation of sensor's coord origin @unit m,m,m,rad,rad,rad @version 0x0100 */ + int32_t spare[4]; /**< for future use @unit _ @version 0x0100 */ +} RDB_SENSOR_STATE_t; + +/** ------ information about an object registered within a sensor ------ */ +typedef struct +{ + uint8_t category; /**< object category @unit @link RDB_OBJECT_CATEGORY @endlink @version 0x0100 */ + uint8_t type; /**< object type @unit @link RDB_OBJECT_TYPE @endlink @version 0x0100 */ + uint16_t flags; /**< sensor object flags @unit @link RDB_SENSOR_OBJECT_FLAG @endlink @version 0x0100 */ + uint32_t id; /**< id of the object @unit _ @version 0x0100 */ + uint32_t sensorId; /**< id of the detecting sensor @unit _ @version 0x0100 */ + double dist; /**< distance between object and referring device @unit m @version 0x0100 */ + RDB_COORD_t sensorPos; /**< position and orientation of object in sensor coord @unit m,m,m,rad,rad,rad @version 0x0100 */ + int8_t occlusion; /**< degree of occlusion for viewer (-1 = not valid, 0..127 = 0..100% occlusion) @unit [-1, 0..127] @version 0x0100 */ + uint8_t spare0[3]; /**< for future use @unit _ @version 0x0100 */ + uint32_t spare[3]; /**< for future use @unit _ @version 0x0100 */ +} RDB_SENSOR_OBJECT_t; + +/** ------ camera information ------ */ +typedef struct +{ + uint16_t id; /**< unique ID of the camera @unit _ @version 0x0100 */ + uint16_t width; /**< width of viewport @unit pixel @version 0x0100 */ + uint16_t height; /**< height of viewport @unit pixel @version 0x0100 */ + uint16_t spare0; /**< for future use @unit _ @version 0x0100 */ + float clipNear; /**< near clipping plane @unit m @version 0x0100 */ + float clipFar; /**< far clipping plane @unit m @version 0x0100 */ + float focalX; /**< focal length in x direction @unit pixel @version 0x0100 */ + float focalY; /**< focal length in y direction @unit pixel @version 0x0100 */ + float principalX; /**< position of principal point in x direction @unit pixel @version 0x0100 */ + float principalY; /**< position of principal point in y direction @unit pixel @version 0x0100 */ + RDB_COORD_t pos; /**< position and orientation @unit m,m,m,rad,rad,rad @version 0x0100 */ + uint32_t spare1[4]; /**< for future use @unit _ @version 0x0100 */ +} RDB_CAMERA_t; + +/** ------ basic info about a light illuminating the scene ------ */ +typedef struct +{ + uint16_t id; /**< unique ID of the light source @unit _ @version 0x0100 */ + int8_t templateId; /**< template definition of light source (-1 deletes light source) @unit _ @version 0x0100 */ + uint8_t state; /**< state of light source @unit _ @version 0x0100 */ + int32_t playerId; /**< ID of the player to which light source shall be linked @unit _ @version 0x0100 */ + RDB_COORD_t pos; /**< position and orientation of light source @unit m,m,m,rad,rad,rad @version 0x0100 */ + uint16_t flags; /**< additional flags @unit @link RDB_LIGHT_SOURCE_FLAG @endlink @version 0x0100 */ + uint16_t spare0; /**< just another spare @unit _ @version 0x0100 */ + int32_t spare1[2]; /**< yet another spare @unit _ @version 0x0100 */ +} RDB_LIGHT_SOURCE_BASE_t; + +/** ------ extended info about a light illuminating the scene ------ */ +typedef struct +{ + float nearFar[2]; /**< near and far clip of light soure @unit m,m @version 0x0100 */ + float frustumLRBT[4]; /**< frustum left / right / bottom / top @unit m,m,m,m @version 0x0100 */ + float intensity[3]; /**< intensity of the light (ambient, diffuse, specular) @unit _,_,_ @version 0x0100 */ + float atten[3]; /**< attenuation (constant, linear, quadratic) @unit _,_,_ @version 0x0100 */ + int32_t spare1[3]; /**< yet another spare @unit _ @version 0x0100 */ +} RDB_LIGHT_SOURCE_EXT_t; + +/** ------ complete light source data (basic and extended info) ------- */ +typedef struct +{ + RDB_LIGHT_SOURCE_BASE_t base; /**< basic info about a light illuminating the scene @unit RDB_LIGHT_SOURCE_BASE_t @version 0x0100 */ + RDB_LIGHT_SOURCE_EXT_t ext; /**< extended info about a light illuminating the scene @unit RDB_LIGHT_SOURCE_EXT_t @version 0x0100 */ +} RDB_LIGHT_SOURCE_t; + +/** ------ info about an arbitrary contact point ------ */ +typedef struct +{ + uint16_t id; /**< unique ID of the contact point @unit _ @version 0x0100 */ + uint16_t flags; /**< various flags with contact point options @unit @link RDB_CONTACT_POINT_FLAG @endlink @version 0x0102 */ + RDB_COORD_t roadDataIn; /**< inertial position of contact point; heading=0; pitch and roll relative to vehicle axis @unit m,m,m,rad,rad,rad @version 0x0100 */ + float friction; /**< road friction at contact point @unit _ @version 0x0100 */ + int32_t playerId; /**< ID of the player to which CP belongs; only valid if corresponding flag is set @unit _ @version 0x0102 */ + int32_t spare1; /**< just another spare @unit _ @version 0x0100 */ +} RDB_CONTACT_POINT_t; + +/** ------ signal / sign info for a given vehicle ------ */ +typedef struct +{ + uint32_t id; /**< ID of the signal @unit _ @version 0x0100 */ + uint32_t playerId; /**< ID of the player who "detected" the signal @unit _ @version 0x0100 */ + float roadDist; /**< distance to signal along road @unit m @version 0x0100 */ + RDB_COORD_t pos; /**< inertial position of signal @unit m,m,m,rad,rad,rad @version 0x0100 */ + int32_t type; /**< signal type according to OpenDRIVE @unit _ @version 0x0100 */ + int32_t subType; /**< signal sub-type according to OpenDRIVE @unit _ @version 0x0100 */ + float value; /**< value associated with signal @unit _ @version 0x0100 */ + uint32_t state; /**< traffic sign's state (if dynamic) @unit _ @version 0x0100 */ + int8_t readability; /**< sign's readability (-1 = not valid, 0..127 = 0..100% readability) @unit [-1, 0..127] @version 0x0100 */ + int8_t occlusion; /**< degree of occlusion for viewer (-1 = not valid, 0..127 = 0..100% occlusion) @unit [-1, 0..127] @version 0x0100 */ + uint16_t spare0; /**< some more spare @unit _ @version 0x0100 */ + uint32_t addOnId; /**< ID of additional sign which extends this sign @unit _ @version 0x0100 */ + int8_t minLane; /**< ID minimum lane for which sign is valid @unit [-127..127] @version 0x0100 */ + int8_t maxLane; /**< ID maximum lane for which sign is valid @unit [-127..127] @version 0x0100 */ + uint16_t spare; /**< spare for upcoming info @unit _ @version 0x0100 */ +} RDB_TRAFFIC_SIGN_t; + +/** ------ road state for a given vehicle ------ */ +typedef struct +{ + uint32_t playerId; /**< ID of the player for which the state applies @unit _ @version 0x0100 */ + int8_t wheelId; /**< unique ID of the player's wheel for which state is valid (-1 for all) @unit @link RDB_WHEEL_ID @endlink @version 0x0100 */ + uint8_t spare0; /**< yet another spare @unit _ @version 0x0100 */ + uint16_t spare1; /**< yet another spare @unit _ @version 0x0100 */ + uint32_t roadId; /**< unique ID of the road @unit _ @version 0x0100 */ + float defaultSpeed; /**< default speed of the road @unit m/s @version 0x0100 */ + float waterLevel; /**< rain level on road @unit [0.0..1.0] @version 0x0100 */ + uint32_t eventMask; /**< road events @unit @link RDB_ROAD_EVENT @endlink @version 0x0100 */ + int32_t spare2[12]; /**< for future use @unit _ @version 0x0100 */ +} RDB_ROAD_STATE_t; + +/** ------ information about the environment state ------ */ +typedef struct +{ + float visibility; /**< visibility range @unit m @version 0x0100 */ + uint32_t timeOfDay; /**< time of day at sim start @unit s @version 0x0100 */ + float brightness; /**< brightness of ambient light @unit [0.0..1.0] @version 0x0100 */ + uint8_t precipitation; /**< intensity of precipitation @unit [0..255] @version 0x0100 */ + uint8_t cloudState; /**< cloud state @unit @link RDB_ENV_CLOUD_STATE @endlink @version 0x0100 */ + uint16_t flags; /**< a series of environment flags @unit @link RDB_ENV_FLAG @endlink @version 0x0100 */ + uint32_t spare1[8]; /**< yet another spare @unit _ @version 0x0100 */ +} RDB_ENVIRONMENT_t; + +/** ------ pedestrians animation data ------ +* @note this package is followed immediately by "dataSize" bytes of data, containing hinge information etc. +*/ +typedef struct +{ + uint32_t playerId; /**< unique player ID @unit _ @version 0x0100 */ + RDB_COORD_t pos; /**< real-world position and orientation of reference point32_t @unit m,m,m,rad,rad,rad @version 0x0100 */ + uint32_t spare[4]; /**< some more spares @unit _ @version 0x0100 */ + uint32_t noCoords; /**< number of valid co-ordinates in coord array @unit _ @version 0x0100 */ + uint32_t dataSize; /**< size of the following data containing the actual co-ordinates @unit byte @version 0x0100 */ +} RDB_PED_ANIMATION_t; + +/** ------ scoring information (for racing applications) ------ */ +typedef struct +{ + uint32_t playerId; /**< unique player ID @unit _ @version 0x0100 */ + float pathS; /**< path position (negative if no path is available) @unit m @version 0x0100 */ + float roadS; /**< road position (negative if no road is available) @unit m @version 0x0100 */ + float fuelCurrent; /**< current fuel consumption @unit l/100km @version 0x0100 */ + float fuelAverage; /**< average fuel consumption @unit l/100km @version 0x0100 */ + uint32_t stateFlags; /**< arbitrary state information @unit @link RDB_SCORING_FLAG @endlink @version 0x0100 */ + float slip; /**< slip factor [0.0..1.0] @unit _ @version 0x0100 */ + uint32_t spare[4]; /**< we'll certainly have some more ideas.... @unit _ @version 0x0100 */ +} RDB_CUSTOM_SCORING_t; + +/** ------ simulation frame trigger information ------ */ +typedef struct +{ + float deltaT; /**< delta time by which to advance the simulation @unit s @version 0x0100 */ + uint32_t frameNo; /**< number of the simulation frame which is triggered @unit _ @version 0x0100 */ + int32_t spare; /**< spare for future use @unit _ @version 0x0100 */ +} RDB_TRIGGER_t; + +/** ------ information about driver control inputs (may be used e.g. for dynamics input) ------ */ +typedef struct +{ + uint32_t playerId; /**< unique player ID to which the controls apply @unit _ @version 0x0100 */ + float steeringWheel; /**< steering wheel angle @unit rad @version 0x0100 */ + float steeringSpeed; /**< steering speed @unit rad/s @version 0x0100 */ + float throttlePedal; /**< throttle pedal position @unit [0.0..1.0] @version 0x0100 */ + float brakePedal; /**< brake pedal position @unit [0.0..1.0] @version 0x0100 */ + float clutchPedal; /**< clutch pedal position @unit [0.0..1.0] @version 0x0100 */ + float accelTgt; /**< desired acceleration @unit m/s2 @version 0x0100 */ + float steeringTgt; /**< desired steering angle at wheels @unit rad @version 0x0100 */ /* TODO: maybe this should become the turn rate */ + double curvatureTgt; /**< desired resulting curvature of the lateral motion @unit 1/m @version 0x0100 */ + float steeringTorque; /**< torque at steering wheel @unit Nm @version 0x0100 */ + float engineTorqueTgt; /**< target engine torque @unit Nm @version 0x0100 */ + float speedTgt; /**< target speed @unit m/s @version 0x0100 */ + uint8_t gear; /**< desired gear box position @unit @link RDB_GEAR_BOX_POS @endlink @version 0x0100 */ + uint8_t sourceId; /**< unique number of the source providing this input @unit @link RDB_DRIVER_SOURCE @endlink @version 0x010E */ + uint8_t spare0[2]; /**< some spares for future use @unit _ @version 0x0100 */ + uint32_t validityFlags; /**< flags which of the above inputs are valid @unit @link RDB_DRIVER_INPUT_VALIDITY @endlink @version 0x0100 */ + uint32_t flags; /**< input flags (indicator etc.) @unit @link RDB_DRIVER_FLAG @endlink @version 0x0100 */ + uint32_t mockupInput0; /**< flags resulting from mockup buttons, part 1 @unit @link RDB_MOCKUP_INPUT0 @endlink @version 0x010A */ + uint32_t mockupInput1; /**< flags resulting from mockup buttons, part 2 @unit @link RDB_MOCKUP_INPUT1 @endlink @version 0x010A */ + uint32_t mockupInput2; /**< flags resulting from mockup buttons, part 3 @unit @link RDB_MOCKUP_INPUT2 @endlink @version 0x010A */ + uint32_t spare; /**< some spare for future use @unit _ @version 0x010A */ +} RDB_DRIVER_CTRL_t; + +/** ------ information about driver control inputs (may be used e.g. for dynamics input) ------ */ +typedef struct +{ + uint32_t playerId; /**< unique player ID to which the controls apply @unit _ @version 0x0100 */ + float speedFromRules; /**< speed from rules (i.e. road, signs etc.) @unit m/s @version 0x0100 */ + float distToSpeed; /**< distance to next speed from rules (-1.0 to disable) @unit m @version 0x0100 */ + float spare0[4]; /**< just some spares @unit _ @version 0x0100 */ + uint32_t flags; /**< input flags (turn dir etc.) @unit @link RDB_DRIVER_PERCEPTION_FLAG @endlink @version 0x0100 */ + uint32_t spare[4]; /**< some spares for future use @unit _ @version 0x0100 */ +} RDB_DRIVER_PERCEPTION_t; + +/** ------ information about a traffic light (state) ------ */ +typedef struct +{ + int32_t id; /**< unique ID of the traffic light @unit _ @version 0x0100 */ + float state; /**< current state (normalized) @unit [0.0..1.0] @version 0x0100 */ + uint32_t stateMask; /**< current state mask (light mask, e.g. for gfx) @unit _ @version 0x0100 */ +} RDB_TRAFFIC_LIGHT_BASE_t; + +/** ------ traffic light phase information entry ------ */ +typedef struct +{ + float duration; /**< normalized duration of the phase, invalid phases will have duration 0.0 @unit [0.0..1.0] @version 0x0100 */ + uint8_t type; /**< type of the phase @unit @link RDB_TRLIGHT_PHASE @endlink @version 0x0100 */ + uint8_t spare[3]; /**< spares for future use @unit _ @version 0x0100 */ +} RDB_TRAFFIC_LIGHT_PHASE_t; + +/** ------ extended information about a traffic light (phases, state details) ------ + * @note this package is followed immediately by "dataSize" bytes of data, containing "noPhases" phase information entries RDB_TRAFFIC_LIGHT_PHASE_t */ +typedef struct +{ + int32_t ctrlId; /**< ID of the traffic light's controller @unit _ @version 0x0100 */ + float cycleTime; /**< duration of a complete cycle of all phases @unit s @version 0x0100 */ + uint16_t noPhases; /**< number of phases provided by this traffic light @unit _ @version 0x0100 */ + uint32_t dataSize; /**< total size of phase data following the package @unit _ @version 0x0100 */ +} RDB_TRAFFIC_LIGHT_EXT_t; + +/** ------ complete traffic light data (basic and extended info) ------- */ +typedef struct +{ + RDB_TRAFFIC_LIGHT_BASE_t base; /**< information about a traffic light state @unit RDB_TRAFFIC_LIGHT_BASE_t @version 0x0100 */ + RDB_TRAFFIC_LIGHT_EXT_t ext; /**< extended information about a traffic light @unit RDB_TRAFFIC_LIGHT_EXT_t @version 0x0100 */ +} RDB_TRAFFIC_LIGHT_t; + +/** ------ synchronization package ------- */ +typedef struct +{ + uint32_t mask; /**< mask of required sync sources which are fulfilled by this sender @unit _ @version 0x0100 */ + uint32_t cmdMask; /**< mask of commands included in the sync message @unit RDB_SYNC_CMD @version 0x010E */ + uint32_t spare[2]; /**< spares for future use @unit _ @version 0x010E */ +} RDB_SYNC_t; + +/** ------ road query package ------- */ +typedef struct +{ + uint16_t id; /**< unique ID of the road query point (reflected in answer) @unit _ @version 0x0107 */ + uint16_t flags; /**< query flags @unit _ @version 0x0107 */ + uint16_t spare[2]; /**< spare for future use @unit _ @version 0x0107 */ + double x; /**< x co-ordinate (inertial) of query location @unit m @version 0x0107 */ + double y; /**< y co-ordinate (inertial) of query location @unit m @version 0x0107 */ +} RDB_ROAD_QUERY_t; + +/** ------ wrapper for SCP messages ------- + * @note this package is followed immediately by "dataSize" bytes of data, containing the actual SCP command string */ +typedef struct +{ + uint16_t version; /**< upper byte = major, lower byte = minor @unit _ @version 0x010C */ + uint16_t spare; /**< just another spare @unit _ @version 0x010C */ + char sender[RDB_SIZE_SCP_NAME]; /**< name of the sender as text @unit _ @version 0x010C */ + char receiver[RDB_SIZE_SCP_NAME]; /**< name of the receiver as text @unit _ @version 0x010C */ + uint32_t dataSize; /**< number of data bytes following this entry @unit _ @version 0x010C */ +} RDB_SCP_t; + +/** ------ trajectory planning points of a player ------- + * @note this package is immediately followed by "noDataPoints" entries of type RDB_POINT_t +*/ +typedef struct +{ + uint32_t playerId; /**< unique player / object ID @unit _ @version 0x0110 */ + double spacing; /**< spacing of data points, either in space or time domain @unit m, s @version 0x0110 */ + uint16_t flags; /**< flags for treatment of trajectory @unit RDB_TRAJECTORY_FLAG @version 0x0110 */ + uint16_t noDataPoints; /**< number of trajectory points following this package @unit _ @version 0x0110 */ + uint32_t spare[4]; /**< some more spares @unit _ @version 0x0110 */ +} RDB_TRAJECTORY_t; + + +/** ------ empty structure for end-of-frame message (not to be used) ------- */ +typedef struct +{ +} RDB_END_OF_FRAME_t; + +/** ------ empty structure for start-of-frame message (not to be used) ------- */ +typedef struct +{ +} RDB_START_OF_FRAME_t; + +/** ------ header of a complete message ------ */ +typedef struct +{ + uint16_t magicNo; /**< must be RDB_MAGIC_NO (35712) @unit @link GENERAL_DEFINITIONS @endlink @version 0x0100 */ + uint16_t version; /**< upper byte = major, lower byte = minor @unit _ @version 0x0100 */ + uint32_t headerSize; /**< size of this header structure when transmitted @unit byte @version 0x0100 */ + uint32_t dataSize; /**< size of data following the header @unit byte @version 0x0100 */ + uint32_t frameNo; /**< number of the simulation frame @unit _ @version 0x0100 */ + double simTime; /**< simulation time @unit s @version 0x0100 */ +} RDB_MSG_HDR_t; + +/** ------ header of a package vector within a message ------ */ +typedef struct +{ + uint32_t headerSize; /**< size of this header structure when transmitted @unit byte @version 0x0100 */ + uint32_t dataSize; /**< size of data following the header @unit byte @version 0x0100 */ + uint32_t elementSize; /**< if data following the header contains an array of elements of equal size: + size of one element in this data + (elementSize is equivalent to dataSize if only one element is transmitted) @unit byte @version 0x0100 */ + uint16_t pkgId; /**< package identifier @unit _ @version 0x0100 */ + uint16_t flags; /**< various flags concerning the package's contents (e.g. extension) @unit @link RDB_PKG_FLAG @endlink @version 0x0100 */ +} RDB_MSG_ENTRY_HDR_t; + + +/** ------ the message union (use for very simplistic casting only)------ */ +typedef struct +{ + RDB_COORD_SYSTEM_t coordSystem; /**< (custom) co-ordinate system @msgid RDB_PKG_ID_COORD_SYSTEM */ + RDB_COORD_t coord; /**< single co-ordinate extending previous object information @msgid RDB_PKG_ID_COORD */ + RDB_ROAD_POS_t roadPos; /**< detailed road position of a given entity @msgid RDB_PKG_ID_ROAD_POS */ + RDB_LANE_INFO_t laneInfo; /**< lane information for a given entity @msgid RDB_PKG_ID_LANE_INFO */ + RDB_ROADMARK_t roadMark; /**< road mark information for a player @msgid RDB_PKG_ID_ROADMARK */ + RDB_OBJECT_CFG_t objectCfg; /**< info about a (traffic) object configuration @msgid RDB_PKG_ID_OBJECT_CFG */ + RDB_OBJECT_STATE_t objectState; /**< info about an arbitrary object's state @msgid RDB_PKG_ID_OBJECT_STATE */ + RDB_VEHICLE_SYSTEMS_t vehicleSystems; /**< vehicle systems' states (lights etc.) @msgid RDB_PKG_ID_VEHICLE_SYSTEMS */ + RDB_VEHICLE_SETUP_t vehicleSetup; /**< basic information about a vehicle (mass etc.) @msgid RDB_PKG_ID_VEHICLE_SETUP */ + RDB_ENGINE_t engine; /**< info about a vehicle's engine @msgid RDB_PKG_ID_ENGINE */ + RDB_DRIVETRAIN_t drivetrain; /**< info about a vehicle's drivetrain @msgid RDB_PKG_ID_DRIVETRAIN */ + RDB_WHEEL_t wheel; /**< info about a wheel of a player @msgid RDB_PKG_ID_WHEEL */ + RDB_PED_ANIMATION_t pedAnimation; /**< pedestrian animation details (joint angles etc.) @msgid RDB_PKG_ID_PED_ANIMATION */ + RDB_SENSOR_STATE_t sensorState; /**< state of a sensor @msgid RDB_PKG_ID_SENSOR_STATE */ + RDB_SENSOR_OBJECT_t sensorObject; /**< state of an object detected by a sensor @msgid RDB_PKG_ID_SENSOR_OBJECT */ + RDB_CAMERA_t camera; /**< camera settings used for video image @msgid RDB_PKG_ID_CAMERA */ + RDB_CONTACT_POINT_t contactPoint; /**< info about contact points @msgid RDB_PKG_ID_CONTACT_POINT */ + RDB_TRAFFIC_SIGN_t trafficSign; /**< info about traffic signs seen by a vehicle @msgid RDB_PKG_ID_TRAFFIC_SIGN */ + RDB_ROAD_STATE_t roadState; /**< road state informaton for a given player @msgid RDB_PKG_ID_ROAD_STATE */ + RDB_IMAGE_t image; /**< video image (followed by data) @msgid RDB_PKG_ID_IMAGE */ + RDB_LIGHT_SOURCE_t lightSrc; /**< info about a light source @msgid RDB_PKG_ID_LIGHT_SOURCE */ + RDB_ENVIRONMENT_t environment; /**< info about environment state @msgid RDB_PKG_ID_ENVIRONMENT */ + RDB_TRIGGER_t trigger; /**< trigger information @msgid RDB_PKG_ID_TRIGGER */ + RDB_DRIVER_CTRL_t driverCtrl; /**< driver input (e.g. from mockup) - serves also as dynamics input @msgid RDB_PKG_ID_DRIVER_CTRL */ + RDB_TRAFFIC_LIGHT_t trafficLight; /**< info about a traffic light @msgid RDB_PKG_ID_TRAFFIC_LIGHT */ + RDB_SYNC_t sync; /**< sync source message @msgid RDB_PKG_ID_SYNC */ + RDB_DRIVER_PERCEPTION_t driverPerception; /**< perception of road/rule environment by driver @msgid RDB_PKG_ID_DRIVER_PERCEPTION */ + RDB_IMAGE_t lightMap; /**< light distribution image (followed by data) @msgid RDB_PKG_ID_LIGHT_MAP */ + RDB_FUNCTION_t toneMapping; /**< tone mapping function @msgid RDB_PKG_ID_TONE_MAPPING */ +/* custom packages here, please */ + RDB_CUSTOM_SCORING_t scoring; /**< scoring information @msgid RDB_PKG_ID_CUSTOM_SCORING */ +} RDB_MSG_UNION_t; +} +/** ------ now a complete message containing one element only ------ */ +typedef struct +{ + RDB_MSG_HDR_t hdr; /**< header of a complete message @unit RDB_MSG_HDR_t @version 0x0100 */ + RDB_MSG_ENTRY_HDR_t entryHdr; /**< header of a package vector within a message @unit RDB_MSG_ENTRY_HDR_t @version 0x0100 */ + RDB_MSG_UNION_t u; /**< the message union @unit RDB_MSG_UNION_t @version 0x0100 */ +} RDB_MSG_t; + +/** ------ shared memory segment header, located of beginning of shared memory segment ------ */ +typedef struct +{ + uint32_t thisSize; /**< size of this info structure @unit byte @version 0x0100 */ + uint32_t bufferSize; /**< size of the associated buffer @unit byte @version 0x0100 */ + uint16_t id; /**< unique ID of the buffer @unit _ @version 0x0100 */ + uint16_t spare0; /**< just some spare @unit _ @version 0x0100 */ + uint32_t flags; /**< access flags etc. @unit @link RDB_SHM_BUFFER_FLAG @endlink @version 0x0100 */ + uint32_t offset; /**< offset to start of buffer from start of shared memory @unit byte @version 0x0100 */ + uint32_t spare1[4]; /**< just some spares @unit _ @version 0x0100 */ +} RDB_SHM_BUFFER_INFO_t; + +/** ------ shared memory management header, located of beginning of shared memory ------ +* @note this entry is followed immediately by "noBuffers" bytes of type RDB_SHM_BUFFER_INFO_t, containing "noBuffers" buffer information entries +*/ +typedef struct +{ + uint32_t headerSize; /**< size of this header structure @unit byte @version 0x0100 */ + uint32_t dataSize; /**< size of data following this header @unit byte @version 0x0100 */ + uint8_t noBuffers; /**< number of data buffers in the shared memory @unit _ @version 0x0100 */ +} RDB_SHM_HDR_t; + +#endif /* _VIRES_RDB_ICD_H */ + +// object controller? +// intitialization via SCP + +// end of pragma 4 +#pragma pack(pop) diff --git a/test/headerrepresentation/files/viRDBIcd_expected.description b/test/headerrepresentation/files/viRDBIcd_expected.description new file mode 100644 index 0000000..05c2e9c --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd_expected.description @@ -0,0 +1,561 @@ + + +
+ 3.00 + ANOAFR4 + 11.04.2016 + 11.04.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/viRDBIcd_expected.h b/test/headerrepresentation/files/viRDBIcd_expected.h new file mode 100644 index 0000000..72aa9d3 --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd_expected.h @@ -0,0 +1,765 @@ +// This is a generated file, changes to it may be overwritten in the future. + +typedef enum { + PF_UNKNOWN=0, + PF_8BIT=10, + PF_GREYSCALE_8=11, + PF_RGB_8=12, + PF_16BIT=20, + PF_GREYSCALE_10=21, + PF_GREYSCALE_12=22, + PF_GREYSCALE_14=23, + PF_GREYSCALE_16=24, + PF_RGB_444=25, + PF_RGB_555=26, + PF_RGB_565=27, + PF_RGBA_4444=28, + PF_ABGR_4444=29, + PF_RIII_10=30, + PF_RIII_12=31, + PF_RIII_14=32, + PF_RIII_16=33, + PF_BGR_555=34, + PF_BGR_565=35, + PF_24BIT=40, + PF_GREYSCALE_18=41, + PF_GREYSCALE_20=42, + PF_GREYSCALE_22=43, + PF_GREYSCALE_24=44, + PF_RGB_888=45, + PF_BGR_888=46, + PF_32BIT=50, + PF_ARGB_8888=51, + PF_ABGR_8888=52, + PF_RGBA_8888=53, + PF_BGRA_8888=54, + PF_GREYSCALE_32=55, + PF_GREYSCALE_FLOAT32=56, + PF_YUV420P_888=60, + PF_CUSTOM=1000 +} tPixelFormat; + +#pragma pack(push,4) +typedef struct +{ + tFloat64 x; + tFloat64 y; + tFloat64 z; + tUInt8 flags; + tUInt8 type; + tUInt16 system; +} RDB_POINT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat64 x; + tFloat64 y; + tFloat64 z; + tFloat32 h; + tFloat32 p; + tFloat32 r; + tUInt8 flags; + tUInt8 type; + tUInt16 system; +} RDB_COORD_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 id; + tUInt16 spare; + RDB_COORD_t pos; +} RDB_COORD_SYSTEM_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tUInt16 roadId; + tInt8 laneId; + tUInt8 flags; + tFloat32 roadS; + tFloat32 roadT; + tFloat32 laneOffset; + tFloat32 hdgRel; + tFloat32 pitchRel; + tFloat32 rollRel; + tUInt8 roadType; + tUInt8 spare1; + tUInt16 spare2; + tFloat32 pathS; +} RDB_ROAD_POS_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tInt8 id; + tInt8 prevId; + tInt8 nextId; + tUInt8 spare0; + tFloat32 lateralDist; + tFloat32 yawRel; + tFloat64 curvHor; + tFloat64 curvHorDot; + tFloat32 startDx; + tFloat32 previewDx; + tFloat32 width; + tFloat32 height; + tFloat64 curvVert; + tFloat64 curvVertDot; + tUInt8 type; + tUInt8 color; + tUInt16 noDataPoints; + tUInt32 spare1[2]; +} RDB_ROADMARK_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 roadId; + tInt8 id; + tUInt8 neighborMask; + tInt8 leftLaneId; + tInt8 rightLaneId; + tUInt8 borderType; + tUInt8 material; + tUInt16 status; + tUInt16 type; + tFloat32 width; + tFloat64 curvVert; + tFloat64 curvVertDot; + tFloat64 curvHor; + tFloat64 curvHorDot; + tUInt32 playerId; + tUInt32 spare1; +} RDB_LANE_INFO_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt8 category; + tUInt8 type; + tInt16 modelId; + tChar name[32]; + tChar modelName[32]; + tChar fileName[1024]; + tUInt16 flags; + tUInt16 spare0; + tUInt32 spare1; +} RDB_OBJECT_CFG_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 dimX; + tFloat32 dimY; + tFloat32 dimZ; + tFloat32 offX; + tFloat32 offY; + tFloat32 offZ; +} RDB_GEOMETRY_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt8 category; + tUInt8 type; + tUInt16 visMask; + tChar name[32]; + RDB_GEOMETRY_t geo; + RDB_COORD_t pos; + tUInt32 parent; + tUInt32 spare1; +} RDB_OBJECT_STATE_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_COORD_t speed; + RDB_COORD_t accel; + tUInt32 spare[4]; +} RDB_OBJECT_STATE_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_OBJECT_STATE_BASE_t base; + RDB_OBJECT_STATE_EXT_t ext; +} RDB_OBJECT_STATE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat32 rps; + tFloat32 load; + tUInt32 spare1[2]; +} RDB_ENGINE_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 rpsStart; + tFloat32 torque; + tFloat32 torqueInner; + tFloat32 torqueMax; + tFloat32 torqueFriction; + tFloat32 fuelCurrent; + tFloat32 fuelAverage; + tUInt32 spare[2]; +} RDB_ENGINE_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_ENGINE_BASE_t base; + RDB_ENGINE_EXT_t ext; +} RDB_ENGINE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tUInt8 gearBoxType; + tUInt8 driveTrainType; + tUInt8 gear; + tUInt8 spare0; + tUInt32 spare1[2]; +} RDB_DRIVETRAIN_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 torqueGearBoxIn; + tFloat32 torqueCenterDiffOut; + tFloat32 torqueShaft; + tUInt32 spare1[2]; +} RDB_DRIVETRAIN_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_DRIVETRAIN_BASE_t base; + RDB_DRIVETRAIN_EXT_t ext; +} RDB_DRIVETRAIN_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tUInt8 id; + tUInt8 spare0[3]; + tFloat32 radiusStatic; + tFloat32 springCompression; + tFloat32 rotAngle; + tFloat32 slip; + tFloat32 steeringAngle; + tUInt32 spare1[4]; +} RDB_WHEEL_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 vAngular; + tFloat32 forceZ; + tFloat32 forceLat; + tFloat32 forceLong; + tFloat32 forceTireWheelXYZ[3]; + tFloat32 radiusDynamic; + tFloat32 brakePressure; + tFloat32 torqueDriveShaft; + tFloat32 damperSpeed; + tUInt32 spare2[4]; +} RDB_WHEEL_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_WHEEL_BASE_t base; + RDB_WHEEL_EXT_t ext; +} RDB_WHEEL_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tUInt32 lightMask; + tFloat32 steering; + tFloat32 steeringWheelTorque; + tUInt8 accMask; + tUInt8 accSpeed; + tUInt8 batteryState; + tInt8 batteryRate; + tUInt16 displayLightMask; + tUInt16 spare0; + tUInt32 spare[5]; +} RDB_VEHICLE_SYSTEMS_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat32 mass; + tFloat32 wheelBase; + tInt32 spare[4]; +} RDB_VEHICLE_SETUP_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt16 width; + tUInt16 height; + tUInt8 pixelSize; + tUInt8 pixelFormat; + tUInt16 spare0; + tUInt32 imgSize; + tUInt8 color[4]; + tUInt32 spare1[3]; +} RDB_IMAGE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt8 type; + tUInt8 dimension; + tUInt16 spare; + tUInt32 dataSize; + tUInt32 spare1[4]; +} RDB_FUNCTION_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt8 type; + tUInt8 hostCategory; + tUInt16 spare0; + tUInt32 hostId; + tChar name[32]; + tFloat32 fovHV[2]; + tFloat32 clipNF[2]; + RDB_COORD_t pos; + RDB_COORD_t originCoordSys; + tInt32 spare[4]; +} RDB_SENSOR_STATE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt8 category; + tUInt8 type; + tUInt16 flags; + tUInt32 id; + tUInt32 sensorId; + tFloat64 dist; + RDB_COORD_t sensorPos; + tInt8 occlusion; + tUInt8 spare0[3]; + tUInt32 spare[3]; +} RDB_SENSOR_OBJECT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 id; + tUInt16 width; + tUInt16 height; + tUInt16 spare0; + tFloat32 clipNear; + tFloat32 clipFar; + tFloat32 focalX; + tFloat32 focalY; + tFloat32 principalX; + tFloat32 principalY; + RDB_COORD_t pos; + tUInt32 spare1[4]; +} RDB_CAMERA_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 id; + tInt8 templateId; + tUInt8 state; + tInt32 playerId; + RDB_COORD_t pos; + tUInt16 flags; + tUInt16 spare0; + tInt32 spare1[2]; +} RDB_LIGHT_SOURCE_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 nearFar[2]; + tFloat32 frustumLRBT[4]; + tFloat32 intensity[3]; + tFloat32 atten[3]; + tInt32 spare1[3]; +} RDB_LIGHT_SOURCE_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_LIGHT_SOURCE_BASE_t base; + RDB_LIGHT_SOURCE_EXT_t ext; +} RDB_LIGHT_SOURCE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 id; + tUInt16 flags; + RDB_COORD_t roadDataIn; + tFloat32 friction; + tInt32 playerId; + tInt32 spare1; +} RDB_CONTACT_POINT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt32 playerId; + tFloat32 roadDist; + RDB_COORD_t pos; + tInt32 type; + tInt32 subType; + tFloat32 value; + tUInt32 state; + tInt8 readability; + tInt8 occlusion; + tUInt16 spare0; + tUInt32 addOnId; + tInt8 minLane; + tInt8 maxLane; + tUInt16 spare; +} RDB_TRAFFIC_SIGN_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tInt8 wheelId; + tUInt8 spare0; + tUInt16 spare1; + tUInt32 roadId; + tFloat32 defaultSpeed; + tFloat32 waterLevel; + tUInt32 eventMask; + tInt32 spare2[12]; +} RDB_ROAD_STATE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 visibility; + tUInt32 timeOfDay; + tFloat32 brightness; + tUInt8 precipitation; + tUInt8 cloudState; + tUInt16 flags; + tUInt32 spare1[8]; +} RDB_ENVIRONMENT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + RDB_COORD_t pos; + tUInt32 spare[4]; + tUInt32 noCoords; + tUInt32 dataSize; +} RDB_PED_ANIMATION_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat32 pathS; + tFloat32 roadS; + tFloat32 fuelCurrent; + tFloat32 fuelAverage; + tUInt32 stateFlags; + tFloat32 slip; + tUInt32 spare[4]; +} RDB_CUSTOM_SCORING_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 deltaT; + tUInt32 frameNo; + tInt32 spare; +} RDB_TRIGGER_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat32 steeringWheel; + tFloat32 steeringSpeed; + tFloat32 throttlePedal; + tFloat32 brakePedal; + tFloat32 clutchPedal; + tFloat32 accelTgt; + tFloat32 steeringTgt; + tFloat64 curvatureTgt; + tFloat32 steeringTorque; + tFloat32 engineTorqueTgt; + tFloat32 speedTgt; + tUInt8 gear; + tUInt8 sourceId; + tUInt8 spare0[2]; + tUInt32 validityFlags; + tUInt32 flags; + tUInt32 mockupInput0; + tUInt32 mockupInput1; + tUInt32 mockupInput2; + tUInt32 spare; +} RDB_DRIVER_CTRL_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat32 speedFromRules; + tFloat32 distToSpeed; + tFloat32 spare0[4]; + tUInt32 flags; + tUInt32 spare[4]; +} RDB_DRIVER_PERCEPTION_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tInt32 id; + tFloat32 state; + tUInt32 stateMask; +} RDB_TRAFFIC_LIGHT_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 duration; + tUInt8 type; + tUInt8 spare[3]; +} RDB_TRAFFIC_LIGHT_PHASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tInt32 ctrlId; + tFloat32 cycleTime; + tUInt16 noPhases; + tUInt32 dataSize; +} RDB_TRAFFIC_LIGHT_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_TRAFFIC_LIGHT_BASE_t base; + RDB_TRAFFIC_LIGHT_EXT_t ext; +} RDB_TRAFFIC_LIGHT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 mask; + tUInt32 cmdMask; + tUInt32 spare[2]; +} RDB_SYNC_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 id; + tUInt16 flags; + tUInt16 spare[2]; + tFloat64 x; + tFloat64 y; +} RDB_ROAD_QUERY_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 version; + tUInt16 spare; + tChar sender[64]; + tChar receiver[64]; + tUInt32 dataSize; +} RDB_SCP_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tFloat64 spacing; + tUInt16 flags; + tUInt16 noDataPoints; + tUInt32 spare[4]; +} RDB_TRAJECTORY_t; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ +} RDB_END_OF_FRAME_t; +#pragma pack(pop) + +#pragma pack(push,1) +typedef struct +{ +} RDB_START_OF_FRAME_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt16 magicNo; + tUInt16 version; + tUInt32 headerSize; + tUInt32 dataSize; + tUInt32 frameNo; + tFloat64 simTime; +} RDB_MSG_HDR_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 headerSize; + tUInt32 dataSize; + tUInt32 elementSize; + tUInt16 pkgId; + tUInt16 flags; +} RDB_MSG_ENTRY_HDR_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_MSG_HDR_t hdr; + RDB_MSG_ENTRY_HDR_t entryHdr; +} RDB_MSG_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 thisSize; + tUInt32 bufferSize; + tUInt16 id; + tUInt16 spare0; + tUInt32 flags; + tUInt32 offset; + tUInt32 spare1[4]; +} RDB_SHM_BUFFER_INFO_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 headerSize; + tUInt32 dataSize; + tUInt8 noBuffers; +} RDB_SHM_HDR_t; +#pragma pack(pop) + +typedef double tFloat64; + +typedef uint8_t tUInt8; + +typedef uint16_t tUInt16; + +typedef float tFloat32; + +typedef uint32_t tUInt32; + +typedef int8_t tInt8; + +typedef int16_t tInt16; + +typedef char tChar; + +typedef int32_t tInt32; + +// The following type is assumed to be known: +// double + +// The following type is assumed to be known: +// uint8_t + +// The following type is assumed to be known: +// uint16_t + +// The following type is assumed to be known: +// float + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// int8_t + +// The following type is assumed to be known: +// int16_t + +// The following type is assumed to be known: +// char + +// The following type is assumed to be known: +// int32_t + diff --git a/test/headerrepresentation/files/viRDBIcd_extract_expected.description b/test/headerrepresentation/files/viRDBIcd_extract_expected.description new file mode 100644 index 0000000..6a1a3f9 --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd_extract_expected.description @@ -0,0 +1,152 @@ + + +
+ 3.00 + ANOAFR4 + 11.04.2016 + 11.04.2016 + Generated by ADTF 2.14.0beta +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/test/headerrepresentation/files/viRDBIcd_extract_expected.h b/test/headerrepresentation/files/viRDBIcd_extract_expected.h new file mode 100644 index 0000000..0402111 --- /dev/null +++ b/test/headerrepresentation/files/viRDBIcd_extract_expected.h @@ -0,0 +1,99 @@ +// This is a generated file, changes to it may be overwritten in the future. + +#pragma pack(push,4) +typedef struct +{ + tUInt32 playerId; + tUInt8 gearBoxType; + tUInt8 driveTrainType; + tUInt8 gear; + tUInt8 spare0; + tUInt32 spare1[2]; +} RDB_DRIVETRAIN_BASE_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat32 torqueGearBoxIn; + tFloat32 torqueCenterDiffOut; + tFloat32 torqueShaft; + tUInt32 spare1[2]; +} RDB_DRIVETRAIN_EXT_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + RDB_DRIVETRAIN_BASE_t base; + RDB_DRIVETRAIN_EXT_t ext; +} RDB_DRIVETRAIN_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tFloat64 x; + tFloat64 y; + tFloat64 z; + tFloat32 h; + tFloat32 p; + tFloat32 r; + tUInt8 flags; + tUInt8 type; + tUInt16 system; +} RDB_COORD_t; +#pragma pack(pop) + +#pragma pack(push,4) +typedef struct +{ + tUInt32 id; + tUInt8 type; + tUInt8 hostCategory; + tUInt16 spare0; + tUInt32 hostId; + tChar name[32]; + tFloat32 fovHV[2]; + tFloat32 clipNF[2]; + RDB_COORD_t pos; + RDB_COORD_t originCoordSys; + tInt32 spare[4]; +} RDB_SENSOR_STATE_t; +#pragma pack(pop) + +typedef uint32_t tUInt32; + +typedef uint8_t tUInt8; + +typedef float tFloat32; + +typedef double tFloat64; + +typedef uint16_t tUInt16; + +typedef char tChar; + +typedef int32_t tInt32; + +// The following type is assumed to be known: +// uint32_t + +// The following type is assumed to be known: +// uint8_t + +// The following type is assumed to be known: +// float + +// The following type is assumed to be known: +// double + +// The following type is assumed to be known: +// uint16_t + +// The following type is assumed to be known: +// char + +// The following type is assumed to be known: +// int32_t + diff --git a/test/headerrepresentation/files/wrong_header.h b/test/headerrepresentation/files/wrong_header.h new file mode 100644 index 0000000..858391e --- /dev/null +++ b/test/headerrepresentation/files/wrong_header.h @@ -0,0 +1,19 @@ +// For type # see implementation of cHeaderImporter::BuildStructs() + +// Type #4 +struct +{ + tUInt8 a; +} simple_var; + +// Type #5 +struct +{ + tUInt8 b; +}; + +// Type #6 +typedef struct +{ + tUInt8 c; +}; \ No newline at end of file diff --git a/test/headerrepresentation/src/CMakeLists.txt b/test/headerrepresentation/src/CMakeLists.txt new file mode 100644 index 0000000..b5bf6ef --- /dev/null +++ b/test/headerrepresentation/src/CMakeLists.txt @@ -0,0 +1,25 @@ +# to use generator lib we add sources to test because tester doesn't have this +# internal lib for linking +include(../../../ddlgenerators/generator_library/ddl_generator_lib.sources) +include_directories(../../../ddlgenerators/generator_library/headerrepresentation) + +set(TEST_NAME headerrepresentation) + +add_executable(tester_${TEST_NAME} tester_${TEST_NAME}.cpp + ${HEADER_PRESENTATION_H} + ${HEADER_PRESENTATION_CPP} + ddl_definitions.h) + +set_target_properties(tester_${TEST_NAME} PROPERTIES FOLDER test/ddl) +set_target_properties(tester_${TEST_NAME} PROPERTIES TIMEOUT 120) + +target_link_libraries(tester_${TEST_NAME} PRIVATE + ddl_test_compat + ddl + a_util_result + GTest::Main + $<$:Threads::Threads> +) +add_test(NAME tester_${TEST_NAME} + COMMAND tester_${TEST_NAME} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../") diff --git a/test/headerrepresentation/src/ddl_definitions.h b/test/headerrepresentation/src/ddl_definitions.h new file mode 100644 index 0000000..9de7658 --- /dev/null +++ b/test/headerrepresentation/src/ddl_definitions.h @@ -0,0 +1,616 @@ +/** + * @file + * Headerfile for the tester for the DDL representation. + * + * @copyright + * @verbatim + Copyright @ 2017 Audi Electronics Venture GmbH. All rights reserved. + + This Source Code Form is subject to the terms of the Mozilla + Public License, v. 2.0. If a copy of the MPL was not distributed + with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + + If it is not possible or desirable to put the notice in a particular file, then + You may include the notice in a location (such as a LICENSE file in a + relevant directory) where a recipient would be likely to look for such a notice. + + You may add additional accurate notices of copyright ownership. + @endverbatim +*/ + +#ifndef _TESTER_DDL_DEFINITIONS_HEADER_ +#define _TESTER_DDL_DEFINITIONS_HEADER_ + +static const std::string DDL_TEST_STRING = +"\n \ +\n \ +
\n \ + 1.0+\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +
"; + +// Test DDL that differs in the type of tBitmapFormat::nBytesPerLine +static const std::string DDL_TEST_STRING_DIFF = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + +// Test DDL that differs by names +static const std::string DDL_TEST_STRING_DIFF_NAMES = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + + +// Test DDL that differs by version +static const std::string DDL_TEST_STRING_DIFF_VERSION = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + +// Test DDL that differs by version +static const std::string DDL_TEST_STRING_DIFF_ARRAY = +"\n \ +\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ +"; + + +// Test DDL where tBitmapFormat is only a subset +static const std::string DDL_TEST_STRING_SUBSET = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + + +// Test DDL where tMediaTypInfo is one element short +static const std::string DDL_TEST_STRING_INVALID_SUBSET = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content +static const std::string DDL_TEST_STRING_DYNAMIC = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content but with different naming +static const std::string DDL_TEST_STRING_DYNAMIC_NAME_DIFF = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content that is not binary equal (tBitmapFormat::nPixelFormat2) +static const std::string DDL_TEST_STRING_DYNAMIC_BIN_DIFF = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL with dynamic content that is not binary equal in dynamic part (tMediaTypeInfo::ui32Flags has different type) +static const std::string DDL_TEST_STRING_DYNAMIC_BIN_DIFF_2 = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL to where the orignial struct layout is not the same (tTest1 vs tTest2) but the binary positions match +static const std::string DDL_TEST_STRING_LAYOUT_TEST = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + +// Test DDL to where the array size element is different +static const std::string DDL_TEST_STRING_DYNAMIC_DIFF_ARRAY_SPEC = + "\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + "; + + +static const std::string DDL_TEST_STRING_UNITS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + 1.0 \ + 1.0 \ + 1.0 \ + \ + \ + \ + 1.0 \ + 1.0 \ + 1.0 \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_ENUMS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \n \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_HEADER = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ + \ + \ +
\n \ + \ + \ + \ +
"; + + +static const std::string DDL_TEST_STRING_USER_BASE_UNITS = +"\n \ +\n \ +
\n \ + 3.0\n \ + AUDI Electronics Venture GmbH\n \ + 20100407\n \ + \n \ + ADTF Common Description File\n \ +
\n \ + \ + \ + \ + \n \ + \n \ + \n \ + \ + \ + \ + \ + \ + \ +
"; + +static const std::string DDL_TEST_STRING_STREAM_TO_PREFIX = +"\ +\ +
\ + 1.02\ + AUDI Electronics Venture GmbH\ + 07.04.2010\ + 03.04.2014\ + ADTF Common Description File\ +
\ + \ + \ + \ + \ + 1\ + 1\ + 1.000000\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
\ +"; + +#endif diff --git a/test/headerrepresentation/src/tester_headerrepresentation.cpp b/test/headerrepresentation/src/tester_headerrepresentation.cpp new file mode 100644 index 0000000..a1401cb --- /dev/null +++ b/test/headerrepresentation/src/tester_headerrepresentation.cpp @@ -0,0 +1,956 @@ +/** + * + * Test functions for