From b0703c7e0a9564613d4a6c25fe0c8c5eb2cad2f0 Mon Sep 17 00:00:00 2001 From: Roberto Martin Fantini Date: Fri, 25 Jul 2025 09:04:15 +0200 Subject: [PATCH 1/2] Correct the case of initial value at parse time for set and enums --- src/fast_type_gen/cpp_gen.cpp | 21 +++++++++++++++++---- src/mfast/xml_parser/templates_builder.cpp | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/fast_type_gen/cpp_gen.cpp b/src/fast_type_gen/cpp_gen.cpp index 2571021..1d5c89a 100644 --- a/src/fast_type_gen/cpp_gen.cpp +++ b/src/fast_type_gen/cpp_gen.cpp @@ -635,6 +635,8 @@ void cpp_gen::visit(const mfast::enum_field_instruction *inst, void *pIndex) { std::string context = gen_op_context(inst->name(), inst->op_context()); + const mfast::value_storage &init_value = inst->initial_value(); + out_ << "const static " << instruction_type.str() << "\n" << instruction_variable_name << "(\n" << " " << get_operator_name(inst) << ",\n" @@ -643,8 +645,12 @@ void cpp_gen::visit(const mfast::enum_field_instruction *inst, void *pIndex) { << " \"" << inst->name() << "\", // name\n" << " \"" << inst->ns() << "\", // ns\n" << " " << context << ", // opContext\n" - << " int_value_storage(" - << inst->initial_value().get() << "), // initial_value\n" + << " int_value_storage("; + + if (!init_value.is_empty()) + out_ << init_value.get(); + + out_ << "), // initial_value\n" << " " << elements_variable_name.str() << ", // element names\n" << " " << values_variable_name << ", // element values\n" << " " << num_elements_name.str() << ",// num elements\n" @@ -702,6 +708,9 @@ void cpp_gen::visit(const mfast::set_field_instruction *inst, void *pIndex) out_ << "};\n"; } std::string context = gen_op_context(inst->name(), inst->op_context()); + + const mfast::value_storage &init_value = inst->initial_value(); + out_ << "const static " << instruction_type.str() << "\n" << instruction_variable_name << "(\n" << " " << get_operator_name(inst) << ",\n" @@ -710,8 +719,12 @@ void cpp_gen::visit(const mfast::set_field_instruction *inst, void *pIndex) << " \"" << inst->name() << "\", // name\n" << " \"" << inst->ns() << "\", // ns\n" << " " << context << ", // opContext\n" - << " int_value_storage(" - << inst->initial_value().get() << "), // initial_value\n" + << " int_value_storage("; + + if (!init_value.is_empty()) + out_ << init_value.get(); + + out_ << "), // initial_value\n" << " " << elements_variable_name.str() << ", // element names\n" << " " << num_elements_name.str() << ",// num elements\n" << " nullptr, // ref_instruction\n" diff --git a/src/mfast/xml_parser/templates_builder.cpp b/src/mfast/xml_parser/templates_builder.cpp index 6f5b923..eac4853 100644 --- a/src/mfast/xml_parser/templates_builder.cpp +++ b/src/mfast/xml_parser/templates_builder.cpp @@ -35,10 +35,10 @@ templates_builder::templates_builder(dynamic_templates_description *definition, instructions_view_t(nullptr, 0), nullptr, nullptr, &length_instruction_prototype, "", "", cpp_ns_), enum_field_instruction_prototype_(operator_none, presence_mandatory, 0, - nullptr, "", nullptr, 0, nullptr, + nullptr, "", nullptr, int_value_storage(), nullptr, nullptr, 0, nullptr, cpp_ns_), set_field_instruction_prototype_(operator_none, presence_mandatory, 0, - nullptr, "", nullptr, 0, nullptr, + nullptr, "", nullptr, int_value_storage(), nullptr, 0, nullptr, cpp_ns_) { static const int32_field_instruction int32_field_instruction_prototype( operator_none, presence_mandatory, 0, nullptr, "", nullptr, From 581e0cee8d22c7081be8b7c2bc629316b83a63b7 Mon Sep 17 00:00:00 2001 From: Roberto Martin Fantini Date: Fri, 25 Jul 2025 09:10:18 +0200 Subject: [PATCH 2/2] Unit test for the empty default value --- tests/enum_encoder_decoder.cpp | 30 +++++++++++++++++++++++++ tests/enum_encoder_decoder_v2.cpp | 19 ++++++++++++++++ tests/set_encoder_decoder.cpp | 26 +++++++++++++++++++++ tests/set_encoder_decoder_v2.cpp | 26 +++++++++++++++++++++ tests/simple16.xml | 4 ++++ tests/simple18.xml | 6 ++++- tests/xetra_enum_encoder_decoder.cpp | 25 ++++++++++++++++++++- tests/xetra_enum_encoder_decoder_v2.cpp | 25 ++++++++++++++++++++- 8 files changed, 158 insertions(+), 3 deletions(-) diff --git a/tests/enum_encoder_decoder.cpp b/tests/enum_encoder_decoder.cpp index e8a0ca8..ba70223 100644 --- a/tests/enum_encoder_decoder.cpp +++ b/tests/enum_encoder_decoder.cpp @@ -27,3 +27,33 @@ TEST_CASE("enum test copy encoder/decoder","[enum_copy_encoder_decoder]") REQUIRE(test_case.encoding(test_3.cref(),"\xE0\x83\x83",true)); REQUIRE(test_case.decoding("\xE0\x83\x83",test_3.cref(),true)); } + +TEST_CASE("optional value present in enum with default encoder/decoder","[optional_preset_enum_default_encoder_decoder]") +{ + fast_test_coding_case test_case; + simple16::Test_4 test_4; + simple16::Test_4_mref test_4_mref = test_4.mref(); + test_4_mref.set_discrete().as_Three(); + REQUIRE(test_4.cref().get_discrete().present()); + // \xE0 : 1110 : OK + // 1 : Stop Bit. + // 1 : Set Template Id. + // 1 : Set Field discrete + // 0 : Not used + REQUIRE(test_case.encoding(test_4.cref(),"\xE0\x84\x84", true)); + REQUIRE(test_case.decoding("\xE0\x84\x84",test_4.cref(), true)); +} + +TEST_CASE("optional value not present in enum with default encoder/decoder","[optional_preset_enum_default_encoder_decoder]") +{ + fast_test_coding_case test_case; + simple16::Test_4 test_4; + REQUIRE(!test_4.cref().get_discrete().present()); + // \xC0 : 1100 : OK + // 1 : Stop Bit. + // 1 : Set Template Id. + // 0 : Not Set Field discrete + // 0 : Not used + REQUIRE(test_case.encoding(test_4.cref(),"\xC0\x84", true)); + REQUIRE(test_case.decoding("\xC0\x84",test_4.cref(), true)); +} diff --git a/tests/enum_encoder_decoder_v2.cpp b/tests/enum_encoder_decoder_v2.cpp index 0643b6c..7b9e2ea 100644 --- a/tests/enum_encoder_decoder_v2.cpp +++ b/tests/enum_encoder_decoder_v2.cpp @@ -27,3 +27,22 @@ TEST_CASE("enum test copy encoder_V2/decoder_v2","[enum_copy_encoder_v2_decoder_ REQUIRE(test_case.encoding(test_3.cref(),"\xE0\x83\x83",true)); REQUIRE(test_case.decoding("\xE0\x83\x83",test_3.cref(),true)); } + +TEST_CASE("optional value present in enum with default encoder_V2/decoder_v2","[optional_preset_enum_default_encoder_v2_decoder_v2]") +{ + fast_test_coding_case_v2 test_case; + simple16::Test_4 test_4; + simple16::Test_4_mref test_4_mref = test_4.mref(); + test_4_mref.set_discrete().as_Three(); + REQUIRE(test_case.encoding(test_4.cref(),"\xE0\x84\x84", true)); + REQUIRE(test_case.decoding("\xE0\x84\x84",test_4.cref(), true)); +} + +TEST_CASE("optional value not present in enum with default encoder_V2/decoder_v2","[optional_preset_enum_default_encoder_v2_decoder_v2]") +{ + fast_test_coding_case_v2 test_case; + simple16::Test_4 test_4; + REQUIRE(!test_4.cref().get_discrete().present()); + REQUIRE(test_case.encoding(test_4.cref(),"\xC0\x84", true)); + REQUIRE(test_case.decoding("\xC0\x84",test_4.cref(), true)); +} diff --git a/tests/set_encoder_decoder.cpp b/tests/set_encoder_decoder.cpp index 564cbf7..6d0003f 100644 --- a/tests/set_encoder_decoder.cpp +++ b/tests/set_encoder_decoder.cpp @@ -23,3 +23,29 @@ TEST_CASE("set encoder/decoder","[set_encoder_decoder]") REQUIRE(test_case.encoding(test_1.cref(),"\xF0\x81\x8A\x94",true)); REQUIRE(test_case.decoding("\xF0\x81\x8A\x94",test_1.cref(),true)); } + +TEST_CASE("set optional field encoder/decoder","[set_optional_encoder_decoder]") +{ + SECTION("optional field present") + { + fast_test_coding_case test_case; + simple19::Test_3 test_3; + simple19::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_field3().as(10); + test_3_mref.set_TradeCondition().set_VolumeOnly(); + REQUIRE(test_3.cref().get_TradeCondition().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xF0\x83\x8A\x02\x81", true)); + REQUIRE(test_case.decoding("\xF0\x83\x8A\x02\x81", test_3.cref(), true)); + } + + SECTION("optional field not present") + { + fast_test_coding_case test_case; + simple19::Test_3 test_3; + simple19::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_field3().as(10); + REQUIRE(!test_3.cref().get_TradeCondition().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xE0\x83\x8A", true)); + REQUIRE(test_case.decoding("\xE0\x83\x8A", test_3.cref(), true)); + } +} diff --git a/tests/set_encoder_decoder_v2.cpp b/tests/set_encoder_decoder_v2.cpp index b0133ac..9a5a2f0 100644 --- a/tests/set_encoder_decoder_v2.cpp +++ b/tests/set_encoder_decoder_v2.cpp @@ -23,3 +23,29 @@ TEST_CASE("set encoder_V2/decoder_v2","[set_encoder_v2_decoder_v2]") REQUIRE(test_case.encoding(test_1.cref(),"\xF0\x81\x8A\x94",true)); REQUIRE(test_case.decoding("\xF0\x81\x8A\x94",test_1.cref(),true)); } + +TEST_CASE("set optional field encoder_V2/decoder_v2","[set_optional_encoder_v2_decoder_v2]") +{ + SECTION("optional field present") + { + fast_test_coding_case_v2 test_case; + simple19::Test_3 test_3; + simple19::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_field3().as(10); + test_3_mref.set_TradeCondition().set_VolumeOnly(); + REQUIRE(test_3.cref().get_TradeCondition().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xF0\x83\x8A\x02\x81", true)); + REQUIRE(test_case.decoding("\xF0\x83\x8A\x02\x81", test_3.cref(), true)); + } + + SECTION("optional field not present") + { + fast_test_coding_case_v2 test_case; + simple19::Test_3 test_3; + simple19::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_field3().as(10); + REQUIRE(!test_3.cref().get_TradeCondition().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xE0\x83\x8A", true)); + REQUIRE(test_case.decoding("\xE0\x83\x8A", test_3.cref(), true)); + } +} diff --git a/tests/simple16.xml b/tests/simple16.xml index cb8207c..33da558 100644 --- a/tests/simple16.xml +++ b/tests/simple16.xml @@ -22,4 +22,8 @@ + diff --git a/tests/simple18.xml b/tests/simple18.xml index 1601294..d2019fe 100644 --- a/tests/simple18.xml +++ b/tests/simple18.xml @@ -27,4 +27,8 @@ - \ No newline at end of file + + diff --git a/tests/xetra_enum_encoder_decoder.cpp b/tests/xetra_enum_encoder_decoder.cpp index 75e0770..78fc24a 100644 --- a/tests/xetra_enum_encoder_decoder.cpp +++ b/tests/xetra_enum_encoder_decoder.cpp @@ -40,4 +40,27 @@ TEST_CASE("xetra enum test encoder/decoder","[xetra_enum_encoder_decoder]") REQUIRE(test_case.encoding(test_1.cref(),"\xe0\x81\x81\x83",true)); REQUIRE(test_case.decoding("\xe0\x81\x81\x83",test_1.cref(),true)); } -} \ No newline at end of file +} + +TEST_CASE("xetra enum optional test encoder/decoder","[xetra_enum_encoder_decoder]") +{ + SECTION("enum optional present") + { + fast_test_coding_case test_case; + simple18::Test_3 test_3; + simple18::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_MDStatisticIntervalUnit().as_MilliSeconds(); + REQUIRE(test_3.cref().get_MDStatisticIntervalUnit().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xE0\x83\x82", true)); + REQUIRE(test_case.decoding("\xE0\x83\x82", test_3.cref(), true)); + } + + SECTION("enum optional not present") + { + fast_test_coding_case test_case; + simple18::Test_3 test_3; + REQUIRE(!test_3.cref().get_MDStatisticIntervalUnit().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xC0\x83", true)); + REQUIRE(test_case.decoding("\xC0\x83", test_3.cref(), true)); + } +} diff --git a/tests/xetra_enum_encoder_decoder_v2.cpp b/tests/xetra_enum_encoder_decoder_v2.cpp index 543d941..eed0973 100644 --- a/tests/xetra_enum_encoder_decoder_v2.cpp +++ b/tests/xetra_enum_encoder_decoder_v2.cpp @@ -40,4 +40,27 @@ TEST_CASE("xetra enum test encoder_V2/decoder_v2","[xetra_enum_encoder_v2_decode REQUIRE(test_case.encoding(test_1.cref(),"\xe0\x81\x81\x83",true)); REQUIRE(test_case.decoding("\xe0\x81\x81\x83",test_1.cref(),true)); } -} \ No newline at end of file +} + +TEST_CASE("xetra enum optional test encoder_V2/decoder_v2","[xetra_enum_optional_encoder_v2_decoder_v2]") +{ + SECTION("enum optional present") + { + fast_test_coding_case_v2 test_case; + simple18::Test_3 test_3; + simple18::Test_3_mref test_3_mref = test_3.mref(); + test_3_mref.set_MDStatisticIntervalUnit().as_MilliSeconds(); + REQUIRE(test_3.cref().get_MDStatisticIntervalUnit().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xE0\x83\x82", true)); + REQUIRE(test_case.decoding("\xE0\x83\x82", test_3.cref(), true)); + } + + SECTION("enum optional not present") + { + fast_test_coding_case_v2 test_case; + simple18::Test_3 test_3; + REQUIRE(!test_3.cref().get_MDStatisticIntervalUnit().present()); + REQUIRE(test_case.encoding(test_3.cref(), "\xC0\x83", true)); + REQUIRE(test_case.decoding("\xC0\x83", test_3.cref(), true)); + } +}