diff --git a/compiler2/Identifier.cc b/compiler2/Identifier.cc index 3b08ca1d71d8ec278bca01d9634ef1807aa6f45b..c4e19a4fb1e809a1271388c9c4dfe1c4be62de38 100644 --- a/compiler2/Identifier.cc +++ b/compiler2/Identifier.cc @@ -598,6 +598,7 @@ namespace Common { {"char2int__", "char2int", "char2int_"}, {"char2oct__", "char2oct", "char2oct_"}, {"component__", "component", "component_"}, + {"decmatch__", "decmatch", "decmatch_"}, {"decomp__", "decomp", "decomp_"}, {"float2int__", "float2int", "float2int_"}, {"float2str__", "float2str", "float2str_"}, diff --git a/compiler2/Type.hh b/compiler2/Type.hh index 96ea75acc58051a2be3860d5c9b53880ef9fe5ea..4ea6af34d71f2d0b5cc0402b41e3ad6feb855c1e 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -815,7 +815,8 @@ namespace Common { void chk_this_template_length_restriction(Template *t); bool chk_this_template(Template *t, namedbool is_modified, namedbool sub_chk, namedbool implicit_omit, Common::Assignment *); - void chk_this_template_Str(Template *t); + bool chk_this_template_Str(Template *t, namedbool implicit_omit, + Common::Assignment *lhs); /** Checks whether \a v is a correct range boundary for this type. * Applicable to the following types: integer, float, charstring, * universal charstring. diff --git a/compiler2/Type_chk.cc b/compiler2/Type_chk.cc index 54ef103b6b00e7809888e5c45c4d81f1c94487fb..2049c9bc74aea5414e9589e007ae34316901d03e 100644 --- a/compiler2/Type_chk.cc +++ b/compiler2/Type_chk.cc @@ -5624,7 +5624,7 @@ bool Type::chk_this_template(Template *t, namedbool is_modified, namedbool, case T_UTCTIME: case T_GENERALIZEDTIME: case T_OBJECTDESCRIPTOR: - t_last->chk_this_template_Str(t); + self_ref = t_last->chk_this_template_Str(t, implicit_omit, lhs); break; case T_INT: case T_INT_A: @@ -5676,8 +5676,10 @@ bool Type::chk_this_template(Template *t, namedbool is_modified, namedbool, return self_ref; } -void Type::chk_this_template_Str(Template *t) +bool Type::chk_this_template_Str(Template *t, namedbool implicit_omit, + Common::Assignment *lhs) { + bool self_ref = false; typetype_t tt = get_typetype_ttcn3(typetype); bool report_error = false; switch (t->get_templatetype()) { @@ -5737,6 +5739,48 @@ void Type::chk_this_template_Str(Template *t) if (!pstr->has_refs()) pstr->chk_pattern(); } else report_error = true; break; + case Ttcn::Template::DECODE_MATCH: + { + Error_Context cntxt(t, "In decoding target"); + TemplateInstance* target = t->get_decode_target(); + target->get_Template()->set_lowerid_to_ref(); + Type* target_type = target->get_expr_governor(EXPECTED_TEMPLATE); + if (target_type == NULL) { + target->error("Type of template instance cannot be determined"); + break; + } + if (target->get_Type() != NULL) { + target_type = target_type->get_type_refd(); + } + self_ref = target_type->chk_this_template_generic( + target->get_Template(), (target->get_DerivedRef() != NULL) ? + INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED, + OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, implicit_omit, lhs); + target_type->get_type_refd_last()->chk_coding(false); + } + { + Value* str_enc = t->get_string_encoding(); + if (str_enc != NULL) { + if (tt != T_USTR) { + str_enc->error("The encoding format parameter is only available to " + "universal charstring templates"); + break; + } + Error_Context cntxt(t, "In encoding format"); + str_enc->set_lowerid_to_ref(); + get_pooltype(T_CSTR)->chk_this_value(str_enc, lhs, EXPECTED_DYNAMIC_VALUE, + INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, NO_SUB_CHK); + if (!str_enc->is_unfoldable()) { + string enc_name = str_enc->get_val_str(); + if (enc_name != "UTF-8" && enc_name != "UTF-16" && enc_name != "UTF-32" + && enc_name != "UTF-16LE" && enc_name != "UTF-16BE" + && enc_name != "UTF-32LE" && enc_name != "UTF-32BE") { + str_enc->error("'%s' is not a valid encoding format", enc_name.c_str()); + } + } + } + } + break; default: report_error = true; break; @@ -5745,6 +5789,7 @@ void Type::chk_this_template_Str(Template *t) t->error("%s cannot be used for type `%s'", t->get_templatetype_str(), get_typename().c_str()); } + return self_ref; } void Type::chk_range_boundary_infinity(Value *v, bool is_upper) diff --git a/compiler2/Value.cc b/compiler2/Value.cc index e6cf738b27d5264e879c4869842a69aa9c9f5f7b..9789faa6c7a8c9628baf47a0d15d731bd97b8128 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -10085,6 +10085,9 @@ error: break; // self-ref can't happen case Ttcn::Template::TEMPLATE_INVOKE: break; // assume self-ref can't happen + case Ttcn::Template::DECODE_MATCH: + self_ref |= chk_expr_self_ref_templ(t->get_decode_target()->get_Template(), lhs); + break; case Ttcn::Template::TEMPLATE_ERROR: //FATAL_ERROR("Value::chk_expr_self_ref_templ()"); break; diff --git a/compiler2/subtype.cc b/compiler2/subtype.cc index 814f8e769cf534596a2c34ba74fc08f153f8d9af..0099ec9ae1f6f0920ba810dde37fb8d8a0036ba9 100644 --- a/compiler2/subtype.cc +++ b/compiler2/subtype.cc @@ -1951,6 +1951,7 @@ void SubType::chk_this_template(Template *templ) break; case Template::ALL_FROM: case Template::VALUE_LIST_ALL_FROM: + case Template::DECODE_MATCH: break; case Template::SUPERSET_MATCH: case Template::SUBSET_MATCH: diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 44ecabe0635ff9df5293a07dfc0fa9fb32db4a23..b2168d441ce80ff32814bbd18c70e76010102213 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -8116,6 +8116,9 @@ namespace Ttcn { } // next break; } + case Template::DECODE_MATCH: + chk_defpar_template(body->get_decode_target()->get_Template(), exp_val); + break; } // switch templatetype } diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index caeec80b215fc782d03d627dbb8578766f55e81c..d0a29a51dac3ec744f45dc148380b38a9d7331b6 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -92,6 +92,11 @@ namespace Ttcn { case USTR_PATTERN: u.pstring = p.u.pstring->clone(); break; + case DECODE_MATCH: + u.dec_match.str_enc = p.u.dec_match.str_enc != NULL ? + p.u.dec_match.str_enc->clone() : NULL; + u.dec_match.target = p.u.dec_match.target->clone(); + break; // default: // FATAL_ERROR("Template::Template()"); } @@ -149,6 +154,12 @@ namespace Ttcn { case USTR_PATTERN: delete u.pstring; break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + delete u.dec_match.str_enc; + } + delete u.dec_match.target; + break; // default: // FATAL_ERROR("Template::clean_up()"); } @@ -272,6 +283,18 @@ namespace Ttcn { ret_val += u.pstring->get_full_str(); ret_val += "\""; break; + case DECODE_MATCH: + ret_val += "decmatch "; + if (u.dec_match.str_enc != NULL) { + ret_val += "("; + ret_val += u.dec_match.str_enc->get_val_str(); + ret_val += ") "; + } + ret_val += u.dec_match.target->get_expr_governor( + Type::EXPECTED_TEMPLATE)->get_stringRepr(); + ret_val += ": "; + ret_val += u.dec_match.target->get_Template()->create_stringRepr(); + break; default: ret_val += "<unknown template>"; break; @@ -441,6 +464,19 @@ namespace Ttcn { if (!p_ps) FATAL_ERROR("Template::Template()"); u.pstring = p_ps; } + + Template::Template(Value* v, TemplateInstance* ti) + : GovernedSimple(S_TEMPLATE), + templatetype(DECODE_MATCH), my_governor(0), length_restriction(0), + is_ifpresent(false), specific_value_checked(false), + has_permutation(false), flattened(true), base_template(0) + { + if (ti == NULL) { + FATAL_ERROR("Template::Template()"); + } + u.dec_match.str_enc = v; + u.dec_match.target = ti; + } Template::~Template() { @@ -513,6 +549,12 @@ namespace Ttcn { case USTR_PATTERN: u.pstring->set_fullname(p_fullname); break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + u.dec_match.str_enc->set_fullname(p_fullname + ".<string_encoding>"); + } + u.dec_match.target->set_fullname(p_fullname + ".<decoding_target>"); + break; // default: // FATAL_ERROR("Template::set_fullname()"); } @@ -569,6 +611,12 @@ namespace Ttcn { case USTR_PATTERN: u.pstring->set_my_scope(p_scope); break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + u.dec_match.str_enc->set_my_scope(p_scope); + } + u.dec_match.target->set_my_scope(p_scope); + break; // default: // FATAL_ERROR("Template::set_my_scope()"); } @@ -681,6 +729,12 @@ namespace Ttcn { case USTR_PATTERN: u.pstring->set_code_section(p_code_section); break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + u.dec_match.str_enc->set_code_section(p_code_section); + } + u.dec_match.target->set_code_section(p_code_section); + break; default: break; } @@ -849,6 +903,8 @@ namespace Ttcn { return "character string pattern"; case USTR_PATTERN: return "universal string pattern"; + case DECODE_MATCH: + return "decoded content match"; default: return "unknown template"; } @@ -1297,6 +1353,22 @@ namespace Ttcn { } return t; } + + Value* Template::get_string_encoding() const + { + if (templatetype != DECODE_MATCH) { + FATAL_ERROR("Template::get_decode_target()"); + } + return u.dec_match.str_enc; + } + + TemplateInstance* Template::get_decode_target() const + { + if (templatetype != DECODE_MATCH) { + FATAL_ERROR("Template::get_decode_target()"); + } + return u.dec_match.target; + } Template* Template::get_template_refd(ReferenceChain *refch) { @@ -1867,6 +1939,9 @@ namespace Ttcn { case USTR_PATTERN: t->u.pstring->chk_recursions(refch); break; + case DECODE_MATCH: + t->u.dec_match.target->chk_recursions(refch); + break; default: break; } @@ -2551,7 +2626,7 @@ end: case VALUE_RANGE: case ALL_FROM: case BSTR_PATTERN: case HSTR_PATTERN: case OSTR_PATTERN: - case CSTR_PATTERN: case USTR_PATTERN: + case CSTR_PATTERN: case USTR_PATTERN: case DECODE_MATCH: break; // NOP } @@ -3053,6 +3128,9 @@ end: warning("Don't know how to init PERMUT"); str = mputprintf(str, "/* FIXME: PERMUT goes here, name=%s*/\n", name); break; + case DECODE_MATCH: + str = generate_code_init_dec_match(str, name); + break; case TEMPLATE_NOTUSED: break; case TEMPLATE_ERROR: @@ -3329,6 +3407,7 @@ end: switch (templatetype) { case ALL_FROM: case VALUE_LIST_ALL_FROM: + case DECODE_MATCH: return false; case TEMPLATE_ERROR: /**< erroneous template */ case TEMPLATE_NOTUSED: /**< not used symbol (-) */ @@ -4432,6 +4511,108 @@ compile_time: } return str; } + + char* Template::generate_code_init_dec_match(char* str, const char* name) + { + // generate a new class for this decmatch template + string class_tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id(); + Type* target_type = u.dec_match.target->get_expr_governor( + Type::EXPECTED_TEMPLATE)->get_type_refd_last(); + // use the name of the type at the end of the reference chain for logging + const char* type_name_ptr = target_type->get_typename_builtin( + target_type->get_typetype_ttcn3()); + if (type_name_ptr == NULL) { + type_name_ptr = target_type->get_type_refd_last()->get_dispname().c_str(); + } + // copy the character pointer returned by Type::get_dispname() as it might + // change before its use + char* type_name = mcopystr(type_name_ptr); + str = mputprintf(str, + "class Dec_Match_%s : public Dec_Match_Interface {\n" + // store the decoding target as a member, since both functions use it + "%s target;\n" + "public:\n" + "Dec_Match_%s(%s p_target): target(p_target) { }\n" + // called when matching, the buffer parameter contains the string to be matched + "virtual boolean match(TTCN_Buffer& buff) const\n" + "{\n" + "%s val;\n" + // decode the value + "val.decode(%s_descr_, buff, TTCN_EncDec::CT_%s);\n" + // make sure the buffer is empty after decoding and no errors occurred + "if (TTCN_EncDec::get_last_error_type() != TTCN_EncDec::ET_NONE || " + "buff.get_read_len() != 0) return FALSE;\n" + // finally, match the decoded value against the target template + "return target.match(val%s);\n" + "}\n" + "virtual void log() const\n" + "{\n" + // the decoding target is always logged as an in-line template + "TTCN_Logger::log_event_str(\"%s: \");\n" + "target.log();\n" + "}\n" + "};\n" + "%s.set_type(DECODE_MATCH);\n" + "{\n", class_tmp_id.c_str(), + target_type->get_genname_template(my_scope).c_str(), class_tmp_id.c_str(), + target_type->get_genname_template(my_scope).c_str(), + target_type->get_genname_value(my_scope).c_str(), + target_type->get_genname_typedescriptor(my_scope).c_str(), + target_type->get_coding(false).c_str(), + omit_in_value_list ? ", TRUE" : "", type_name, name); + Free(type_name); + + // generate the decoding target into a temporary + string target_tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id(); + if (u.dec_match.target->get_DerivedRef() != NULL) { + // it's a derived reference: initialize the decoding target with the + // base template first + expression_struct ref_expr; + Code::init_expr(&ref_expr); + u.dec_match.target->get_DerivedRef()->generate_code(&ref_expr); + if (ref_expr.preamble != NULL) { + str = mputstr(str, ref_expr.preamble); + } + str = mputprintf(str, "%s %s(%s);\n", + target_type->get_genname_template(my_scope).c_str(), + target_tmp_id.c_str(), ref_expr.expr); + if (ref_expr.postamble != NULL) { + str = mputstr(str, ref_expr.postamble); + } + Code::free_expr(&ref_expr); + } + else { + str = mputprintf(str, "%s %s;\n", + target_type->get_genname_template(my_scope).c_str(), + target_tmp_id.c_str()); + } + str = u.dec_match.target->get_Template()->generate_code_init(str, + target_tmp_id.c_str()); + + // the string encoding format might be an expression, generate its preamble here + expression_struct coding_expr; + Code::init_expr(&coding_expr); + if (u.dec_match.str_enc != NULL) { + u.dec_match.str_enc->generate_code_expr(&coding_expr); + if (coding_expr.preamble != NULL) { + str = mputstr(str, coding_expr.preamble); + } + } + // initialize the decmatch template with an instance of the new class + // (pass the temporary template to the new instance's constructor) and + // the encoding format if it's an universal charstring + str = mputprintf(str, + "%s.set_decmatch(new Dec_Match_%s(%s)%s%s);\n", + name, class_tmp_id.c_str(), target_tmp_id.c_str(), + (coding_expr.expr != NULL) ? ", " : "", + (coding_expr.expr != NULL) ? coding_expr.expr : ""); + if (coding_expr.postamble != NULL) { + str = mputstr(str, coding_expr.postamble); + } + Code::free_expr(&coding_expr); + str = mputstr(str, "}\n"); + return str; + } void Template::generate_code_expr_invoke(expression_struct *expr) { @@ -4564,6 +4745,7 @@ compile_time: case VALUE_RANGE: case SUPERSET_MATCH: case SUBSET_MATCH: + case DECODE_MATCH: return true; case TEMPLATE_ERROR: FATAL_ERROR("Template::needs_temp_ref()"); @@ -4621,6 +4803,7 @@ compile_time: case SUPERSET_MATCH: case SUBSET_MATCH: case PERMUTATION_MATCH: + case DECODE_MATCH: return false; case ALL_FROM: case VALUE_LIST_ALL_FROM: @@ -4758,6 +4941,14 @@ compile_time: case VALUE_LIST_ALL_FROM: u.all_from->dump(level+1); break; + case DECODE_MATCH: + if (u.dec_match.str_enc != NULL) { + DEBUG(level, "string encoding:"); + u.dec_match.str_enc->dump(level + 1); + } + DEBUG(level, "decoding target:"); + u.dec_match.target->dump(level + 1); + break; default: break; } diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh index a2bc69bc7dfd9765e6b405835b4076eb84fd8b14..69b24efde9436b9106b69e7318c654c65ab0c22a 100644 --- a/compiler2/ttcn3/TtcnTemplate.hh +++ b/compiler2/ttcn3/TtcnTemplate.hh @@ -68,7 +68,8 @@ namespace Ttcn { HSTR_PATTERN, /**< hexstring pattern */ OSTR_PATTERN, /**< octetstring pattern */ CSTR_PATTERN, /**< character string pattern */ - USTR_PATTERN /**< universal charstring pattern */ + USTR_PATTERN, /**< universal charstring pattern */ + DECODE_MATCH /**< decoded content match */ }; /** Status codes for the verification of template body completeness. */ @@ -122,6 +123,11 @@ namespace Ttcn { Ttcn::ParsedActualParameters *t_list; Ttcn::ActualParList *ap_list; } invoke; + /** Used by DECODE_MATCH */ + struct { + Value* str_enc; + TemplateInstance* target; + } dec_match; } u; /** This points to the type of the template */ @@ -203,6 +209,9 @@ namespace Ttcn { /** Constructor for CSTR_PATTERN. */ Template(PatternString *p_ps); + + /** Constructor for DECODE_MATCH */ + Template(Value* v, TemplateInstance* ti); virtual ~Template(); @@ -289,6 +298,8 @@ namespace Ttcn { Template* get_refd_sub_template(Ttcn::FieldOrArrayRefs *subrefs, bool usedInIsbound, ReferenceChain *refch); + Value* get_string_encoding() const; + TemplateInstance* get_decode_target() const; private: Template* get_template_refd(ReferenceChain *refch); Template* get_refd_field_template(const Identifier& field_id, @@ -462,6 +473,8 @@ namespace Ttcn { * representations in runtime. */ char *generate_code_init_set(char *str, const char *name, bool is_superset); + + char* generate_code_init_dec_match(char* str, const char* name); char *generate_code_init_all_from(char *str, const char *name); char *generate_code_init_all_from_list(char *str, const char *name); diff --git a/compiler2/ttcn3/compiler.l b/compiler2/ttcn3/compiler.l index 7442e68b77273593e81f126c1e1b6b23dd90f3c4..8ef00263a7a2c959aaa8aca27eab21acca01ba5f 100644 --- a/compiler2/ttcn3/compiler.l +++ b/compiler2/ttcn3/compiler.l @@ -390,6 +390,7 @@ const RETURN(ConstKeyword); continue RETURN(ContinueKeyword); control RETURN(ControlKeyword); create RETURN_DOT(CreateKeyword); +decmatch RETURN(DecodedMatchKeyword); deactivate RETURN(DeactivateKeyword); default RETURN(DefaultKeyword); derefers RETURN(DerefersKeyword); diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y index baf1a8e339337b6360f8ea0efd77427fc3f37066..c34e8f520732fb67ce25b7bb7800bb224bf6e7ba 100644 --- a/compiler2/ttcn3/compiler.y +++ b/compiler2/ttcn3/compiler.y @@ -535,6 +535,11 @@ static const string anyname("anytype"); struct { visibility_t visibility; } visbilitytype; + + struct { + Value* string_encoding; + TemplateInstance* target_template; + } decode_match; } /* Tokens of TTCN-3 */ @@ -604,6 +609,7 @@ static const string anyname("anytype"); %token ContinueKeyword %token ControlKeyword %token CreateKeyword +%token DecodedMatchKeyword %token DeactivateKeyword %token DefaultKeyword %token DerefersKeyword @@ -1047,6 +1053,7 @@ static const string anyname("anytype"); %type <float_val> FloatOrSpecialFloatValue %type <erroneous_indicator> ErroneousIndicator %type <imptype> ImportSpec ImportElement +%type <decode_match> DecodedContentMatch /********************************************************************* * Destructors @@ -1737,6 +1744,14 @@ PortElementList } optRunsOnComprefOrSelf +%destructor { + if ($$.string_encoding != NULL) { + delete $$.string_encoding; + } + delete $$.target_template; +} +DecodedContentMatch + /********************************************************************* * Operator precedences (lowest first) *********************************************************************/ @@ -1756,12 +1771,12 @@ optRunsOnComprefOrSelf %left '*' '/' ModKeyword RemKeyword %left UnarySign -%expect 26 +%expect 53 %start GrammarRoot /* -XXX Source of conflicts (26 S/R): +XXX Source of conflicts (53 S/R): 1.) 9 conflicts in one state The Expression after 'return' keyword is optional in ReturnStatement. @@ -1769,7 +1784,7 @@ For 9 tokens the parser cannot decide whether the token is a part of the return expression (shift) or it is the beginning of the next statement (reduce). -2.) 9 distinct states, each with one conflict caused by token '[' +2.) 10 distinct states, each with one conflict caused by token '[' The local definitions in altsteps can be followed immediately by the guard expression. When the parser sees the '[' token it cannot decide whether it belongs to the local definition as array dimension or array subreference @@ -1784,6 +1799,7 @@ The situations are the following: - var t v := ref.objid{...}.subref <here> [ - var template t v <here> [ - var t v := function(...)<subrefs> <here> [ +- var template t v := decmatch (...) ref <here> [ 3.) 1 conflict The sequence identifier.objid can be either the beginning of a module name @@ -1800,6 +1816,13 @@ non-standard language extension. 6.) 1 Conflict due to pattern concatenation +7.) 26 conflicts in one state +In the DecodedContentMatch rule a SingleExpression encased in round brackets is +followed by an in-line template. For 26 tokens (after the ')' ) the parser cannot +decide whether the token is the beginning of the in-line template (shift) or +the brackets are only part of the SingleExpression itself and the conflicting +token is the next segment in the expression (reduce). + Note that the parser implemented by bison always chooses to shift instead of reduce in case of conflicts. */ @@ -3176,6 +3199,11 @@ TemplateBody: // 101 is a Template* $$->set_length_restriction($2.len_restr); $$->set_ifpresent($2.is_ifpresent); } +| DecodedContentMatch + { + $$ = new Template($1.string_encoding, $1.target_template); + $$->set_location(infile, @$); + } ; SimpleSpec: // 102 @@ -3546,6 +3574,19 @@ PermutationMatch: // 137 is a Templates* PermutationKeyword ValueList { $$ = $2; } ; +DecodedContentMatch: + DecodedMatchKeyword '(' SingleExpression ')' InLineTemplate + { + $$.string_encoding = $3; + $$.target_template = $5; + } +| DecodedMatchKeyword InLineTemplate + { + $$.string_encoding = NULL; + $$.target_template = $2; + } +; + AnyValue: // 140 '?' ; diff --git a/core/Basetype.hh b/core/Basetype.hh index f18f4434c02a5a038b7243c7e02a773dbf17efca..a0e7eb3bb0cb28f982c38839553b7f20192f12d6 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -1087,4 +1087,17 @@ public: } }; +/** Interface/base class for decoded content matching + * + * For every decmatch template the compiler generates a new class that inherits + * this one and implements its virtual functions. An instance of the new class + * is stored in the template object, which calls the appropriate virtual + * functions when the template object's match() or log() functions are called. */ +class Dec_Match_Interface { +public: + virtual boolean match(TTCN_Buffer&) const = 0; + virtual void log() const = 0; + virtual ~Dec_Match_Interface() {} +}; + #endif diff --git a/core/Bitstring.cc b/core/Bitstring.cc index a093000a510143f0e0b75356a7998905c29dae84..56d4905c86c6e81c30c19bbb376c74c0f165251a 100644 --- a/core/Bitstring.cc +++ b/core/Bitstring.cc @@ -32,6 +32,7 @@ #include "Error.hh" #include "Logger.hh" #include "Encdec.hh" +#include "Addfunc.hh" #include "../common/dbgnew.hh" @@ -1410,6 +1411,19 @@ void BITSTRING_template::clean_up() else TTCN_error("Internal error: Invalid reference counter in a bitstring " "pattern."); break; + case DECODE_MATCH: + if (dec_match->ref_count > 1) { + dec_match->ref_count--; + } + else if (dec_match->ref_count == 1) { + delete dec_match->instance; + delete dec_match; + } + else { + TTCN_error("Internal error: Invalid reference counter in a " + "decoded content match."); + } + break; default: break; } @@ -1438,6 +1452,10 @@ void BITSTRING_template::copy_template(const BITSTRING_template& other_value) pattern_value = other_value.pattern_value; pattern_value->ref_count++; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported bitstring template."); } @@ -1693,6 +1711,15 @@ boolean BITSTRING_template::match(const BITSTRING& other_value, return template_selection == COMPLEMENTED_LIST; case STRING_PATTERN: return match_pattern(pattern_value, other_value.val_ptr); + case DECODE_MATCH: { + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_EncDec::clear_error(); + OCTETSTRING os(bit2oct(other_value)); + TTCN_Buffer buff(os); + boolean ret_val = dec_match->instance->match(buff); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + return ret_val; } default: TTCN_error("Matching an uninitialized/unsupported bitstring template."); } @@ -1766,14 +1793,17 @@ int BITSTRING_template::lengthof() const } void BITSTRING_template::set_type(template_sel template_type, - unsigned int list_length) + unsigned int list_length /* = 0 */) { - if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) + if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST && + template_type != DECODE_MATCH) TTCN_error("Setting an invalid list type for a bitstring template."); clean_up(); set_selection(template_type); - value_list.n_values = list_length; - value_list.list_value = new BITSTRING_template[list_length]; + if (template_type != DECODE_MATCH) { + value_list.n_values = list_length; + value_list.list_value = new BITSTRING_template[list_length]; + } } BITSTRING_template& BITSTRING_template::list_item(unsigned int list_index) @@ -1786,6 +1816,17 @@ BITSTRING_template& BITSTRING_template::list_item(unsigned int list_index) return value_list.list_value[list_index]; } +void BITSTRING_template::set_decmatch(Dec_Match_Interface* new_instance) +{ + if (template_selection != DECODE_MATCH) { + TTCN_error("Setting the decoded content matching mechanism of a non-decmatch " + "bitstring template."); + } + dec_match = new decmatch_struct; + dec_match->ref_count = 1; + dec_match->instance = new_instance; +} + static const char patterns[] = { '0', '1', '?', '*' }; void BITSTRING_template::log() const @@ -1814,6 +1855,10 @@ void BITSTRING_template::log() const } TTCN_Logger::log_event_str("'B"); break; + case DECODE_MATCH: + TTCN_Logger::log_event_str("decmatch "); + dec_match->instance->log(); + break; default: log_generic(); break; @@ -1928,6 +1973,9 @@ Module_Param* BITSTRING_template::get_param(Module_Param_Name& param_name) const memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements); mp = new Module_Param_Bitstring_Template(pattern_value->n_elements, val_cpy); break; } + case DECODE_MATCH: + mp->error("Referencing a decoded content matching template is not supported."); + break; default: break; } diff --git a/core/Bitstring.hh b/core/Bitstring.hh index 354e5bea78b1835d7188375e6e7c5178734956df..877a564957b20719b4feb2e950e0544dc61abd2b 100644 --- a/core/Bitstring.hh +++ b/core/Bitstring.hh @@ -245,6 +245,8 @@ public: }; /// bitstring template class +struct decmatch_struct; + class BITSTRING_template : public Restricted_Length_Template { #ifdef __SUNPRO_CC public: @@ -258,6 +260,7 @@ private: BITSTRING_template *list_value; } value_list; bitstring_pattern_struct *pattern_value; + decmatch_struct* dec_match; }; void copy_template(const BITSTRING_template& other_value); @@ -292,8 +295,10 @@ public: int lengthof() const; - void set_type(template_sel template_type, unsigned int list_length); + void set_type(template_sel template_type, unsigned int list_length = 0); BITSTRING_template& list_item(unsigned int list_index); + + void set_decmatch(Dec_Match_Interface* new_instance); void log() const; void log_match(const BITSTRING& match_value, boolean legacy = FALSE) const; diff --git a/core/Charstring.cc b/core/Charstring.cc index ef42df83d649242795625b26d7bdc7b7aa8bf488..c3123705a75748a8132921f376d0e91fb842ad6e 100644 --- a/core/Charstring.cc +++ b/core/Charstring.cc @@ -2007,6 +2007,19 @@ void CHARSTRING_template::clean_up() case STRING_PATTERN: if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp); break; + case DECODE_MATCH: + if (dec_match->ref_count > 1) { + dec_match->ref_count--; + } + else if (dec_match->ref_count == 1) { + delete dec_match->instance; + delete dec_match; + } + else { + TTCN_error("Internal error: Invalid reference counter in a " + "decoded content match."); + } + break; default: break; } @@ -2041,6 +2054,10 @@ void CHARSTRING_template::copy_template(const CHARSTRING_template& other_value) "not set when copying a charstring value range template."); value_range = other_value.value_range; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported charstring template."); } @@ -2268,6 +2285,14 @@ boolean CHARSTRING_template::match(const CHARSTRING& other_value, } return TRUE; break; } + case DECODE_MATCH: { + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_EncDec::clear_error(); + TTCN_Buffer buff(other_value); + boolean ret_val = dec_match->instance->match(buff); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + return ret_val; } default: TTCN_error("Matching with an uninitialized/unsupported charstring " "template."); @@ -2352,6 +2377,9 @@ void CHARSTRING_template::set_type(template_sel template_type, value_range.min_is_set = FALSE; value_range.max_is_set = FALSE; break; + case DECODE_MATCH: + set_selection(DECODE_MATCH); + break; default: TTCN_error("Setting an invalid type for a charstring template."); } @@ -2403,6 +2431,20 @@ void CHARSTRING_template::set_max(const CHARSTRING& max_value) value_range.min_value); } +void CHARSTRING_template::set_decmatch(Dec_Match_Interface* new_instance) +{ + if (template_selection != DECODE_MATCH) { + TTCN_error("Setting the decoded content matching mechanism of a non-decmatch " + "charstring template."); + } + dec_match = new unichar_decmatch_struct; + dec_match->ref_count = 1; + dec_match->instance = new_instance; + // the character coding is only used if this template is copied to a + // universal charstring template + dec_match->coding = CharCoding::UTF_8; +} + void CHARSTRING_template::log_pattern(int n_chars, const char *chars_ptr) { TTCN_Logger::log_event_str("pattern \""); @@ -2567,6 +2609,10 @@ void CHARSTRING_template::log() const } else TTCN_Logger::log_event_str("<unknown upper bound>"); TTCN_Logger::log_char(')'); break; + case DECODE_MATCH: + TTCN_Logger::log_event_str("decmatch "); + dec_match->instance->log(); + break; default: log_generic(); } @@ -2708,6 +2754,9 @@ Module_Param* CHARSTRING_template::get_param(Module_Param_Name& param_name) cons case STRING_PATTERN: mp = new Module_Param_Pattern(mcopystr(single_value)); break; + case DECODE_MATCH: + mp->error("Referencing a decoded content matching template is not supported."); + break; default: break; } diff --git a/core/Charstring.hh b/core/Charstring.hh index 0387429e5d92dccae7b7550af572aa4508c95b8d..8b41a970205d3bd842bdc136d67961555da3c497 100644 --- a/core/Charstring.hh +++ b/core/Charstring.hh @@ -348,6 +348,8 @@ extern CHARSTRING operator>>=(const char *string_value, // charstring template class +struct unichar_decmatch_struct; + class CHARSTRING_template : public Restricted_Length_Template { friend class UNIVERSAL_CHARSTRING_template; @@ -367,6 +369,7 @@ private: boolean regexp_init; regex_t posix_regexp; } pattern_value; + unichar_decmatch_struct* dec_match; }; void copy_template(const CHARSTRING_template& other_value); @@ -422,9 +425,11 @@ public: void set_type(template_sel template_type, unsigned int list_length = 0); CHARSTRING_template& list_item(unsigned int list_index); - + void set_min(const CHARSTRING& min_value); void set_max(const CHARSTRING& max_value); + + void set_decmatch(Dec_Match_Interface* new_instance); void log() const; void log_match(const CHARSTRING& match_value, boolean legacy = FALSE) const; diff --git a/core/Hexstring.cc b/core/Hexstring.cc index 11c15b945e824fdc6162827a21c2e6913d3b09a6..968a6e140543197d7460d5e778700f0f6a14e27d 100644 --- a/core/Hexstring.cc +++ b/core/Hexstring.cc @@ -1304,6 +1304,19 @@ void HEXSTRING_template::clean_up() TTCN_error("Internal error: Invalid reference counter in a hexstring " "pattern."); break; + case DECODE_MATCH: + if (dec_match->ref_count > 1) { + dec_match->ref_count--; + } + else if (dec_match->ref_count == 1) { + delete dec_match->instance; + delete dec_match; + } + else { + TTCN_error("Internal error: Invalid reference counter in a " + "decoded content match."); + } + break; default: break; } @@ -1332,6 +1345,10 @@ void HEXSTRING_template::copy_template(const HEXSTRING_template& other_value) pattern_value = other_value.pattern_value; pattern_value->ref_count++; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported hexstring template."); } @@ -1582,6 +1599,15 @@ boolean HEXSTRING_template::match(const HEXSTRING& other_value, return template_selection == COMPLEMENTED_LIST; case STRING_PATTERN: return match_pattern(pattern_value, other_value.val_ptr); + case DECODE_MATCH: { + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_EncDec::clear_error(); + OCTETSTRING os(hex2oct(other_value)); + TTCN_Buffer buff(os); + boolean ret_val = dec_match->instance->match(buff); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + return ret_val; } default: TTCN_error("Matching an uninitialized/unsupported hexstring template."); } @@ -1655,12 +1681,15 @@ int HEXSTRING_template::lengthof() const void HEXSTRING_template::set_type(template_sel template_type, unsigned int list_length) { - if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) TTCN_error( + if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST && + template_type != DECODE_MATCH) TTCN_error( "Setting an invalid list type for a hexstring template."); clean_up(); set_selection(template_type); - value_list.n_values = list_length; - value_list.list_value = new HEXSTRING_template[list_length]; + if (template_type != DECODE_MATCH) { + value_list.n_values = list_length; + value_list.list_value = new HEXSTRING_template[list_length]; + } } HEXSTRING_template& HEXSTRING_template::list_item(unsigned int list_index) @@ -1673,6 +1702,17 @@ HEXSTRING_template& HEXSTRING_template::list_item(unsigned int list_index) return value_list.list_value[list_index]; } +void HEXSTRING_template::set_decmatch(Dec_Match_Interface* new_instance) +{ + if (template_selection != DECODE_MATCH) { + TTCN_error("Setting the decoded content matching mechanism of a non-decmatch " + "hexstring template."); + } + dec_match = new decmatch_struct; + dec_match->ref_count = 1; + dec_match->instance = new_instance; +} + void HEXSTRING_template::log() const { switch (template_selection) { @@ -1705,6 +1745,10 @@ void HEXSTRING_template::log() const } TTCN_Logger::log_event_str("'H"); break; + case DECODE_MATCH: + TTCN_Logger::log_event_str("decmatch "); + dec_match->instance->log(); + break; default: log_generic(); break; @@ -1821,6 +1865,9 @@ Module_Param* HEXSTRING_template::get_param(Module_Param_Name& param_name) const memcpy(val_cpy, pattern_value->elements_ptr, pattern_value->n_elements); mp = new Module_Param_Hexstring_Template(pattern_value->n_elements, val_cpy); break; } + case DECODE_MATCH: + mp->error("Referencing a decoded content matching template is not supported."); + break; default: break; } diff --git a/core/Hexstring.hh b/core/Hexstring.hh index cb68ad9d38bac85808b223730e6cca75b9c41ce6..0792afa425511374361fd88e0d55ac688d39561f 100644 --- a/core/Hexstring.hh +++ b/core/Hexstring.hh @@ -199,6 +199,7 @@ public: }; // hexstring template class +struct decmatch_struct; class HEXSTRING_template : public Restricted_Length_Template { #ifdef __SUNPRO_CC @@ -213,6 +214,7 @@ private: HEXSTRING_template *list_value; } value_list; hexstring_pattern_struct *pattern_value; + decmatch_struct* dec_match; }; void copy_template(const HEXSTRING_template& other_value); @@ -247,9 +249,11 @@ public: int lengthof() const; - void set_type(template_sel template_type, unsigned int list_length); + void set_type(template_sel template_type, unsigned int list_length = 0); HEXSTRING_template& list_item(unsigned int list_index); + void set_decmatch(Dec_Match_Interface* new_instance); + void log() const; void log_match(const HEXSTRING& match_value, boolean legacy = FALSE) const; diff --git a/core/Octetstring.cc b/core/Octetstring.cc index 1af0c58a2bfe2c9a672559a059e1b0de3197516d..7d9dd6eac32787413eaef0a2797122cdfb51d8da 100644 --- a/core/Octetstring.cc +++ b/core/Octetstring.cc @@ -1538,6 +1538,19 @@ void OCTETSTRING_template::clean_up() else TTCN_error("Internal error: Invalid reference counter in an " "octetstring pattern."); break; + case DECODE_MATCH: + if (dec_match->ref_count > 1) { + dec_match->ref_count--; + } + else if (dec_match->ref_count == 1) { + delete dec_match->instance; + delete dec_match; + } + else { + TTCN_error("Internal error: Invalid reference counter in a " + "decoded content match."); + } + break; default: break; } @@ -1567,6 +1580,10 @@ void OCTETSTRING_template::copy_template pattern_value = other_value.pattern_value; pattern_value->ref_count++; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported octetstring template."); } @@ -1817,6 +1834,14 @@ boolean OCTETSTRING_template::match(const OCTETSTRING& other_value, return template_selection == COMPLEMENTED_LIST; case STRING_PATTERN: return match_pattern(pattern_value, other_value.val_ptr); + case DECODE_MATCH: { + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_EncDec::clear_error(); + TTCN_Buffer buff(other_value); + boolean ret_val = dec_match->instance->match(buff); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + return ret_val; } default: TTCN_error("Matching an uninitialized/unsupported octetstring template."); } @@ -1892,12 +1917,15 @@ int OCTETSTRING_template::lengthof() const void OCTETSTRING_template::set_type(template_sel template_type, unsigned int list_length) { - if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) - TTCN_error("Setting an invalid list type for an octetstring template."); + if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST && + template_type != DECODE_MATCH) + TTCN_error("Setting an invalid type for an octetstring template."); clean_up(); set_selection(template_type); - value_list.n_values = list_length; - value_list.list_value = new OCTETSTRING_template[list_length]; + if (template_type != DECODE_MATCH) { + value_list.n_values = list_length; + value_list.list_value = new OCTETSTRING_template[list_length]; + } } OCTETSTRING_template& OCTETSTRING_template::list_item(unsigned int list_index) @@ -1910,6 +1938,17 @@ OCTETSTRING_template& OCTETSTRING_template::list_item(unsigned int list_index) return value_list.list_value[list_index]; } +void OCTETSTRING_template::set_decmatch(Dec_Match_Interface* new_instance) +{ + if (template_selection != DECODE_MATCH) { + TTCN_error("Setting the decoded content matching mechanism of a non-decmatch " + "octetstring template."); + } + dec_match = new decmatch_struct; + dec_match->ref_count = 1; + dec_match->instance = new_instance; +} + void OCTETSTRING_template::log() const { switch (template_selection) { @@ -1938,6 +1977,10 @@ void OCTETSTRING_template::log() const } TTCN_Logger::log_event_str("'O"); break; + case DECODE_MATCH: + TTCN_Logger::log_event_str("decmatch "); + dec_match->instance->log(); + break; default: log_generic(); break; @@ -2054,6 +2097,9 @@ Module_Param* OCTETSTRING_template::get_param(Module_Param_Name& param_name) con sizeof(unsigned short)); mp = new Module_Param_Octetstring_Template(pattern_value->n_elements, val_cpy); break; } + case DECODE_MATCH: + mp->error("Referencing a decoded content matching template is not supported."); + break; default: break; } diff --git a/core/Octetstring.hh b/core/Octetstring.hh index 055314ef82082fc57d9dff309ad39ef3c79262fc..7e33563ff4a260fb82d01485f7777896fb8bdee1 100644 --- a/core/Octetstring.hh +++ b/core/Octetstring.hh @@ -230,6 +230,8 @@ public: // octetstring template class +struct decmatch_struct; + class OCTETSTRING_template : public Restricted_Length_Template { #ifdef __SUNPRO_CC public: @@ -243,6 +245,7 @@ private: OCTETSTRING_template *list_value; } value_list; octetstring_pattern_struct *pattern_value; + decmatch_struct* dec_match; }; void copy_template(const OCTETSTRING_template& other_value); @@ -277,8 +280,10 @@ public: int lengthof() const; - void set_type(template_sel template_type, unsigned int list_length); + void set_type(template_sel template_type, unsigned int list_length = 0); OCTETSTRING_template& list_item(unsigned int list_index); + + void set_decmatch(Dec_Match_Interface* new_instance); void log() const; void log_match(const OCTETSTRING& match_value, boolean legacy = FALSE) const; diff --git a/core/String_struct.hh b/core/String_struct.hh index 5db39f66fafed7dcbbe5be78dc9b5fe14674e488..957d0eff48b059700a51a7b38c8a6d02c492fe62 100644 --- a/core/String_struct.hh +++ b/core/String_struct.hh @@ -22,6 +22,7 @@ #include "Charstring.hh" #include "Universal_charstring.hh" #include "Encdec.hh" +#include "CharCoding.hh" /** Type of the reference counters in all structures. */ typedef unsigned int ref_count_t; @@ -89,4 +90,19 @@ struct TTCN_Buffer::buffer_struct { unsigned char data_ptr[sizeof(int)]; }; +/** Structure for storing a decoded content matching mechanism + * (for bitstrings, hexstrings, octetstrings and charstrings) */ +struct decmatch_struct { + ref_count_t ref_count; + Dec_Match_Interface* instance; +}; + +/** Structure for storing a decoded content matching mechanism for universal + * charstrings (also contains the character coding method) */ +struct unichar_decmatch_struct { + ref_count_t ref_count; + Dec_Match_Interface* instance; + CharCoding::CharCodingType coding; +}; + #endif diff --git a/core/Template.cc b/core/Template.cc index 39cb4b0f78e39796e5477382dd43d862db502a69..5ec57a5ace343306d339d99e72683c28ea276995 100644 --- a/core/Template.cc +++ b/core/Template.cc @@ -973,6 +973,7 @@ int Record_Of_Template::n_elem() const case STRING_PATTERN: case SUPERSET_MATCH: case SUBSET_MATCH: + case DECODE_MATCH: break; } TTCN_error("Performing n_elem() operation on an uninitialized/unsupported " @@ -1719,6 +1720,7 @@ int Set_Of_Template::size_of(boolean is_size) const case UNINITIALIZED_TEMPLATE: case VALUE_RANGE: case STRING_PATTERN: + case DECODE_MATCH: TTCN_error("Performing %sof() operation on an uninitialized/unsupported " "template of type %s.", op_name, get_descriptor()->name); } @@ -1745,6 +1747,7 @@ int Set_Of_Template::n_elem() const case VALUE_LIST: case VALUE_RANGE: case STRING_PATTERN: + case DECODE_MATCH: break; } TTCN_error("Performing n_elem() operation on an uninitialized/unsupported " diff --git a/core/Template.hh b/core/Template.hh index bd874424d730770a120fed18c2f24a1003c1dd23..014d98ab991244505140becb2a6891ab5985a707 100644 --- a/core/Template.hh +++ b/core/Template.hh @@ -47,7 +47,8 @@ enum template_sel { VALUE_RANGE = 6, STRING_PATTERN = 7, SUPERSET_MATCH = 8, - SUBSET_MATCH = 9 + SUBSET_MATCH = 9, + DECODE_MATCH = 10 }; enum template_res { diff --git a/core/Universal_charstring.cc b/core/Universal_charstring.cc index ebc97ec6b92e82929cb9b008a546648a122ce9c6..079a1335e1bb3c2351fec21f493614c0e9f157bd 100644 --- a/core/Universal_charstring.cc +++ b/core/Universal_charstring.cc @@ -3577,6 +3577,19 @@ void UNIVERSAL_CHARSTRING_template::clean_up() if (pattern_value.regexp_init) regfree(&pattern_value.posix_regexp); delete pattern_string; } + else if (template_selection == DECODE_MATCH) { + if (dec_match->ref_count > 1) { + dec_match->ref_count--; + } + else if (dec_match->ref_count == 1) { + delete dec_match->instance; + delete dec_match; + } + else { + TTCN_error("Internal error: Invalid reference counter in a " + "decoded content match."); + } + } template_selection = UNINITIALIZED_TEMPLATE; } @@ -3622,6 +3635,10 @@ void UNIVERSAL_CHARSTRING_template::copy_template pattern_string = new CHARSTRING(other_value.single_value); pattern_value.regexp_init=FALSE; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported charstring template to a " "universal charstring template."); @@ -3660,6 +3677,10 @@ void UNIVERSAL_CHARSTRING_template::copy_template pattern_string = new CHARSTRING(*(other_value.pattern_string)); pattern_value.regexp_init=FALSE; break; + case DECODE_MATCH: + dec_match = other_value.dec_match; + dec_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported universal charstring " "template."); @@ -3975,6 +3996,32 @@ boolean UNIVERSAL_CHARSTRING_template::match TTCN_error("Pattern matching error: %s", msg); } break;} + case DECODE_MATCH: { + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_EncDec::clear_error(); + TTCN_Buffer buff; + switch (dec_match->coding) { + case CharCoding::UTF_8: + other_value.encode_utf8(buff, false); + break; + case CharCoding::UTF16: + case CharCoding::UTF16LE: + case CharCoding::UTF16BE: + other_value.encode_utf16(buff, dec_match->coding); + break; + case CharCoding::UTF32: + case CharCoding::UTF32LE: + case CharCoding::UTF32BE: + other_value.encode_utf32(buff, dec_match->coding); + break; + default: + TTCN_error("Internal error: Invalid string serialization for " + "universal charstring template with decoded content matching."); + } + boolean ret_val = dec_match->instance->match(buff); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,TTCN_EncDec::EB_DEFAULT); + TTCN_EncDec::clear_error(); + return ret_val; } default: TTCN_error("Matching with an uninitialized/unsupported universal " "charstring template."); @@ -4059,6 +4106,9 @@ void UNIVERSAL_CHARSTRING_template::set_type(template_sel template_type, value_range.min_is_set = FALSE; value_range.max_is_set = FALSE; break; + case DECODE_MATCH: + set_selection(DECODE_MATCH); + break; default: TTCN_error("Setting an invalid type for a universal charstring template."); } @@ -4110,6 +4160,43 @@ void UNIVERSAL_CHARSTRING_template::set_max "is smaller than the lower bound."); } +void UNIVERSAL_CHARSTRING_template::set_decmatch(Dec_Match_Interface* new_instance, + const char* coding_str /* = NULL */) +{ + if (template_selection != DECODE_MATCH) { + TTCN_error("Setting the decoded content matching mechanism of a non-decmatch " + "universal charstring template."); + } + CharCoding::CharCodingType new_coding = CharCoding::UTF_8; + if (coding_str != NULL && strcmp(coding_str, "UTF-8") != 0) { + if (strcmp(coding_str, "UTF-16") == 0) { + new_coding = CharCoding::UTF16; + } + else if (strcmp(coding_str, "UTF-16LE") == 0) { + new_coding = CharCoding::UTF16LE; + } + else if (strcmp(coding_str, "UTF-16BE") == 0) { + new_coding = CharCoding::UTF16BE; + } + else if (strcmp(coding_str, "UTF-32") == 0) { + new_coding = CharCoding::UTF32; + } + else if (strcmp(coding_str, "UTF-32LE") == 0) { + new_coding = CharCoding::UTF32LE; + } + else if (strcmp(coding_str, "UTF-32BE") == 0) { + new_coding = CharCoding::UTF32BE; + } + else { + TTCN_error("Invalid string serialization for decoded content matching."); + } + } + dec_match = new unichar_decmatch_struct; + dec_match->ref_count = 1; + dec_match->instance = new_instance; + dec_match->coding = new_coding; +} + void UNIVERSAL_CHARSTRING_template::log() const { switch (template_selection) { @@ -4158,6 +4245,37 @@ void UNIVERSAL_CHARSTRING_template::log() const } else TTCN_Logger::log_event_str("<unknown upper bound>"); TTCN_Logger::log_char(')'); break; + case DECODE_MATCH: + TTCN_Logger::log_event_str("decmatch("); + switch (dec_match->coding) { + case CharCoding::UTF_8: + TTCN_Logger::log_event_str("UTF-8"); + break; + case CharCoding::UTF16: + TTCN_Logger::log_event_str("UTF-16"); + break; + case CharCoding::UTF16LE: + TTCN_Logger::log_event_str("UTF-16LE"); + break; + case CharCoding::UTF16BE: + TTCN_Logger::log_event_str("UTF-16BE"); + break; + case CharCoding::UTF32: + TTCN_Logger::log_event_str("UTF-32"); + break; + case CharCoding::UTF32LE: + TTCN_Logger::log_event_str("UTF-32LE"); + break; + case CharCoding::UTF32BE: + TTCN_Logger::log_event_str("UTF-32BE"); + break; + default: + TTCN_Logger::log_event_str("<unknown coding>"); + break; + } + TTCN_Logger::log_event_str(") "); + dec_match->instance->log(); + break; default: log_generic(); break; @@ -4305,6 +4423,9 @@ Module_Param* UNIVERSAL_CHARSTRING_template::get_param(Module_Param_Name& param_ case STRING_PATTERN: mp = new Module_Param_Pattern(mcopystr(*pattern_string)); break; + case DECODE_MATCH: + mp->error("Referencing a decoded content matching template is not supported."); + break; default: break; } diff --git a/core/Universal_charstring.hh b/core/Universal_charstring.hh index 7ffec3b2dd02b4e954166de5bc48a6e4bb76f071..e76cb63aa897d279479bef59155c26f011babd1e 100644 --- a/core/Universal_charstring.hh +++ b/core/Universal_charstring.hh @@ -522,6 +522,8 @@ extern UNIVERSAL_CHARSTRING operator+(const char *string_value, const UNIVERSAL_CHARSTRING_ELEMENT& other_value); +struct unichar_decmatch_struct; + class UNIVERSAL_CHARSTRING_template : public Restricted_Length_Template { private: UNIVERSAL_CHARSTRING single_value; @@ -539,6 +541,7 @@ private: boolean regexp_init; regex_t posix_regexp; } pattern_value; + unichar_decmatch_struct* dec_match; }; void copy_template(const CHARSTRING_template& other_value); @@ -597,6 +600,8 @@ public: void set_min(const UNIVERSAL_CHARSTRING& min_value); void set_max(const UNIVERSAL_CHARSTRING& max_value); + + void set_decmatch(Dec_Match_Interface* new_instance, const char* coding_str = NULL); void log() const; void log_match(const UNIVERSAL_CHARSTRING& match_value, boolean legacy = FALSE) const; diff --git a/regression_test/Makefile b/regression_test/Makefile index e359cf66841accd94e209c026636c796aa67525c..961fff4deef269a46bd9027b9ac436a7d975f97d 100644 --- a/regression_test/Makefile +++ b/regression_test/Makefile @@ -37,8 +37,8 @@ include $(TOPDIR)/Makefile.regression DIRS := intOper boolOper floatOper bitstrOper octetstrOper charOper charstrOper \ verdictOper recordOper recofOper setOper setofOper setofMatch unionOper \ enumOper arrayOper anytypeOper templateInt templateBool templateFloat templateBitstr \ -templateOctetstr templateChar templateCharstr templateRec templateRecof \ -templateSet templateSetof templateUnion templateEnum modifiedTemplate \ +templateHexstr templateOctetstr templateChar templateCharstr templateUnicharstr \ +templateRec templateRecof templateSet templateSetof templateUnion templateEnum modifiedTemplate \ basicStatem configOper commMessage commProcedure lostTimer controlTimer \ BER BER_x682 ASN1 predefFunction ERC preCompilerFlags functionReference \ nonMandatoryPar logFiles logger_control namedActualParameters \ diff --git a/regression_test/templateBitstr/TtemplateBitstr.ttcn b/regression_test/templateBitstr/TtemplateBitstr.ttcn index c6ef0b040e851838683d2a0723d1f065c2cf6bb2..f9db2ef6f4c6586b4b5ec10b73154a3dd47218fa 100644 --- a/regression_test/templateBitstr/TtemplateBitstr.ttcn +++ b/regression_test/templateBitstr/TtemplateBitstr.ttcn @@ -6,6 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: + * Baranyi, Botond * Balasko, Jeno * Kovacs, Ferenc * Raduly, Csaba @@ -18,7 +19,39 @@ type component templateBitstr_mycomp {}; type record templateBitstr_rec { bitstring x1, bitstring x2, - bitstring x3 optional }; + bitstring x3 optional +} +with { + encode "JSON"; + variant(x1) "JSON: name as first"; + variant(x2) "JSON: name as second"; + variant(x3) "JSON: name as third"; +} + +type record decmatch_rec { + integer i, + charstring s +} +with { + encode "JSON"; +} + +type record of integer decmatch_list +with { + encode "XML"; + variant "list"; +} + +type union decmatch_uni { + integer i, + charstring s +} +with { + encode "RAW"; + variant(i) "FIELDLENGTH(16)"; +} + + template templateBitstr_rec templateBitstr_tSpec :={ //specific values x1:='001'B, x2:='010'B, @@ -73,6 +106,22 @@ template templateBitstr_rec templateBitstr_tAnyorNoneEl :={ //specific value and x3:='10*'B }; template bitstring t_param1(templateBitstr_rec par) := substr(par.x1, 0, 1); // parameterised template + +template decmatch_uni decmatch_tUnion := { i := ? }; + +template decmatch_rec decmatch_tRecord := { i := (0..infinity), s := ? }; + +template templateBitstr_rec templateBitstr_tDecmatch := { // decoded content match + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } +}; + +template templateBitstr_rec templateBitstr_tDecmatchSelfRef := { // decoded content match with self-reference + x1 := '1011'B, + x2 := decmatch templateBitstr_tDecmatchSelfRef.x1, + x3 := decmatch templateBitstr_rec: { x1 := templateBitstr_tDecmatchSelfRef.x1, x2 := ?, x3 := * } +}; testcase templateBitstrSpec() runs on templateBitstr_mycomp { var templateBitstr_rec x1,x2; //specific value @@ -317,6 +366,95 @@ testcase CR_TR00018474() runs on templateBitstr_mycomp { if (match('1011110000'B, vtb1)) { setverdict(pass) } else { setverdict(fail) } } +testcase templateBitstrDecmatch() runs on templateBitstr_mycomp { + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var decmatch_list bad_list, good_list; + bad_list := { 4, 7, 10 }; + good_list := { 2, 15, 28 }; + var decmatch_uni bad_uni, good_uni; + bad_uni := { s := "five" }; + good_uni := { i := 5 }; + var bitstring bad_rec_enc, good_rec_enc, bad_list_enc, good_list_enc, bad_uni_enc, good_uni_enc; + bad_rec_enc := encvalue(bad_rec); + good_rec_enc := encvalue(good_rec); + bad_list_enc := encvalue(bad_list); + good_list_enc := encvalue(good_list); + bad_uni_enc := encvalue(bad_uni); + good_uni_enc := encvalue(good_uni); + var templateBitstr_rec r1, r2, r3, r4, r5; + r1 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r2 := { x1 := bad_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r3 := { x1 := good_list_enc, x2 := bad_uni_enc, x3 := good_rec_enc }; + r4 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := bad_rec_enc }; + r5 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := '11110011'B }; + // match: all 3 are good + if (match(r1, templateBitstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded list does not match + if (not match(r2, templateBitstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded union does not match + if (not match(r3, templateBitstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded record does not match + if (not match(r4, templateBitstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 4); } + // no match: x3 is not a valid encoded record value + if (not match(r5, templateBitstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 5); } + // match r1 with the same template declared as an in-line template + if (match(r1, templateBitstr_rec: { + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } + })) { setverdict(pass); } + else { setverdict(fail, 6); } +} + +external function ef_enc_rec_x1(in templateBitstr_rec.x1 x) return octetstring +with { extension "prototype(convert) encode(JSON)" } + +testcase templateBitstrDecmatchSelfRef() runs on templateBitstr_mycomp { + // global self-referencing template + var templateBitstr_rec.x1 bad_bs, good_bs; + bad_bs := '11'B; + good_bs := '1011'B; + var templateBitstr_rec bad_rec, good_rec; + bad_rec := { x1 := '01'B, x2 := '10'B, x3 := '11'B }; + good_rec := { x1 := '1011'B, x2 := '10'B, x3 := '11'B }; + var bitstring bad_bs_enc, good_bs_enc, bad_rec_enc, good_rec_enc; + bad_bs_enc := oct2bit(ef_enc_rec_x1(bad_bs)); + good_bs_enc := oct2bit(ef_enc_rec_x1(good_bs)); + bad_rec_enc := encvalue(bad_rec); + good_rec_enc := encvalue(good_rec); + var templateBitstr_rec r1, r2, r3; + r1 := { x1 := '1011'B, x2 := good_bs_enc, x3 := good_rec_enc }; + r2 := { x1 := '1011'B, x2 := bad_bs_enc, x3 := good_rec_enc }; + r3 := { x1 := '1011'B, x2 := good_bs_enc, x3 := bad_rec_enc }; + // match: all 2 are good + if (match(r1, templateBitstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded octetstring does not match + if (not match(r2, templateBitstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded record does not match + if (not match(r3, templateBitstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 3); } + + // local self-referencing template + var template templateBitstr_rec t := { x1 := '1011'B, x2 := ?, x3 := ? }; + t.x1 := decmatch t; + var templateBitstr_rec r4, r5; + r4 := { x1 := good_rec_enc, x2 := '10'B, x3 := '11'B }; + r5 := { x1 := bad_rec_enc, x2 := '10'B, x3 := '11'B }; + if (match(r4, t)) { setverdict(pass); } + else { setverdict(fail, 4); } + if (not match(r5, t)) { setverdict(pass); } + else { setverdict(fail, 5); } +} + control { execute(templateBitstrSpec()); execute(templateBitstrList()); @@ -332,5 +470,7 @@ control { execute(templateBitstrAnyEl()); execute(templateBitstrAnyorNoneEl()); execute(CR_TR00018474()); + execute(templateBitstrDecmatch()); + execute(templateBitstrDecmatchSelfRef()); } } diff --git a/regression_test/templateCharstr/TtemplateCharstr.ttcn b/regression_test/templateCharstr/TtemplateCharstr.ttcn index 2b9d93c2744676256419dc3407f02e6ea21c9982..a9fa8c274cce2f3d3c63583b8038ef014766cf43 100644 --- a/regression_test/templateCharstr/TtemplateCharstr.ttcn +++ b/regression_test/templateCharstr/TtemplateCharstr.ttcn @@ -21,7 +21,39 @@ type component templateCharstr_mycomp {}; type record templateCharstr_rec { charstring x1, charstring x2, - charstring x3 optional }; + charstring x3 optional +} +with { + encode "JSON"; + variant(x1) "JSON: name as first"; + variant(x2) "JSON: name as second"; + variant(x3) "JSON: name as third"; +} + +type record decmatch_rec { + integer i, + charstring s +} +with { + encode "JSON"; +} + +type record of integer decmatch_list +with { + encode "XML"; + variant "list"; +} + +type union decmatch_uni { + integer i, + charstring s +} +with { + encode "RAW"; + variant(i) "FIELDLENGTH(16)"; +} + + template templateCharstr_rec templateCharstr_tSpec :={ //specific values x1:="00AA", x2:="01AA", @@ -102,6 +134,22 @@ template templateCharstr_rec templateCharstr_tPattern := { x1 := pattern "abc?xyz", x2 := pattern @nocase "abc?xyz", x3 := pattern @nocase "abc*xyz" }; + +template decmatch_uni decmatch_tUnion := { i := ? }; + +template decmatch_rec decmatch_tRecord := { i := (0..infinity), s := ? }; + +template templateCharstr_rec templateCharstr_tDecmatch := { // decoded content match + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } +}; + +template templateCharstr_rec templateCharstr_tDecmatchSelfRef := { // decoded content match with self-reference + x1 := "a", + x2 := decmatch templateCharstr_tDecmatchSelfRef.x1, + x3 := decmatch templateCharstr_rec: { x1 := templateCharstr_tDecmatchSelfRef.x1, x2 := ?, x3 := * } +}; testcase templateCharstrSpec() runs on templateCharstr_mycomp { var templateCharstr_rec x1,x2; //specific value @@ -711,6 +759,95 @@ testcase CR_TR00018474() runs on templateCharstr_mycomp { if (match("**?****", vtc2)) { setverdict(pass) } else { setverdict(fail) } } +testcase templateCharstrDecmatch() runs on templateCharstr_mycomp { + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var decmatch_list bad_list, good_list; + bad_list := { 4, 7, 10 }; + good_list := { 2, 15, 28 }; + var decmatch_uni bad_uni, good_uni; + bad_uni := { s := "five" }; + good_uni := { i := 5 }; + var charstring bad_rec_enc, good_rec_enc, bad_list_enc, good_list_enc, bad_uni_enc, good_uni_enc; + bad_rec_enc := oct2char(bit2oct(encvalue(bad_rec))); + good_rec_enc := oct2char(bit2oct(encvalue(good_rec))); + bad_list_enc := oct2char(bit2oct(encvalue(bad_list))); + good_list_enc := oct2char(bit2oct(encvalue(good_list))); + bad_uni_enc := oct2char(bit2oct(encvalue(bad_uni))); + good_uni_enc := oct2char(bit2oct(encvalue(good_uni))); + var templateCharstr_rec r1, r2, r3, r4, r5; + r1 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r2 := { x1 := bad_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r3 := { x1 := good_list_enc, x2 := bad_uni_enc, x3 := good_rec_enc }; + r4 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := bad_rec_enc }; + r5 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := "xyz" }; + // match: all 3 are good + if (match(r1, templateCharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded list does not match + if (not match(r2, templateCharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded union does not match + if (not match(r3, templateCharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded record does not match + if (not match(r4, templateCharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 4); } + // no match: x3 is not a valid encoded record value + if (not match(r5, templateCharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 5); } + // match r1 with the same template declared as an in-line template + if (match(r1, templateCharstr_rec: { + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } + })) { setverdict(pass); } + else { setverdict(fail, 6); } +} + +external function ef_enc_rec_x1(in templateCharstr_rec.x1 x) return octetstring +with { extension "prototype(convert) encode(JSON)" } + +testcase templateCharstrDecmatchSelfRef() runs on templateCharstr_mycomp { + // global self-referencing template + var templateCharstr_rec.x1 bad_cs, good_cs; + bad_cs := "x"; + good_cs := "a"; + var templateCharstr_rec bad_rec, good_rec; + bad_rec := { x1 := "x1", x2 := "x2", x3 := "x3" }; + good_rec := { x1 := "a", x2 := "x2", x3 := "x3" }; + var charstring bad_cs_enc, good_cs_enc, bad_rec_enc, good_rec_enc; + bad_cs_enc := oct2char(ef_enc_rec_x1(bad_cs)); + good_cs_enc := oct2char(ef_enc_rec_x1(good_cs)); + bad_rec_enc := oct2char(bit2oct(encvalue(bad_rec))); + good_rec_enc := oct2char(bit2oct(encvalue(good_rec))); + var templateCharstr_rec r1, r2, r3; + r1 := { x1 := "a", x2 := good_cs_enc, x3 := good_rec_enc }; + r2 := { x1 := "a", x2 := bad_cs_enc, x3 := good_rec_enc }; + r3 := { x1 := "a", x2 := good_cs_enc, x3 := bad_rec_enc }; + // match: all 2 are good + if (match(r1, templateCharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded octetstring does not match + if (not match(r2, templateCharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded record does not match + if (not match(r3, templateCharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 3); } + + // local self-referencing template + var template templateCharstr_rec t := { x1 := "a", x2 := ?, x3 := ? }; + t.x1 := decmatch t; + var templateCharstr_rec r4, r5; + r4 := { x1 := good_rec_enc, x2 := "x", x3 := "y" }; + r5 := { x1 := bad_rec_enc, x2 := "x", x3 := "y" }; + if (match(r4, t)) { setverdict(pass); } + else { setverdict(fail, 4); } + if (not match(r5, t)) { setverdict(pass); } + else { setverdict(fail, 5); } +} + control { execute(templateCharstrSpec()); execute(templateCharstrList()); @@ -742,5 +879,7 @@ control { execute(pattern_reference()); execute(HO30913_reference()); execute(CR_TR00018474()); + execute(templateCharstrDecmatch()); + execute(templateCharstrDecmatchSelfRef()); } } diff --git a/regression_test/templateHexstr/Makefile b/regression_test/templateHexstr/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..cdc6aae3b0b001c9fc3e1cefdd49a8f6993eb1ef --- /dev/null +++ b/regression_test/templateHexstr/Makefile @@ -0,0 +1,51 @@ +############################################################################## +# Copyright (c) 2000-2016 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: +# Baranyi, Botond – initial implementation +# +############################################################################## +TOPDIR := .. +include $(TOPDIR)/Makefile.regression + +.SUFFIXES: .ttcn .hh +.PHONY: all clean dep run + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +TTCN3_MODULES = TtemplateHexstr.ttcn + +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef CODE_SPLIT +GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) +endif + +OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +TARGET = TtemplateHexstr$(EXESUFFIX) + +all: $(TARGET) + +$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +.ttcn.cc .ttcn.hh: + $(TTCN3_COMPILER) $< + +clean distclean: + -rm -f $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) *.log Makefile.bak + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) + +run: $(TARGET) config.cfg + ./$^ + +.NOTPARALLEL: + diff --git a/regression_test/templateHexstr/TtemplateHexstr.ttcn b/regression_test/templateHexstr/TtemplateHexstr.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..fd119258558fee4e03779e4abc5349b98e856ef3 --- /dev/null +++ b/regression_test/templateHexstr/TtemplateHexstr.ttcn @@ -0,0 +1,161 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 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: + * Baranyi, Botond – initial implementation + * + ******************************************************************************/ +module TtemplateHexstr { + +type component templateHexstr_mycomp {}; + +type record templateHexstr_rec { + hexstring x1, + hexstring x2, + hexstring x3 optional +} +with { + encode "JSON"; + variant(x1) "JSON: name as first"; + variant(x2) "JSON: name as second"; + variant(x3) "JSON: name as third"; +} + +type record decmatch_rec { + integer i, + charstring s +} +with { + encode "JSON"; +} + +type record of integer decmatch_list +with { + encode "XML"; + variant "list"; +} + +type union decmatch_uni { + integer i, + charstring s +} +with { + encode "RAW"; + variant(i) "FIELDLENGTH(16)"; +} + +template decmatch_uni decmatch_tUnion := { i := ? }; + +template decmatch_rec decmatch_tRecord := { i := (0..infinity), s := ? }; + +template templateHexstr_rec templateHexstr_tDecmatch := { // decoded content match + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } +}; + +template templateHexstr_rec templateHexstr_tDecmatchSelfRef := { // decoded content match with self-reference + x1 := '01A'H, + x2 := decmatch templateHexstr_tDecmatchSelfRef.x1, + x3 := decmatch templateHexstr_rec: { x1 := templateHexstr_tDecmatchSelfRef.x1, x2 := ?, x3 := * } +}; + +testcase templateHexstrDecmatch() runs on templateHexstr_mycomp { + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var decmatch_list bad_list, good_list; + bad_list := { 4, 7, 10 }; + good_list := { 2, 15, 28 }; + var decmatch_uni bad_uni, good_uni; + bad_uni := { s := "five" }; + good_uni := { i := 5 }; + var hexstring bad_rec_enc, good_rec_enc, bad_list_enc, good_list_enc, bad_uni_enc, good_uni_enc; + bad_rec_enc := bit2hex(encvalue(bad_rec)); + good_rec_enc := bit2hex(encvalue(good_rec)); + bad_list_enc := bit2hex(encvalue(bad_list)); + good_list_enc := bit2hex(encvalue(good_list)); + bad_uni_enc := bit2hex(encvalue(bad_uni)); + good_uni_enc := bit2hex(encvalue(good_uni)); + var templateHexstr_rec r1, r2, r3, r4, r5; + r1 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r2 := { x1 := bad_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r3 := { x1 := good_list_enc, x2 := bad_uni_enc, x3 := good_rec_enc }; + r4 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := bad_rec_enc }; + r5 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := '00FF'H }; + // match: all 3 are good + if (match(r1, templateHexstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded list does not match + if (not match(r2, templateHexstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded union does not match + if (not match(r3, templateHexstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded record does not match + if (not match(r4, templateHexstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 4); } + // no match: x3 is not a valid encoded record value + if (not match(r5, templateHexstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 5); } + // match r1 with the same template declared as an in-line template + if (match(r1, templateHexstr_rec: { + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } + })) { setverdict(pass); } + else { setverdict(fail, 6); } +} + +external function ef_enc_rec_x1(in templateHexstr_rec.x1 x) return octetstring +with { extension "prototype(convert) encode(JSON)" } + +testcase templateHexstrDecmatchSelfRef() runs on templateHexstr_mycomp { + // global self-referencing template + var templateHexstr_rec.x1 bad_hs, good_hs; + bad_hs := 'FE98'H; + good_hs := '01A'H; + var templateHexstr_rec bad_rec, good_rec; + bad_rec := { x1 := 'D01'H, x2 := 'D02'H, x3 := 'D03'H }; + good_rec := { x1 := '01A'H, x2 := 'D02'H, x3 := 'D03'H }; + var hexstring bad_hs_enc, good_hs_enc, bad_rec_enc, good_rec_enc; + bad_hs_enc := oct2hex(ef_enc_rec_x1(bad_hs)); + good_hs_enc := oct2hex(ef_enc_rec_x1(good_hs)); + bad_rec_enc := bit2hex(encvalue(bad_rec)); + good_rec_enc := bit2hex(encvalue(good_rec)); + var templateHexstr_rec r1, r2, r3; + r1 := { x1 := '01A'H, x2 := good_hs_enc, x3 := good_rec_enc }; + r2 := { x1 := '01A'H, x2 := bad_hs_enc, x3 := good_rec_enc }; + r3 := { x1 := '01A'H, x2 := good_hs_enc, x3 := bad_rec_enc }; + // match: all 2 are good + if (match(r1, templateHexstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded octetstring does not match + if (not match(r2, templateHexstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded record does not match + if (not match(r3, templateHexstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 3); } + + // local self-referencing template + var template templateHexstr_rec t := { x1 := '01A'H, x2 := ?, x3 := ? }; + t.x1 := decmatch t; + var templateHexstr_rec r4, r5; + r4 := { x1 := good_rec_enc, x2 := 'A1'H, x3 := 'A2'H }; + r5 := { x1 := bad_rec_enc, x2 := 'A1'H, x3 := 'A2'H }; + if (match(r4, t)) { setverdict(pass); } + else { setverdict(fail, 4); } + if (not match(r5, t)) { setverdict(pass); } + else { setverdict(fail, 5); } +} + +control { + execute(templateHexstrDecmatch()); + execute(templateHexstrDecmatchSelfRef()); +} + +} diff --git a/regression_test/templateHexstr/config.cfg b/regression_test/templateHexstr/config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..dec9ba1a36cff0a3d3efdcd6086a486092017c98 --- /dev/null +++ b/regression_test/templateHexstr/config.cfg @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Baranyi, Botond – initial implementation +# +############################################################################### +[MODULE_PARAMETERS] +[LOGGING] +Logfile := "templateHexstr.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS +[EXECUTE] +TtemplateHexstr diff --git a/regression_test/templateOctetstr/TtemplateOctetstr.ttcn b/regression_test/templateOctetstr/TtemplateOctetstr.ttcn index 5c295f496d73fa2be79828b2e78dd4a075db2f88..154afd75d4c55b738c0f7687c2e5aede3f7c2bae 100644 --- a/regression_test/templateOctetstr/TtemplateOctetstr.ttcn +++ b/regression_test/templateOctetstr/TtemplateOctetstr.ttcn @@ -6,6 +6,7 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: + * Baranyi, Botond * Balasko, Jeno * Kovacs, Ferenc * Raduly, Csaba @@ -18,7 +19,38 @@ type component templateOctetstr_mycomp {}; type record templateOctetstr_rec { octetstring x1, octetstring x2, - octetstring x3 optional }; + octetstring x3 optional +} +with { + encode "JSON"; + variant(x1) "JSON: name as first"; + variant(x2) "JSON: name as second"; + variant(x3) "JSON: name as third"; +} + +type record decmatch_rec { + integer i, + charstring s +} +with { + encode "JSON"; +} + +type record of integer decmatch_list +with { + encode "XML"; + variant "list"; +} + +type union decmatch_uni { + integer i, + charstring s +} +with { + encode "RAW"; + variant(i) "FIELDLENGTH(16)"; +} + template templateOctetstr_rec templateOctetstr_tSpec :={ //specific values x1:='00AA'O, x2:='01AA'O, @@ -71,6 +103,23 @@ template templateOctetstr_rec templateOctetstr_tAnyorNoneEl :={ //specific value x1:='00AA'O, x2:='01AA'O, x3:='10*'O }; + +template decmatch_uni decmatch_tUnion := { i := ? }; + +template decmatch_rec decmatch_tRecord := { i := (0..infinity), s := ? }; + +template templateOctetstr_rec templateOctetstr_tDecmatch := { // decoded content match + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } +}; + +template templateOctetstr_rec templateOctetstr_tDecmatchSelfRef := { // decoded content match with self-reference + x1 := '00AA'O, + x2 := decmatch templateOctetstr_tDecmatchSelfRef.x1, + x3 := decmatch templateOctetstr_rec: { x1 := templateOctetstr_tDecmatchSelfRef.x1, x2 := ?, x3 := * } +}; + testcase templateOctetstrSpec() runs on templateOctetstr_mycomp { var templateOctetstr_rec x1,x2; //specific value @@ -315,6 +364,125 @@ testcase CR_TR00018474() runs on templateOctetstr_mycomp { if (match('BBBAABBA'O, vto1)) { setverdict(pass) } else { setverdict(fail) } } +testcase templateOctetstrDecmatch() runs on templateOctetstr_mycomp { + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var decmatch_list bad_list, good_list; + bad_list := { 4, 7, 10 }; + good_list := { 2, 15, 28 }; + var decmatch_uni bad_uni, good_uni; + bad_uni := { s := "five" }; + good_uni := { i := 5 }; + var octetstring bad_rec_enc, good_rec_enc, bad_list_enc, good_list_enc, bad_uni_enc, good_uni_enc; + bad_rec_enc := bit2oct(encvalue(bad_rec)); + good_rec_enc := bit2oct(encvalue(good_rec)); + bad_list_enc := bit2oct(encvalue(bad_list)); + good_list_enc := bit2oct(encvalue(good_list)); + bad_uni_enc := bit2oct(encvalue(bad_uni)); + good_uni_enc := bit2oct(encvalue(good_uni)); + var templateOctetstr_rec r1, r2, r3, r4, r5; + r1 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r2 := { x1 := bad_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r3 := { x1 := good_list_enc, x2 := bad_uni_enc, x3 := good_rec_enc }; + r4 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := bad_rec_enc }; + r5 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := 'FF00'O }; + // match: all 3 are good + if (match(r1, templateOctetstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded list does not match + if (not match(r2, templateOctetstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded union does not match + if (not match(r3, templateOctetstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded record does not match + if (not match(r4, templateOctetstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 4); } + // no match: x3 is not a valid encoded record value + if (not match(r5, templateOctetstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 5); } + // match r1 with the same template declared as an in-line template + if (match(r1, templateOctetstr_rec: { + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } + })) { setverdict(pass); } + else { setverdict(fail, 6); } +} + +external function ef_enc_rec_x1(in templateOctetstr_rec.x1 x) return octetstring +with { extension "prototype(convert) encode(JSON)" } + +testcase templateOctetstrDecmatchSelfRef() runs on templateOctetstr_mycomp { + // global self-referencing template + var templateOctetstr_rec.x1 bad_os, good_os; + bad_os := 'AA00'O; + good_os := '00AA'O; + var templateOctetstr_rec bad_rec, good_rec; + bad_rec := { x1 := '00'O, x2 := '01'O, x3 := '02'O }; + good_rec := { x1 := '00AA'O, x2 := '01'O, x3 := '02'O }; + var octetstring bad_os_enc, good_os_enc, bad_rec_enc, good_rec_enc; + bad_os_enc := ef_enc_rec_x1(bad_os); + good_os_enc := ef_enc_rec_x1(good_os); + bad_rec_enc := bit2oct(encvalue(bad_rec)); + good_rec_enc := bit2oct(encvalue(good_rec)); + var templateOctetstr_rec r1, r2, r3; + r1 := { x1 := '00AA'O, x2 := good_os_enc, x3 := good_rec_enc }; + r2 := { x1 := '00AA'O, x2 := bad_os_enc, x3 := good_rec_enc }; + r3 := { x1 := '00AA'O, x2 := good_os_enc, x3 := bad_rec_enc }; + // match: all 2 are good + if (match(r1, templateOctetstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded octetstring does not match + if (not match(r2, templateOctetstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded record does not match + if (not match(r3, templateOctetstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 3); } + + // local self-referencing template + var template templateOctetstr_rec t := { x1 := '00AA'O, x2 := ?, x3 := ? }; + t.x1 := decmatch t; + var templateOctetstr_rec r4, r5; + r4 := { x1 := good_rec_enc, x2 := 'AA'O, x3 := 'AB'O }; + r5 := { x1 := bad_rec_enc, x2 := 'AA'O, x3 := 'AB'O }; + if (match(r4, t)) { setverdict(pass); } + else { setverdict(fail, 4); } + if (not match(r5, t)) { setverdict(pass); } + else { setverdict(fail, 5); } +} + +function f_decmatch(in template templateOctetstr_rec par_temp := + { x1 := ?, x2 := ?, x3 := decmatch decmatch_rec: { i := (1, 2, 3), s := ? } }) +{ + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var octetstring bad_rec_enc, good_rec_enc; + bad_rec_enc := bit2oct(encvalue(bad_rec)); + good_rec_enc := bit2oct(encvalue(good_rec)); + var templateOctetstr_rec r1, r2; + r1 := { x1 := '1A'O, x2 := '1B'O, x3 := good_rec_enc }; + r2 := { x1 := '1A'O, x2 := '1B'O, x3 := bad_rec_enc }; + if (match(r1, par_temp)) { setverdict(pass); } + else { setverdict(fail, 1); } + if (not match(r2, par_temp)) { setverdict(pass); } + else { setverdict(fail, 2); } +} + +testcase templateOctetstrDecmatchExtra() runs on templateOctetstr_mycomp { + // testing decmatch template as parameter default value + f_decmatch(); + // testing logging of decmatch template + if (log2str(templateOctetstr_tDecmatch) == "{ " & + "x1 := decmatch decmatch_list: { (1 .. 10), (11 .. 20), (21 .. 30) }, " & + "x2 := decmatch decmatch_uni: { i := ? }, " & + "x3 := decmatch decmatch_rec: { i := (0 .. infinity), s := \"abc\" } }") + { setverdict(pass); } + else { setverdict(fail, templateOctetstr_tDecmatch); } +} + control { execute(templateOctetstrSpec()); execute(templateOctetstrList()); @@ -330,5 +498,8 @@ control { execute(templateOctetstrAnyEl()); execute(templateOctetstrAnyorNoneEl()); execute(CR_TR00018474()); + execute(templateOctetstrDecmatch()); + execute(templateOctetstrDecmatchSelfRef()); + execute(templateOctetstrDecmatchExtra()); } } diff --git a/regression_test/templateUnicharstr/Makefile b/regression_test/templateUnicharstr/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..9a99c779b00cefb20978bfbc8896e079f3d6c3fe --- /dev/null +++ b/regression_test/templateUnicharstr/Makefile @@ -0,0 +1,51 @@ +############################################################################## +# Copyright (c) 2000-2016 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: +# Botond, Baranyi – initial implementation +# +############################################################################## +TOPDIR := .. +include $(TOPDIR)/Makefile.regression + +.SUFFIXES: .ttcn .hh +.PHONY: all clean dep run + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +TTCN3_MODULES = TtemplateUnicharstr.ttcn + +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef CODE_SPLIT +GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) +endif + +OBJECTS = $(GENERATED_SOURCES:.cc=.o) + +TARGET = TtemplateUnicharstr$(EXESUFFIX) + +all: $(TARGET) + +$(TARGET): $(GENERATED_SOURCES) $(USER_SOURCES) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +.ttcn.cc .ttcn.hh: + $(TTCN3_COMPILER) $< + +clean distclean: + -rm -f $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) *.log Makefile.bak + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(GENERATED_SOURCES) + +run: $(TARGET) config.cfg + ./$^ + +.NOTPARALLEL: + diff --git a/regression_test/templateUnicharstr/TtemplateUnicharstr.ttcn b/regression_test/templateUnicharstr/TtemplateUnicharstr.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..258ee8eaa41c5a0d458700b80ba84c92cea47c4f --- /dev/null +++ b/regression_test/templateUnicharstr/TtemplateUnicharstr.ttcn @@ -0,0 +1,254 @@ +/****************************************************************************** + * Copyright (c) 2000-2016 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: + * Baranyi, Botond – initial implementation + * + ******************************************************************************/ +module TtemplateUnicharstr { + +type component templateUnicharstr_mycomp {}; +type record templateUnicharstr_rec { + universal charstring x1, + universal charstring x2, + universal charstring x3 optional +} +with { + encode "JSON"; + variant(x1) "JSON: name as first"; + variant(x2) "JSON: name as second"; + variant(x3) "JSON: name as third"; +} + +type record decmatch_rec { + integer i, + charstring s +} +with { + encode "JSON"; +} + +type record of integer decmatch_list +with { + encode "XML"; + variant "list"; +} + +type union decmatch_uni { + integer i, + charstring s +} +with { + encode "RAW"; + variant(i) "FIELDLENGTH(16)"; +} + +type octetstring OS +with { + encode "RAW"; +} + + +template decmatch_uni decmatch_tUnion := { i := ? }; + +template decmatch_rec decmatch_tRecord := { i := (0..infinity), s := ? }; + +template templateUnicharstr_rec templateUnicharstr_tDecmatch := { // decoded content match + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, // no format parameter = UTF-8 + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } +}; + +template templateUnicharstr_rec templateUnicharstr_tDecmatchSelfRef := { // decoded content match with self-reference + x1 := "a", + x2 := decmatch("UTF-8") templateUnicharstr_tDecmatchSelfRef.x1, + x3 := decmatch("UTF-8") templateUnicharstr_rec: { x1 := templateUnicharstr_tDecmatchSelfRef.x1, x2 := ?, x3 := * } +}; + +template templateUnicharstr_rec templateUnicharstr_tDecmatch16 := { // decoded content match in UTF-16 format + x1 := decmatch("UTF-16") OS: 'FEFF'O, // just the BOM + x2 := decmatch("UTF-16LE") OS: ? length (4..6), // BOM + 1-2 characters below FFFF or 1 character above FFFF + x3 := decmatch("UTF-16BE") OS: ? length (8..infinity) // BOM + 3 or more characters (2 or more if one of them is above FFFF) +}; + +template templateUnicharstr_rec templateUnicharstr_tDecmatch32 := { // decoded content match in UTF-32 format + x1 := decmatch("UTF-32") OS: '0000FEFF'O, // just the BOM + x2 := decmatch("UTF-32LE") OS: ? length (4..8), // BOM + 1 optional character + x3 := decmatch("UTF-32BE") OS: ? length (16..infinity) // BOM + 3 or more characters +}; + +template charstring templateUnicharstr_tCharDecmatch := decmatch decmatch_rec: { i := 1, s := ? }; + + +testcase templateUnicharstrDecmatch() runs on templateUnicharstr_mycomp { + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 11, s := "xyz" }; + good_rec := { i := 3, s := "abc" }; + var decmatch_list bad_list, good_list; + bad_list := { 4, 7, 10 }; + good_list := { 2, 15, 28 }; + var decmatch_uni bad_uni, good_uni; + bad_uni := { s := "five" }; + good_uni := { i := 5 }; + var universal charstring bad_rec_enc, good_rec_enc, bad_list_enc, good_list_enc, bad_uni_enc, good_uni_enc; + bad_rec_enc := oct2unichar(bit2oct(encvalue(bad_rec)), "UTF-8"); + good_rec_enc := oct2unichar(bit2oct(encvalue(good_rec)), "UTF-8"); + bad_list_enc := oct2unichar(bit2oct(encvalue(bad_list)), "UTF-8"); + good_list_enc := oct2unichar(bit2oct(encvalue(good_list)), "UTF-8"); + bad_uni_enc := oct2unichar(bit2oct(encvalue(bad_uni)), "UTF-8"); + good_uni_enc := oct2unichar(bit2oct(encvalue(good_uni)), "UTF-8"); + var templateUnicharstr_rec r1, r2, r3, r4, r5; + r1 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r2 := { x1 := bad_list_enc, x2 := good_uni_enc, x3 := good_rec_enc }; + r3 := { x1 := good_list_enc, x2 := bad_uni_enc, x3 := good_rec_enc }; + r4 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := bad_rec_enc }; + r5 := { x1 := good_list_enc, x2 := good_uni_enc, x3 := "xyz" }; + // match: all 3 are good + if (match(r1, templateUnicharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded list does not match + if (not match(r2, templateUnicharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded union does not match + if (not match(r3, templateUnicharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded record does not match + if (not match(r4, templateUnicharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 4); } + // no match: x3 is not a valid encoded record value + if (not match(r5, templateUnicharstr_tDecmatch)) { setverdict(pass); } + else { setverdict(fail, 5); } + // match r1 with the same template declared as an in-line template + if (match(r1, templateUnicharstr_rec: { + x1 := decmatch decmatch_list: { (1..10), (11..20), (21..30) }, + x2 := decmatch decmatch_tUnion, + x3 := decmatch modifies decmatch_tRecord := { s := "abc" } + })) { setverdict(pass); } + else { setverdict(fail, 6); } +} + +external function ef_enc_rec_x1(in templateUnicharstr_rec.x1 x) return octetstring +with { extension "prototype(convert) encode(JSON)" } + +testcase templateUnicharstrDecmatchSelfRef() runs on templateUnicharstr_mycomp { + // global self-referencing template + var templateUnicharstr_rec.x1 bad_ucs, good_ucs; + bad_ucs := char(0, 0, 1, 113); + good_ucs := "a"; + var templateUnicharstr_rec bad_rec, good_rec; + bad_rec := { x1 := char(0, 0, 0, 255), x2 := char(0, 0, 1, 0), x3 := char(0, 0, 1, 1) }; + good_rec := { x1 := "a", x2 := char(0, 0, 1, 0), x3 := char(0, 0, 1, 1) }; + var universal charstring bad_ucs_enc, good_ucs_enc, bad_rec_enc, good_rec_enc; + bad_ucs_enc := oct2unichar(ef_enc_rec_x1(bad_ucs), "UTF-8"); + good_ucs_enc := oct2unichar(ef_enc_rec_x1(good_ucs), "UTF-8"); + bad_rec_enc := oct2unichar(bit2oct(encvalue(bad_rec)), "UTF-8"); + good_rec_enc := oct2unichar(bit2oct(encvalue(good_rec)), "UTF-8"); + var templateUnicharstr_rec r1, r2, r3; + r1 := { x1 := "a", x2 := good_ucs_enc, x3 := good_rec_enc }; + r2 := { x1 := "a", x2 := bad_ucs_enc, x3 := good_rec_enc }; + r3 := { x1 := "a", x2 := good_ucs_enc, x3 := bad_rec_enc }; + // match: all 2 are good + if (match(r1, templateUnicharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded octetstring does not match + if (not match(r2, templateUnicharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded record does not match + if (not match(r3, templateUnicharstr_tDecmatchSelfRef)) { setverdict(pass); } + else { setverdict(fail, 3); } + + // local self-referencing template + var template templateUnicharstr_rec t := { x1 := "a", x2 := ?, x3 := ? }; + t.x1 := decmatch t; + var templateUnicharstr_rec r4, r5; + r4 := { x1 := good_rec_enc, x2 := "x", x3 := "y" }; + r5 := { x1 := bad_rec_enc, x2 := "x", x3 := "y" }; + if (match(r4, t)) { setverdict(pass); } + else { setverdict(fail, 4); } + if (not match(r5, t)) { setverdict(pass); } + else { setverdict(fail, 5); } +} + +testcase templateUnicharstrDecmatch16() runs on templateUnicharstr_mycomp { + var universal charstring bad16, good16, bad16le, good16le, bad16be, good16be; + bad16 := "abc"; + good16 := ""; + bad16le := char(0, 1, 2, 3) & char(0, 4, 5, 6); + good16le := char(0, 1, 2, 3); + bad16be := char(0, 1, 10, 100); + good16be := "ab" & char(0, 1, 10, 100) & "xy"; + var templateUnicharstr_rec r1, r2, r3, r4; + r1 := { x1 := good16, x2 := good16le, x3 := good16be }; + r2 := { x1 := bad16, x2 := good16le, x3 := good16be }; + r3 := { x1 := good16, x2 := bad16le, x3 := good16be }; + r4 := { x1 := good16, x2 := good16le, x3 := bad16be }; + // match: all 3 are good + if (match(r1, templateUnicharstr_tDecmatch16)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded string in UTF-16 format is not empty + if (not match(r2, templateUnicharstr_tDecmatch16)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded string in UTF-16LE format is too long + if (not match(r3, templateUnicharstr_tDecmatch16)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded string in UTF-16BE format is too short + if (not match(r4, templateUnicharstr_tDecmatch16)) { setverdict(pass); } + else { setverdict(fail, 4); } +} + +testcase templateUnicharstrDecmatch32() runs on templateUnicharstr_mycomp { + var universal charstring bad32, good32, bad32le, good32le, bad32be, good32be; + bad32 := "abc"; + good32 := ""; + bad32le := char(0, 1, 2, 3) & char(0, 4, 5, 6); + good32le := char(0, 1, 2, 3); + bad32be := char(0, 1, 10, 100); + good32be := "ab" & char(0, 1, 10, 100) & "xy"; + var templateUnicharstr_rec r1, r2, r3, r4; + r1 := { x1 := good32, x2 := good32le, x3 := good32be }; + r2 := { x1 := bad32, x2 := good32le, x3 := good32be }; + r3 := { x1 := good32, x2 := bad32le, x3 := good32be }; + r4 := { x1 := good32, x2 := good32le, x3 := bad32be }; + // match: all 3 are good + if (match(r1, templateUnicharstr_tDecmatch32)) { setverdict(pass); } + else { setverdict(fail, 1); } + // no match: decoded string in UTF-32 format is not empty + if (not match(r2, templateUnicharstr_tDecmatch32)) { setverdict(pass); } + else { setverdict(fail, 2); } + // no match: decoded string in UTF-32LE format is too long + if (not match(r3, templateUnicharstr_tDecmatch32)) { setverdict(pass); } + else { setverdict(fail, 3); } + // no match: decoded string in UTF-32BE format is too short + if (not match(r4, templateUnicharstr_tDecmatch32)) { setverdict(pass); } + else { setverdict(fail, 4); } +} + +testcase templateUnicharstrDecmatchCopyCharstr() runs on templateUnicharstr_mycomp { + // testing a universal charstring template copied from a + // charstring template (with decoded content matching) + var template universal charstring t := templateUnicharstr_tCharDecmatch; + var decmatch_rec bad_rec, good_rec; + bad_rec := { i := 6, s := "xyz" }; + good_rec := { i := 1, s := "abc" }; + var universal charstring bad_rec_enc, good_rec_enc; + bad_rec_enc := oct2unichar(bit2oct(encvalue(bad_rec)), "UTF-8"); + good_rec_enc := oct2unichar(bit2oct(encvalue(good_rec)), "UTF-8"); + if (match(good_rec_enc, t)) { setverdict(pass); } + else { setverdict(fail, 1); } + if (not match(bad_rec_enc, t)) { setverdict(pass); } + else { setverdict(fail, 2); } +} + +control { + execute(templateUnicharstrDecmatch()); + execute(templateUnicharstrDecmatchSelfRef()); + execute(templateUnicharstrDecmatch16()); + execute(templateUnicharstrDecmatch32()); + execute(templateUnicharstrDecmatchCopyCharstr()); +} + +} diff --git a/regression_test/templateUnicharstr/config.cfg b/regression_test/templateUnicharstr/config.cfg new file mode 100644 index 0000000000000000000000000000000000000000..7e6b68cdc4ad4c7ac516542046ec8c2782812747 --- /dev/null +++ b/regression_test/templateUnicharstr/config.cfg @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2000-2016 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: +# Baranyi, Botond – initial implementation +# +############################################################################### +[MODULE_PARAMETERS] +[LOGGING] +Logfile := "templateUnicharstr.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_WARNING | TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS +[EXECUTE] +TtemplateUnicharstr diff --git a/xsdconvert/GeneralFunctions.cc b/xsdconvert/GeneralFunctions.cc index 33f646f0d7b3c1d1cc4da1b1fd00d642bac89186..24e55a4f26638c587cc4bcd352d7a07be5e6ba3c 100644 --- a/xsdconvert/GeneralFunctions.cc +++ b/xsdconvert/GeneralFunctions.cc @@ -56,7 +56,7 @@ void XSDName2TTCN3Name(const Mstring& in, QualifiedNames & used_names, modeType "bitstring", "boolean", "break", "call", "case", "catch", "char", "charstring", "check", "clear", "complement", "component", "connect", "const", "continue", "control", "create", - "deactivate", "default", "derefers", "disconnect", "display", "do", "done", + "decmatch", "deactivate", "default", "derefers", "disconnect", "display", "do", "done", "else", "encode", "enumerated", "error", "except", "exception", "execute", "extends", "extension", "external", "fail", "false", "float", "for", "friend", "from", "function",