diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 1c37fdf5357ad33441dfdbc76d3271e718fd8699..f31abf996ec521d201a0971f606c6f57619d424c 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -1211,7 +1211,7 @@ namespace Ttcn { return component_defs->has_ass_withId(p_id) || parent_scope->has_ass_withId(p_id); } - + // ================================= // ===== FriendMod // ================================= @@ -6231,7 +6231,7 @@ namespace Ttcn { if (!my_module) FATAL_ERROR("Def_Function::get_runs_on_scope()"); return my_module->get_runs_on_scope(comptype); } - + void Def_Function::chk() { if (checked) return; @@ -6662,10 +6662,13 @@ namespace Ttcn { } } else { - if (Common::Type::CT_XER == encoding_type - && input_type->get_type_refd_last()->is_untagged()) { - // "untagged" on the (toplevel) input type will have no effect. - warning("UNTAGGED encoding attribute is ignored on top-level type"); + if (Common::Type::CT_XER == encoding_type) { + Type* last = input_type->get_type_refd_last(); + if (last->is_untagged() && + last->get_typetype() == Type::T_CHOICE_A || last->get_typetype() == Type::T_CHOICE_T) { + // "untagged" on the (toplevel) input type will have no effect unless it is union + warning("UNTAGGED encoding attribute is ignored on top-level type"); + } } if (Common::Type::CT_CUSTOM == encoding_type || Common::Type::CT_PER == encoding_type) { diff --git a/compiler2/union.c b/compiler2/union.c index 7bf83ffb3d611ac57b82578fe42ea1331f6050ab..3223e47d0600ec2dfe79371486c63a0062cb88ac 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -1520,7 +1520,9 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " if (is_exer(p_flavor)) flavor_1 &= ~XER_RECOF;\n" " if (!(p_flavor & XER_LIST)) flavor_2 |= FROM_UNION_USETYPE;\n" " boolean omit_tag = begin_xml(p_td, p_buf, flavor_1, p_indent, FALSE, " - "(collector_fn)&%s::collect_ns%s, flavor_2);\n" + "(collector_fn)&%s::collect_ns%s, flavor_2 | THIS_UNION);\n" + // Top level union can be untagged, so don't increase the indentation + " int p_indent_tmp = (is_exer(p_flavor) && p_indent == 0 && (p_td.xer_bits & UNTAGGED)) ? p_indent : p_indent + (!p_indent || !omit_tag);\n" , sdef->name , sdef->xerUseTypeAttr ? ", type_atr" : ", 0"); src = mputprintf(src, @@ -1531,7 +1533,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " case %s_%s:\n" " ec_1.set_msg(\"%s': \");\n" " field_%s->XER_encode(%s_xer_, p_buf, flavor_0, " - "flavor_2, p_indent + (!p_indent || !omit_tag), 0);\n" + "flavor_2, p_indent_tmp, 0);\n" " break;\n", selection_prefix, sdef->elements[i].name, sdef->elements[i].dispname, @@ -1546,7 +1548,7 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputstr(src, " if (p_buf.get_data()[p_buf.get_len()-1] != '\\n') flavor_1 |= SIMPLE_TYPE;\n"); } src = mputstr(src, - " end_xml(p_td, p_buf, flavor_1, p_indent, 0);\n" + " end_xml(p_td, p_buf, flavor_1, p_indent, 0, flavor_2 | THIS_UNION);\n" " return (int)p_buf.get_len() - encoded_length;\n" "}\n\n"); @@ -1739,7 +1741,6 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " int rd_ok=1, xml_depth=-1;\n" "%s%s" " unsigned long xerbits = p_td.xer_bits;\n" - " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" " if (xerbits & USE_TYPE_ATTR) p_flavor &= ~XER_RECOF;\n" " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT | UNTAGGED)) " "|| (p_flavor & (USE_NIL|(e_xer ? XER_LIST : XER_RECOF)))));\n" diff --git a/core/Basetype.cc b/core/Basetype.cc index eba72a6c2e21f481c6147f2e23419a35de46fe39..3d1386ae8ad27783b9955886b93f33d71fe960d5 100644 --- a/core/Basetype.cc +++ b/core/Basetype.cc @@ -235,7 +235,9 @@ int Base_Type::begin_xml(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, collector_fn collector, const char *type_atr, unsigned int flavor2) const { const int exer = is_exer(flavor); - int omit_tag = (indent != 0) // can never omit the tag at the toplevel + int omit_tag = + // can never omit the tag at the toplevel, except when the type is union + (indent != 0 || (flavor2 & THIS_UNION)) && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 || (exer /*&& */ @@ -335,10 +337,12 @@ int Base_Type::begin_xml(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, } void Base_Type::end_xml (const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent, boolean empty) const + unsigned int flavor, int indent, boolean empty, unsigned int flavor2) const { int exer = is_exer(flavor); - boolean omit_tag = (indent != 0) // can never omit the tag at the toplevel + boolean omit_tag = + // can never omit the tag at the toplevel, except when the type is union + (indent != 0 || (flavor2 & THIS_UNION)) && ( ((flavor & XER_RECOF) // can remove the tag even if not EXER && !(exer && (flavor & BXER_EMPTY_ELEM))) // except 26.6, 26.7 || (exer /*&& */ diff --git a/core/Basetype.hh b/core/Basetype.hh index 3fb85a51606dc20032d71242a2290d465864ccdc..b927adaf832ff80ac0386afef470f2187090fc4e 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -588,7 +588,7 @@ public: * @param[in] empty true if an empty-element tag is needed */ VIRTUAL_IF_RUNTIME_2 void end_xml (const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, - unsigned int flavor, int indent, boolean empty) const; + unsigned int flavor, int indent, boolean empty, unsigned int flavor2 = 0) const; /** Encode JSON. * @return encoded length diff --git a/core/XER.hh b/core/XER.hh index e4838ab779c38d0665f4078009ee044541b5c653..5904edfbaae9f114d8aeef1af36fb98792ad363e 100644 --- a/core/XER.hh +++ b/core/XER.hh @@ -107,7 +107,8 @@ enum XER_flavor { enum XER_flavor2 { USE_NIL_PARENT_TAG = 1U << 0, // Content field has attribute that was read by parent - FROM_UNION_USETYPE = 1U << 1 // When the parent of a useUnion field is a union with useType + FROM_UNION_USETYPE = 1U << 1, // When the parent of a useUnion field is a union with useType + THIS_UNION = 1U << 2 // When the type is a union }; /** WHITESPACE actions. diff --git a/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp b/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp index a30132a8adf8a185d33930d213727c158e226cdb..ba4930d3d8175159bc1084016ff7d3a23ad6a9fa 100644 --- a/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp +++ b/regression_test/XML/EXER-whitepaper/Untagged.ttcnpp @@ -9,6 +9,7 @@ * Balasko, Jeno * Baranyi, Botond * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module Untagged { @@ -696,7 +697,94 @@ testcase decode_ut_recof() runs on UTA CHECK_DECODE(exer_dec_recof, s_recof, r_recof, c_recof); } +// ------- untagged top level union +type integer MyInt +with { + variant "element"; +} + +type charstring MyChar +with { + variant "element"; +} + +type union UntaggedUnion { + MyInt i, + MyChar c +} with { + variant "untagged"; +} + +DECLARE_EXER_ENCODERS(UntaggedUnion, untunion); + +const UntaggedUnion c_untunion := { i := 44 }; + +const universal charstring s_untunion := "<i>44</i>\n\n"; + +testcase encode_ut_union() runs on UTA +{ + CHECK_METHOD(exer_enc_untunion, c_untunion, s_untunion); +} + +testcase decode_ut_union() runs on UTA +{ + CHECK_DECODE(exer_dec_untunion, s_untunion, UntaggedUnion, c_untunion); +} + +// ------- untagged top level record of union +type record of UntaggedUnion UntaggedRecofUnion +with { + variant "untagged"; +} + + +DECLARE_EXER_ENCODERS(UntaggedRecofUnion, untunionrecof); + +const UntaggedRecofUnion c_untunionrecof := { { i := 44 }, {c := "asdf"} }; + +const universal charstring s_untunionrecof := +"<UntaggedRecofUnion>\n"& +"\t<i>44</i>\n"& +"\t<c>asdf</c>\n"& +"</UntaggedRecofUnion>\n\n"; + +testcase encode_ut_union_recof() runs on UTA +{ + CHECK_METHOD(exer_enc_untunionrecof, c_untunionrecof, s_untunionrecof); +} + +testcase decode_ut_union_recof() runs on UTA +{ + CHECK_DECODE(exer_dec_untunionrecof, s_untunionrecof, UntaggedRecofUnion, c_untunionrecof); +} + +// ------- untagged top level union with nested untagged union + +type union UntaggedUnion2 { + UntaggedUnion unt, + MyInt i, + MyChar c +} with { + variant "untagged"; + variant (unt) "untagged"; +} + +DECLARE_EXER_ENCODERS(UntaggedUnion2, untunion2); + +const UntaggedUnion2 c_untunion2 := { unt := { i := 44 } }; + +const universal charstring s_untunion2 := "<i>44</i>\n\n"; + +testcase encode_ut_union2() runs on UTA +{ + CHECK_METHOD(exer_enc_untunion2, c_untunion2, s_untunion2); +} + +testcase decode_ut_union2() runs on UTA +{ + CHECK_DECODE(exer_dec_untunion2, s_untunion2, UntaggedUnion2, c_untunion2); +} /* * * * * * * * * * * Run it! * * * * * * * * * * */ @@ -736,6 +824,15 @@ control { execute(encode_ut_recof()); execute(decode_ut_recof()); + + execute(encode_ut_union()); + execute(decode_ut_union()); + + execute(encode_ut_union2()); + execute(decode_ut_union2()); + + execute(encode_ut_union_recof()); + execute(decode_ut_union_recof()); } } diff --git a/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp b/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp index 20aeabe378d8ee558f8fdfa740a9c64f640362c5..31e703b8ca56368303438a6e5efa97fafa0dd9a6 100644 --- a/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp +++ b/regression_test/XML/EXER-whitepaper/Untagged1.ttcnpp @@ -8,6 +8,7 @@ * Contributors: * Balasko, Jeno * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module Untagged1 { @@ -336,7 +337,7 @@ testcase tc_dec_ints() runs on Unt CHECK_DECODE(exer_dec_ints, estr_twoints, Ints, twoints); } -// Untagged at toplevel (ignored) for union +// not Untagged at toplevel for union // HM71472 type union Choice { @@ -345,7 +346,6 @@ type union Choice } with { variant "element" - variant "untagged" variant "namespace as 'foo:bar' prefix 'baz'"; } @@ -375,6 +375,83 @@ testcase tc_dec_choice() runs on Unt CHECK_DECODE(exer_dec_ch, estr_itg, Choice, itg); } +// Untagged at toplevel for union +// HM71472 +type union Choice2 +{ + integer answer, + charstring s +} +with { + variant "element" + variant "untagged" + // the namespace as variant will be not visible because it will be lost due to + // untagged + variant "namespace as 'foo:bar' prefix 'baz'"; +} + +DECLARE_XER_ENCODERS(Choice2, ch2); +DECLARE_EXER_ENCODERS(Choice2, ch2); + +const Choice2 itg2 := { answer := 42 }; +const universal charstring bstr_itg2 := +"<Choice2>\n" & +"\t<answer>42</answer>\n" & +"</Choice2>\n\n"; +const universal charstring estr_itg2 := +"<answer>42</answer>\n\n"; + + +testcase tc_enc_choice2() runs on Unt +{ + CHECK_METHOD(bxer_enc_ch2, itg2, bstr_itg2); + CHECK_METHOD(exer_enc_ch2, itg2, estr_itg2); +} + +testcase tc_dec_choice2() runs on Unt +{ + CHECK_DECODE(bxer_dec_ch2, bstr_itg2, Choice2, itg2); + CHECK_DECODE(exer_dec_ch2, estr_itg2, Choice2, itg2); +} + +// Untagged at toplevel for union +// HM71472 +type union Choice3 +{ + integer answer, + charstring s +} +with { + variant "element" + variant "untagged" + variant (answer) "namespace as 'foo:bar' prefix 'baz'"; + variant (answer) "element"; +} + +DECLARE_XER_ENCODERS(Choice3, ch3); +DECLARE_EXER_ENCODERS(Choice3, ch3); + +const Choice3 itg3 := { answer := 42 }; +const universal charstring bstr_itg3 := +"<Choice3>\n" & +"\t<answer>42</answer>\n" & +"</Choice3>\n\n"; +const universal charstring estr_itg3 := +"<baz:answer xmlns:baz='foo:bar'>42</baz:answer>\n\n"; + + +testcase tc_enc_choice3() runs on Unt +{ + CHECK_METHOD(bxer_enc_ch3, itg3, bstr_itg3); + CHECK_METHOD(exer_enc_ch3, itg3, estr_itg3); +} + +testcase tc_dec_choice3() runs on Unt +{ + CHECK_DECODE(bxer_dec_ch3, bstr_itg3, Choice3, itg3); + CHECK_DECODE(exer_dec_ch3, estr_itg3, Choice3, itg3); +} + // HM80553 type record AddRequest @@ -476,6 +553,12 @@ control { execute(tc_enc_choice()); execute(tc_dec_choice()); + execute(tc_enc_choice2()); + execute(tc_dec_choice2()); + + execute(tc_enc_choice3()); + execute(tc_dec_choice3()); + execute(tc_enc_widget()); execute(tc_dec_widget()); }