added encvalue_unichar and decvalue_unichar built in functions (artf725502)
authorebensza <bence.janos.szabo@ericsson.com>
Thu, 21 Apr 2016 12:45:23 +0000 (14:45 +0200)
committerebensza <bence.janos.szabo@ericsson.com>
Thu, 21 Apr 2016 12:45:23 +0000 (14:45 +0200)
Signed-off-by: ebensza <bence.janos.szabo@ericsson.com>
compiler2/Value.cc
compiler2/Value.hh
compiler2/ttcn3/compiler.l
compiler2/ttcn3/compiler.y
regression_test/ucharstrOper/EncDecvalueUnichar.ttcn [new file with mode: 0644]
regression_test/ucharstrOper/Makefile
regression_test/ucharstrOper/config.cfg

index 72e85de10f560f2b28e84280fbec62780cc6c91a..3fb3b9838b5c96d734a0a4ae725ce20e58f5e4b4 100644 (file)
@@ -21,6 +21,7 @@
  *   Ormandi, Matyas
  *   Raduly, Csaba
  *   Szabados, Kristof
+ *   Szabo, Bence Janos
  *   Szabo, Janos Zoltan – initial implementation
  *   Szalai, Gabor
  *   Tatarka, Gabor
@@ -278,6 +279,15 @@ namespace Common {
       case OPTYPE_TTCN2STRING:
         u.expr.ti1=p.u.expr.ti1->clone();
         break;
+      case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+        u.expr.ti1=p.u.expr.ti1->clone();
+        u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0;
+        break; 
+      case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+        u.expr.r1 = p.u.expr.r1->clone();
+        u.expr.r2 = p.u.expr.r2->clone();
+        u.expr.v3=p.u.expr.v3?p.u.expr.v3->clone():0;
+        break;
       case OPTYPE_UNDEF_RUNNING:
       case OPTYPE_TMR_READ:
       case OPTYPE_TMR_RUNNING:
@@ -581,6 +591,15 @@ namespace Common {
     case OPTYPE_TTCN2STRING:
       delete u.expr.ti1;
       break;
+    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+      delete u.expr.ti1;
+      delete u.expr.v2;
+      break;
+    case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+      delete u.expr.r1;
+      delete u.expr.r2;
+      delete u.expr.v3;
+      break;
     case OPTYPE_UNDEF_RUNNING:
     case OPTYPE_TMR_READ:
     case OPTYPE_TMR_RUNNING:
@@ -909,6 +928,7 @@ namespace Common {
     case OPTYPE_ISVALUE:
     case OPTYPE_ISBOUND:
     case OPTYPE_ENCODE:
+    case OPTYPE_ENCVALUE_UNICHAR:
     case OPTYPE_ISPRESENT:
     case OPTYPE_TTCN2STRING:
       if(!p_ti1) FATAL_ERROR("Value::Value()");
@@ -1094,12 +1114,29 @@ namespace Common {
       u.expr.v1=p_v1;
       u.expr.v2=p_v2;
       u.expr.v3=p_v3;
-      break;
+      break;   
     default:
       FATAL_ERROR("Value::Value()");
     } // switch
   }
 
+  // ti1 [v2]
+  Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1,  Value *p_v2)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+  {
+    u.expr.v_optype = p_optype;
+    u.expr.state = EXPR_NOT_CHECKED;
+    switch(p_optype) {
+    case OPTYPE_ENCVALUE_UNICHAR:
+      if(!p_ti1 || !p_v2) FATAL_ERROR("Value::Value()");
+      u.expr.ti1=p_ti1;
+      u.expr.v2=p_v2;
+      break;
+    default:
+      FATAL_ERROR("Value::Value()");
+    } // switch
+  }
+  
   // ti1 v2 v3
   Value::Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2, Value *p_v3)
     : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
@@ -1275,6 +1312,7 @@ namespace Common {
     u.expr.state = EXPR_NOT_CHECKED;
     switch(p_optype) {
     case OPTYPE_DECODE:
+    case OPTYPE_DECVALUE_UNICHAR:
       if(!p_r1 || !p_r2) FATAL_ERROR("Value::Value()");
       u.expr.r1=p_r1;
       u.expr.r2=p_r2;
@@ -1283,6 +1321,25 @@ namespace Common {
       FATAL_ERROR("Value::Value()");
     } // switch
   }
+  
+  // r1 r2 [v3]
+  Value::Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2,
+          Value *p_v3)
+    : GovernedSimple(S_V), valuetype(V_EXPR), my_governor(0)
+  {
+    u.expr.v_optype = p_optype;
+    u.expr.state = EXPR_NOT_CHECKED;
+    switch(p_optype) {
+    case OPTYPE_DECVALUE_UNICHAR:
+      if(!p_r1 || !p_r2 || !p_v3) FATAL_ERROR("Value::Value()");
+      u.expr.r1=p_r1;
+      u.expr.r2=p_r2;
+      u.expr.v3=p_v3;
+      break;
+    default:
+      FATAL_ERROR("Value::Value()");
+    } // switch
+  }
 
   Value::~Value()
   {
@@ -1528,6 +1585,14 @@ namespace Common {
     case OPTYPE_TTCN2STRING:
       u.expr.ti1->set_fullname(p_fullname+".<operand>");
       break;
+    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+      u.expr.ti1->set_fullname(p_fullname+".<operand1>");
+      if (u.expr.v2) u.expr.v2->set_fullname(p_fullname+".<operand2>");
+      break;
+    case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+      u.expr.r1->set_fullname(p_fullname+".<operand1>");
+      u.expr.r2->set_fullname(p_fullname+".<operand2>");
+      if (u.expr.v3) u.expr.v3->set_fullname(p_fullname+".<operand3>");
     case OPTYPE_UNDEF_RUNNING: // r1
     case OPTYPE_TMR_READ:
     case OPTYPE_TMR_RUNNING:
@@ -1708,6 +1773,15 @@ namespace Common {
     case OPTYPE_TTCN2STRING:
       u.expr.ti1->set_my_scope(p_scope);
       break;
+    case OPTYPE_ENCVALUE_UNICHAR: //ti1 [v2]
+      u.expr.ti1->set_my_scope(p_scope);
+      if(u.expr.v2) u.expr.v2->set_my_scope(p_scope);
+      break;
+    case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+      u.expr.r1->set_my_scope(p_scope);
+      u.expr.r2->set_my_scope(p_scope);
+      if(u.expr.v3) u.expr.v3->set_my_scope(p_scope);
+      break;
     case OPTYPE_UNDEF_RUNNING: // r1
     case OPTYPE_TMR_READ:
     case OPTYPE_TMR_RUNNING:
@@ -2018,6 +2092,15 @@ namespace Common {
       case OPTYPE_TTCN2STRING:
         u.expr.ti1->set_code_section(p_code_section);
         break;
+      case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+        u.expr.ti1->set_code_section(p_code_section);
+        if (u.expr.v2) u.expr.v2->set_code_section(p_code_section);
+        break;
+      case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+        u.expr.r1->set_code_section(p_code_section);
+        u.expr.r2->set_code_section(p_code_section);
+        if (u.expr.v3) u.expr.v3->set_code_section(p_code_section);
+        break;
       case OPTYPE_UNDEF_RUNNING: // r1
       case OPTYPE_TMR_READ:
       case OPTYPE_TMR_RUNNING:
@@ -3029,6 +3112,7 @@ namespace Common {
       case OPTYPE_SIZEOF:
       case OPTYPE_DECODE:
       case OPTYPE_ENUM2INT:
+      case OPTYPE_DECVALUE_UNICHAR:
         return Type::T_INT;
       case OPTYPE_BIT2STR:
       case OPTYPE_FLOAT2STR:
@@ -3046,6 +3130,7 @@ namespace Common {
         return Type::T_CSTR;
       case OPTYPE_INT2UNICHAR:
       case OPTYPE_OCT2UNICHAR:
+      case OPTYPE_ENCVALUE_UNICHAR:
         return Type::T_USTR;
       case OPTYPE_INT2BIT:
       case OPTYPE_HEX2BIT:
@@ -3446,6 +3531,10 @@ namespace Common {
       return "int2oct()";
     case OPTYPE_OCT2UNICHAR:
       return "oct2unichar()";
+    case OPTYPE_ENCVALUE_UNICHAR:
+      return "encvalue_unichar()";
+    case OPTYPE_DECVALUE_UNICHAR:
+      return "decvalue_unichar()";
     case OPTYPE_SUBSTR:
       return "substr()";
     case OPTYPE_REGEXP:
@@ -5331,7 +5420,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
       error("Cannot determine type of value");
       goto error;
     }
-
+    
     // todo: fix this
     /*if (u.expr.par1_is_value && u.expr.v1->get_valuetype() != V_REFD) {
       error("Expecting a value of a type with coding attributes in first"
@@ -5343,7 +5432,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1,
     if(!disable_attribute_validation()) {
       t_type->chk_coding(true);
     }
-
+    
     switch (t_type->get_typetype()) {
     case Type::T_UNDEF:
     case Type::T_ERROR:
@@ -5370,9 +5459,9 @@ error:
     set_valuetype(V_ERROR);
   }
 
-  void Value::chk_expr_operands_decode()
+  void Value::chk_expr_operands_decode(operationtype_t p_optype)
   {
-    Error_Context cntxt(this, "In the parameters of decvalue()");
+    Error_Context cntxt(this, "In the parameters of decvalue()"); //todo
     Ttcn::Ref_base* ref = u.expr.r1;
     Ttcn::FieldOrArrayRefs* t_subrefs = ref->get_subrefs();
     Type* t_type = 0;
@@ -5426,9 +5515,22 @@ error:
     if (!t_type) {
       goto error;
     }
-    if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){
-      error("First parameter has to be a bitstring");
-      goto error;
+    switch(p_optype) {
+      case OPTYPE_DECODE:
+        if (t_type->get_type_refd_last()->get_typetype() != Type::T_BSTR){
+          error("First parameter has to be a bitstring");
+          goto error;
+        }
+        break;
+      case OPTYPE_DECVALUE_UNICHAR:
+        if (t_type->get_type_refd_last()->get_typetype() != Type::T_USTR){
+          error("First parameter has to be a universal charstring");
+          goto error;
+        }
+        break; 
+      default:
+        FATAL_ERROR("Value::chk_expr_decode_operands()");
+        break;
     }
 
     ref = u.expr.r2;
@@ -6471,6 +6573,30 @@ error:
         chk_expr_eval_value(v2, t_chk, refch, exp_val);
       }
       break;
+    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+      chk_expr_operand_encode(refch, exp_val);
+      v2=u.expr.v2 ? u.expr.v2 : 0;
+      if (v2)
+      {
+        Error_Context cntxt(this, "In the second operand of operation `%s'", opname);
+        v2->set_lowerid_to_ref();
+        tt2=v2->get_expr_returntype(exp_val);
+        chk_expr_operandtype_charstr(tt2, second, opname, v2);
+        chk_expr_eval_value(v2, t_chk, refch, exp_val);
+      }
+      break;
+    case OPTYPE_DECVALUE_UNICHAR:
+      chk_expr_operands_decode(OPTYPE_DECVALUE_UNICHAR);
+      v3=u.expr.v3 ? u.expr.v3 : 0;
+      if (v3)
+      {
+        Error_Context cntxt(this, "In the thrid operand of operation `%s'", opname);
+        v3->set_lowerid_to_ref();
+        tt3=v3->get_expr_returntype(exp_val);
+        chk_expr_operandtype_charstr(tt3, third, opname, v3);
+        chk_expr_eval_value(v3, t_chk, refch, exp_val);
+      }
+      break;
     case OPTYPE_ADD: // v1 v2
     case OPTYPE_SUBTRACT:
     case OPTYPE_MULTIPLY:
@@ -6752,7 +6878,7 @@ error:
       chk_expr_operands_int2binstr();
       break;
     case OPTYPE_DECODE:
-      chk_expr_operands_decode();
+      chk_expr_operands_decode(OPTYPE_DECODE);
       break;
     case OPTYPE_SUBSTR:
       {
@@ -7067,6 +7193,8 @@ error:
     case OPTYPE_OCT2UNICHAR:
     case OPTYPE_ENCODE_BASE64:
     case OPTYPE_DECODE_BASE64:
+    case OPTYPE_ENCVALUE_UNICHAR:
+    case OPTYPE_DECVALUE_UNICHAR:
       break;
     case OPTYPE_TESTCASENAME: { // -
       if (!my_scope) FATAL_ERROR("Value::evaluate_value()");
@@ -8363,6 +8491,8 @@ error:
       case OPTYPE_UNICHAR2OCT:
       case OPTYPE_ENCODE_BASE64:
       case OPTYPE_DECODE_BASE64:
+      case OPTYPE_ENCVALUE_UNICHAR:
+      case OPTYPE_DECVALUE_UNICHAR:
         return true;
       case OPTYPE_COMP_NULL: // -
         return false;
@@ -9682,6 +9812,25 @@ error:
       u.expr.ti1->chk_recursions(refch);
       refch.prev_state();
       break;
+    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+      refch.mark_state();
+      u.expr.ti1->chk_recursions(refch);
+      refch.prev_state();
+      if (u.expr.v2){
+        refch.mark_state();
+        u.expr.v2->chk_recursions(refch);
+        refch.prev_state();
+      }
+      break;
+    case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3]
+      chk_recursions_expr_decode(u.expr.r1, refch);
+      chk_recursions_expr_decode(u.expr.r2, refch);
+      if (u.expr.v3){
+        refch.mark_state();
+        u.expr.v3->chk_recursions(refch);
+        refch.prev_state();
+      }
+      break;
     case OPTYPE_MATCH: // v1 t2
       refch.mark_state();
       u.expr.v1->chk_recursions(refch);
@@ -9973,7 +10122,16 @@ error:
     case OPTYPE_TTCN2STRING:
       self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs);
       break;
-
+    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2]
+      self_ref |= chk_expr_self_ref_templ(u.expr.ti1->get_Template(), lhs);
+      if (u.expr.v2) self_ref |= chk_expr_self_ref_val(u.expr.v2, lhs);
+      break;
+    case OPTYPE_DECVALUE_UNICHAR: { // r1 r2 [v3]
+      Common::Assignment *ass = u.expr.r2->get_refd_assignment();
+      self_ref |= (ass == lhs);
+      if (u.expr.v3) self_ref |= chk_expr_self_ref_val(u.expr.v3, lhs);
+      goto label_r1;
+      break; }
     case OPTYPE_COMP_CREATE: // r1 [v2] [v3] b4
       // component.create -- assume no self-ref
     case OPTYPE_ACTIVATE: // r1
@@ -10277,6 +10435,24 @@ error:
          if (u.expr.v2) return create_stringRepr_predef2("unichar2oct");
          else return create_stringRepr_predef1("unichar2oct");
       }
+      case OPTYPE_ENCVALUE_UNICHAR: {
+         if (u.expr.v2) return create_stringRepr_predef2("encvalue_unichar");
+         else return create_stringRepr_predef1("encvalue_unichar");
+      }
+      case OPTYPE_DECVALUE_UNICHAR: {
+         if (u.expr.v3) {
+           string ret_val("decvalue_unichar");
+           ret_val += '(';
+           ret_val += u.expr.v1->get_stringRepr();
+           ret_val += ", ";
+           ret_val += u.expr.v2->get_stringRepr();
+           ret_val += ", ";
+           ret_val += u.expr.v3->get_stringRepr();
+           ret_val += ')';
+           return ret_val;
+         }
+         else return create_stringRepr_predef2("decvalue_unichar");
+      }
       case OPTYPE_STR2BIT:
         return create_stringRepr_predef1("str2bit");
       case OPTYPE_STR2FLOAT:
@@ -10655,7 +10831,7 @@ error:
   {
     string ret_val(function_name);
     ret_val += '(';
-    if (u.expr.v_optype == OPTYPE_ENCODE) { // ti1, not v1
+    if (u.expr.v_optype == OPTYPE_ENCODE || u.expr.v_optype == OPTYPE_ENCVALUE_UNICHAR) { // ti1, not v1
       ret_val += u.expr.ti1->get_specific_value()->get_stringRepr();
     }
     else ret_val += u.expr.v1->get_stringRepr();
@@ -11272,6 +11448,20 @@ error:
       case OPTYPE_TTCN2STRING:
         str = u.expr.ti1->rearrange_init_code(str, usage_mod);
         break;
+      case OPTYPE_ENCVALUE_UNICHAR:
+        str = u.expr.ti1->rearrange_init_code(str, usage_mod);
+        if (u.expr.v2) str = u.expr.v2->rearrange_init_code(str, usage_mod);
+        break;
+      case OPTYPE_DECVALUE_UNICHAR: {
+        Ttcn::ActualParList *parlist = u.expr.r1->get_parlist();
+        Common::Assignment *ass = u.expr.r1->get_refd_assignment();
+        if (parlist) str = parlist->rearrange_init_code(str, usage_mod);
+
+        parlist = u.expr.r2->get_parlist();
+        ass = u.expr.r2->get_refd_assignment();
+        if (parlist) str = parlist->rearrange_init_code(str, usage_mod);
+        if (u.expr.v3) str = u.expr.v3->rearrange_init_code(str, usage_mod);
+        break; }
       case OPTYPE_ISCHOSEN_T:
         str = u.expr.t1->rearrange_init_code(str, usage_mod);
         break;
@@ -11496,6 +11686,12 @@ error:
       else
         generate_code_expr_predef1(expr, "unichar2oct", u.expr.v1);
       break;
+    case OPTYPE_ENCVALUE_UNICHAR:
+        generate_code_expr_encvalue_unichar(expr);
+      break;
+    case OPTYPE_DECVALUE_UNICHAR:
+        generate_code_expr_decvalue_unichar(expr);
+      break;
     case OPTYPE_OCT2HEX:
       generate_code_expr_predef1(expr, "oct2hex", u.expr.v1);
       break;
@@ -12346,7 +12542,7 @@ error:
         is_templ ? ".valueof()" : "");
     Code::free_expr(&expr2);
   }
-
+  
   void Value::generate_code_expr_decode(expression_struct *expr)
   {
     expression_struct expr1, expr2;
@@ -12431,6 +12627,197 @@ error:
     Code::free_expr(&expr1);
     Code::free_expr(&expr2);
   }
+  
+void Value::generate_code_expr_encvalue_unichar(expression_struct *expr)
+  {
+    Value* v1 = 0;
+
+    Template* templ = u.expr.ti1->get_Template()->get_template_refd_last();
+    if (templ->get_templatetype() == Template::SPECIFIC_VALUE)
+      v1 = templ->get_specific_value();
+    Type* gov_last = templ->get_my_governor()->get_type_refd_last();
+
+    expression_struct expr2;
+    Code::init_expr(&expr2);
+
+    bool is_templ = false;
+    switch (templ->get_templatetype()) {
+    case Template::SPECIFIC_VALUE:
+      v1->generate_code_expr_mandatory(&expr2);
+      break;
+    default:
+      u.expr.ti1->generate_code(&expr2);
+      is_templ = true;
+      break;
+    }
+
+    if (!gov_last->is_coding_by_function()) {
+      const string& tmp_id = get_temporary_id();
+      const string& tmp_buf_id = get_temporary_id();
+      const string& tmp_ref_id = get_temporary_id();
+      expr->preamble = mputprintf(expr->preamble, "OCTETSTRING %s;\n",
+        tmp_id.c_str());
+      expr->preamble = mputprintf(expr->preamble, "TTCN_Buffer %s;\n",
+        tmp_buf_id.c_str());
+      if (expr2.preamble) { // copy preamble setting up the argument, if any
+        expr->preamble = mputstr(expr->preamble, expr2.preamble);
+        expr->preamble = mputc  (expr->preamble, '\n');
+      }
+      expr->preamble = mputprintf(expr->preamble, "%s const& %s = %s",
+        gov_last->get_genname_typedescriptor(
+          u.expr.ti1->get_Template()->get_my_scope()
+        ).c_str(),
+        tmp_ref_id.c_str(),
+        expr2.expr);
+      if (is_templ) // make a value out of the template, if needed
+        expr->preamble = mputprintf(expr->preamble, ".valueof()");
+      expr->preamble = mputprintf(expr->preamble,
+        ";\n%s.encode(%s_descr_, %s, TTCN_EncDec::CT_%s",
+        tmp_ref_id.c_str(),
+        gov_last->get_genname_typedescriptor(
+          u.expr.ti1->get_Template()->get_my_scope()
+        ).c_str(),
+        tmp_buf_id.c_str(),
+        gov_last->get_coding(true).c_str()
+      );
+      expr->preamble = mputstr(expr->preamble, ");\n");
+      expr->preamble = mputprintf(expr->preamble, "%s.get_string(%s);\n",
+        tmp_buf_id.c_str(),
+        tmp_id.c_str()
+      );
+      const char * v2_code = NULL;
+      if(u.expr.v2) {
+        v2_code = generate_code_char_coding_check(expr, u.expr.v2, "encvalue_unichar");
+      }
+      expr->expr = mputprintf(expr->expr, "oct2unichar(%s", tmp_id.c_str());
+      if(u.expr.v2) {
+        expr->expr = mputprintf(expr->expr, ", %s", v2_code);
+      } else {
+        expr->expr = mputprintf(expr->expr, ", \"UTF-8\"");  //default
+      }
+      expr->expr = mputprintf(expr->expr, ")");
+      if (expr2.postamble)
+        expr->postamble = mputstr(expr->postamble, expr2.postamble);
+    } else
+      expr->expr = mputprintf(expr->expr, "%s(%s%s)",
+        gov_last->get_coding(true).c_str(), expr2.expr,
+        is_templ ? ".valueof()" : "");
+    Code::free_expr(&expr2);
+  }
+
+  void Value::generate_code_expr_decvalue_unichar(expression_struct *expr)
+  {
+    expression_struct expr1, expr2;
+    Code::init_expr(&expr1);
+    Code::init_expr(&expr2);
+    u.expr.r1->generate_code(&expr1);
+    u.expr.r2->generate_code(&expr2);
+
+    Type* _type = u.expr.r2->get_refd_assignment()->get_Type()->
+      get_field_type(u.expr.r2->get_subrefs(), Type::EXPECTED_DYNAMIC_VALUE)->
+      get_type_refd_last();
+
+    if (expr1.preamble)
+      expr->preamble = mputprintf(expr->preamble, "%s", expr1.preamble);
+    if (expr2.preamble)
+      expr->preamble = mputprintf(expr->preamble, "%s", expr2.preamble);
+
+    if (!_type->is_coding_by_function()) {
+      const string& tmp_id = get_temporary_id();
+      const string& buffer_id = get_temporary_id();
+      const string& retval_id = get_temporary_id();
+      const bool optional = u.expr.r2->get_refd_assignment()->get_Type()->
+        field_is_optional(u.expr.r2->get_subrefs());
+
+      const char* v3_code = NULL;
+      if(u.expr.v3) {
+        v3_code = generate_code_char_coding_check(expr, u.expr.v3, "decvalue_unichar");
+      }
+      expr->preamble = mputprintf(expr->preamble,
+        "TTCN_Buffer %s(unichar2oct(%s, %s));\n"
+        "INTEGER %s;\n"
+        "TTCN_EncDec::set_error_behavior("
+        "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n"
+        "TTCN_EncDec::clear_error();\n",
+        buffer_id.c_str(),
+        expr1.expr,
+        u.expr.v3 ? v3_code : "\"UTF-8\"",
+        retval_id.c_str()
+      );
+      expr->preamble = mputprintf(expr->preamble,
+        "%s%s.decode(%s_descr_, %s, TTCN_EncDec::CT_%s);\n",
+        expr2.expr,
+        optional ? "()" : "",
+          _type->get_genname_typedescriptor(
+            u.expr.r2->get_my_scope()
+          ).c_str(),
+          buffer_id.c_str(),
+          _type->get_coding(false).c_str()
+      );
+      expr->preamble = mputprintf(expr->preamble,
+        "switch (TTCN_EncDec::get_last_error_type()) {\n"
+        "case TTCN_EncDec::ET_NONE: {\n"
+        "%s.cut();\n"
+        "OCTETSTRING %s;\n"
+        "%s.get_string(%s);\n"
+        "%s = oct2unichar(%s, %s);\n"
+        "%s = 0;\n"
+        "}break;\n"
+        "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
+        "case TTCN_EncDec::ET_LEN_ERR:\n"
+        "%s = 2;\n"
+        "break;\n"
+        "default:\n"
+        "%s = 1;\n"
+        "}\n"
+        "TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL,"
+        "TTCN_EncDec::EB_DEFAULT);\n"
+        "TTCN_EncDec::clear_error();\n",
+        buffer_id.c_str(),
+        tmp_id.c_str(),
+        buffer_id.c_str(),
+        tmp_id.c_str(),
+        expr1.expr,
+        tmp_id.c_str(),
+        u.expr.v3 ? v3_code : "\"UTF-8\"",
+        retval_id.c_str(),
+        retval_id.c_str(),
+        retval_id.c_str()
+      );
+      expr->expr = mputprintf(expr->expr, "%s", retval_id.c_str());
+    } else
+      expr->expr = mputprintf(expr->expr, "%s(%s, %s)",
+        _type->get_coding(false).c_str(), expr1.expr, expr2.expr);
+    if (expr1.postamble)
+      expr->postamble = mputprintf(expr->postamble, "%s", expr1.postamble);
+    if (expr2.postamble)
+      expr->postamble = mputprintf(expr->postamble, "%s", expr2.postamble);
+    Code::free_expr(&expr1);
+    Code::free_expr(&expr2);
+  }
+  
+  char* Value::generate_code_char_coding_check(expression_struct *expr, Value *v, const char *name)
+  {
+    expression_struct expr2;
+    Code::init_expr(&expr2);
+    v->generate_code_expr_mandatory(&expr2);
+    expr->preamble = mputprintf(expr->preamble,
+      "if (\"UTF-8\" != %s && \"UTF-16\" != %s && \"UTF-16LE\" != %s && \n"
+      "  \"UTF-16BE\" != %s && \"UTF-32\" != %s && \"UTF-32LE\" != %s && \n"
+      "  \"UTF-32BE\" != %s) {\n"
+      "   TTCN_error(\"%s: Invalid encoding parameter: %%s\", (const char*)%s);\n"
+      "}\n", //todo errorbehaviour?
+      expr2.expr,
+      expr2.expr,
+      expr2.expr,
+      expr2.expr,
+      expr2.expr,
+      expr2.expr,
+      expr2.expr,
+      name,
+      expr2.expr);
+    return expr2.expr;
+  }
 
   char *Value::generate_code_init_choice(char *str, const char *name)
   {
@@ -13091,6 +13478,8 @@ error:
     case OPTYPE_ISBOUND:
     case OPTYPE_ISPRESENT:
     case OPTYPE_TTCN2STRING:
+    case OPTYPE_ENCVALUE_UNICHAR:
+    case OPTYPE_DECVALUE_UNICHAR:
       return false;
     case OPTYPE_UNARYPLUS: // v1
     case OPTYPE_UNARYMINUS:
index 60b0a18df64dfa80f51fdcf28f950b0e4b0a1858..dd75c42fcdf010d4c574427663a8eca62cb8dcaf 100644 (file)
@@ -18,6 +18,7 @@
  *   Kovacs, Ferenc
  *   Raduly, Csaba
  *   Szabados, Kristof
+ *   Szabo, Bence Janos
  *   Szabo, Janos Zoltan – initial implementation
  *   Tatarka, Gabor
  *   Zalanyi, Balazs Andor
@@ -259,6 +260,9 @@ namespace Common {
 
       OPTYPE_LOG2STR, // logagrs
       OPTYPE_PROF_RUNNING, // -     99
+      
+      OPTYPE_ENCVALUE_UNICHAR, // ti1 [v2]
+      OPTYPE_DECVALUE_UNICHAR, // r1 r2 [v3]
 
       NUMBER_OF_OPTYPES // must be last
     };
@@ -414,6 +418,8 @@ namespace Common {
     Value(operationtype_t p_optype, Value *p_v1, Value *p_v2);
     /** Constructor used by V_EXPR "v1 v2 v3" */
     Value(operationtype_t p_optype, Value *p_v1, Value *p_v2, Value *p_v3);
+    /** Constructor used by encvalue_unichar "ti1 [v2]" */
+    Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2);
     /** Constructor used by V_EXPR "ti1 v2 v3" */
     Value(operationtype_t p_optype, TemplateInstance *p_ti1, Value *p_v2, Value *p_v3);
     /** Constructor used by V_EXPR "ti1 t2 v3" */
@@ -435,6 +441,8 @@ namespace Common {
     Value(valuetype_t p_vt, verdict_t p_verdict);
     /** Constructor used by decode */
     Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2);
+    /** Constructor used by decvalue_unichar*/
+    Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2, Value *p_v3);
     virtual ~Value();
     virtual Value* clone() const;
     valuetype_t get_valuetype() const {return valuetype;}
@@ -628,7 +636,8 @@ namespace Common {
       Type::expected_value_t exp_val);
     void chk_expr_operand_encode(ReferenceChain *refch,
       Type::expected_value_t exp_val);
-    void chk_expr_operands_decode();
+    /** \a has two possible value: OPTYPE_DECODE | OPTYPE_DECVALUE_UNICHAR */
+    void chk_expr_operands_decode(operationtype_t p_optype);
     /** Checks whether \a this can be compared with omit value (i.e. \a this
      * should be a referenced value pointing to a optional record/set field. */
     void chk_expr_omit_comparison(Type::expected_value_t exp_val);
@@ -907,6 +916,12 @@ namespace Common {
     void generate_code_expr_encode(expression_struct *expr);
 
     void generate_code_expr_decode(expression_struct *expr);
+    
+    void generate_code_expr_encvalue_unichar(expression_struct *expr);
+    
+    void generate_code_expr_decvalue_unichar(expression_struct *expr);
+    
+    char* generate_code_char_coding_check(expression_struct *expr, Value *v, const char *name);
 
     /** Helper function for \a generate_code_init(). It handles the
      *  union (CHOICE) values. */
index 4fe0e83c47e444908c438451fe94b2115a3b0609..47682da8d6aabc169535b8217f5f9acb8920ce74 100644 (file)
@@ -585,6 +585,8 @@ remove_bom  RETURN(remove_bomKeyWord);
 get_stringencoding     RETURN(get_stringencodingKeyWord);
 encode_base64  RETURN(encode_base64KeyWord);
 decode_base64  RETURN(decode_base64KeyWord);
+encvalue_unichar RETURN(encvalue_unicharKeyWord);
+decvalue_unichar RETURN(decvalue_unicharKeyWord);
 
        /* Values */
 
index 194a48e9c2c2c846a1d737d9a6665922e8adc236..f6f16f3d81536fe82a1e2147c6000c6f6fa56d88 100644 (file)
@@ -832,6 +832,8 @@ static const string anyname("anytype");
 %token get_stringencodingKeyWord
 %token encode_base64KeyWord
 %token decode_base64KeyWord
+%token encvalue_unicharKeyWord
+%token decvalue_unicharKeyWord
 
 /* Multi-character operators */
 
@@ -8739,6 +8741,43 @@ PredefinedOps:
     $$ = new Value(Value::V_ERROR);
     $$->set_location(infile, @$);
   }
+| encvalue_unicharKeyWord '(' optError TemplateInstance optError ',' optError
+  Expression optError ')'
+  {
+    $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, $4, $8);
+    $$->set_location(infile, @$);
+  }
+| encvalue_unicharKeyWord '(' optError TemplateInstance optError ')'
+  {
+    $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, $4);
+    $$->set_location(infile, @$);
+  }
+| encvalue_unicharKeyWord '(' error ')'
+  {
+    Template *t1 = new Template(Template::TEMPLATE_ERROR);
+    t1->set_location(infile, @3);
+    TemplateInstance *ti1 = new TemplateInstance(0, 0, t1);
+    ti1->set_location(infile, @3);
+    $$ = new Value(Value::OPTYPE_ENCVALUE_UNICHAR, ti1);
+    $$->set_location(infile, @$);
+  }
+| decvalue_unicharKeyWord '(' optError DecValueArg optError ',' optError
+  DecValueArg optError ')'
+  {
+    $$ = new Value(Value::OPTYPE_DECVALUE_UNICHAR, $4, $8);
+    $$->set_location(infile, @$);
+  }
+| decvalue_unicharKeyWord '(' optError DecValueArg optError ',' optError
+  DecValueArg optError ',' optError Expression optError ')'
+  {
+    $$ = new Value(Value::OPTYPE_DECVALUE_UNICHAR, $4, $8, $12);
+    $$->set_location(infile, @$);
+  }
+| decvalue_unicharKeyWord '(' error ')'
+  {
+    $$ = new Value(Value::V_ERROR);
+    $$->set_location(infile, @$);
+  }
 ;
 
 DecValueArg:
diff --git a/regression_test/ucharstrOper/EncDecvalueUnichar.ttcn b/regression_test/ucharstrOper/EncDecvalueUnichar.ttcn
new file mode 100644 (file)
index 0000000..d5f1699
--- /dev/null
@@ -0,0 +1,142 @@
+/******************************************************************************
+ * 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:
+ *   Szabo, Bence Janos
+ *
+ ******************************************************************************/
+
+module EncDecvalueUnichar {
+
+type integer Byte (-128 .. 127) with { variant "8 bit" };
+
+type bitstring BStr16 with { variant "16 bit" };
+
+type hexstring HStr;
+
+type octetstring OStr;
+
+type charstring CStr;
+
+type universal charstring UStr;
+
+// Component type
+type component CT {}
+
+// Test cases
+testcase tc_byte() runs on CT
+{
+
+  var Byte x := 30;
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var Byte x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+testcase tc_bstr() runs on CT
+{
+  var BStr16 x := '0100010101110011'B;
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var BStr16 x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+  
+  // with default UTF-8 coding
+  x := '0100010101110011'B;
+  enc := encvalue_unichar(x);
+  res := decvalue_unichar(enc, x_exp);
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+testcase tc_hstr() runs on CT
+{
+  var HStr x := '44'H;
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var HStr x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+testcase tc_ostr() runs on CT
+{
+  var OStr x := '1255'O;
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var OStr x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+testcase tc_cstr() runs on CT
+{
+  var CStr x := "CdVsBgAa";
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var CStr x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+testcase tc_ustr() runs on CT
+{
+  var UStr x := "CdVsBgAa";
+  var universal charstring enc := encvalue_unichar(x, "UTF-8");
+  var UStr x_exp;
+  var integer res := decvalue_unichar(enc, x_exp, "UTF-8");
+  if (match(x_exp, x) and res == 0 and match(lengthof(enc),0)) {
+    setverdict(pass);
+  }
+  else {
+    setverdict(fail);
+  }
+}
+
+  
+// Control part
+control {
+  execute(tc_byte());
+  execute(tc_bstr());
+  execute(tc_hstr());
+  execute(tc_ostr());
+  execute(tc_cstr());
+  execute(tc_ustr());
+}
+
+}
+with {
+  encode "RAW";
+}
+
index e5ddf9fc45b631dad14dae0ce8d4055e85651153..2b40fb98552916da2f1593a22de54930138009c9 100644 (file)
@@ -20,7 +20,7 @@ include $(TOPDIR)/Makefile.regression
 
 TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX)
 
-TTCN3_MODULES = TucharstrOper.ttcn cstr_content.ttcn Common.ttcn UTF8Testcases.ttcn UTF16Testcases.ttcn UTF32Testcases.ttcn Base64Testcases.ttcn
+TTCN3_MODULES = TucharstrOper.ttcn cstr_content.ttcn Common.ttcn UTF8Testcases.ttcn UTF16Testcases.ttcn UTF32Testcases.ttcn Base64Testcases.ttcn EncDecvalueUnichar.ttcn
 
 GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc)
 GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh)
index 7fdafe8bb939644d74cc9e7404e00e559e44e5e4..f50ffe85e42d7c00076444f6d71546bfe2c0baef 100644 (file)
@@ -30,3 +30,4 @@ UTF8Testcases.control
 UTF16Testcases.control
 UTF32Testcases.control
 Base64Testcases.control
+EncDecvalueUnichar.control
This page took 0.039856 seconds and 5 git commands to generate.