diff --git a/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlGrammar.hpp b/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlGrammar.hpp index 9393b83b884..faa3ba397ab 100644 --- a/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlGrammar.hpp +++ b/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlGrammar.hpp @@ -281,8 +281,8 @@ struct string_type : seq> {}; struct wide_string_type : seq> {}; struct map_type; struct type_spec; -struct sequence_size : opt {}; -struct sequence_type : seq {}; +struct sequence_size : collection_size {}; +struct sequence_type : seq, close_ang_bracket> {}; struct template_type_spec : sor {}; struct simple_type_spec : sor {}; struct type_spec : seq, sor, opt> {}; diff --git a/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlParser.hpp b/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlParser.hpp index 4db535ccb28..9278e8b5bf2 100644 --- a/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlParser.hpp +++ b/src/cpp/fastdds/xtypes/dynamic_types/idl_parser/IdlParser.hpp @@ -194,19 +194,28 @@ struct action { if (!state["type"].empty()) { + // In case of the struct member is a sequence, two possible cases: + if (state["type"] == "sequence") + { + // 1. Matched identifier is the member name. In this case, update state with the member name. + if ((!state["element_type"].empty()) && state["current_struct_member_name"].empty()) + { + // The identifier is the member name + state["current_struct_member_name"] = identifier_name; + } + // 2. Matched identifier is the element type of the sequence. + // Element type should be previously declared, so updating state + // should be managed in action and not here. + } + // In case a struct member is an array and the array size is an identifier, // use below check to avoid overwriting the member name with the size identifier. - if (state["current_struct_member_name"].empty()) + else if (state["current_struct_member_name"].empty()) { // The identifier is a member name state["current_struct_member_name"] = identifier_name; } } - else - { - // The identifier is a type - state["type"] = identifier_name; - } } } else if (state.count("union_name")) @@ -228,29 +237,73 @@ struct action } else if (!state["type"].empty()) { - // Union member type is primitive type - state["union_member_types"] += state["type"]; - state["union_member_names"] += identifier_name; - } - else - { - if (state["union_expecting_member_name"] == "true") + // In case of the union member is a sequence, two possible cases: + if (state["type"] == "sequence") { - state["union_member_names"] += identifier_name; - state["union_expecting_member_name"] = ""; + // 1. Matched identifier is the member name. In this case, update state with the member name. + if ((!state["element_type"].empty()) && state["current_union_member_name"].empty()) + { + // The identifier is the member name + state["current_union_member_name"] = identifier_name; + } + // 2. Matched identifier is the element type of the sequence. In this case, element type + // should be previously declared, + // so updating state should be managed in action ad not here. } - else + + // In case a union member is an array and the array size is an identifier, + // use below check to avoid overwriting the member name with the size identifier. + else if (state["current_union_member_name"].empty()) { - state["union_member_types"] += identifier_name; - state["union_expecting_member_name"] = "true"; + // The identifier is a member name + state["current_union_member_name"] = identifier_name; } } } } else if (state.count("alias")) { - // save alias type and alias name into state["alias"] - state["alias"] += state["alias"].empty() ? identifier_name : "," + identifier_name; + // Store the new alias name into state["alias"]. There are different cases: + + // 1. The aliased type is a custom and previously declared type (parsed using action), + // and identifier_name refers to the name of the alias. + if (!state["alias"].empty()) + { + // Append the identifier name to state["alias"]. + state["alias"] += "," + identifier_name; + } + + // 2. The aliased type is not a previously declared type + // (i.e: typedef , when is a Primitive type, string type, sequence type or map type + // not previously declared). + // In this case, aliased type info is stored in state["type"] and other additional state keys, + // so state["alias"] is empty and state["type"] is non-empty. + else if (!state["type"].empty()) + { + + // 2.1. Declared type contains internal types (e.g: element types in a sequence), + // and these types are previosly declared by the user, + // i.e: :=external_type, being a previously declared type. + // In this case, identifier_name should be stored in specific states keys and must be handled depending on state["type"]. + if ((state["type"] == "sequence") && state.count("element_type") && state["element_type"].empty()) + { + // State updates should be handled in action. + return; + } + + // 2.2: Declared type does not contain internal types, or its internal types are not previously declared by the user. + // In this case, the identifier_name matched correspond to the alias name, so it should be stored in state["alias"]. + state["alias"] = identifier_name; + } + + // 3. The aliased type is a custom and previously declared type, + // and the identifier_name refers to the name of the aliased type or its scope. + // In this case, state["alias"] and state["type"] should be both empty. + else + { + // State updates should be handled in action. + return; + } } else { @@ -287,6 +340,23 @@ struct action throw std::runtime_error("Unknown constant or identifier: " + identifier_name); } } + else if (state["type"] == "sequence" && state["element_type"].empty()) + { + // is the element type of a sequence (previously declared) + state["element_type"] = identifier_name; + + // Ready to parse the sequence size (if provided) + state["arithmetic_expr"] = ""; + } + else if (state.count("alias")) + { + // makes reference to the aliased type name. + state["alias"] = identifier_name; + } + else + { + state["type"] = identifier_name; + } } }; @@ -301,28 +371,100 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { - if (!state["type"].empty() && state.count("current_struct_member_name") && - !state["current_struct_member_name"].empty()) + if (!state["type"].empty()) { - // Add the type and name to the member lists - state["struct_member_types"] += state["type"] + ";"; - state["struct_member_names"] += state["current_struct_member_name"] + ";"; - - // Add the array dimensions for this member to `all_array_sizes` - std::string current_array_sizes = state["current_array_sizes"].empty() ? "0" : state["current_array_sizes"]; - if (!state["all_array_sizes"].empty()) + if (state.count("current_struct_member_name") && !state["current_struct_member_name"].empty()) { - state["all_array_sizes"] += ";" + current_array_sizes; + // Add the type and name to the member lists + // NOTE: For sequence types, the type stored in "struct_member_types" + // is the type of each element in the sequence, not "sequence". + // Sequence type can be inferred by checking if "sequence_sizes" contains a valid value for this member. + std::string current_member_type = (state["type"] == "sequence") ? state["element_type"] : state["type"]; + state["struct_member_types"] += current_member_type + ";"; + state["struct_member_names"] += state["current_struct_member_name"] + ";"; + + // Add the array dimensions for this member to `all_array_sizes` + std::string current_array_sizes = state["current_array_sizes"].empty() ? "0" : state["current_array_sizes"]; + if (!state["all_array_sizes"].empty()) + { + state["all_array_sizes"] += ";" + current_array_sizes; + } + else + { + state["all_array_sizes"] = current_array_sizes; + } + + // Add the sequence size for this member to "sequence_sizes" + std::string current_sequence_size = "0"; + if (state.count("sequence_size")) + { + current_sequence_size = state["sequence_size"]; + + // Key not more needed, remove it + state.erase("sequence_size"); + } + + // Add the sequence size to the member list + if (!state["sequence_sizes"].empty()) + { + state["sequence_sizes"] += ";" + current_sequence_size; + } + else + { + state["sequence_sizes"] = current_sequence_size; + } } - else + else if (state.count("union_name") && !state["union_name"].empty()) { - state["all_array_sizes"] = current_array_sizes; + // Add the type and name to the member lists + // NOTE: For sequence types, the type stored in "union_member_types" + // is the type of each element in the sequence, not "sequence". + // Sequence type can be inferred by checking if "sequence_sizes" contains a valid value for this member. + std::string current_member_type = (state["type"] == "sequence") ? state["element_type"] : state["type"]; + state["union_member_types"] += current_member_type; + state["union_member_names"] += state["current_union_member_name"]; + + // Add the sequence size for this member to "sequence_sizes" + std::string current_sequence_size = "0"; + if (state.count("sequence_size")) + { + current_sequence_size = state["sequence_size"]; + + // Key not more needed, remove it + state.erase("sequence_size"); + } + + // Add the sequence size to the member list + state["sequence_sizes"] += current_sequence_size; } // Clear the temporary states for the next member state["type"].clear(); - state["current_struct_member_name"].clear(); - state["current_array_sizes"].clear(); + + if (state.count("element_type")) + { + state.erase("element_type"); + } + + if (state.count("alias")) + { + state.erase("alias"); + } + + if (state.count("current_struct_member_name")) + { + state["current_struct_member_name"].clear(); + } + + if (state.count("current_union_member_name")) + { + state["current_union_member_name"].clear(); + } + + if (state.count("current_array_sizes")) + { + state["current_array_sizes"].clear(); + } } } @@ -339,11 +481,30 @@ struct action std::map& state, \ std::vector::ref_type>& /*operands*/) \ { \ - state["type"] = std::string(#id); \ - if (state["type"] == "string" || state["type"] == "wstring") \ + std::string type{#id}; \ + if (type == "sequence") \ { \ + state["type"] = type; \ + state.erase("parsing_sequence"); \ + if (state.count("arithmetic_expr")) \ + { \ + state.erase("arithmetic_expr"); \ + } \ + } \ + else if (state.count("parsing_sequence") && (state["parsing_sequence"] == "true")) \ + { \ + state["element_type"] = type; \ + state["arithmetic_expr"] = ""; \ + } \ + else if (type == "string" || type == "wstring") \ + { \ + state["type"] = type; \ state.erase("parsing_string"); \ } \ + else \ + { \ + state["type"] = type; \ + } \ } \ }; @@ -362,6 +523,7 @@ load_type_action(double_type, double) load_type_action(long_double_type, long double) load_type_action(string_type, string) load_type_action(wide_string_type, wstring) +load_type_action(sequence_type, sequence) template<> struct action @@ -373,20 +535,34 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { + std::string type_key; + if (state.count("parsing_sequence") && (state["parsing_sequence"] == "true")) + { + // We are parsing a sequence, thus is the type of the sequence's elements + type_key = "element_type"; + + // Ready to parse the sequence size (if provided) + state["arithmetic_expr"] = ""; + } + else + { + type_key = "type"; + } + switch (ctx->char_translation) { case Context::CHAR: - state["type"] = "char"; + state[type_key] = "char"; break; case Context::UINT8: - state["type"] = "uint8"; + state[type_key] = "uint8"; break; case Context::INT8: - state["type"] = "int8"; + state[type_key] = "int8"; break; default: EPROSIMA_LOG_ERROR(IDLPARSER, "Invalid char type " << ctx->char_translation); - state["type"] = "char"; + state[type_key] = "char"; break; } } @@ -403,17 +579,31 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { + std::string type_key; + if (state.count("parsing_sequence") && (state["parsing_sequence"] == "true")) + { + // We are parsing a sequence, thus is the type of the sequence's elements + type_key = "element_type"; + + // Ready to parse the sequence size (if provided) + state["arithmetic_expr"] = ""; + } + else + { + type_key = "type"; + } + switch (ctx->wchar_type) { case Context::WCHAR_T: - state["type"] = "wchar"; + state[type_key] = "wchar"; break; case Context::CHAR16_T: - state["type"] = "char16"; + state[type_key] = "char16"; break; default: EPROSIMA_LOG_ERROR(IDLPARSER, "Invalid wchar type " << ctx->char_translation); - state["type"] = "wchar"; + state[type_key] = "wchar"; break; } } @@ -484,6 +674,48 @@ struct action }; +template<> +struct action +{ + template + static void apply( + const Input& /*in*/, + Context* /*ctx*/, + std::map& state, + std::vector::ref_type>& operands) + { + if (!operands.empty()) + { + DynamicData::_ref_type xdata = operands.back(); + operands.pop_back(); + if (!operands.empty()) + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Finished sequence size parsing with non-empty operands stack."); + throw std::runtime_error("Finished sequence size parsing with non-empty operands stack."); + } + + int64_t value; + xdata->get_int64_value(value, MEMBER_ID_INVALID); + + if (value <= 0) + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Invalid sequence size: " << value); + throw std::runtime_error("Invalid sequence size: " + std::to_string(value)); + } + + state["sequence_size"] = std::to_string(value); + } + else + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Empty operands stack while parsing sequence_size"); + throw std::runtime_error("Empty operands stack while parsing sequence_size"); + } + + state.erase("arithmetic_expr"); + } + +}; + template<> struct action { @@ -494,7 +726,13 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { - state["parsing_string"] = "true"; + // In case of parsing a sequence, represents the type of the sequence's elements. + // Bounded string declaration inside a sequence is not supported, + // so we don't need to parse string size in this case. + if (!state.count("parsing_sequence")) + { + state["parsing_string"] = "true"; + } } }; @@ -509,7 +747,13 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { - state["parsing_string"] = "true"; + // In case of parsing a sequence, represents the type of the sequence's elements. + // Bounded string declaration inside a sequence is not supported, + // so we don't need to parse string size in this case. + if (!state.count("parsing_sequence")) + { + state["parsing_string"] = "true"; + } } }; @@ -524,7 +768,7 @@ struct action std::map& state, std::vector::ref_type>& /*operands*/) { - if (state.count("parsing_string") && state["parsing_string"] == "true") + if ((state.count("parsing_string") && state["parsing_string"] == "true")) { state["arithmetic_expr"] = ""; } @@ -577,19 +821,27 @@ load_stringsize_action(string_size, string_size) load_stringsize_action(wstring_size, wstring_size) template<> -struct action +struct action { template static void apply( - const Input& in, + const Input& /*in*/, Context* /*ctx*/, std::map& state, std::vector::ref_type>& /*operands*/) { - state["type"] = in.string(); - EPROSIMA_LOG_INFO(IDLPARSER, "[TODO] sequence_type parsing not supported: " << state["type"]); - } + state["type"] = "sequence"; + // Set the default sequence size to LENGTH_UNLIMITED. In case of bounded sequence, it will be overrided later. + state["sequence_size"] = std::to_string(LENGTH_UNLIMITED); + state["parsing_sequence"] = "true"; + state["element_type"] = ""; + // Sequence size is only parsed after the sequence's elements + if (state.count("arithmetic_expr")) + { + state.erase("arithmetic_expr"); + } + } }; template<> @@ -1165,9 +1417,12 @@ struct action state.erase("union_name"); state.erase("union_discriminant"); state.erase("union_labels"); - state.erase("union_member_types"); state.erase("union_member_names"); - state.erase("union_expecting_member_name"); + state.erase("union_member_types"); + state.erase("current_union_member_name"); + state.erase("sequence_sizes"); + state.erase("type"); + // state.erase("union_expecting_member_name"); } template @@ -1342,6 +1597,7 @@ struct action state["type"] = ""; state["all_array_sizes"] = ""; state["current_array_sizes"] = ""; + state["sequence_sizes"] = ""; } }; @@ -1360,6 +1616,7 @@ struct action state["type"] = ""; state["all_array_sizes"] = ""; state["current_array_sizes"] = ""; + state["sequence_sizes"] = ""; } template @@ -1393,13 +1650,15 @@ struct action std::vector types = ctx->split_string(state["struct_member_types"], ';'); std::vector names = ctx->split_string(state["struct_member_names"], ';'); std::vector all_array_sizes = ctx->split_string(state["all_array_sizes"], ';'); + std::vector sequence_sizes = ctx->split_string(state["sequence_sizes"], ';'); for (size_t i = 0; i < types.size(); i++) { + // For arrays/sequences, ctx->get_type() should return the type of each element DynamicType::_ref_type member_type = ctx->get_type(state, types[i]); if (!member_type) { - EPROSIMA_LOG_INFO(IDLPARSER, "[TODO] member type not supported: " << types[i]); + EPROSIMA_LOG_WARNING(IDLPARSER, "[TODO] member type not supported: " << types[i]); return; } @@ -1425,7 +1684,44 @@ struct action // Create the multi-dimensional array type DynamicTypeBuilder::_ref_type array_builder {factory->create_array_type(member_type, sizes)}; - member_type = array_builder->build(); + if (!array_builder) + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Error creating array member."); + } + else + { + member_type = array_builder->build(); + } + } + + // If a non-null sequence size is specified for this member, create a sequence type. + // If the member is not a sequence, it has a sequence size of 0 assigned. + if (i < sequence_sizes.size() && sequence_sizes[i] != "0") + { + uint32_t size; + + if (module.has_constant(sequence_sizes[i])) + { + DynamicData::_ref_type xdata = module.constant(sequence_sizes[i]); + int64_t size_val = 0; + xdata->get_int64_value(size_val, MEMBER_ID_INVALID); + size = static_cast(size_val); + } + else + { + size = static_cast(std::stoul(sequence_sizes[i])); + } + + // Create the sequence type + DynamicTypeBuilder::_ref_type sequence_builder {factory->create_sequence_type(member_type, size)}; + if (!sequence_builder) + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Error creating sequence member."); + } + else + { + member_type = sequence_builder->build(); + } } MemberDescriptor::_ref_type member_descriptor {traits::make_shared()}; @@ -1461,7 +1757,8 @@ struct action state["union_labels"] = ""; state["union_member_names"] = ""; state["union_member_types"] = ""; - state["union_expecting_member_name"] = ""; + state["current_union_member_name"] = ""; + state["sequence_sizes"] = ""; state["type"] = ""; } @@ -1586,6 +1883,7 @@ struct action state["union_labels"] += ";"; state["union_member_types"] += ";"; state["union_member_names"] += ";"; + state["sequence_sizes"] += ";"; } }; @@ -1602,7 +1900,7 @@ struct action state.erase("union_labels"); state.erase("union_member_types"); state.erase("union_member_names"); - state.erase("union_expecting_member_name"); + state.erase("sequence_sizes"); } template @@ -1632,7 +1930,7 @@ struct action DynamicType::_ref_type discriminant_type = ctx->get_type(state, state["union_discriminant"]); if (!discriminant_type) { - EPROSIMA_LOG_INFO(IDLPARSER, "[TODO] union type not supported: " << state["union_discriminant"]); + EPROSIMA_LOG_WARNING(IDLPARSER, "[TODO] union type not supported: " << state["union_discriminant"]); return; } type_descriptor->kind(TK_UNION); @@ -1643,6 +1941,7 @@ struct action std::vector label_groups = ctx->split_string(state["union_labels"], ';'); std::vector types = ctx->split_string(state["union_member_types"], ';'); std::vector names = ctx->split_string(state["union_member_names"], ';'); + std::vector sequence_sizes = ctx->split_string(state["sequence_sizes"], ';'); std::vector> labels(types.size()); int default_label_index = -1; @@ -1674,14 +1973,46 @@ struct action } } - for (uint32_t i = 0; i < (uint32_t)types.size(); i++) + for (size_t i = 0; i < types.size(); i++) { + // For sequences, ctx->get_type() should return the type of each element DynamicType::_ref_type member_type = ctx->get_type(state, types[i]); if (!member_type) { EPROSIMA_LOG_INFO(IDLPARSER, "[TODO] member type not supported: " << types[i]); return; } + + // If a non-null sequence size is specified for this member, create a sequence type. + // If the member is not a sequence, it has a sequence size of 0 assigned. + if (i < sequence_sizes.size() && sequence_sizes[i] != "0") + { + uint32_t size; + + if (module.has_constant(sequence_sizes[i])) + { + DynamicData::_ref_type xdata = module.constant(sequence_sizes[i]); + int64_t size_val = 0; + xdata->get_int64_value(size_val, MEMBER_ID_INVALID); + size = static_cast(size_val); + } + else + { + size = static_cast(std::stoul(sequence_sizes[i])); + } + + // Create the sequence type + DynamicTypeBuilder::_ref_type sequence_builder {factory->create_sequence_type(member_type, size)}; + if (!sequence_builder) + { + EPROSIMA_LOG_ERROR(IDLPARSER, "Error creating sequence member."); + } + else + { + member_type = sequence_builder->build(); + } + } + MemberDescriptor::_ref_type member_descriptor {traits::make_shared()}; member_descriptor->name(names[i]); member_descriptor->type(member_type); @@ -1740,6 +2071,14 @@ struct action { state.erase("alias"); state["current_array_sizes"] = ""; + + if (state["type"] == "sequence") + { + state.erase("sequence_size"); + state.erase("element_type"); + } + + state["type"].clear(); } template @@ -1786,10 +2125,13 @@ struct action alias_name = state["alias"]; } - DynamicType::_ref_type alias_type = ctx->get_type(state, state["type"]); + // For sequence types, ctx->get_type() should return the type of the elements + DynamicType::_ref_type alias_type = (state["type"] == "sequence") ? ctx->get_type(state, state["element_type"]) + : ctx->get_type(state, state["type"]); + if (!alias_type) { - EPROSIMA_LOG_INFO(IDLPARSER, "[TODO] alias type not supported: " << state["type"]); + EPROSIMA_LOG_WARNING(IDLPARSER, "[TODO] alias type not supported: " << state["type"]); return; } @@ -1797,12 +2139,22 @@ struct action TypeDescriptor::_ref_type type_descriptor {traits::make_shared()}; type_descriptor->kind(TK_ALIAS); type_descriptor->name(alias_name); - if (array_sizes.empty()) + + if (state["type"] == "sequence") { - type_descriptor->base_type(alias_type); + // Aliased type is a sequence type + assert(state.count("sequence_size")); + DynamicTypeBuilder::_ref_type sequence_builder + { + factory->create_sequence_type( + alias_type, + static_cast(std::stoul(state["sequence_size"]))) + }; + type_descriptor->base_type(sequence_builder->build()); } - else + else if (!array_sizes.empty()) { + // Aliased type is an array type std::vector sizes; for (const auto& size : array_sizes) { @@ -1811,6 +2163,10 @@ struct action DynamicTypeBuilder::_ref_type array_builder {factory->create_array_type(alias_type, sizes)}; type_descriptor->base_type(array_builder->build()); } + else + { + type_descriptor->base_type(alias_type); + } DynamicTypeBuilder::_ref_type builder {factory->create_type(type_descriptor)}; @@ -1960,7 +2316,7 @@ class Parser else { context_->success = false; - EPROSIMA_LOG_INFO(IDLPARSER, "IDL parsing failed."); + EPROSIMA_LOG_ERROR(IDLPARSER, "IDL parsing failed."); return false; } } diff --git a/test/feature/idl_parser/IdlParserTests.cpp b/test/feature/idl_parser/IdlParserTests.cpp index 2687472b59c..bc2f0ed2c02 100644 --- a/test/feature/idl_parser/IdlParserTests.cpp +++ b/test/feature/idl_parser/IdlParserTests.cpp @@ -374,11 +374,10 @@ TEST_F(IdlParserTests, structures) DynamicType::_ref_type type21 = builder21->build(); ASSERT_TRUE(type21); - // TODO StructSequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder22 = factory->create_type_w_uri("IDL/structures.idl", "StructSequence", include_paths); - // EXPECT_TRUE(builder22); - // DynamicType::_ref_type type22 = builder22->build(); - // ASSERT_TRUE(type22); + DynamicTypeBuilder::_ref_type builder22 = factory->create_type_w_uri("IDL/structures.idl", "StructSequence", include_paths); + EXPECT_TRUE(builder22); + DynamicType::_ref_type type22 = builder22->build(); + ASSERT_TRUE(type22); // TODO StructMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder23 = factory->create_type_w_uri("IDL/structures.idl", "StructMap", include_paths); @@ -546,11 +545,10 @@ TEST_F(IdlParserTests, aliases) DynamicType::_ref_type type20 = builder20->build(); ASSERT_TRUE(type20); - // TODO AliasSequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder21 = factory->create_type_w_uri("IDL/aliases.idl", "AliasSequence", include_paths); - // EXPECT_TRUE(builder21); - // DynamicType::_ref_type type21 = builder21->build(); - // ASSERT_TRUE(type21); + DynamicTypeBuilder::_ref_type builder21 = factory->create_type_w_uri("IDL/aliases.idl", "AliasSequence", include_paths); + EXPECT_TRUE(builder21); + DynamicType::_ref_type type21 = builder21->build(); + ASSERT_TRUE(type21); // TODO AliasMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder22 = factory->create_type_w_uri("IDL/aliases.idl", "AliasMap", include_paths); @@ -710,11 +708,10 @@ TEST_F(IdlParserTests, arrays) DynamicType::_ref_type type22 = builder22->build(); ASSERT_TRUE(type22); - // TODO ArraySequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder23 = factory->create_type_w_uri("IDL/arrays.idl", "ArraySequence", include_paths); - // EXPECT_TRUE(builder23); - // DynamicType::_ref_type type23 = builder23->build(); - // ASSERT_TRUE(type23); + DynamicTypeBuilder::_ref_type builder23 = factory->create_type_w_uri("IDL/arrays.idl", "ArraySequence", include_paths); + EXPECT_TRUE(builder23); + DynamicType::_ref_type type23 = builder23->build(); + ASSERT_TRUE(type23); // TODO ArrayMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder24 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMap", include_paths); @@ -862,11 +859,10 @@ TEST_F(IdlParserTests, arrays) DynamicType::_ref_type type47 = builder47->build(); ASSERT_TRUE(type47); - // TODO ArrayMultiDimensionSequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder48 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionSequence", include_paths); - // EXPECT_TRUE(builder48); - // DynamicType::_ref_type type48 = builder48->build(); - // ASSERT_TRUE(type48); + DynamicTypeBuilder::_ref_type builder48 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionSequence", include_paths); + EXPECT_TRUE(builder48); + DynamicType::_ref_type type48 = builder48->build(); + ASSERT_TRUE(type48); // TODO ArrayMultiDimensionMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder49 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionMap", include_paths); @@ -1038,11 +1034,10 @@ TEST_F(IdlParserTests, arrays) DynamicType::_ref_type type73 = builder73->build(); ASSERT_TRUE(type73); - // TODO ArraySingleDimensionLiteralsSequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder74 = factory->create_type_w_uri("IDL/arrays.idl", "ArraySingleDimensionLiteralsSequence", include_paths); - // EXPECT_TRUE(builder74); - // DynamicType::_ref_type type74 = builder74->build(); - // ASSERT_TRUE(type74); + DynamicTypeBuilder::_ref_type builder74 = factory->create_type_w_uri("IDL/arrays.idl", "ArraySingleDimensionLiteralsSequence", include_paths); + EXPECT_TRUE(builder74); + DynamicType::_ref_type type74 = builder74->build(); + ASSERT_TRUE(type74); // TODO ArraySingleDimensionLiteralsMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder75 = factory->create_type_w_uri("IDL/arrays.idl", "ArraySingleDimensionLiteralsMap", include_paths); @@ -1209,11 +1204,10 @@ TEST_F(IdlParserTests, arrays) DynamicType::_ref_type type98 = builder98->build(); ASSERT_TRUE(type98); - // TODO ArrayMultiDimensionLiteralsSequence is skipped since sequence parsing is not supported. - // DynamicTypeBuilder::_ref_type builder99 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionLiteralsSequence", include_paths); - // EXPECT_TRUE(builder99); - // DynamicType::_ref_type type99 = builder99->build(); - // ASSERT_TRUE(type99); + DynamicTypeBuilder::_ref_type builder99 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionLiteralsSequence", include_paths); + EXPECT_TRUE(builder99); + DynamicType::_ref_type type99 = builder99->build(); + ASSERT_TRUE(type99); // TODO ArrayMultiDimensionLiteralsMap is skipped since map parsing is not supported. // DynamicTypeBuilder::_ref_type builder100 = factory->create_type_w_uri("IDL/arrays.idl", "ArrayMultiDimensionLiteralsMap", include_paths); @@ -1407,7 +1401,7 @@ TEST_F(IdlParserTests, unions) data = DynamicDataFactory::get_instance()->create_data(type); ASSERT_TRUE(data); - builder = factory->create_type_w_uri("IDL/unions.idl", "Union_BoundedString", include_paths); + builder = factory->create_type_w_uri("IDL/unions.idl", "Union_BoundedString", include_paths); EXPECT_TRUE(builder); type = builder->build(); ASSERT_TRUE(type); @@ -1450,13 +1444,12 @@ TEST_F(IdlParserTests, unions) data = DynamicDataFactory::get_instance()->create_data(type); ASSERT_TRUE(data); - // TODO Union_Sequence is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Sequence", include_paths); - // EXPECT_TRUE(builder); - // type = builder->build(); - // ASSERT_TRUE(type); - // data = DynamicDataFactory::get_instance()->create_data(type); - // ASSERT_TRUE(data); + builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Sequence", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); // TODO Union_Map is skipped since map parsing is not supported. // builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Map", include_paths); @@ -1579,21 +1572,19 @@ TEST_F(IdlParserTests, unions) data = DynamicDataFactory::get_instance()->create_data(type); ASSERT_TRUE(data); - // TODO Union_Several_Fields is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Several_Fields", include_paths); - // EXPECT_TRUE(builder); - // type = builder->build(); - // ASSERT_TRUE(type); - // data = DynamicDataFactory::get_instance()->create_data(type); - // ASSERT_TRUE(data); + builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Several_Fields", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); - // TODO Union_Several_Fields_With_Default is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Several_Fields_With_Default", include_paths); - // EXPECT_TRUE(builder); - // type = builder->build(); - // ASSERT_TRUE(type); - // data = DynamicDataFactory::get_instance()->create_data(type); - // ASSERT_TRUE(data); + builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Several_Fields_With_Default", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); // TODO Union_Fixed_String_In_Module_Alias is skipped since module parsing is not supported. // builder = factory->create_type_w_uri("IDL/unions.idl", "Union_Fixed_String_In_Module_Alias", include_paths); @@ -1751,13 +1742,12 @@ TEST_F(IdlParserTests, unions) data = DynamicDataFactory::get_instance()->create_data(type); ASSERT_TRUE(data); - // TODO UnionSequence is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSequence", include_paths); - // EXPECT_TRUE(builder); - // type = builder->build(); - // ASSERT_TRUE(type); - // data = DynamicDataFactory::get_instance()->create_data(type); - // ASSERT_TRUE(data); + builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSequence", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); // TODO UnionMap is skipped since map parsing is not supported. // builder = factory->create_type_w_uri("IDL/unions.idl", "UnionMap", include_paths); @@ -1880,23 +1870,276 @@ TEST_F(IdlParserTests, unions) data = DynamicDataFactory::get_instance()->create_data(type); ASSERT_TRUE(data); - // TODO UnionSeveralFields is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSeveralFields", include_paths); + builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSeveralFields", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSeveralFieldsWithDefault", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + // TODO The rest types are skipped since annotation/module parsing are not supported. +} + +TEST_F(IdlParserTests, sequences) +{ + DynamicTypeBuilderFactory::_ref_type factory {DynamicTypeBuilderFactory::get_instance()}; + std::vector include_paths; + include_paths.push_back("IDL/helpers/basic_inner_types.idl"); + + /* sequence */ + DynamicTypeBuilder::_ref_type builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceShort", include_paths); + EXPECT_TRUE(builder); + DynamicType::_ref_type type = builder->build(); + ASSERT_TRUE(type); + DynamicData::_ref_type data {DynamicDataFactory::get_instance()->create_data(type)}; + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceUShort", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceLong", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceULong", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceLongLong", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceULongLong", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceFloat", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceDouble", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceLongDouble", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceBoolean", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceOctet", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceChar", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceWChar", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceString", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceWString", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceStringBounded", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceWStringBounded", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceEnum", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + // TODO: SequenceBitMask is skipped since bitmask parsing is not supported. + // builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceBitMask", include_paths); // EXPECT_TRUE(builder); // type = builder->build(); // ASSERT_TRUE(type); // data = DynamicDataFactory::get_instance()->create_data(type); // ASSERT_TRUE(data); - // TODO UnionSeveralFieldsWithDefault is skipped since sequence parsing is not supported. - // builder = factory->create_type_w_uri("IDL/unions.idl", "UnionSeveralFieldsWithDefault", include_paths); + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceAlias", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceShortArray", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceSequence", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + // TODO: SequenceMap is skipped since map parsing is not supported. + // builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceMap", include_paths); // EXPECT_TRUE(builder); // type = builder->build(); // ASSERT_TRUE(type); // data = DynamicDataFactory::get_instance()->create_data(type); // ASSERT_TRUE(data); - // TODO The rest types are skipped since annotation/module parsing are not supported. + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceUnion", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceStructure", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /* sequence */ + // TODO: SequenceBitset is skipped since bitset parsing is not supported. + // builder = factory->create_type_w_uri("IDL/sequences.idl", "SequenceBitset", include_paths); + // EXPECT_TRUE(builder); + // type = builder->build(); + // ASSERT_TRUE(type); + // data = DynamicDataFactory::get_instance()->create_data(type); + // ASSERT_TRUE(data); + + /** + * sequence + * sequence + */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "BoundedSmallSequences", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + /** + * sequence + * sequence + */ + builder = factory->create_type_w_uri("IDL/sequences.idl", "BoundedBigSequences", include_paths); + EXPECT_TRUE(builder); + type = builder->build(); + ASSERT_TRUE(type); + data = DynamicDataFactory::get_instance()->create_data(type); + ASSERT_TRUE(data); + + // TODO: The rest types are skipped since module parsing is not supported. + // builder = factory->create_type_w_uri("IDL/sequences.idl", "Common_Module", include_paths); + // EXPECT_TRUE(builder); + // type = builder->build(); + // ASSERT_TRUE(type); + // data = DynamicDataFactory::get_instance()->create_data(type); + // ASSERT_TRUE(data); + + // builder = factory->create_type_w_uri("IDL/sequences.idl", "NoCommon_Module", include_paths); + // EXPECT_TRUE(builder); + // type = builder->build(); + // ASSERT_TRUE(type); + // data = DynamicDataFactory::get_instance()->create_data(type); + // ASSERT_TRUE(data); } int main( diff --git a/versions.md b/versions.md index 636ce37df2d..5d093fbf9e6 100644 --- a/versions.md +++ b/versions.md @@ -1,6 +1,10 @@ Forthcoming ----------- +* Improve `IDLParser` adding support to new types: + * Add support for parsing sequence types. + * Move logic for managing `state["type"]` changes to `action`. + * Refactor union types parsing to be similar to array types. Version v3.2.0 --------------