diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 55317df02b737c13b2059e51ed03ca7c8fe52638..fc74f72ead7824ffbeb8a6c5412c52ed6fb3fb03 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -3098,10 +3098,92 @@ void Type::chk_oer() { } } break; } + case T_CHOICE_A: + oerattrib->extendable = t->u.secho.ctss->has_ellipsis(); + if (oerattrib->extendable) { + oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps(); + } + break; + case T_SET_A: { + oerattrib->extendable = t->u.secho.ctss->has_ellipsis(); + if (oerattrib->extendable) { + oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps(); + } + // TITAN will reorder the fields for DER coding, which is mostly fine. + // Until the extensions... In OER the DER ordering is good, but the extended + // fields do not need the reordering. + // Here a "map" called p is created which contains the good indexes of the fields. + size_t nElements = t->get_nof_comps(); + vector<CompField> se_comps; + map<Tag, CompField> se_comps_map; + for(size_t i=0; i<nElements; i++) { + CompField* cf=t->get_comp_byIndex(i); + Tag *tag = cf->get_type()->get_smallest_tag(); + se_comps_map.add(*tag, cf); + delete tag; + } + for(size_t i=0; i<nElements; i++) + se_comps.add(se_comps_map.get_nth_elem(i)); + se_comps_map.clear(); + + size_t limit = oerattrib->extendable ? oerattrib->nr_of_root_comps : nElements; + vector<CompField> se_comps2; + for(size_t i=0; i<limit; i++) { + CompField* cf=t->get_comp_byIndex(i); + Tag *tag = cf->get_type()->get_smallest_tag(); + se_comps_map.add(*tag, cf); + delete tag; + } + for(size_t i=0; i<limit; i++) + se_comps2.add(se_comps_map.get_nth_elem(i)); + se_comps_map.clear(); + for(size_t i=limit; i<nElements; i++) + se_comps2.add(t->get_comp_byIndex(i)); + + for (size_t i = 0; i < nElements; i++) { + const Identifier& id = se_comps[i]->get_name(); + for (size_t j = 0; j < nElements; j++) { + if (id == se_comps2[j]->get_name()) { + oerattrib->p.add(new int(j)); + break; + } + } + } + se_comps.clear(); + se_comps2.clear(); + } case T_SEQ_A: { - // extendable is always false. Probably a bug with is_extendable() - if (t->get_sub_type()) { - oerattrib->extendable = t->get_sub_type()->is_extendable(); + oerattrib->extendable = t->u.secho.ctss->has_ellipsis(); + if (oerattrib->extendable) { + oerattrib->nr_of_root_comps = t->u.secho.ctss->get_nof_root_comps(); + ExtAdds* eas = t->u.secho.ctss->get_ext_and_exc()->get_eas(); + int last_idx = 0; + for (size_t i = 0; i < eas->get_nof_comps(); i++) { + int idx = eas->get_group_byIndex(i); + if (last_idx != 0 && last_idx == idx) { + // do nothing, the field is part of the group + } else if (last_idx != 0 && idx == 0) { + // the group is ended + oerattrib->ext_attr_groups.add(new int(i)); + last_idx = 0; + } else if (last_idx != 0 && idx != 0) { + // The group is ended, but new one comes immediately + last_idx = idx; + oerattrib->ext_attr_groups.add(new int(i)); + oerattrib->ext_attr_groups.add(new int(i)); + } else if (last_idx == 0 && idx != 0) { + // new group + last_idx = idx; + oerattrib->ext_attr_groups.add(new int(i)); + } + } + if (last_idx != 0) { + oerattrib->ext_attr_groups.add(new int(eas->get_nof_comps())); + } + } + if (t->typetype != T_SET_A) { + for (size_t i = 0; i < t->get_nof_comps(); i++) + oerattrib->p.add(new int(i)); } break; } case T_SEQOF: diff --git a/compiler2/Type_codegen.cc b/compiler2/Type_codegen.cc index 37f5d021569a1c0a865556e08bd36efd650482bd..d4d2e4bd6aafd5935b00033c6f895a5e3006767d 100644 --- a/compiler2/Type_codegen.cc +++ b/compiler2/Type_codegen.cc @@ -1087,16 +1087,47 @@ void Type::generate_code_oerdescriptor(output_struct *target) if (NULL == oerattrib) { target->source.global_vars = mputprintf(target->source.global_vars, - "const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE, -1, FALSE };\n" + "const TTCN_OERdescriptor_t %s_oer_ = { -1, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL };\n" , get_genname_own().c_str()); } else { + target->source.global_vars = mputprintf(target->source.global_vars, + "const int %s_oer_ext_arr_[%lu] = {" + , get_genname_own().c_str() + , oerattrib->ext_attr_groups.size()); + for (size_t i = 0; i < oerattrib->ext_attr_groups.size(); i++) { + target->source.global_vars = mputprintf(target->source.global_vars, + "%i", *oerattrib->ext_attr_groups[i]); + if (i != oerattrib->ext_attr_groups.size() - 1) { + target->source.global_vars = mputstr(target->source.global_vars, ", "); + } + } + target->source.global_vars = mputstr(target->source.global_vars, "};\n"); + target->source.global_vars = mputprintf(target->source.global_vars, + "const int %s_oer_p_[%lu] = {" + , get_genname_own().c_str() + , oerattrib->p.size()); + for (size_t i = 0; i < oerattrib->p.size(); i++) { + target->source.global_vars = mputprintf(target->source.global_vars, + "%i", *oerattrib->p[i]); + if (i != oerattrib->p.size() - 1) { + target->source.global_vars = mputstr(target->source.global_vars, ", "); + } + } + target->source.global_vars = mputstr(target->source.global_vars, "};\n"); target->source.global_vars = mputprintf(target->source.global_vars, - "const TTCN_OERdescriptor_t %s_oer_ = { %i, %s, %i, %s };\n" + "const TTCN_OERdescriptor_t %s_oer_ = { %i, %s, %i, %s, %i, %lu, %s_oer_ext_arr_, %lu, %s_oer_p_" , get_genname_own().c_str() , oerattrib->bytes , oerattrib->signed_ ? "TRUE" : "FALSE" , oerattrib->length - , oerattrib->extendable ? "TRUE" : "FALSE"); + , oerattrib->extendable ? "TRUE" : "FALSE" + , oerattrib->nr_of_root_comps + , oerattrib->ext_attr_groups.size() + , get_genname_own().c_str() + , oerattrib->p.size() + , get_genname_own().c_str()); + + target->source.global_vars = mputstr(target->source.global_vars, "};\n"); } } @@ -1219,6 +1250,10 @@ void Type::generate_code_Choice(output_struct *target) get_gen_coder_functions(CT_XER); sdef.hasJson = get_gen_coder_functions(CT_JSON); sdef.hasOer = get_gen_coder_functions(CT_OER); + if (oerattrib) { + sdef.oerExtendable = oerattrib->extendable; + sdef.oerNrOrRootcomps = oerattrib->nr_of_root_comps; + } sdef.has_opentypes = get_has_opentypes(); sdef.opentype_outermost = get_is_opentype_outermost(); sdef.ot = generate_code_ot(pool); @@ -1632,6 +1667,20 @@ void Type::generate_code_Se(output_struct *target) get_gen_coder_functions(CT_XER); sdef.hasJson = get_gen_coder_functions(CT_JSON); sdef.hasOer = get_gen_coder_functions(CT_OER); + if (oerattrib) { + sdef.oerExtendable = oerattrib->extendable; + sdef.oerNrOrRootcomps = oerattrib->nr_of_root_comps; + sdef.oerEagNum = oerattrib->ext_attr_groups.size(); + sdef.oerEag = (int*)Malloc(sdef.oerEagNum*sizeof(int)); + for (int i = 0; i < sdef.oerEagNum; i++) { + sdef.oerEag[i] = *(oerattrib->ext_attr_groups[i]); + } + sdef.oerPNum = oerattrib->p.size(); + sdef.oerP = (int*)Malloc(sdef.oerPNum*sizeof(int)); + for (int i = 0; i < sdef.oerPNum; i++) { + sdef.oerP[i] = *(oerattrib->p[i]); + } + } if (xerattrib){ Module *my_module = get_my_scope()->get_scope_mod(); sdef.xerHasNamespaces = my_module->get_nof_ns() != 0; @@ -2046,6 +2095,12 @@ void Type::generate_code_Se(output_struct *target) } } Free(sdef.elements); + if (sdef.oerEag) { + Free(sdef.oerEag); + } + if (sdef.oerP) { + Free(sdef.oerP); + } } bool Type::is_untagged() const { return xerattrib && xerattrib->untagged_; } diff --git a/compiler2/Typestuff.cc b/compiler2/Typestuff.cc index ff5b661b5f7b2d90b64a27e1559201dad1cb55c7..64fb0b98af1f0262756125b105c816f1bbbcf321 100644 --- a/compiler2/Typestuff.cc +++ b/compiler2/Typestuff.cc @@ -709,6 +709,19 @@ namespace Common { get_fullname().c_str(), (unsigned long) n); return 0; } + + int ExtAdds::get_group_byIndex(size_t n) const + { + size_t offset = n; + for(size_t i = 0; i < eas.size(); i++) { + size_t size = eas[i]->get_nof_comps(); + if (offset < size) return eas[i]->get_group_number(); + else offset -= size; + } + FATAL_ERROR("%s: Requested index %lu does not exist.", \ + get_fullname().c_str(), (unsigned long) n); + return 0; + } bool ExtAdds::has_comp_withName(const Identifier& p_name) const { @@ -737,6 +750,10 @@ namespace Common { { if(!p_ea) FATAL_ERROR("NULL parameter: Asn::ExtAdds::add_ea()"); + if (p_ea->is_ext_attr_group()) { + num_of_groups++; + p_ea->set_group_number(num_of_groups); + } eas.add(p_ea); } diff --git a/compiler2/Typestuff.hh b/compiler2/Typestuff.hh index c7ee40fdb79b40f954b601f5025299309e38f163..2ede5e412667b80e93f83332459d9eda375b2200 100644 --- a/compiler2/Typestuff.hh +++ b/compiler2/Typestuff.hh @@ -130,6 +130,7 @@ namespace Common { bool has_comp_withName(const Identifier& p_name); CompField* get_comp_byName(const Identifier& p_name); void tr_compsof(ReferenceChain *refch, bool in_ellipsis); + ExtAndExc* get_ext_and_exc() const { return ee; } bool has_ellipsis() const { return ee != 0; } bool needs_auto_tags(); void add_auto_tags(); @@ -160,6 +161,9 @@ namespace Common { virtual bool has_comp_withName(const Identifier& p_name) const = 0; virtual CompField* get_comp_byName(const Identifier& p_name) const = 0; virtual void tr_compsof(ReferenceChain *refch, bool is_set) = 0; + virtual bool is_ext_attr_group() const { return false; } + virtual int get_group_number() const { return 0; } + virtual void set_group_number(int) {} }; /** @@ -168,18 +172,21 @@ namespace Common { class ExtAdds : public Node { private: vector<ExtAdd> eas; + // The number of ExtAddGrps + int num_of_groups; /** Copy constructor not implemented */ ExtAdds(const ExtAdds& p); /** Assignment disabled */ ExtAdds& operator=(const ExtAdds& p); public: - ExtAdds() : Node(), eas() { } + ExtAdds() : Node(), eas(), num_of_groups(0) { } virtual ~ExtAdds(); virtual ExtAdds *clone() const; virtual void set_fullname(const string& p_fullname); virtual void set_my_scope(Scope *p_scope); size_t get_nof_comps() const; CompField* get_comp_byIndex(size_t n) const; + int get_group_byIndex(size_t n) const; bool has_comp_withName(const Identifier& p_name) const; CompField* get_comp_byName(const Identifier& p_name) const; void tr_compsof(ReferenceChain *refch, bool is_set); @@ -215,6 +222,7 @@ namespace Common { void tr_compsof(ReferenceChain *refch, bool is_set) { eas->tr_compsof(refch, is_set); } void set_eas(ExtAdds *p_eas); + ExtAdds * get_eas() const { return eas; } virtual void dump(unsigned level) const; }; @@ -226,6 +234,8 @@ namespace Common { /** can be NULL if not present */ Value *versionnumber; CTs *cts; + // Needed for oer coding + int groupnumber; /** Copy constructor not implemented */ ExtAddGrp(const ExtAddGrp& p); /** Assignment disabled */ @@ -242,6 +252,10 @@ namespace Common { virtual CompField* get_comp_byName(const Identifier& p_name) const; virtual void tr_compsof(ReferenceChain *refch, bool is_set); virtual void dump(unsigned level) const; + virtual bool is_ext_attr_group() const { return true; } + virtual int get_group_number() const { return groupnumber; } + virtual void set_group_number(int num) { groupnumber = num; } + }; /** diff --git a/compiler2/datatypes.h b/compiler2/datatypes.h index 7cce1d644f7440a5c47baf0077a55bd25cfff0bb..f85fd171c07bba4a59328a41df50d405fe9019a6 100644 --- a/compiler2/datatypes.h +++ b/compiler2/datatypes.h @@ -104,6 +104,12 @@ typedef struct { boolean hasXer; boolean hasJson; boolean hasOer; + boolean oerExtendable; + int oerNrOrRootcomps; + int oerEagNum; + int* oerEag; + int oerPNum; + int* oerP; boolean xerUntagged; boolean xerUntaggedOne; /**< from Type::u.secho.has_single_charenc */ boolean xerUseNilPossible; /* for sequence */ diff --git a/compiler2/record.c b/compiler2/record.c index b016a22d68834cb9f7959038022cf7413d9cef30..53333fec1080e96375f94ac8f02431b29d1fa92f 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -4655,56 +4655,193 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) if (oer_needed) { // OER encode, RT1 src = mputprintf(src, - "int %s::OER_encode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const\n" + "int %s::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n" "{\n" " if (!is_bound()) {\n" " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" " \"Encoding an unbound %s value.\");\n" " return -1;\n" " }\n", name, sdef->kind == SET ? "set" : "record"); + + if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) { + src = mputstr(src, + " boolean has_extension = FALSE;\n"); + for (i = sdef->oerNrOrRootcomps; i < sdef->nElements; i++) { + src = mputprintf(src, + " has_extension = has_extension || (field_%s.is_bound() && field_%s.is_present());\n", + sdef->elements[i].name, sdef->elements[sdef->oerP[i]].name); + } + } size_t opt_elements = 0; - for (i = 0; i < sdef->nElements; i++) { - if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + size_t limit = sdef->oerExtendable ? sdef->oerNrOrRootcomps : sdef->nElements; + for (i = 0; i < limit; i++) { + if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) { opt_elements++; } } - int needed_bytes = opt_elements / 8 + 1; + int bits = opt_elements+(sdef->oerExtendable == TRUE); + int needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1); - if (opt_elements != 0) { - src = mputprintf(src, - " unsigned char c[%i] = {0};\n" - , needed_bytes); + int pos = 8; + if (opt_elements != 0 || sdef->oerExtendable) { + src = mputstr(src, + " char c = 0;\n"); + if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) { + pos--; + src = mputprintf(src, + " if (has_extension) {\n" + " c += %i;\n" + " }\n", 1 << 7); + } } + int ind = 0; - int pos = 8; - for (i = 0; i < sdef->nElements; i++) { - if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + for (i = 0; i < limit; i++) { + if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) { pos--; src = mputprintf(src, " if (field_%s.is_present()) {\n" - " c[%i] += 1 << %i;\n" + " c += %i;\n" " }\n" - , sdef->elements[i].name, ind, pos); + , sdef->elements[sdef->oerP[i]].name + , 1 << pos); if (pos == 0) { pos = 8; ind++; + src = mputstr(src, + " p_buf.put_c(c);\n" + " c = 0\n;"); } } } - if (opt_elements != 0) { - src = mputprintf(src, - " p_buf.put_s(%i, c);\n" - , needed_bytes); + if (opt_elements != 0 || sdef->oerExtendable) { + if (pos != 8 || ind == 0) { + src = mputstr(src, + " p_buf.put_c(c);\n"); + } } - for (i = 0; i < sdef->nElements; i++) { - if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + for (i = 0; i < limit; i++) { + if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) { src = mputprintf(src, " if (field_%s.is_present())\n " - , sdef->elements[i].name); + , sdef->elements[sdef->oerP[i]].name); } src = mputprintf(src, " field_%s.OER_encode(%s_descr_, p_buf);\n" - , sdef->elements[i].name, sdef->elements[i].typedescrname); + , sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname); + } + + if (sdef->oerExtendable && sdef->oerNrOrRootcomps != sdef->nElements) { + bits = 0; + int eag_pos = 0; + for (i = limit; i < sdef->nElements; i++) { + if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) { + eag_pos++; + bits++; + i += sdef->oerEag[eag_pos] - sdef->oerEag[eag_pos-1] - 1; + eag_pos++; + } else { + bits++; + } + } + needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1); + src = mputprintf(src, + " if (has_extension) {\n" + "%s" + " TTCN_Buffer tmp_buf;\n" + " TTCN_Buffer tmp_buf2;\n" + " TTCN_Buffer tmp_buf3;\n" + " c = 0;\n" + , sdef->oerEagNum != 0 ? " boolean has_present = FALSE;\n" : ""); + eag_pos = 0; + pos = 8; + ind = 0; + for (i = limit; i < sdef->nElements; i++) { + pos--; + if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) { + eag_pos++; + int opt_elems = 0; + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) { + opt_elems++; + } + src = mputprintf(src, + " has_present = has_present || field_%s.is_present();\n", sdef->elements[sdef->oerP[j]].name); + } + src = mputprintf(src, + " if (has_present) {\n" + " has_present = FALSE;\n" + " c += %i;\n", 1 << pos); + if (opt_elems != 0) { + src = mputstr(src, + " char c2 = 0;\n"); + int pos2 = 8; + int ind2 = 0; + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) { + pos2--; + src = mputprintf(src, + " if (field_%s.is_present()) {\n" + " c2 += %i;\n" + " }\n" + , sdef->elements[sdef->oerP[j]].name, 1 << pos2); + if (pos2 == 0) { + pos2 = 8; + ind2++; + src = mputstr(src, + " tmp_buf2.put_c(c2);\n" + " c2 = 0;\n"); + } + } + } + if (pos2 != 8) { + src = mputstr(src, + " tmp_buf2.put_c(c2);\n"); + } + } + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + src = mputprintf(src, + " field_%s.OER_encode(%s_descr_, tmp_buf2);\n" + , sdef->elements[sdef->oerP[j]].name, sdef->elements[sdef->oerP[j]].typedescrname); + } + src = mputstr(src, + " encode_oer_length(tmp_buf2.get_len(), tmp_buf, FALSE);\n" + " tmp_buf.put_buf(tmp_buf2);\n" + " tmp_buf2.clear();\n" + " }\n"); + i += sdef->oerEag[eag_pos] - sdef->oerEag[eag_pos-1] - 1; + eag_pos++; + } else { + src = mputprintf(src, + " if (field_%s.is_present()) {\n" + " c += %i;\n" + " field_%s.OER_encode(%s_descr_, tmp_buf2);\n" + " encode_oer_length(tmp_buf2.get_len(), tmp_buf, FALSE);\n" + " tmp_buf.put_buf(tmp_buf2);\n" + " tmp_buf2.clear();\n" + " }\n" + , sdef->elements[sdef->oerP[i]].name, 1 << pos + , sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname); + } + if (pos == 0) { + ind++; + pos = 8; + src = mputstr(src, + " tmp_buf3.put_c(c);\n" + " c = 0;\n"); + } + } + if (pos != 8) { + src = mputstr(src, + " tmp_buf3.put_c(c);\n"); + } + src = mputprintf(src, + " encode_oer_length(%i, p_buf, FALSE);\n" + " p_buf.put_c(%i);\n" + " p_buf.put_buf(tmp_buf3);\n" + " p_buf.put_buf(tmp_buf);\n" + " tmp_buf.clear();\n" + " }\n", needed_bytes+1, pos); } src = mputstr(src, " return 0;\n" @@ -4714,7 +4851,9 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) src = mputprintf(src, "int %s::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer)\n" "{\n", name); - if (opt_elements != 0) { + bits = opt_elements+(sdef->oerExtendable == TRUE); + needed_bytes = bits / 8 + (bits % 8 == 0 ? 0 : 1); + if (needed_bytes != 0) { src = mputprintf(src, " const unsigned char* uc = p_buf.get_read_data();\n" " p_buf.increase_pos(%i);\n" @@ -4722,18 +4861,26 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) } ind = 0; pos = 8; - for (i = 0; i < sdef->nElements; i++) { - if (sdef->elements[i].isOptional || sdef->elements[i].isDefault) { + if (sdef->oerExtendable) { + src = mputstr(src, + " boolean has_extension = FALSE;\n" + " if (uc[0] & 0x80) {\n" + " has_extension = TRUE;\n" + " }\n"); + pos--; + } + for (i = 0; i < limit; i++) { + if (sdef->elements[sdef->oerP[i]].isOptional || sdef->elements[sdef->oerP[i]].isDefault) { pos--; src = mputprintf(src, " if (uc[%i] & (1 << %i))\n" " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" , ind, pos, sdef->elements[i].name - , sdef->elements[i].typedescrname); - if (sdef->elements[i].isOptional) { + , sdef->elements[sdef->oerP[i]].typedescrname); + if (sdef->elements[sdef->oerP[i]].isOptional) { src = mputprintf(src, " else\n" " field_%s = OMIT_VALUE;\n" - , sdef->elements[i].name); + , sdef->elements[sdef->oerP[i]].name); } if (pos == 0) { ind++; @@ -4742,10 +4889,104 @@ void defRecordClass1(const struct_def *sdef, output_struct *output) } else { src = mputprintf(src, " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" - , sdef->elements[i].name - , sdef->elements[i].typedescrname); + , sdef->elements[sdef->oerP[i]].name + , sdef->elements[sdef->oerP[i]].typedescrname); + } + } + + if (sdef->oerExtendable) { + src = mputstr(src, + " if (has_extension) {\n" + " size_t bytes = decode_oer_length(p_buf, FALSE);\n" + " uc = p_buf.get_read_data();\n" + " p_buf.increase_pos(bytes);\n" + " uc++;\n"); + int eag_pos = 0; + pos = 8; + ind = 0; + for (i = limit; i < sdef->nElements; i++) { + pos--; + src = mputprintf(src, + " if (!(uc[%i] & %i)) {\n" + , ind, 1 << pos); + if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) { + eag_pos++; + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + if (sdef->elements[sdef->oerP[j]].isOptional) { + src = mputprintf(src, + " field_%s = OMIT_VALUE;\n" + , sdef->elements[sdef->oerP[j]].name); + } + } + eag_pos--; + } else { + if (sdef->elements[sdef->oerP[i]].isOptional) { + src = mputprintf(src, + " field_%s = OMIT_VALUE;\n" + , sdef->elements[i].name); + } + } + src = mputstr(src, + " } else {\n" + " decode_oer_length(p_buf, FALSE);\n"); + if (sdef->oerEagNum != 0 && sdef->oerEag[eag_pos] == i - limit) { + eag_pos++; + int nof_opt = 0; + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) { + nof_opt++; + } + } + needed_bytes = nof_opt / 8 + (nof_opt % 8 == 0 ? 0 : 1); + src = mputprintf(src, + " const unsigned char* uc2 = p_buf.get_read_data();\n" + " (void)uc2;\n" + " p_buf.increase_pos(%i);\n" + , needed_bytes); + int pos2 = 8; + int ind2 = 0; + for (int j = i; j < limit + sdef->oerEag[eag_pos]; j++) { + if (sdef->elements[sdef->oerP[j]].isOptional || sdef->elements[sdef->oerP[j]].isDefault) { + pos2--; + src = mputprintf(src, + " if (uc2[%i] & %i) {\n" + " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" + " }\n" + , ind2, 1 << pos2, sdef->elements[sdef->oerP[j]].name, sdef->elements[sdef->oerP[j]].typedescrname); + if (sdef->elements[sdef->oerP[j]].isOptional) { + src = mputprintf(src, + " else {\n" + " field_%s = OMIT_VALUE;\n" + " }\n" + , sdef->elements[sdef->oerP[j]].name); + } + if (pos2 == 0) { + pos2 = 8; + ind2++; + } + } else { + src = mputprintf(src, + " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" + , sdef->elements[sdef->oerP[j]].name, sdef->elements[sdef->oerP[j]].typedescrname); + } + } + i += sdef->oerEag[eag_pos] - sdef->oerEag[eag_pos-1] - 1; + eag_pos++; + } else { + src = mputprintf(src, + " field_%s.OER_decode(%s_descr_, p_buf, p_oer);\n" + , sdef->elements[sdef->oerP[i]].name, sdef->elements[sdef->oerP[i]].typedescrname); + } + src = mputstr(src, " }\n"); + if (pos == 0) { + pos = 8; + ind++; + } } + src = mputstr(src, + " }\n"); } + if (sdef->opentype_outermost) { src = mputstr(src, " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");" diff --git a/compiler2/ttcn3/OerAST.cc b/compiler2/ttcn3/OerAST.cc index a4a754150c1b9d096655d4a59219d72fd2a7171e..0cf688c514000a10b9ca24963c17a0b5c5bdbbcd 100644 --- a/compiler2/ttcn3/OerAST.cc +++ b/compiler2/ttcn3/OerAST.cc @@ -15,10 +15,24 @@ OerAST::OerAST() : bytes(-1), signed_(false), length(-1), - extendable(false) + extendable(false), + nr_of_root_comps(0), + ext_attr_groups(), + p() {} +OerAST::~OerAST() { + for (size_t i = 0; i < ext_attr_groups.size(); i++) { + delete ext_attr_groups[i]; + } + ext_attr_groups.clear(); + for (size_t i = 0; i < p.size(); i++) { + delete p[i]; + } + p.clear(); +} + bool OerAST::empty() const { return bytes == -1 && signed_ == false && length == -1 && - extendable == false; + extendable == false && nr_of_root_comps == 0 && ext_attr_groups.empty() && p.empty(); } diff --git a/compiler2/ttcn3/OerAST.hh b/compiler2/ttcn3/OerAST.hh index eb047006fb8429fdad40358af1543f13ab8240fa..26e3e9d39b32e55cecba91cca60ac019ad2a468c 100644 --- a/compiler2/ttcn3/OerAST.hh +++ b/compiler2/ttcn3/OerAST.hh @@ -12,14 +12,20 @@ #ifndef OERAST_HH #define OERAST_HH +#include "../vector.hh" + class OerAST { public: int bytes; bool signed_; int length; bool extendable; + int nr_of_root_comps; + vector<int> ext_attr_groups; + vector<int> p; OerAST(); + ~OerAST(); bool empty() const; }; diff --git a/compiler2/union.c b/compiler2/union.c index 5b1a117c49e1e526339382cde4f0b8addfdc0f7c..4023b471336fbc73e621e64a4a6f37fd88249352 100644 --- a/compiler2/union.c +++ b/compiler2/union.c @@ -2381,10 +2381,14 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " case %s_%s:\n", selection_prefix, sdef->elements[i].name); if (sdef->has_opentypes == FALSE) { src = mputprintf(src, + " {TTCN_Buffer buf;\n" " encode_oer_tag(*%s_descr_.ber, p_buf);\n" - " field_%s->OER_encode(%s_descr_, p_buf);\n" - " break;\n" - , sdef->elements[i].typedescrname, sdef->elements[i].name, sdef->elements[i].typedescrname); + " field_%s->OER_encode(%s_descr_, buf);\n" + "%s" + " p_buf.put_buf(buf);\n" + " break;\n}" + , sdef->elements[i].typedescrname, sdef->elements[i].name, sdef->elements[i].typedescrname + , (!sdef->oerExtendable || i < sdef->oerNrOrRootcomps) ? "" : " encode_oer_length(buf.get_len(), p_buf, FALSE);\n"); } else { src = mputprintf(src, " {\n" @@ -2428,26 +2432,32 @@ void defUnionClass(struct_def const *sdef, output_struct *output) " err_vals = p_err_descr->get_field_err_values(%d);\n" " emb_descr = p_err_descr->get_field_emb_descr(%d);\n" " if (NULL != err_vals && NULL != err_vals->value) {\n" + " TTCN_Buffer tmp_buf;\n" " if (NULL != err_vals->value->errval) {\n" " if(err_vals->value->raw){\n" - " err_vals->value->errval->OER_encode_negtest_raw(p_buf);\n" + " err_vals->value->errval->OER_encode_negtest_raw(tmp_buf);\n" " } else {\n" " if (NULL == err_vals->value->type_descr) {\n" " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n" " }\n" " encode_oer_tag(*err_vals->value->type_descr->ber, p_buf);\n" - " err_vals->value->errval->OER_encode(*err_vals->value->type_descr, p_buf);\n" + " err_vals->value->errval->OER_encode(*err_vals->value->type_descr, tmp_buf);\n" + "%s" " }\n" " }\n" + " p_buf.put_buf(tmp_buf);\n" " } else {\n" " if (NULL != emb_descr) {\n" " field_%s->OER_encode_negtest(emb_descr, %s_descr_, p_buf);\n" " } else {\n" + " encode_oer_tag(*err_vals->value->type_descr->ber, p_buf);\n" " field_%s->OER_encode(%s_descr_, p_buf);\n" " }\n" " }\n" " break;\n" , selection_prefix, sdef->elements[i].name, (int)i, (int)i + , (!sdef->oerExtendable || i < sdef->oerNrOrRootcomps) ? + "" : " encode_oer_length(tmp_buf.get_len(), p_buf, FALSE);\n" , sdef->elements[i].name, sdef->elements[i].typedescrname , sdef->elements[i].name, sdef->elements[i].typedescrname); } @@ -2482,10 +2492,13 @@ void defUnionClass(struct_def const *sdef, output_struct *output) src = mputprintf(src, " if (%s_descr_.ber->tags[%s_descr_.ber->n_tags-1].tagclass == descr.tagclass &&\n" " %s_descr_.ber->tags[%s_descr_.ber->n_tags-1].tagnumber == descr.tagnumber) {\n" + "%s" " %s%s().OER_decode(%s_descr_, p_buf, p_oer);\n" " } else \n" , sdef->elements[i].typedescrname, sdef->elements[i].typedescrname, sdef->elements[i].typedescrname - , sdef->elements[i].typedescrname, at_field, sdef->elements[i].name, sdef->elements[i].typedescrname); + , sdef->elements[i].typedescrname, + (!sdef->oerExtendable || i < sdef->oerNrOrRootcomps) ? "" : " decode_oer_length(p_buf, FALSE);\n" + , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname); } src = mputprintf(src, "{\n" diff --git a/core/OER.cc b/core/OER.cc index 009f71853aa5e0d7ef8f754ff139eed557680eed..3ab33adf3a1dade933d624e926b75d79950a5645 100644 --- a/core/OER.cc +++ b/core/OER.cc @@ -159,46 +159,46 @@ ASN_Tag_t decode_oer_tag(TTCN_Buffer& buf) { return tag; } -const TTCN_OERdescriptor_t BOOLEAN_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t BOOLEAN_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t INTEGER_oer_ = { -1, TRUE, 0, FALSE }; +const TTCN_OERdescriptor_t INTEGER_oer_ = { -1, TRUE, 0, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t BITSTRING_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t BITSTRING_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t OCTETSTRING_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t OCTETSTRING_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL , 0, NULL}; -const TTCN_OERdescriptor_t FLOAT_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t FLOAT_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t ASN_NULL_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t ASN_NULL_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t IA5String_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t IA5String_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t VisibleString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t VisibleString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t NumericString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t NumericString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t PrintableString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t PrintableString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t BMPString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t BMPString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t UniversalString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t UniversalString_oer_ = { 0, FALSE, -1, FALSE , 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t UTF8String_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t UTF8String_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t TeletexString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t TeletexString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL , 0, NULL}; -const TTCN_OERdescriptor_t VideotexString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t VideotexString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t GraphicString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t GraphicString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t GeneralString_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t GeneralString_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t OBJID_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t OBJID_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t ASN_ROID_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t ASN_ROID_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t EMBEDDED_PDV_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t EMBEDDED_PDV_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t EXTERNAL_oer_ = { 0, FALSE, -1, FALSE }; +const TTCN_OERdescriptor_t EXTERNAL_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; -const TTCN_OERdescriptor_t ObjectDescriptor_oer_ = { 0, FALSE, -1, FALSE }; \ No newline at end of file +const TTCN_OERdescriptor_t ObjectDescriptor_oer_ = { 0, FALSE, -1, FALSE, 0, 0, NULL, 0, NULL }; \ No newline at end of file diff --git a/core/OER.hh b/core/OER.hh index d1bbab55d5bd00ab5768c4dd842e9409c451461a..d2af25c69269c25893cc221d6887c50c0a30efe3 100644 --- a/core/OER.hh +++ b/core/OER.hh @@ -24,7 +24,20 @@ struct TTCN_OERdescriptor_t int bytes; boolean signed_; int length; - boolean extendable; // Always false. Possibly a bug with is_extendable() + boolean extendable; + int nr_of_root_comps; + // length of the eag int array + int eag_len; + // contains the start and end index of the extension groups, indexed from the + // index of last root component. + // {2 4} means that the 3rd and 4th element of the extensions are in a group. + // always contains even number of integers + const int * const eag; + int p_len; + // Contains the correct order of fields. (CER coding reorders fields) + // p[1] = 2 means that the reordered fields are not correct for OER coding, + // and the first field must be the second while coding in oer. + const int * const p; }; struct OER_struct diff --git a/core2/Basetype2.cc b/core2/Basetype2.cc index 71eac887b270f1b3f39e9089bf5f481a609fc92e..886b2050067f84c8b4782c801c7184f56848e6c8 100644 --- a/core2/Basetype2.cc +++ b/core2/Basetype2.cc @@ -36,6 +36,7 @@ #include "Addfunc.hh" #include "PreGenRecordOf.hh" #include "Encdec.hh" +#include "OER.hh" //////////////////////////////////////////////////////////////////////////////// @@ -6262,14 +6263,30 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu int field_count = get_count(); int pos = 8; char c = 0; - for (int i = 0; i < field_count; i++) { - boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + int limit = field_count; + bool has_extension = false; + // If extendable record and has real extensions the first bit of the + // preamble is 1 + if (p_td.oer->extendable) { + for (int i = p_td.oer->nr_of_root_comps; i < field_count; i++) { + // If there are extension fields the first bit is 1 + if (get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present()) { + c = 1 << 7; + has_extension = true; + break; + } + } + pos--; + limit = p_td.oer->nr_of_root_comps; + } + for (int i = 0; i < limit; i++) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); if (is_default_field) { next_default_idx++; } - if (get_at(i)->is_optional() || is_default_field) { + if (get_at(p_td.oer->p[i])->is_optional() || is_default_field) { pos--; - c += get_at(i)->is_present() << pos; + c += get_at(p_td.oer->p[i])->is_present() << pos; if (pos == 0) { p_buf.put_c(c); pos = 8; @@ -6280,13 +6297,113 @@ int Record_Type::OER_encode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_bu if (pos != 8) { p_buf.put_c(c); } - for (int i = 0; i < field_count; ++i) { - get_at(i)->OER_encode(*fld_descr(i), p_buf); + for (int i = 0; i < limit; ++i) { + get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), p_buf); + } + + // If the record is extendable and has real extensions + if (has_extension) { + // Calculate the extension addition presence bitmap + TTCN_Buffer tmp_buf; + c = 0; + pos = 8; + int eag_pos = p_td.oer->eag_len == 0 ? -1 : 0; + for (int i = limit; i < field_count; i++) { + pos--; + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + eag_pos++; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + if (get_at(p_td.oer->p[j])->is_bound() && get_at(p_td.oer->p[j])->is_present()) { + // Add bit if there are at least one present field + c += 1 << pos; + break; + } + } + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else { + // extension attribute groups counted as one in the presence bitmap + if (get_at(p_td.oer->p[i])->is_present()) { + c += 1 << pos; + } + } + // Prepare next octet of the bitmap + if (pos == 0) { + tmp_buf.put_c(c); + pos = 8; + c = 0; + } + } + // Put remaining presence bitmap + if (pos != 8) { + tmp_buf.put_c(c); + } + + encode_oer_length(1 + tmp_buf.get_len(), p_buf, FALSE); + // Put the 'remaining bit' octet if there are any + p_buf.put_c(pos); + p_buf.put_buf(tmp_buf); + tmp_buf.clear(); + + eag_pos = p_td.oer->eag_len == 0 ? -1 : 0; + for (int i = limit; i < field_count; ++i) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); + if (is_default_field) { + next_default_idx++; + } + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + // If it is the start of the ext attribute group then calculate presence bitmap, + // because it is encoded as a sequence + eag_pos++; + c = 0; + pos = 8; + if (is_default_field) { + next_default_idx--; + } + bool has_present = false; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + if (get_at(p_td.oer->p[j])->is_present()) { + has_present = true; + } + is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]); + if (is_default_field) { + next_default_idx++; + } + if (get_at(p_td.oer->p[j])->is_optional() || is_default_field) { + pos--; + c += get_at(p_td.oer->p[j])->is_present() << pos; + if (pos == 0) { + tmp_buf.put_c(c); + pos = 8; + c = 0; + } + } + } + if (pos != 8) { + tmp_buf.put_c(c); + } + if (has_present) { + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + get_at(p_td.oer->p[j])->OER_encode(*fld_descr(p_td.oer->p[j]), tmp_buf); + } + encode_oer_length(tmp_buf.get_len(), p_buf, FALSE); + p_buf.put_buf(tmp_buf); + } + tmp_buf.clear(); + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else if (get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present()) { + get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), tmp_buf); + encode_oer_length(tmp_buf.get_len(), p_buf, FALSE); + p_buf.put_buf(tmp_buf); + tmp_buf.clear(); + } + } } return 0; } -int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf) const { +int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const { int values_idx = 0; int edescr_idx = 0; int field_count = get_count(); @@ -6294,16 +6411,37 @@ int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, c const default_struct* default_indexes = get_default_indexes(); int pos = 8; char c = 0; - for (int i = 0; i < field_count; i++) { - boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + int limit = field_count; + bool has_extension = false; + // If extendable record and has real extensions the first bit of the + // preamble is 1 + if (p_td.oer->extendable) { + for (int i = p_td.oer->nr_of_root_comps; i < field_count; i++) { + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[i], values_idx); + boolean present = FALSE; + if (NULL != err_vals && NULL != err_vals->value && NULL != err_vals->value->errval) { + present = TRUE; + } + // If there are extension fields the first bit is 1 + if ((get_at(p_td.oer->p[i])->is_bound() && get_at(p_td.oer->p[i])->is_present()) || present) { + c = 1 << 7; + has_extension = true; + break; + } + } + pos--; + limit = p_td.oer->nr_of_root_comps; + } + for (int i = 0; i < limit; i++) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); if (is_default_field) { next_default_idx++; } - if (get_at(i)->is_optional() || is_default_field) { + if (get_at(p_td.oer->p[i])->is_optional() || is_default_field) { pos--; - const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx); + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[i], values_idx); int present = 1; - if ((NULL != err_vals && NULL != err_vals->value && NULL == err_vals->value->errval) || !get_at(i)->is_present()) { + if ((NULL != err_vals && NULL != err_vals->value && NULL == err_vals->value->errval) || !get_at(p_td.oer->p[i])->is_present()) { present = 0; } c += present << pos; @@ -6318,13 +6456,13 @@ int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, c p_buf.put_c(c); } values_idx = 0; - for (int i = 0; i < field_count; ++i) { + for (int i = 0; i < limit; ++i) { if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) { continue; } - const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx); - const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx); + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[i], values_idx); + const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(p_td.oer->p[i], edescr_idx); if (NULL != err_vals && NULL != err_vals->before) { if (NULL == err_vals->before->errval) { @@ -6353,11 +6491,11 @@ int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, c } } } else { - if (NULL != fld_descr(i)->oer || get_at(i)->is_present()) { + if (NULL != fld_descr(p_td.oer->p[i])->oer || get_at(p_td.oer->p[i])->is_present()) { if (NULL != emb_descr) { - get_at(i)->OER_encode_negtest(emb_descr, *fld_descr(i), p_buf); + get_at(p_td.oer->p[i])->OER_encode_negtest(emb_descr, *fld_descr(p_td.oer->p[i]), p_buf); } else { - get_at(i)->OER_encode(*fld_descr(i), p_buf); + get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), p_buf); } } } @@ -6381,38 +6519,303 @@ int Record_Type::OER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, c break; } } + + // If the record is extendable and has real extensions + if (has_extension) { + // Calculate the extension addition presence bitmap + TTCN_Buffer tmp_buf; + c = 0; + pos = 8; + int eag_pos = p_td.oer->eag_len == 0 ? -1 : 0; + int old_values_idx = values_idx; + for (int i = limit; i < field_count; i++) { + pos--; + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + eag_pos++; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[j], values_idx); + boolean present = FALSE; + boolean omit = FALSE; + if (NULL != err_vals && NULL != err_vals->value && NULL != err_vals->value->errval) { + present = TRUE; + } + if (NULL != err_vals && NULL != err_vals->value && NULL == err_vals->value->errval) { + omit = TRUE; + } + if (!omit && ((get_at(p_td.oer->p[j])->is_bound() && get_at(p_td.oer->p[j])->is_present()) || present)) { + // Add bit if there are at least one present field + c += 1 << pos; + break; + } + } + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else { + // Normal extension field + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[i], values_idx); + boolean present = FALSE; + boolean omit = FALSE; + if (NULL != err_vals && NULL != err_vals->value && NULL != err_vals->value->errval) { + present = TRUE; + } + if (NULL != err_vals && NULL != err_vals->value && NULL == err_vals->value->errval) { + omit = TRUE; + } + if (!omit && (get_at(p_td.oer->p[i])->is_present() || present)) { + c += 1 << pos; + } + } + // Prepare next octet of the bitmap + if (pos == 0) { + tmp_buf.put_c(c); + pos = 8; + c = 0; + } + } + // Put remaining presence bitmap + if (pos != 8) { + tmp_buf.put_c(c); + } + + encode_oer_length(1 + tmp_buf.get_len(), p_buf, FALSE); + // Put the 'remaining bit' octet if there are any + p_buf.put_c(pos); + p_buf.put_buf(tmp_buf); + tmp_buf.clear(); + values_idx = old_values_idx; + eag_pos = p_td.oer->eag_len == 0 ? -1 : 0; + for (int i = limit; i < field_count; ++i) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); + if (is_default_field) { + next_default_idx++; + } + + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + // If it is the start of the ext attribute group then calculate presence bitmap, + // because it is encoded as a sequence + eag_pos++; + c = 0; + pos = 8; + if (is_default_field) { + next_default_idx--; + } + bool has_present = false; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[j], values_idx); + boolean present = FALSE; + boolean omit = FALSE; + if (NULL != err_vals && NULL != err_vals->value && NULL != err_vals->value->errval) { + present = TRUE; + } + if (NULL != err_vals && NULL != err_vals->value && NULL == err_vals->value->errval) { + omit = TRUE; + } + if (!omit && (get_at(p_td.oer->p[j])->is_present() || present)) { + has_present = true; + } + is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]); + if (is_default_field) { + next_default_idx++; + } + if (get_at(p_td.oer->p[j])->is_optional() || is_default_field) { + pos--; + c += (!omit && (get_at(p_td.oer->p[j])->is_present() || present)) << pos; + if (pos == 0) { + tmp_buf.put_c(c); + pos = 8; + c = 0; + } + } + } + if (pos != 8) { + tmp_buf.put_c(c); + } + if (has_present) { + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[j], values_idx); + const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(p_td.oer->p[j], edescr_idx); + if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > j) { + continue; + } + if (NULL != err_vals && NULL != err_vals->before) { + if (NULL == err_vals->before->errval) { + TTCN_error("internal error: erroneous before value missing"); + } + if (err_vals->before->raw) { + err_vals->before->errval->OER_encode_negtest_raw(tmp_buf); + } else { + if (NULL == err_vals->before->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + // it's an extra field + err_vals->before->errval->OER_encode(*(err_vals->before->type_descr), tmp_buf); + } + } + + if (NULL != err_vals && NULL != err_vals->value) { + if (NULL != err_vals->value->errval) { + if (err_vals->value->raw) { + err_vals->value->errval->OER_encode_negtest_raw(tmp_buf); + } else { + if (NULL == err_vals->value->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + err_vals->value->errval->OER_encode(*(err_vals->value->type_descr), tmp_buf); + } + } + } else { + if (NULL != fld_descr(p_td.oer->p[j])->oer || get_at(p_td.oer->p[j])->is_present()) { + if (NULL != emb_descr) { + get_at(p_td.oer->p[j])->OER_encode_negtest(emb_descr, *fld_descr(p_td.oer->p[j]), tmp_buf); + } else if (get_at(p_td.oer->p[j])->is_bound()) { + get_at(p_td.oer->p[j])->OER_encode(*fld_descr(p_td.oer->p[j]), tmp_buf); + } + } + } + + if (NULL != err_vals && NULL != err_vals->after) { + if (NULL == err_vals->after->errval) { + TTCN_error("internal error: erroneous after value missing"); + } + if (err_vals->after->raw) { + err_vals->after->errval->OER_encode_negtest_raw(tmp_buf); + } else { + if (NULL == err_vals->after->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + // it's an extra field + err_vals->after->errval->OER_encode(*(err_vals->after->type_descr), tmp_buf); + } + } + if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= j) { + break; + } + } + encode_oer_length(tmp_buf.get_len(), p_buf, FALSE); + p_buf.put_buf(tmp_buf); + } + tmp_buf.clear(); + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else if (get_at(p_td.oer->p[i])->is_bound()) { + const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(p_td.oer->p[i], values_idx); + const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(p_td.oer->p[i], edescr_idx); + if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) { + continue; + } + boolean need_length = TRUE; + if (NULL != err_vals && NULL != err_vals->before) { + if (NULL == err_vals->before->errval) { + TTCN_error("internal error: erroneous before value missing"); + } + if (err_vals->before->raw) { + err_vals->before->errval->OER_encode_negtest_raw(tmp_buf); + } else { + if (NULL == err_vals->before->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + // it's an extra field + err_vals->before->errval->OER_encode(*(err_vals->before->type_descr), tmp_buf); + } + } + + if (NULL != err_vals && NULL != err_vals->value) { + if (NULL != err_vals->value->errval) { + if (err_vals->value->raw) { + err_vals->value->errval->OER_encode_negtest_raw(p_buf); + } else { + if (NULL == err_vals->value->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + err_vals->value->errval->OER_encode(*(err_vals->value->type_descr), tmp_buf); + } + } else { + need_length = FALSE; + } + } else { + if (NULL != fld_descr(p_td.oer->p[i])->oer || get_at(p_td.oer->p[i])->is_present()) { + if (NULL != emb_descr) { + get_at(p_td.oer->p[i])->OER_encode_negtest(emb_descr, *fld_descr(p_td.oer->p[i]), tmp_buf); + } else { + if (!get_at(p_td.oer->p[i])->is_present()) { + need_length = FALSE; + } + get_at(p_td.oer->p[i])->OER_encode(*fld_descr(p_td.oer->p[i]), tmp_buf); + } + } + } + + if (NULL != err_vals && NULL != err_vals->after) { + if (NULL == err_vals->after->errval) { + TTCN_error("internal error: erroneous after value missing"); + } + if (err_vals->after->raw) { + err_vals->after->errval->OER_encode_negtest_raw(tmp_buf); + } else { + if (NULL == err_vals->after->type_descr) { + TTCN_error("internal error: erroneous before typedescriptor missing"); + } + // it's an extra field + err_vals->after->errval->OER_encode(*(err_vals->after->type_descr), tmp_buf); + } + } + if (need_length) { + encode_oer_length(tmp_buf.get_len(), p_buf, FALSE); + p_buf.put_buf(tmp_buf); + } + tmp_buf.clear(); + + if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) { + break; + } + } + } + } return 0; } -int Record_Type::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OER_struct& p_oer) { +int Record_Type::OER_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, OER_struct& p_oer) { int field_count = get_count(); + + const unsigned char* uc = p_buf.get_read_data(); + bool has_extension = false; + size_t act_pos = 0; size_t nof_opt = 0; + int limit = field_count; + if (p_td.oer->extendable) { + // First bit 1 if there are extensions + if (uc[0] & 0x80) { + has_extension = true; + } + act_pos++; + nof_opt++; + limit = p_td.oer->nr_of_root_comps; + } + int next_default_idx = 0; const default_struct* default_indexes = get_default_indexes(); - for (int i = 0; i < field_count; i++) { - boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + for (int i = 0; i < limit; i++) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); if (is_default_field) { next_default_idx++; } - if (get_at(i)->is_optional() || is_default_field) { + if (get_at(p_td.oer->p[i])->is_optional() || is_default_field) { nof_opt++; } } - size_t act_pos = 0; size_t bytes = nof_opt / 8 + (nof_opt % 8 == 0 ? 0 : 1); - const unsigned char* uc = p_buf.get_read_data(); p_buf.increase_pos(bytes); next_default_idx = 0; - for (int i = 0; i < field_count; ++i) { - boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==i); + for (int i = 0; i < limit; ++i) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); if (is_default_field) { next_default_idx++; } - if (get_at(i)->is_optional() || is_default_field) { + if (get_at(p_td.oer->p[i])->is_optional() || is_default_field) { if (!(uc[0] & 1 << (7-act_pos))) { - get_at(i)->set_to_omit(); + get_at(p_td.oer->p[i])->set_to_omit(); } else { - get_at(i)->OER_decode(*fld_descr(i), p_buf, p_oer); + get_at(p_td.oer->p[i])->OER_decode(*fld_descr(p_td.oer->p[i]), p_buf, p_oer); } act_pos++; if (act_pos == 8) { @@ -6420,9 +6823,110 @@ int Record_Type::OER_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer& p_buf, OE act_pos = 0; } } else { - get_at(i)->OER_decode(*fld_descr(i), p_buf, p_oer); + get_at(p_td.oer->p[i])->OER_decode(*fld_descr(p_td.oer->p[i]), p_buf, p_oer); } } + + // If there are extensions in the sequence + if (has_extension) { + bytes = decode_oer_length(p_buf, FALSE); + // uc points to the 'remaining bit' octet + uc = p_buf.get_read_data(); + p_buf.increase_pos(bytes); + // uc points to the extension presence bitmap + uc++; + int eag_pos = p_td.oer->eag_len == 0 ? -1 : 0; + act_pos = 0; + // Decode fields + for (int i = limit; i < field_count; ++i) { + boolean is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[i]); + if (is_default_field) { + next_default_idx++; + } + // If extension field is not present in the presence bitmap + if (!(uc[0] & 1 << (7-act_pos))) { + // If its an extension attribute group, handle the group as one + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + eag_pos++; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + if (get_at(p_td.oer->p[j])->is_optional()) { + get_at(p_td.oer->p[j])->set_to_omit(); + } + } + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else { + if (get_at(p_td.oer->p[i])->is_optional()) { + get_at(p_td.oer->p[i])->set_to_omit(); + } + } + } else { + // Extension field or group is present + decode_oer_length(p_buf, FALSE); + if (eag_pos != -1 && p_td.oer->eag[eag_pos] == i - limit) { + eag_pos++; + nof_opt = 0; + // Compensate for earlier increment + if (is_default_field) { + next_default_idx--; + } + int old_next_default_idx = next_default_idx; + // Count optional and default fields + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]); + if (is_default_field) { + next_default_idx++; + } + if (get_at(p_td.oer->p[j])->is_optional() || is_default_field) { + nof_opt++; + } + } + // uc2 points to the presence bitmap of the extension attr group + const unsigned char* uc2 = p_buf.get_read_data(); + size_t act_pos2 = 0; + bytes = nof_opt / 8 + (nof_opt % 8 == 0 ? 0 : 1); + p_buf.increase_pos(bytes); + next_default_idx = old_next_default_idx; + for (int j = i; j < limit + p_td.oer->eag[eag_pos]; j++) { + is_default_field = default_indexes && (default_indexes[next_default_idx].index==p_td.oer->p[j]); + if (is_default_field) { + next_default_idx++; + } + if (get_at(p_td.oer->p[j])->is_optional() || is_default_field) { + // Field is not present + if (!(uc2[0] & 1 << (7-act_pos2))) { + if (get_at(p_td.oer->p[j])->is_optional()) { + get_at(p_td.oer->p[j])->set_to_omit(); + } + } else { + // Field is present + get_at(p_td.oer->p[j])->OER_decode(*fld_descr(p_td.oer->p[j]), p_buf, p_oer); + } + act_pos2++; + // Fetch the remaining of the presence bitmap from the next octet + if (act_pos2 == 8) { + uc2++; + act_pos2 = 0; + } + } else { + get_at(p_td.oer->p[j])->OER_decode(*fld_descr(p_td.oer->p[j]), p_buf, p_oer); + } + } + i += p_td.oer->eag[eag_pos] - p_td.oer->eag[eag_pos-1] - 1; + eag_pos++; + } else { + get_at(p_td.oer->p[i])->OER_decode(*fld_descr(p_td.oer->p[i]), p_buf, p_oer); + } + } + act_pos++; + // Fetch the remaining of the extension presence bitmap from the next octet + if (act_pos == 8) { + uc++; + act_pos = 0; + } + } + } + if (is_opentype_outermost()) { TTCN_EncDec_ErrorContext ec_1("While decoding opentypes: "); TTCN_Type_list p_typelist; diff --git a/regression_test/OER/OER.ttcn b/regression_test/OER/OER.ttcn index 94be9cbf6abd82f9c5b44834c7a4122402786a50..775f39a57a759f5128a809b932c31c428527b463 100644 --- a/regression_test/OER/OER.ttcn +++ b/regression_test/OER/OER.ttcn @@ -2056,6 +2056,12 @@ with { extension "prototype (convert) encode(OER)" } external function dec_Union(in octetstring stream) return Union + with { extension "prototype (convert) decode(OER)" } + + external function enc_UnionExtended(in UnionExtended pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_UnionExtended(in octetstring stream) return UnionExtended with { extension "prototype (convert) decode(OER)" } testcase tc_union() runs on EmptyCT { @@ -2170,6 +2176,20 @@ setverdict(fail, "tc_union: ", match(u, ures)); } + var UnionExtended u2, ures2; + + u2 := { + f10 := 10 + } + os := enc_UnionExtended(u2); + if (os != 'E102010A'O) { + setverdict(fail, "tc_union: ", match('E102010A'O, os)); + } + ures2 := dec_UnionExtended(os); + if (u2 != ures2) { + setverdict(fail, "tc_union: ", match(u2, ures2)); + } + setverdict(pass); } @@ -2185,6 +2205,36 @@ external function dec_ExtensionRecord(in octetstring stream) return ExtensionRecord with { extension "prototype (convert) decode(OER)" } + external function enc_ExtensionRecord2(in ExtensionRecord2 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord2(in octetstring stream) return ExtensionRecord2 + with { extension "prototype (convert) decode(OER)" } + + external function enc_ExtensionRecord3(in ExtensionRecord3 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord3(in octetstring stream) return ExtensionRecord3 + with { extension "prototype (convert) decode(OER)" } + + external function enc_ExtensionRecord4(in ExtensionRecord4 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord4(in octetstring stream) return ExtensionRecord4 + with { extension "prototype (convert) decode(OER)" } + + external function enc_ExtensionRecord5(in ExtensionRecord5 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord5(in octetstring stream) return ExtensionRecord5 + with { extension "prototype (convert) decode(OER)" } + + external function enc_ExtensionRecord6(in ExtensionRecord6 pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_ExtensionRecord6(in octetstring stream) return ExtensionRecord6 + with { extension "prototype (convert) decode(OER)" } + external function enc_NoOptionalRecord(in NoOptionalRecord pdu) return octetstring with { extension "prototype (convert) encode(OER)" } @@ -2203,6 +2253,7 @@ external function dec_SomeOptionalRecord(in octetstring stream) return SomeOptionalRecord with { extension "prototype (convert) decode(OER)" } + testcase tc_sequence() runs on EmptyCT { var octetstring os; @@ -2217,17 +2268,583 @@ setverdict(fail, "tc_sequence: ", match(emr, emrres)); } - // Test extension bit presence, FAILS, possibly some bug with is_extendable() function - /*var ExtensionRecord er, erres; - er := { me := e2 } + var ExtensionRecord er, erres; + er := { me := 1, me2 := 2 } os := enc_ExtensionRecord(er); - if (os != '0001'O) { - setverdict(fail, "tc_sequence: ", match('0001'O, os)); + if (os != '0001010102'O) { + setverdict(fail, "tc_sequence: ", match('0001010102'O, os)); } erres := dec_ExtensionRecord(os); if (er != erres) { setverdict(fail, "tc_sequence: ", match(er, erres)); - }*/ + } + + var ExtensionRecord2 er2, erres2; + er2 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4 + } + os := enc_ExtensionRecord2(er2); + if (os != '40010101020104'O) { + setverdict(fail, "tc_sequence: ", match('40010101020104'O, os)); + } + erres2 := dec_ExtensionRecord2(os); + if (not(match(log2str(er2), log2str(erres2)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er2), log2str(erres2))); + } + + er2 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9 + } + os := enc_ExtensionRecord2(er2); + if (os != 'C00101010201040305FFC0020100020101020102020103020104020105020106020107020108020109'O) { + setverdict(fail, "tc_sequence: ", match('C00101010201040305FFC0020100020101020102020103020104020105020106020107020108020109'O, os)); + } + erres2 := dec_ExtensionRecord2(os); + if (not(match(log2str(er2), log2str(erres2)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er2), log2str(erres2))); + } + + er2 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := 6, + f7 := omit, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord2(er2); + if (os != 'C00101010201040305DAE002010002010102010302010402010602010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C00101010201040305DAE002010002010102010302010402010602010802010900'O, os)); + } + erres2 := dec_ExtensionRecord2(os); + if (not(match(log2str(er2), log2str(erres2)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er2), log2str(erres2))); + } + + var ExtensionRecord2 er3, erres3, erres4; + er3 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := omit, + f8 := 8, + f_nul := NULL + } + os := enc_ExtensionRecord2(er3); + if (os != 'C00101010201040305D2A002010002010102010302010602010800'O) { + setverdict(fail, "tc_sequence: ", match('C00101010201040305D2A002010002010102010302010602010800'O, os)); + } + erres3 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := omit, + f8 := 8, + f9 := -, + f_nul := NULL + } + erres2 := dec_ExtensionRecord2(os); + if (not(match(log2str(erres3), log2str(erres2)))) { + setverdict(fail, "tc_sequence: ", match(log2str(erres3), log2str(erres2))); + } + + var ExtensionRecord2 er4; + er4 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f6 := 6, + f7 := omit, + f8 := 8 + } + os := enc_ExtensionRecord2(er4); + if (os != 'C00101010201040305D280020100020101020103020106020108'O) { + setverdict(fail, "tc_sequence: ", match('C00101010201040305D280020100020101020103020106020108'O, os)); + } + erres4 := { + me := 1, + me2 := 2, + me3 := omit, + me4 := 4, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := 6, + f7 := omit, + f8 := 8, + f9 := -, + f_nul := - + } + erres2 := dec_ExtensionRecord2(os); + if (not(match(log2str(erres4), log2str(erres2)))) { + setverdict(fail, "tc_sequence: ", match(log2str(erres4), log2str(erres2))); + } + + var ExtensionRecord3 er5, erres5; + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := omit, + f7 := -, + f8 := 8, + f9 := 9, + f_nul := NULL + } + @try { + os := enc_ExtensionRecord3(er5); + setverdict(fail); + } @catch (e) { + setverdict(pass); + } + + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := omit, + f6 := omit, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord3(er5); + if (os != 'C0010102029C078001000101010305000107010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C0010102029C078001000101010305000107010802010900'O, os)); + } + erres5 := dec_ExtensionRecord3(os); + if (not(match(log2str(er5), log2str(erres5)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er5), log2str(erres5))); + } + + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := 5, + f6 := omit, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord3(er5); + if (os != 'C001010202BC078001000101010302010505000107010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C001010202BC078001000101010302010505000107010802010900'O, os)); + } + erres5 := dec_ExtensionRecord3(os); + if (not(match(log2str(er5), log2str(erres5)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er5), log2str(erres5))); + } + + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := omit, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord3(er5); + if (os != 'C001010202BC0780010001010103020105078001060107010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C001010202BC0780010001010103020105078001060107010802010900'O, os)); + } + erres5 := dec_ExtensionRecord3(os); + if (not(match(log2str(er5), log2str(erres5)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er5), log2str(erres5))); + } + + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord3(er5); + if (os != 'C001010202FC078001000101010303800104020105078001060107010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C001010202FC078001000101010303800104020105078001060107010802010900'O, os)); + } + erres5 := dec_ExtensionRecord3(os); + if (not(match(log2str(er5), log2str(erres5)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er5), log2str(erres5))); + } + + er5 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord3(er5); + if (os != 'C001010202FC09C0010001010102010303800104020105078001060107010802010900'O) { + setverdict(fail, "tc_sequence: ", match('C001010202FC09C0010001010102010303800104020105078001060107010802010900'O, os)); + } + erres5 := dec_ExtensionRecord3(os); + if (not(match(log2str(er5), log2str(erres5)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er5), log2str(erres5))); + } + + var ExtensionRecord4 er6, erres6; + er6 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord4(er6); + if (os != 'C001010202FC09F001000101010201030380010402010507C00106010701080201090180'O) { + setverdict(fail, "tc_sequence: ", match('C001010202FC09F001000101010201030380010402010507C00106010701080201090180'O, os)); + } + erres6 := dec_ExtensionRecord4(os); + if (not(match(log2str(er6), log2str(erres6)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er6), log2str(erres6))); + } + + er6 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord4(er6); + if (os != 'C001010202FC09F0010001010102010303800104020105030001080201090180'O) { + setverdict(fail, "tc_sequence: ", match('C001010202FC09F0010001010102010303800104020105030001080201090180'O, os)); + } + erres6 := dec_ExtensionRecord4(os); + if (not(match(log2str(er6), log2str(erres6)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er6), log2str(erres6))); + } + + er6 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord4(er6); + if (os != 'C001010202FC07D001000101010303800104020105030001080201090180'O) { + setverdict(fail, "tc_sequence: ", match('C001010202FC07D001000101010303800104020105030001080201090180'O, os)); + } + erres6 := dec_ExtensionRecord4(os); + if (not(match(log2str(er6), log2str(erres6)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er6), log2str(erres6))); + } + + er6 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := 9, + f_nul := omit + } + os := enc_ExtensionRecord4(er6); + if (os != 'C001010202F807D00100010101030380010402010503000108020109'O) { + setverdict(fail, "tc_sequence: ", match('C001010202F807D00100010101030380010402010503000108020109'O, os)); + } + erres6 := dec_ExtensionRecord4(os); + if (not(match(log2str(er6), log2str(erres6)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er6), log2str(erres6))); + } + + + var ExtensionRecord5 er7, erres7, erres71; + + er7 := { + me := 1, + f2 := omit + } + os := enc_ExtensionRecord5(er7); + if (os != '400101'O) { + setverdict(fail, "tc_sequence: ", match('400101'O, os)); + } + erres71 := { me := 1 } + erres7 := dec_ExtensionRecord5(os); + if (not(match(log2str(erres7), log2str(erres71)))) { + setverdict(fail, "tc_sequence: ", match(log2str(erres7), log2str(erres71))); + } + + er7 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord5(er7); + if (os != 'C001010206C016FFC001000101010201030104010501060107010801090180'O) { + setverdict(fail, "tc_sequence: ", match('C001010206C016FFC001000101010201030104010501060107010801090180'O, os)); + } + erres7 := dec_ExtensionRecord5(os); + if (not(match(log2str(er7), log2str(erres7)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er7), log2str(erres7))); + } + + er7 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := omit, + f_nul := NULL + } + os := enc_ExtensionRecord5(er7); + if (os != 'C001010206C00CD880010001010103010401080180'O) { + setverdict(fail, "tc_sequence: ", match('C001010206C00CD880010001010103010401080180'O, os)); + } + erres7 := dec_ExtensionRecord5(os); + if (not(match(log2str(er7), log2str(erres7)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er7), log2str(erres7))); + } + + var ExtensionRecord6 er8, erres8; + er8 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8, + f9 := 9, + f_nul := NULL + } + os := enc_ExtensionRecord6(er8); + if (os != 'C001010302FFE0038001000380010103800102038001030380010403800105038001060380010703800108038001090180'O) { + setverdict(fail, "tc_sequence: ", match('C001010302FFE0038001000380010103800102038001030380010403800105038001060380010703800108038001090180'O, os)); + } + erres8 := dec_ExtensionRecord6(os); + if (not(match(log2str(er8), log2str(erres8)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8))); + } + + er8 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := omit, + f_nul := NULL + } + os := enc_ExtensionRecord6(er8); + if (os != 'C001010302D8A003800100038001010380010303800104038001080180'O) { + setverdict(fail, "tc_sequence: ", match('C001010302D8A003800100038001010380010303800104038001080180'O, os)); + } + erres8 := dec_ExtensionRecord6(os); + if (not(match(log2str(er8), log2str(erres8)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8))); + } + + er8 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := omit, + f_nul := NULL, + f10 := 10 + } + os := enc_ExtensionRecord6(er8); + if (os != 'C001010302D8B00380010003800101038001030380010403800108018002010A'O) { + setverdict(fail, "tc_sequence: ", match('C001010302D8B00380010003800101038001030380010403800108018002010A'O, os)); + } + erres8 := dec_ExtensionRecord6(os); + if (not(match(log2str(er8), log2str(erres8)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8))); + } + + er8 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := omit, + f_nul := NULL, + f10 := 10, + f11 := 11, + f12 := 12 + } + os := enc_ExtensionRecord6(er8); + if (os != 'C001010302D8B80380010003800101038001030380010403800108018002010A04010B010C'O) { + setverdict(fail, "tc_sequence: ", match('C001010302D8B80380010003800101038001030380010403800108018002010A04010B010C'O, os)); + } + erres8 := dec_ExtensionRecord6(os); + if (not(match(log2str(er8), log2str(erres8)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8))); + } + + er8 := { + me := 1, + f0 := 0, + f1 := 1, + f2 := omit, + f3 := 3, + f4 := 4, + f5 := omit, + f6 := omit, + f7 := omit, + f8 := 8, + f9 := omit, + f_nul := NULL, + f10 := 10, + f11 := 11, + f12 := 12, + f13 := 13 + } + os := enc_ExtensionRecord6(er8); + if (os != 'C001010302D8BC0380010003800101038001030380010403800108018002010A04010B010C02010D'O) { + setverdict(fail, "tc_sequence: ", match('C001010302D8BC0380010003800101038001030380010403800108018002010A04010B010C02010D'O, os)); + } + erres8 := dec_ExtensionRecord6(os); + if (not(match(log2str(er8), log2str(erres8)))) { + setverdict(fail, "tc_sequence: ", match(log2str(er8), log2str(erres8))); + } var NoOptionalRecord nr, nrres; @@ -2547,6 +3164,12 @@ with { extension "prototype (convert) encode(OER)" } external function dec_MySet(in octetstring stream) return MySet + with { extension "prototype (convert) decode(OER)" } + + external function enc_MySetExtended(in MySetExtended pdu) return octetstring + with { extension "prototype (convert) encode(OER)" } + + external function dec_MySetExtended(in octetstring stream) return MySetExtended with { extension "prototype (convert) decode(OER)" } testcase tc_set() runs on EmptyCT { @@ -2571,6 +3194,65 @@ setverdict(fail, "tc_set: ", match(ms, msres)); } + var MySetExtended ms2, msres2; + + ms2 := { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6 + } + os := enc_MySetExtended(ms2); + if (os != '400102010401030106010508033331342E452D320101'O) { + setverdict(fail, "tc_set: ", match('400102010401030106010508033331342E452D320101'O, os)); + } + msres2 := dec_MySetExtended(os); + if (log2str(ms2) != log2str(msres2)) { + setverdict(fail, "tc_set: ", match(log2str(ms2), log2str(msres2))); + } + + ms2 := { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7 + } + os := enc_MySetExtended(ms2); + if (os != 'C00102010401030106010508033331342E452D320101020680020107'O) { + setverdict(fail, "tc_set: ", match('C00102010401030106010508033331342E452D320101020680020107'O, os)); + } + msres2 := dec_MySetExtended(os); + if (log2str(ms2) != log2str(msres2)) { + setverdict(fail, "tc_set: ", match(log2str(ms2), log2str(msres2))); + } + + ms2 := { + r1 := 3.14, + f1 := 1, + f2 := 2, + f3 := 3, + f4 := 4, + f5 := 5, + f6 := 6, + f7 := 7, + f8 := 8 + } + os := enc_MySetExtended(ms2); + if (os != 'C00102010401030106010508033331342E452D3201010206C0020107020108'O) { + setverdict(fail, "tc_set: ", match('C00102010401030106010508033331342E452D3201010206C0020107020108'O, os)); + } + msres2 := dec_MySetExtended(os); + if (log2str(ms2) != log2str(msres2)) { + setverdict(fail, "tc_set: ", match(log2str(ms2), log2str(msres2))); + } + setverdict(pass); } diff --git a/regression_test/OER/Types.asn b/regression_test/OER/Types.asn index 413f2c438373fd790acbbd7c2b556f3e921eecc8..8d3d4072389b2b4d1868e26d26003732e19be4c6 100644 --- a/regression_test/OER/Types.asn +++ b/regression_test/OER/Types.asn @@ -242,9 +242,96 @@ OptionalRecord ::= SEQUENCE { } ExtensionRecord ::= SEQUENCE { - me MyEnum, + me INTEGER, + me2 INTEGER, + ... +} + +ExtensionRecord2 ::= SEQUENCE { + me INTEGER DEFAULT 5, + me2 INTEGER, + me3 INTEGER OPTIONAL, + me4 INTEGER, + ..., + f0 INTEGER DEFAULT 5, + f1 INTEGER, + f2 INTEGER OPTIONAL, + f3 INTEGER, + f4 INTEGER OPTIONAL, + f5 INTEGER OPTIONAL, + f6 INTEGER, + f7 INTEGER OPTIONAL, + f8 INTEGER, + f9 INTEGER DEFAULT 2, + f-nul NULL +} + +ExtensionRecord3 ::= SEQUENCE { + me INTEGER DEFAULT 5, + ..., + [[f0 INTEGER DEFAULT 5, + f1 INTEGER, + f2 INTEGER OPTIONAL, + f3 INTEGER]], + [[f4 INTEGER OPTIONAL]], + f5 INTEGER OPTIONAL, + [[f6 INTEGER OPTIONAL, + f7 INTEGER, + f8 INTEGER]], + f9 INTEGER DEFAULT 2, + [[f-nul NULL]] +} + +ExtensionRecord4 ::= SEQUENCE { + me INTEGER DEFAULT 5, + ..., + [[f0 INTEGER DEFAULT 5, + f1 INTEGER DEFAULT 5, + f2 INTEGER OPTIONAL, + f3 INTEGER DEFAULT 5]], + [[f4 INTEGER OPTIONAL]], + f5 INTEGER OPTIONAL, + [[f6 INTEGER OPTIONAL, + f7 INTEGER OPTIONAL, + f8 INTEGER]], + f9 INTEGER OPTIONAL, + [[f-nul NULL OPTIONAL]] +} + +ExtensionRecord5 ::= SEQUENCE { + me INTEGER DEFAULT 5, ..., - f INTEGER + [[f0 INTEGER DEFAULT 5, + f1 INTEGER DEFAULT 5, + f2 INTEGER OPTIONAL, + f3 INTEGER DEFAULT 5, + f4 INTEGER OPTIONAL, + f5 INTEGER OPTIONAL, + f6 INTEGER OPTIONAL, + f7 INTEGER OPTIONAL, + f8 INTEGER DEFAULT 4, + f9 INTEGER OPTIONAL]], + [[f-nul NULL OPTIONAL]] +} + +ExtensionRecord6 ::= SEQUENCE { + me INTEGER DEFAULT 5, + ..., + [[f0 INTEGER DEFAULT 5]], + [[f1 INTEGER DEFAULT 5]], + [[f2 INTEGER OPTIONAL]], + [[f3 INTEGER DEFAULT 5]], + [[f4 INTEGER OPTIONAL]], + [[f5 INTEGER OPTIONAL]], + [[f6 INTEGER OPTIONAL]], + [[f7 INTEGER OPTIONAL]], + [[f8 INTEGER DEFAULT 4]], + [[f9 INTEGER OPTIONAL]], + [[f-nul NULL OPTIONAL]], + f10 INTEGER, + [[f11 INTEGER, + f12 INTEGER]], + f13 INTEGER } EmptyRecord ::= SEQUENCE { @@ -278,6 +365,20 @@ Union ::= CHOICE { f9 [PRIVATE 3] Unsigned1byteInt } +UnionExtended ::= CHOICE { + f1 [APPLICATION 64] INTEGER, + f2 [APPLICATION 63] INTEGER, + f3 [APPLICATION 62] INTEGER, + f4 [APPLICATION 16383] INTEGER, + f5 INTEGER, + f6 [PRIVATE 325] INTEGER, + f7 [PRIVATE 7596] INTEGER, + f8 [PRIVATE 18] INTEGER, + f9 [PRIVATE 3] Unsigned1byteInt, + ..., + f10 [PRIVATE 33] INTEGER +} + MySet ::= SET { r1 [PRIVATE 2] [PRIVATE 7] REAL, f1 [PRIVATE 4] INTEGER, @@ -288,6 +389,19 @@ MySet ::= SET { f6 [1] INTEGER } +MySetExtended ::= SET { + r1 [PRIVATE 2] [PRIVATE 7] REAL, + f1 [PRIVATE 4] INTEGER, + f2 INTEGER OPTIONAL, + f3 [APPLICATION 234] INTEGER, + f4 [APPLICATION 2] INTEGER, + f5 [3] INTEGER, + f6 [1] INTEGER, + ..., + f7 [5] INTEGER, + [[f8 [9] INTEGER]] +} + MyRecordOf ::= SEQUENCE OF SomeOptionalRecord MySetOf ::= SET OF MySet diff --git a/regression_test/negativeTest/Makefile b/regression_test/negativeTest/Makefile index 45185d0be095e51aa5cad95782fc2f580a5aa6e4..1553eabeca19ec933968347ada748e310c3f1c7a 100644 --- a/regression_test/negativeTest/Makefile +++ b/regression_test/negativeTest/Makefile @@ -44,7 +44,7 @@ NegTest_RAW_Types.ttcn NegTest_RAW_Testcases.ttcn \ www_XmlTest_org_negativeTest_XML_Types.ttcn NegTest_XML_Testcases.ttcn XSD.ttcn UsefulTtcn3Types.ttcn \ NegTest_JSON.ttcn NegTest_Update.ttcn NegTest_OER.ttcn -ASN1_MODULES = Types.asn NegTestTypes.asn +ASN1_MODULES = Types.asn NegTestTypes.asn NegTestTypes2.asn GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) $(ASN1_MODULES:.asn=.cc) GENERATED_HEADERS = $(TTCN3_MODULES:.ttcn=.hh) $(ASN1_MODULES:.asn=.hh) diff --git a/regression_test/negativeTest/NegTestTypes.asn b/regression_test/negativeTest/NegTestTypes.asn index fcffefca048f1ee4ef2e966b62fdbb2e803c6d35..8683979a12bfcc728bd7cc7800849ac9df37086c 100644 --- a/regression_test/negativeTest/NegTestTypes.asn +++ b/regression_test/negativeTest/NegTestTypes.asn @@ -341,4 +341,11 @@ MyUnionComplexTypes ::= CHOICE { sofreal MySeqOfReal } +MyUnionExtended ::= CHOICE { + b BOOLEAN, + n NULL, + ..., + i INTEGER +} + END diff --git a/regression_test/negativeTest/NegTestTypes2.asn b/regression_test/negativeTest/NegTestTypes2.asn new file mode 100644 index 0000000000000000000000000000000000000000..43be27826237b8ce01ad73fd014af12b76be785a --- /dev/null +++ b/regression_test/negativeTest/NegTestTypes2.asn @@ -0,0 +1,27 @@ +--///////////////////////////////////////////////////////////////////////////// +-- Copyright (c) 2000-2017 Ericsson Telecom AB +-- All rights reserved. This program and the accompanying materials +-- are made available under the terms of the Eclipse Public License v1.0 +-- which accompanies this distribution, and is available at +-- http://www.eclipse.org/legal/epl-v10.html +-- +-- Contributors: +-- Szabo, Bence Janos +-- +--///////////////////////////////////////////////////////////////////////////// +NegTestTypes2 +DEFINITIONS +AUTOMATIC TAGS +::= BEGIN +IMPORTS ; + + +ExtensionRecord ::= SEQUENCE { + me INTEGER DEFAULT 5, + ..., + f0 INTEGER DEFAULT 5, + f1 INTEGER DEFAULT 5, + f2 INTEGER OPTIONAL +} + +END diff --git a/regression_test/negativeTest/NegTest_OER.ttcn b/regression_test/negativeTest/NegTest_OER.ttcn index 605ea3b1ddd4ae72606e29fe31d490abc926a79e..e2284621c18a2ffa7e2a8cb2ad97af2facf84847 100644 --- a/regression_test/negativeTest/NegTest_OER.ttcn +++ b/regression_test/negativeTest/NegTest_OER.ttcn @@ -14,6 +14,7 @@ module NegTest_OER { import from NegTestTypes all; +import from NegTestTypes2 all; type component CT {} @@ -39,6 +40,12 @@ external function f_enc_MySeqOfInt(in MySeqOfInt x) return octetstring external function f_enc_MyUnionBasicTypes(in MyUnionBasicTypes x) return octetstring with { extension "prototype(convert) encode(OER)" } +external function f_enc_MyUnionExtended(in MyUnionExtended x) return octetstring + with { extension "prototype(convert) encode(OER)" } + +external function f_enc_ExtensionRecord(in ExtensionRecord x) return octetstring + with { extension "prototype(convert) encode(OER)" } + /************* Erroneous values *************/ const MySeqBool msb1 := { b := false } with { erroneous(b) "value := true" }; const MySeqBool msb2 := { b := false } with { erroneous(b) "value := integer:1" }; @@ -78,6 +85,64 @@ const MyUnionBasicTypes mubt2 := { i := 1 } with {erroneous(i) "value := MyChars const MyUnionBasicTypes mubt3 := { i := 1 } with {erroneous(i) "value := omit"}; const MyUnionBasicTypes mubt4 := { i := 1 } with {erroneous(i) "value(raw) := 'ABCD'O"}; +const MyUnionExtended mue1 := { i := 1 } with {erroneous(i) "value := 2"}; +const MyUnionExtended mue2 := { i := 1 } with {erroneous(i) "value(raw) := 'ABCD'O"}; + +const ExtensionRecord er1 := { + me := 1, + f0 := 1 +} with {erroneous(f0) "value := 3"} + +const ExtensionRecord er2 := { + me := 1, + f0 := 1 +} with {erroneous(f0) "value := 3" + erroneous(f0) "after(raw) := 'AABB'O"} + +const ExtensionRecord er3 := { + me := 1, + f0 := 1 +} with {erroneous(f0) "value := 3" + erroneous(f0) "before(raw) := 'AABB'O"} + +const ExtensionRecord er4 := { + me := 1, + f0 := 1, + f1 := 2, + f2 := omit +} with {erroneous(f0) "value := 3" + erroneous(f2) "value := 2"} + +const ExtensionRecord er5 := { + me := 1, + f0 := 1, + f1 := 2, + f2 := omit +} with {erroneous(f0) "value := 3" + erroneous(f2) "value(raw) := 'ABCD'O"} + +const ExtensionRecord er6 := { + me := 1, + f0 := 1, + f1 := 2, + f2 := omit +} with {erroneous(f0) "value := 3" + erroneous(f1) "value := omit"} + +const ExtensionRecord er7 := { + me := 1, + f0 := 1, + f1 := 2, + f2 := omit +} with {erroneous(f1) "before := omit all"} + +const ExtensionRecord er8 := { + me := 1, + f0 := 1, + f1 := 2, + f2 := 3 +} with {erroneous(f0) "after := omit all"} + /******** Test cases for records ********/ testcase tc_record_change_value() runs on CT { var octetstring res := f_enc_msb(msb1); @@ -241,9 +306,63 @@ testcase tc_union_change_value() runs on CT { log(res); if ('ABCD'O == res) { setverdict(pass); } else { setverdict(fail, res); } + + res := f_enc_MyUnionExtended(mue1); + log(res); + if ('02020102'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_MyUnionExtended(mue2); + log(res); + if ('ABCD'O == res) { setverdict(pass); } + else { setverdict(fail, res); } +} + +testcase tc_extension_record() runs on CT { + var octetstring res := f_enc_ExtensionRecord(er1); + log(res); + if ('C00101020580020103'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er2); + log(res); + if ('C00101020580040103AABB'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er3); + log(res); + if ('C0010102058004AABB0103'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er4); + log(res); + if ('C001010205E0020103020102020102'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er5); + log(res); + if ('C001010205E0020103020102ABCD00'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er6); + log(res); + if ('C00101020580020103'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er7); + log(res); + if ('C00205C0020102'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + + res := f_enc_ExtensionRecord(er8); + log(res); + if ('C001010205E0020101'O == res) { setverdict(pass); } + else { setverdict(fail, res); } + } + /*************** Control part ***************/ control { execute(tc_record_change_value()); @@ -259,6 +378,8 @@ control { execute(tc_record_of_insert()); execute(tc_union_change_value()); + + execute(tc_extension_record()); } } diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index fd3d6b5c78b124931fed40039e2e6f83aa9fc173..7bdead365fc986f8c08b970edde399b4c18a4339 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ