implemented decmatch (artf724241)
authorBotond Baranyi <botond.baranyi@ericsson.com>
Mon, 18 Jul 2016 10:12:02 +0000 (12:12 +0200)
committerBotond Baranyi <botond.baranyi@ericsson.com>
Tue, 19 Jul 2016 07:48:58 +0000 (09:48 +0200)
Change-Id: I12c5ff280fa50a82db3ce4096f796146fe94dd38
Signed-off-by: Botond Baranyi <botond.baranyi@ericsson.com>
35 files changed:
compiler2/Identifier.cc
compiler2/Type.hh
compiler2/Type_chk.cc
compiler2/Value.cc
compiler2/subtype.cc
compiler2/ttcn3/AST_ttcn3.cc
compiler2/ttcn3/TtcnTemplate.cc
compiler2/ttcn3/TtcnTemplate.hh
compiler2/ttcn3/compiler.l
compiler2/ttcn3/compiler.y
core/Basetype.hh
core/Bitstring.cc
core/Bitstring.hh
core/Charstring.cc
core/Charstring.hh
core/Hexstring.cc
core/Hexstring.hh
core/Octetstring.cc
core/Octetstring.hh
core/String_struct.hh
core/Template.cc
core/Template.hh
core/Universal_charstring.cc
core/Universal_charstring.hh
regression_test/Makefile
regression_test/templateBitstr/TtemplateBitstr.ttcn
regression_test/templateCharstr/TtemplateCharstr.ttcn
regression_test/templateHexstr/Makefile [new file with mode: 0644]
regression_test/templateHexstr/TtemplateHexstr.ttcn [new file with mode: 0644]
regression_test/templateHexstr/config.cfg [new file with mode: 0644]
regression_test/templateOctetstr/TtemplateOctetstr.ttcn
regression_test/templateUnicharstr/Makefile [new file with mode: 0644]
regression_test/templateUnicharstr/TtemplateUnicharstr.ttcn [new file with mode: 0644]
regression_test/templateUnicharstr/config.cfg [new file with mode: 0644]
xsdconvert/GeneralFunctions.cc

index 3b08ca1d71d8ec278bca01d9634ef1807aa6f45b..c4e19a4fb1e809a1271388c9c4dfe1c4be62de38 100644 (file)
@@ -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_"},
index 96ea75acc58051a2be3860d5c9b53880ef9fe5ea..4ea6af34d71f2d0b5cc0402b41e3ad6feb855c1e 100644 (file)
@@ -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.
index 54ef103b6b00e7809888e5c45c4d81f1c94487fb..2049c9bc74aea5414e9589e007ae34316901d03e 100644 (file)
@@ -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)
index e6cf738b27d5264e879c4869842a69aa9c9f5f7b..9789faa6c7a8c9628baf47a0d15d731bd97b8128 100644 (file)
@@ -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;
index 814f8e769cf534596a2c34ba74fc08f153f8d9af..0099ec9ae1f6f0920ba810dde37fb8d8a0036ba9 100644 (file)
@@ -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:
index 6859e36cc11c7b90c97f61bc1d2e7e2f15091a43..870d68c4afdad3b265007b2c5c90e1990a9297aa 100644 (file)
@@ -8119,6 +8119,9 @@ namespace Ttcn {
       } // next
 
       break; }
+    case Template::DECODE_MATCH:
+      chk_defpar_template(body->get_decode_target()->get_Template(), exp_val);
+      break;
     } // switch templatetype
 
   }
index caeec80b215fc782d03d627dbb8578766f55e81c..d0a29a51dac3ec744f45dc148380b38a9d7331b6 100644 (file)
@@ -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;
     }
index a2bc69bc7dfd9765e6b405835b4076eb84fd8b14..69b24efde9436b9106b69e7318c654c65ab0c22a 100644 (file)
@@ -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);
index 7442e68b77273593e81f126c1e1b6b23dd90f3c4..8ef00263a7a2c959aaa8aca27eab21acca01ba5f 100644 (file)
@@ -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);
index baf1a8e339337b6360f8ea0efd77427fc3f37066..c34e8f520732fb67ce25b7bb7800bb224bf6e7ba 100644 (file)
@@ -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
   '?'
 ;
index f18f4434c02a5a038b7243c7e02a773dbf17efca..a0e7eb3bb0cb28f982c38839553b7f20192f12d6 100644 (file)
@@ -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
index a093000a510143f0e0b75356a7998905c29dae84..56d4905c86c6e81c30c19bbb376c74c0f165251a 100644 (file)
@@ -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;
   }
index 354e5bea78b1835d7188375e6e7c5178734956df..877a564957b20719b4feb2e950e0544dc61abd2b 100644 (file)
@@ -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;
index ef42df83d649242795625b26d7bdc7b7aa8bf488..c3123705a75748a8132921f376d0e91fb842ad6e 100644 (file)
@@ -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;
   }
index 0387429e5d92dccae7b7550af572aa4508c95b8d..8b41a970205d3bd842bdc136d67961555da3c497 100644 (file)
@@ -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;
index 11c15b945e824fdc6162827a21c2e6913d3b09a6..968a6e140543197d7460d5e778700f0f6a14e27d 100644 (file)
@@ -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;
   }
index cb68ad9d38bac85808b223730e6cca75b9c41ce6..0792afa425511374361fd88e0d55ac688d39561f 100644 (file)
@@ -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;
 
index 1af0c58a2bfe2c9a672559a059e1b0de3197516d..7d9dd6eac32787413eaef0a2797122cdfb51d8da 100644 (file)
@@ -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;
   }
index 055314ef82082fc57d9dff309ad39ef3c79262fc..7e33563ff4a260fb82d01485f7777896fb8bdee1 100644 (file)
@@ -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;
index 5db39f66fafed7dcbbe5be78dc9b5fe14674e488..957d0eff48b059700a51a7b38c8a6d02c492fe62 100644 (file)
@@ -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
index 39cb4b0f78e39796e5477382dd43d862db502a69..5ec57a5ace343306d339d99e72683c28ea276995 100644 (file)
@@ -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 "
index bd874424d730770a120fed18c2f24a1003c1dd23..014d98ab991244505140becb2a6891ab5985a707 100644 (file)
@@ -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 {
index ebc97ec6b92e82929cb9b008a546648a122ce9c6..079a1335e1bb3c2351fec21f493614c0e9f157bd 100644 (file)
@@ -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;
   }
index 7ffec3b2dd02b4e954166de5bc48a6e4bb76f071..e76cb63aa897d279479bef59155c26f011babd1e 100644 (file)
@@ -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;
index e359cf66841accd94e209c026636c796aa67525c..961fff4deef269a46bd9027b9ac436a7d975f97d 100644 (file)
@@ -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 \
index c6ef0b040e851838683d2a0723d1f065c2cf6bb2..f9db2ef6f4c6586b4b5ec10b73154a3dd47218fa 100644 (file)
@@ -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());
 }
 }
index 2b9d93c2744676256419dc3407f02e6ea21c9982..a9fa8c274cce2f3d3c63583b8038ef014766cf43 100644 (file)
@@ -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 (file)
index 0000000..cdc6aae
--- /dev/null
@@ -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 (file)
index 0000000..fd11925
--- /dev/null
@@ -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 (file)
index 0000000..dec9ba1
--- /dev/null
@@ -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
index 5c295f496d73fa2be79828b2e78dd4a075db2f88..154afd75d4c55b738c0f7687c2e5aede3f7c2bae 100644 (file)
@@ -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 (file)
index 0000000..9a99c77
--- /dev/null
@@ -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 (file)
index 0000000..258ee8e
--- /dev/null
@@ -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 (file)
index 0000000..7e6b68c
--- /dev/null
@@ -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
index 33f646f0d7b3c1d1cc4da1b1fd00d642bac89186..24e55a4f26638c587cc4bcd352d7a07be5e6ba3c 100644 (file)
@@ -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",
This page took 0.067838 seconds and 5 git commands to generate.