{"char2int__", "char2int", "char2int_"},
{"char2oct__", "char2oct", "char2oct_"},
{"component__", "component", "component_"},
+ {"decmatch__", "decmatch", "decmatch_"},
{"decomp__", "decomp", "decomp_"},
{"float2int__", "float2int", "float2int_"},
{"float2str__", "float2str", "float2str_"},
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.
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:
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()) {
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;
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)
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;
break;
case Template::ALL_FROM:
case Template::VALUE_LIST_ALL_FROM:
+ case Template::DECODE_MATCH:
break;
case Template::SUPERSET_MATCH:
case Template::SUBSET_MATCH:
} // next
break; }
+ case Template::DECODE_MATCH:
+ chk_defpar_template(body->get_decode_target()->get_Template(), exp_val);
+ break;
} // switch templatetype
}
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()");
}
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()");
}
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;
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()
{
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()");
}
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()");
}
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;
}
return "character string pattern";
case USTR_PATTERN:
return "universal string pattern";
+ case DECODE_MATCH:
+ return "decoded content match";
default:
return "unknown template";
}
}
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)
{
case USTR_PATTERN:
t->u.pstring->chk_recursions(refch);
break;
+ case DECODE_MATCH:
+ t->u.dec_match.target->chk_recursions(refch);
+ break;
default:
break;
}
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
}
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:
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 (-) */
}
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)
{
case VALUE_RANGE:
case SUPERSET_MATCH:
case SUBSET_MATCH:
+ case DECODE_MATCH:
return true;
case TEMPLATE_ERROR:
FATAL_ERROR("Template::needs_temp_ref()");
case SUPERSET_MATCH:
case SUBSET_MATCH:
case PERMUTATION_MATCH:
+ case DECODE_MATCH:
return false;
case ALL_FROM:
case VALUE_LIST_ALL_FROM:
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;
}
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. */
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 */
/** Constructor for CSTR_PATTERN. */
Template(PatternString *p_ps);
+
+ /** Constructor for DECODE_MATCH */
+ Template(Value* v, TemplateInstance* ti);
virtual ~Template();
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,
* 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);
continue RETURN(ContinueKeyword);
control RETURN(ControlKeyword);
create RETURN_DOT(CreateKeyword);
+decmatch RETURN(DecodedMatchKeyword);
deactivate RETURN(DeactivateKeyword);
default RETURN(DefaultKeyword);
derefers RETURN(DerefersKeyword);
struct {
visibility_t visibility;
} visbilitytype;
+
+ struct {
+ Value* string_encoding;
+ TemplateInstance* target_template;
+ } decode_match;
}
/* Tokens of TTCN-3 */
%token ContinueKeyword
%token ControlKeyword
%token CreateKeyword
+%token DecodedMatchKeyword
%token DeactivateKeyword
%token DefaultKeyword
%token DerefersKeyword
%type <float_val> FloatOrSpecialFloatValue
%type <erroneous_indicator> ErroneousIndicator
%type <imptype> ImportSpec ImportElement
+%type <decode_match> DecodedContentMatch
/*********************************************************************
* Destructors
}
optRunsOnComprefOrSelf
+%destructor {
+ if ($$.string_encoding != NULL) {
+ delete $$.string_encoding;
+ }
+ delete $$.target_template;
+}
+DecodedContentMatch
+
/*********************************************************************
* Operator precedences (lowest first)
*********************************************************************/
%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.
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
- 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
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.
*/
$$->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
PermutationKeyword ValueList { $$ = $2; }
;
+DecodedContentMatch:
+ DecodedMatchKeyword '(' SingleExpression ')' InLineTemplate
+ {
+ $$.string_encoding = $3;
+ $$.target_template = $5;
+ }
+| DecodedMatchKeyword InLineTemplate
+ {
+ $$.string_encoding = NULL;
+ $$.target_template = $2;
+ }
+;
+
AnyValue: // 140
'?'
;
}
};
+/** 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
#include "Error.hh"
#include "Logger.hh"
#include "Encdec.hh"
+#include "Addfunc.hh"
#include "../common/dbgnew.hh"
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;
}
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.");
}
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.");
}
}
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)
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
}
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;
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;
}
};
/// bitstring template class
+struct decmatch_struct;
+
class BITSTRING_template : public Restricted_Length_Template {
#ifdef __SUNPRO_CC
public:
BITSTRING_template *list_value;
} value_list;
bitstring_pattern_struct *pattern_value;
+ decmatch_struct* dec_match;
};
void copy_template(const BITSTRING_template& other_value);
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;
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;
}
"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.");
}
}
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.");
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.");
}
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 \"");
} 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();
}
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;
}
// charstring template class
+struct unichar_decmatch_struct;
+
class CHARSTRING_template : public Restricted_Length_Template {
friend class UNIVERSAL_CHARSTRING_template;
boolean regexp_init;
regex_t posix_regexp;
} pattern_value;
+ unichar_decmatch_struct* dec_match;
};
void copy_template(const CHARSTRING_template& other_value);
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;
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;
}
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.");
}
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.");
}
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)
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) {
}
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;
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;
}
};
// hexstring template class
+struct decmatch_struct;
class HEXSTRING_template : public Restricted_Length_Template {
#ifdef __SUNPRO_CC
HEXSTRING_template *list_value;
} value_list;
hexstring_pattern_struct *pattern_value;
+ decmatch_struct* dec_match;
};
void copy_template(const HEXSTRING_template& other_value);
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;
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;
}
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.");
}
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.");
}
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)
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) {
}
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;
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;
}
// octetstring template class
+struct decmatch_struct;
+
class OCTETSTRING_template : public Restricted_Length_Template {
#ifdef __SUNPRO_CC
public:
OCTETSTRING_template *list_value;
} value_list;
octetstring_pattern_struct *pattern_value;
+ decmatch_struct* dec_match;
};
void copy_template(const OCTETSTRING_template& other_value);
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;
#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;
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
case STRING_PATTERN:
case SUPERSET_MATCH:
case SUBSET_MATCH:
+ case DECODE_MATCH:
break;
}
TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
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);
}
case VALUE_LIST:
case VALUE_RANGE:
case STRING_PATTERN:
+ case DECODE_MATCH:
break;
}
TTCN_error("Performing n_elem() operation on an uninitialized/unsupported "
VALUE_RANGE = 6,
STRING_PATTERN = 7,
SUPERSET_MATCH = 8,
- SUBSET_MATCH = 9
+ SUBSET_MATCH = 9,
+ DECODE_MATCH = 10
};
enum template_res {
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;
}
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.");
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.");
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.");
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.");
}
"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) {
} 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;
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;
}
const UNIVERSAL_CHARSTRING_ELEMENT& other_value);
+struct unichar_decmatch_struct;
+
class UNIVERSAL_CHARSTRING_template : public Restricted_Length_Template {
private:
UNIVERSAL_CHARSTRING single_value;
boolean regexp_init;
regex_t posix_regexp;
} pattern_value;
+ unichar_decmatch_struct* dec_match;
};
void copy_template(const CHARSTRING_template& other_value);
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;
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 \
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
+ * Baranyi, Botond
* Balasko, Jeno
* Kovacs, Ferenc
* Raduly, Csaba
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,
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
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());
execute(templateBitstrAnyEl());
execute(templateBitstrAnyorNoneEl());
execute(CR_TR00018474());
+ execute(templateBitstrDecmatch());
+ execute(templateBitstrDecmatchSelfRef());
}
}
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",
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
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());
execute(pattern_reference());
execute(HO30913_reference());
execute(CR_TR00018474());
+ execute(templateCharstrDecmatch());
+ execute(templateCharstrDecmatchSelfRef());
}
}
--- /dev/null
+##############################################################################
+# 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:
+
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+###############################################################################
+# 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
+ * Baranyi, Botond
* Balasko, Jeno
* Kovacs, Ferenc
* Raduly, Csaba
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,
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
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());
execute(templateOctetstrAnyEl());
execute(templateOctetstrAnyorNoneEl());
execute(CR_TR00018474());
+ execute(templateOctetstrDecmatch());
+ execute(templateOctetstrDecmatchSelfRef());
+ execute(templateOctetstrDecmatchExtra());
}
}
--- /dev/null
+##############################################################################
+# 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:
+
--- /dev/null
+/******************************************************************************
+ * 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());
+}
+
+}
--- /dev/null
+###############################################################################
+# 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
"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",