diff --git a/compiler2/Type.cc b/compiler2/Type.cc index 58800872e6824eb799d7081944bfac346a138ac4..682bccb74600611c1ab79fe3e3c98ebd1c97f929 100644 --- a/compiler2/Type.cc +++ b/compiler2/Type.cc @@ -176,6 +176,9 @@ namespace Common { Type *Type::get_stream_type(MessageEncodingType_t encoding_type, int stream_variant) { + if (stream_variant == 0) { + return get_pooltype(T_BSTR); + } switch (encoding_type) { case CT_BER: case CT_PER: @@ -184,13 +187,11 @@ namespace Common { case CT_JSON: return get_pooltype(T_OSTR); case CT_TEXT: - if(stream_variant==0){ + if(stream_variant==1){ return get_pooltype(T_CSTR); } else { return get_pooltype(T_OSTR); } - case CT_CUSTOM: - return get_pooltype(T_BSTR); default: FATAL_ERROR("Type::get_stream_type()"); return 0; @@ -606,6 +607,8 @@ namespace Common { chk_finished = false; pard_type_instance = false; needs_any_from_done = false; + encoding_by_function = false; + decoding_by_function = false; asn_encoding = CT_UNDEF; asn_decoding = CT_UNDEF; } @@ -4395,27 +4398,45 @@ namespace Common { void Type::set_coding_function(bool encode, const string& function_name) { - string& coding_str = encode ? encoding_str : decoding_str; - if (!coding_str.empty()) { - error("Multiple custom %s functions declared for type '%s' (function `%s' " - "is already set)", encode ? "encoding" : "decoding", - get_typename().c_str(), coding_str.c_str()); + string& coding_function = encode ? encoding_function : decoding_function; + MessageEncodingType_t& asn_coding = encode ? asn_encoding : asn_decoding; + bool& coding_by_function = encode ? + encoding_by_function : decoding_by_function; + if (!coding_function.empty()) { + // leave coding_by_function as true, this will indicate that there are + // multiple coding functions set + coding_function.clear(); + } + else if (asn_coding != CT_UNDEF) { + // a different encoding type is already set for the ASN.1 type + asn_coding = CT_MULTIPLE; + coding_function.clear(); return; } - coding_str = function_name; - coding_by_function = true; + else { + if (is_asn1()) { + asn_coding = CT_PER; + } + coding_function = function_name; + coding_by_function = true; + } } void Type::set_asn_coding(bool encode, Type::MessageEncodingType_t new_coding) { MessageEncodingType_t& coding = encode ? asn_encoding : asn_decoding; - if (coding == CT_UNDEF) { + bool& coding_by_function = encode ? + encoding_by_function : decoding_by_function; // true = PER coder is set + string& coding_function = encode ? encoding_function : decoding_function; // PER coder + if (coding == CT_UNDEF && !coding_by_function) { // this is the first encoding/decoding function for this type, store it + // (also, no PER coders have been set for the type yet) coding = new_coding; } - else if (coding != new_coding) { + else if (coding != new_coding || coding_by_function) { // there are several encoding/decoding functions declared for this type // with different codings (encvalue/decvalue cannot be used in this case) + coding_function.clear(); coding = CT_MULTIPLE; } } @@ -4424,7 +4445,8 @@ namespace Common { string& coding_str = encode ? encoding_str : decoding_str; if (!coding_str.empty()) return; - coding_by_function = false; + bool& coding_by_function = encode ? + encoding_by_function : decoding_by_function; Type::MessageEncodingType_t coding = CT_UNDEF; if (!is_asn1()) { @@ -4517,18 +4539,18 @@ namespace Common { else { // ASN.1 type coding = encode ? asn_encoding : asn_decoding; if ((coding == CT_UNDEF && delayed) || coding == CT_MULTIPLE) { - // either this is the delayed call and no external function has been + // either this is the delayed call and no external functions have been // found, or there was already more than one function error("Cannot determine the %s rules for ASN.1 type `%s'. " - "%s %s external function%s found%s", encode ? "encoding" : "decoding", + "%s %s external functions found%s", encode ? "encoding" : "decoding", get_typename().c_str(), coding == CT_UNDEF ? "No" : "Multiple", - encode ? "encoding" : "decoding", coding == CT_UNDEF ? "" : "s", + encode ? "encoding" : "decoding", coding == CT_UNDEF ? "" : " with different rules"); return; } - if (coding == CT_UNDEF && !delayed) { - // the coding type is set by the external function's checker in this case; - // it's possible, that the function exists, but has not been reached yet; + if (!delayed) { + // there have been no errors so far in determining the coding type, + // but there might still be unchecked external functions out there; // delay this function until everything else has been checked Modules::delay_type_encode_check(this, encode); return; @@ -4547,9 +4569,6 @@ namespace Common { case CT_TEXT: coding_str = "TEXT"; break; - case CT_PER: - coding_str = "PER"; - break; case CT_XER: coding_str = "XER, XER_EXTENDED"; // TODO: fine tuning this parameter break; @@ -4568,20 +4587,31 @@ namespace Common { if (!berattrib) delete ber; break; } - case CT_CUSTOM: - if (!delayed) { - // coding_str is set by the coding function's checker in this case; - // it's possible, that the function exists, but has not been reached yet; + case CT_PER: + case CT_CUSTOM: { + // the coding function is set by its semantic checker in this case + string& coding_function = encode ? encoding_function : decoding_function; + if (coding_function.empty() && coding_by_function) { + error("Multiple %s %s functions set for type `%s'", + get_encoding_name(coding), encode ? "encoding" : "decoding", + get_typename().c_str()); + } + else if (!delayed) { + // there have been no errors so far in determining the coding function, + // but there might still be unchecked external functions out there; // delay this function until everything else has been checked Modules::delay_type_encode_check(this, encode); } - else if (coding_str.empty()) { - // this is the delayed call, and the custom coding function has still - // not been found - error("No custom %s function found for type `%s'", + else if (coding_function.empty()) { + // this is the delayed call, and the coding function has still not been set + error("No %s %s function found for type `%s'", get_encoding_name(coding), encode ? "encoding" : "decoding", get_typename().c_str()); } - return; + else { + // this is the delayed call, and exactly one coding function has been set + coding_str = coding_function; + } + return; } default: error("Unknown coding selected for type '%s'", get_typename().c_str()); break; @@ -4589,8 +4619,8 @@ namespace Common { coding_by_function = false; } - bool Type::is_coding_by_function() const { - return coding_by_function; + bool Type::is_coding_by_function(bool encode) const { + return encode ? encoding_by_function : decoding_by_function; } const string& Type::get_coding(bool encode) const { diff --git a/compiler2/Type.hh b/compiler2/Type.hh index 4c811023c13711363b909b538a3431dee2064e03..c1e442cc4ef96eeeaa3b239ef39dab592df1cbdf 100644 --- a/compiler2/Type.hh +++ b/compiler2/Type.hh @@ -307,7 +307,10 @@ namespace Common { string encoding_str; // needed by codegen for encvalue() and decvalue() string decoding_str; - bool coding_by_function; // false - coding attribute is set, true - coding via coding function + bool encoding_by_function; // false - coding attribute is set, true - coding via coding function + bool decoding_by_function; // same for decoding + string encoding_function; // name of custom or PER encoder + string decoding_function; // name of custom or PER decoder MessageEncodingType_t asn_encoding; // set by the semantic analysis of encoding MessageEncodingType_t asn_decoding; // and decoding external functions for ASN.1 types /** What kind of AST element owns the type. @@ -659,7 +662,7 @@ namespace Common { void set_coding_function(bool encode, const string& function_name); void set_asn_coding(bool encode, MessageEncodingType_t new_coding); void chk_coding(bool encode, bool delayed = false); - bool is_coding_by_function() const; + bool is_coding_by_function(bool encode) const; const string& get_coding(bool encode) const; private: static MessageEncodingType_t get_enc_type(const Ttcn::SingleWithAttrib& enc); diff --git a/compiler2/Value.cc b/compiler2/Value.cc index babf951260e0eea8d6933bb7c140a6e543ed0362..cf273f8a624020f5947d76cbde328a935dc11495 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -12970,7 +12970,7 @@ error: break; } - if (!gov_last->is_coding_by_function()) { + if (!gov_last->is_coding_by_function(true)) { const string& tmp_id = get_temporary_id(); const string& tmp_buf_id = get_temporary_id(); const string& tmp_ref_id = get_temporary_id(); @@ -13031,7 +13031,7 @@ error: if (expr2.preamble) expr->preamble = mputprintf(expr->preamble, "%s", expr2.preamble); - if (!_type->is_coding_by_function()) { + if (!_type->is_coding_by_function(false)) { const string& tmp_id = get_temporary_id(); const string& buffer_id = get_temporary_id(); const string& retval_id = get_temporary_id(); @@ -13127,7 +13127,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) v2_code = generate_code_char_coding_check(expr, u.expr.v2, "encvalue_unichar"); } - if (!gov_last->is_coding_by_function()) { + if (!gov_last->is_coding_by_function(true)) { const string& tmp_id = get_temporary_id(); const string& tmp_buf_id = get_temporary_id(); const string& tmp_ref_id = get_temporary_id(); @@ -13205,7 +13205,7 @@ void Value::generate_code_expr_encvalue_unichar(expression_struct *expr) v3_code = generate_code_char_coding_check(expr, u.expr.v3, "decvalue_unichar"); } - if (!_type->is_coding_by_function()) { + if (!_type->is_coding_by_function(false)) { const string& tmp_id = get_temporary_id(); const string& buffer_id = get_temporary_id(); const string& retval_id = get_temporary_id(); diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 66b7eb8499e223a99a254d182649276b6b09a387..38453629180a4e1b29b828ba92afdeaf88e3576f 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -6561,9 +6561,11 @@ namespace Ttcn { // "untagged" on the (toplevel) input type will have no effect. warning("UNTAGGED encoding attribute is ignored on top-level type"); } - if (Common::Type::CT_CUSTOM == encoding_type) { + if (Common::Type::CT_CUSTOM == encoding_type || + Common::Type::CT_PER == encoding_type) { if (PROTOTYPE_CONVERT != prototype) { - error("Only `prototype(convert)' is allowed for custom encoding functions"); + error("Only `prototype(convert)' is allowed for %s encoding functions", + Type::get_encoding_name(encoding_type)); } else { // let the input type know that this is its encoding function @@ -6580,17 +6582,25 @@ namespace Ttcn { } } if (output_type) { - if(encoding_type == Common::Type::CT_TEXT) { // TEXT encoding supports both octetstring and charstring stream types + if(encoding_type == Common::Type::CT_TEXT) { + // TEXT encoding supports bitstring, octetstring and charstring stream types Type *stream_type = Type::get_stream_type(encoding_type,0); Type *stream_type2 = Type::get_stream_type(encoding_type,1); - if ( (!stream_type->is_identical(output_type)) && (!stream_type2->is_identical(output_type)) ) { - output_type->error("The output type of %s encoding should be `%s' or `%s' " - "instead of `%s'", Type::get_encoding_name(encoding_type), + Type *stream_type3 = Type::get_stream_type(encoding_type,2); + if ( (!stream_type->is_identical(output_type)) && + (!stream_type2->is_identical(output_type)) && + (!stream_type3->is_identical(output_type))) { + output_type->error("The output type of %s encoding should be `%s', " + "`%s' or `%s' instead of `%s'", Type::get_encoding_name(encoding_type), stream_type->get_typename().c_str(), stream_type2->get_typename().c_str(), + stream_type3->get_typename().c_str(), output_type->get_typename().c_str()); } - } else { + } + else if (encoding_type == Common::Type::CT_CUSTOM || + encoding_type == Common::Type::CT_PER) { + // custom and PER encodings only support the bitstring stream type Type *stream_type = Type::get_stream_type(encoding_type); if (!stream_type->is_identical(output_type)) { output_type->error("The output type of %s encoding should be `%s' " @@ -6599,6 +6609,19 @@ namespace Ttcn { output_type->get_typename().c_str()); } } + else { + // all other encodings support bitstring and octetstring stream types + Type *stream_type = Type::get_stream_type(encoding_type, 0); + Type *stream_type2 = Type::get_stream_type(encoding_type, 1); + if (!stream_type->is_identical(output_type) && + !stream_type2->is_identical(output_type)) { + output_type->error("The output type of %s encoding should be `%s' " + "or '%s' instead of `%s'", Type::get_encoding_name(encoding_type), + stream_type->get_typename().c_str(), + stream_type2->get_typename().c_str(), + output_type->get_typename().c_str()); + } + } } if (eb_list) eb_list->chk(); chk_allowed_encode(); @@ -6608,17 +6631,25 @@ namespace Ttcn { error("Attribute `decode' cannot be used without `prototype'"); } if (input_type) { - if(encoding_type == Common::Type::CT_TEXT) { // TEXT encoding supports both octetstring and charstring stream types + if(encoding_type == Common::Type::CT_TEXT) { + // TEXT encoding supports bitstring, octetstring and charstring stream types Type *stream_type = Type::get_stream_type(encoding_type,0); Type *stream_type2 = Type::get_stream_type(encoding_type,1); - if ( (!stream_type->is_identical(input_type)) && (!stream_type2->is_identical(input_type)) ) { - input_type->error("The input type of %s decoding should be `%s' or `%s' " - "instead of `%s'", Type::get_encoding_name(encoding_type), + Type *stream_type3 = Type::get_stream_type(encoding_type,2); + if ( (!stream_type->is_identical(input_type)) && + (!stream_type2->is_identical(input_type)) && + (!stream_type3->is_identical(input_type))) { + input_type->error("The input type of %s decoding should be `%s', " + "`%s' or `%s' instead of `%s'", Type::get_encoding_name(encoding_type), stream_type->get_typename().c_str(), stream_type2->get_typename().c_str(), + stream_type3->get_typename().c_str(), input_type->get_typename().c_str()); } - } else { + } + else if (encoding_type == Common::Type::CT_CUSTOM || + encoding_type == Common::Type::CT_PER) { + // custom and PER encodings only support the bitstring stream type Type *stream_type = Type::get_stream_type(encoding_type); if (!stream_type->is_identical(input_type)) { input_type->error("The input type of %s decoding should be `%s' " @@ -6627,7 +6658,19 @@ namespace Ttcn { input_type->get_typename().c_str()); } } - + else { + // all other encodings support bitstring and octetstring stream types + Type *stream_type = Type::get_stream_type(encoding_type, 0); + Type *stream_type2 = Type::get_stream_type(encoding_type, 1); + if (!stream_type->is_identical(input_type) && + !stream_type2->is_identical(input_type)) { + input_type->error("The input type of %s decoding should be `%s' " + "or `%s' instead of `%s'", Type::get_encoding_name(encoding_type), + stream_type->get_typename().c_str(), + stream_type2->get_typename().c_str(), + input_type->get_typename().c_str()); + } + } } if (output_type && !output_type->has_encoding(encoding_type, encoding_options)) { if (Common::Type::CT_CUSTOM == encoding_type) { @@ -6641,9 +6684,11 @@ namespace Ttcn { } } else { - if (Common::Type::CT_CUSTOM == encoding_type) { + if (Common::Type::CT_CUSTOM == encoding_type || + Common::Type::CT_PER == encoding_type) { if (PROTOTYPE_SLIDING != prototype) { - error("Only `prototype(sliding)' is allowed for custom decoding functions"); + error("Only `prototype(sliding)' is allowed for %s decoding functions", + Type::get_encoding_name(encoding_type)); } else if (output_type) { // let the output type know that this is its decoding function @@ -6863,13 +6908,25 @@ namespace Ttcn { result_name = 0; } // taking the result from the buffer and producing debug printout - str = mputprintf(str, "ttcn_buffer.get_string(%s);\n" + if (output_type->get_type_refd_last()->get_typetype_ttcn3() == + Common::Type::T_BSTR) { + // cannot extract a bitstring from the buffer, use temporary octetstring + // and convert it to bitstring + str = mputprintf(str, + "OCTETSTRING tmp_os;\n" + "ttcn_buffer.get_string(tmp_os);\n" + "%s = oct2bit(tmp_os);\n", result_name); + } + else { + str = mputprintf(str, "ttcn_buffer.get_string(%s);\n", result_name); + } + str = mputprintf(str, "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n" "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n" "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n" "%s.log();\n" "TTCN_Logger::end_event();\n" - "}\n", result_name, function_name, result_name); + "}\n", function_name, result_name); // returning the result stream if necessary if (prototype == PROTOTYPE_CONVERT) { if (debugger_active) { @@ -6909,9 +6966,17 @@ namespace Ttcn { "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n"); } else str = mputstr(str, "TTCN_EncDec::set_error_behavior(" "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n"); + str = mputstr(str, "TTCN_EncDec::clear_error();\n"); // creating a buffer from the input stream - str = mputprintf(str, "TTCN_EncDec::clear_error();\n" - "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name); + if (input_type->get_type_refd_last()->get_typetype_ttcn3() == + Common::Type::T_BSTR) { + // cannot create a buffer from a bitstring, convert it to octetstring + str = mputprintf(str, "TTCN_Buffer ttcn_buffer(bit2oct(%s));\n", + first_par_name); + } + else { + str = mputprintf(str, "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name); + } const char *result_name; if (prototype == PROTOTYPE_CONVERT) { // creating a local variable for the result @@ -6949,14 +7014,25 @@ namespace Ttcn { "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && " "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n" "ttcn_buffer.cut();\n" - "%s remaining_stream;\n" - "ttcn_buffer.get_string(remaining_stream);\n" + "%s remaining_stream;\n", + input_type->get_genname_value(my_scope).c_str()); + if (input_type->get_type_refd_last()->get_typetype_ttcn3() == + Common::Type::T_BSTR) { + str = mputstr(str, + "OCTETSTRING tmp_os;\n" + "ttcn_buffer.get_string(tmp_os);\n" + "remaining_stream = oct2bit(tmp_os);\n"); + } + else { + str = mputstr(str, "ttcn_buffer.get_string(remaining_stream);\n"); + } + str = mputprintf(str, "TTCN_Logger::begin_event(TTCN_WARNING);\n" "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end " "of the stream after successful decoding: \");\n" "remaining_stream.log();\n" "TTCN_Logger::end_event();\n" - "}\n", input_type->get_genname_value(my_scope).c_str(), function_name); + "}\n", function_name); // closing the block and returning the appropriate result or status code if (prototype == PROTOTYPE_BACKTRACK) { if (debugger_active) { @@ -6984,11 +7060,21 @@ namespace Ttcn { } } else { // result handling and debug printout for sliding decoders - str = mputprintf(str, "switch (TTCN_EncDec::get_last_error_type()) {\n" + str = mputstr(str, "switch (TTCN_EncDec::get_last_error_type()) {\n" "case TTCN_EncDec::ET_NONE:\n" // TTCN_Buffer::get_string will call OCTETSTRING::clean_up() - "ttcn_buffer.cut();\n" - "ttcn_buffer.get_string(%s);\n" + "ttcn_buffer.cut();\n"); + if (input_type->get_type_refd_last()->get_typetype_ttcn3() == + Common::Type::T_BSTR) { + str = mputprintf(str, + "OCTETSTRING tmp_os;\n" + "ttcn_buffer.get_string(tmp_os);\n" + "%s = oct2bit(tmp_os);\n", first_par_name); + } + else { + str = mputprintf(str, "ttcn_buffer.get_string(%s);\n", first_par_name); + } + str = mputprintf(str, "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n" "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n" "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n" @@ -7001,7 +7087,7 @@ namespace Ttcn { "%sreturn 2;\n" "default:\n" "%sreturn 1;\n" - "}\n", first_par_name, function_name, first_par_name, + "}\n", function_name, first_par_name, debugger_active ? "ttcn3_debugger.set_return_value(\"0\");\n" : "", debugger_active ? "ttcn3_debugger.set_return_value(\"2\");\n" : "", debugger_active ? "ttcn3_debugger.set_return_value(\"1\");\n" : ""); diff --git a/compiler2/ttcn3/Attributes.cc b/compiler2/ttcn3/Attributes.cc index 8d247e787cf88fc98543b05460d226f8e6fb50ac..54b972866d8e385bd2453ae7d2da1d696436a5aa 100644 --- a/compiler2/ttcn3/Attributes.cc +++ b/compiler2/ttcn3/Attributes.cc @@ -567,8 +567,8 @@ namespace Ttcn { if (act_attr->get_is_raw()) { switch (ti_type->get_typetype_ttcn3()) { case Type::T_BSTR: - if (!type->has_encoding(Type::CT_PER) && !type->has_encoding(Type::CT_RAW)) { - act_attr->error("A `raw' %s value was used for erroneous type `%s' which has no RAW or PER encodings.", + if (!type->has_encoding(Type::CT_RAW)) { + act_attr->error("A `raw' %s value was used for erroneous type `%s' which has no RAW encoding.", ti_type->get_typename().c_str(), type->get_typename().c_str()); } break; @@ -591,7 +591,6 @@ namespace Ttcn { } else { // the two types must have at least one common encoding if (!((type->has_encoding(Type::CT_BER)&&ti_type->has_encoding(Type::CT_BER)) || - (type->has_encoding(Type::CT_PER)&&ti_type->has_encoding(Type::CT_PER)) || (type->has_encoding(Type::CT_RAW)&&ti_type->has_encoding(Type::CT_RAW)) || (type->has_encoding(Type::CT_TEXT)&&ti_type->has_encoding(Type::CT_TEXT)) || (type->has_encoding(Type::CT_XER)&&ti_type->has_encoding(Type::CT_XER)) || diff --git a/compiler2/ttcn3/Statement.cc b/compiler2/ttcn3/Statement.cc index 1563245199747363599238f9af7f6aa8840a5478..8452c0229be9c81d4cdec46ba79079dbad0c11c0 100644 --- a/compiler2/ttcn3/Statement.cc +++ b/compiler2/ttcn3/Statement.cc @@ -9297,7 +9297,7 @@ error: set_params_str = mputstr(set_params_str, "}\nelse {\n"); } Type::typetype_t tt = par->get_type()->get_type_refd_last()->get_typetype_ttcn3(); - if (ve->get_dec_type()->is_coding_by_function()) { + if (ve->get_dec_type()->is_coding_by_function(false)) { set_params_str = mputstr(set_params_str, "BITSTRING buff("); switch (tt) { case Type::T_BSTR: @@ -10041,7 +10041,7 @@ error: set_values_str = mputstr(set_values_str, "}\nelse {\n"); } Type::typetype_t tt = redir_type->get_type_refd_last()->get_typetype_ttcn3(); - if (member_type->is_coding_by_function()) { + if (member_type->is_coding_by_function(false)) { set_values_str = mputprintf(set_values_str, "BITSTRING buff_%d(", (int)i); switch (tt) { diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 44a8ebcf2d1e30915677ae2ecf49004c5c53793e..0dc39effb84bef0efe83045f8fde3a3419f8d44f 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -4582,7 +4582,7 @@ compile_time: target_type->get_genname_value(my_scope).c_str(), class_tmp_id.c_str(), target_type->get_genname_template(my_scope).c_str(), class_tmp_id.c_str(), target_type->get_genname_value(my_scope).c_str()); - bool dec_by_func = target_type->is_coding_by_function(); + bool dec_by_func = target_type->is_coding_by_function(false); if (dec_by_func) { str = mputprintf(str, // convert the TTCN_Buffer into a bitstring diff --git a/compiler2/ttcn3/Ttcnstuff.cc b/compiler2/ttcn3/Ttcnstuff.cc index e51f7aa230a9b19b9e2668480cfe6e4ea3d39f29..6be807e40b1493bb9d7b5627f8fdfdf972f017af 100644 --- a/compiler2/ttcn3/Ttcnstuff.cc +++ b/compiler2/ttcn3/Ttcnstuff.cc @@ -428,7 +428,7 @@ namespace Ttcn { source_type->get_typename().c_str(), Type::get_encoding_name(u.encdec.coding_type)); } - Type *stream_type = Type::get_stream_type(u.encdec.coding_type); + Type *stream_type = Type::get_stream_type(u.encdec.coding_type, 1); if (!stream_type->is_identical(target_type)) { target_type->error("Target type of %s encoding should be `%s' instead " "of `%s'", Type::get_encoding_name(u.encdec.coding_type), @@ -441,7 +441,7 @@ namespace Ttcn { void TypeMappingTarget::chk_decode(Type *source_type) { Error_Context cntxt(this, "In `decode' mapping"); - Type *stream_type = Type::get_stream_type(u.encdec.coding_type); + Type *stream_type = Type::get_stream_type(u.encdec.coding_type, 1); if (!stream_type->is_identical(source_type)) { source_type->error("Source type of %s encoding should be `%s' instead " "of `%s'", Type::get_encoding_name(u.encdec.coding_type), diff --git a/function_test/Semantic_Analyser/encode/Types_A.asn b/function_test/Semantic_Analyser/encode/Types_A.asn new file mode 100644 index 0000000000000000000000000000000000000000..4a7fbdcdda566b8f3b262615211c702e4ed731bd --- /dev/null +++ b/function_test/Semantic_Analyser/encode/Types_A.asn @@ -0,0 +1,42 @@ +------------------------------------------------------------------------------- +-- 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 +-- +------------------------------------------------------------------------------- + +Types-A +DEFINITIONS + +AUTOMATIC TAGS ::= + +BEGIN +IMPORTS; + +Int ::= INTEGER + +Seq ::= SEQUENCE { --//Cannot determine the encoding rules for ASN.1 type `@Types-A.Seq'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for ASN.1 type `@Types-A.Seq'. Multiple decoding external functions found with different rules// + num INTEGER, + str VisibleString +} + +Set ::= SET { + num INTEGER, + str VisibleString +} + +SeqOf ::= SEQUENCE OF INTEGER --//Multiple PER encoding functions set for type// //Multiple PER decoding functions set for type// + +SetOf ::= SET OF INTEGER + +Choice ::= CHOICE { --//Cannot determine the encoding rules for ASN.1 type `@Types-A.Choice'. Multiple encoding external functions found with different rules// //Cannot determine the decoding rules for ASN.1 type `@Types-A.Choice'. No decoding external functions found// + num INTEGER, + str VisibleString +} + +END diff --git a/function_test/Semantic_Analyser/encode/encode_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_SE.ttcn deleted file mode 100644 index 669a819527e33b16ed7140d063981fd272ec079d..0000000000000000000000000000000000000000 --- a/function_test/Semantic_Analyser/encode/encode_SE.ttcn +++ /dev/null @@ -1,33 +0,0 @@ -/****************************************************************************** - * 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: - * Balasko, Jeno - * Baranyi, Botond - * - ******************************************************************************/ -module encode_SE { - -type integer AnInt with { encode "nonexistent" }; //^error\: No custom decoding function found for type// - -type record ARecord { //^error\: No custom decoding function found for type// - integer i, - octetstring os -} - -control { - var ARecord x; - var AnInt y; - var bitstring bs := '110'B; - - if (decvalue(bs, y) != 0) {} - if (decvalue(bs, x) != 0) {} -} - -} with { - encode "whatever" -} diff --git a/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..74ad46d660c70d02027d1378e143f3694ae7c4b8 --- /dev/null +++ b/function_test/Semantic_Analyser/encode/encode_asn_SE.ttcn @@ -0,0 +1,126 @@ +/****************************************************************************** + * 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 + * + ******************************************************************************/ +module encode_asn_SE { //^In TTCN-3 module// + +import from Types_A all; + + +/* invalid PER coding functions */ +external function f_enc_list1(in Int x, out bitstring y) //^In external function definition// //Only `prototype\(convert\)' is allowed for PER encoding functions// + with { extension "prototype(fast) encode(PER)" } + +external function f_enc_list2(in Int x) return octetstring //^In external function definition// //The output type of PER encoding should be `bitstring' instead of `octetstring'// + with { extension "prototype(convert) encode(PER)" } + +external function f_dec_list1(in bitstring x) return Int //^In external function definition// //Only `prototype\(sliding\)' is allowed for PER decoding functions// + with { extension "prototype(convert) decode(PER)" } + +external function f_dec_list2(in bitstring x, out Int y) //^In external function definition// //Only `prototype\(sliding\)' is allowed for PER decoding functions// + with { extension "prototype(fast) decode(PER)" } + +external function f_dec_list3(in bitstring x, out Int y) return integer //^In external function definition// //Only `prototype\(sliding\)' is allowed for PER decoding functions// + with { extension "prototype(backtrack) decode(PER)" } + +external function f_dec_list4(inout charstring x, out Int y) return integer //^In external function definition// //The input type of PER decoding should be `bitstring' instead of `charstring'// + with { extension "prototype(sliding) decode(PER)" } + + +/* type with multiple different built-in coding funcions */ +external function f_enc_seq1(in Seq x) return bitstring + with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_seq2(in Seq x) return bitstring + with { extension "prototype(convert) encode(BER)" } + +external function f_dec_seq1(inout bitstring x, out Seq y) return integer + with { extension "prototype(sliding) decode(BER)" } + +function f1() { //^In function definition// + var Seq x := { num := 2, str := "x" }; + var bitstring y := encvalue(x); //^In variable definition// //^In the parameter of encvalue// + var integer res := decvalue(y, x); +} + +external function f_dec_seq2(in bitstring x, out Seq y) + with { extension "prototype(fast) decode(JSON)" } + + +/* type with multiple built-in encoding functions with the same coding rules, used by encvalue; + and multiple built-in decoding functions with different coding rules, but with no decvalue */ +external function f_enc_set1(in Set x) return bitstring + with { extension "prototype(convert) encode(BER)" } + +external function f_enc_set2(in Set x) return bitstring + with { extension "prototype(convert) encode(BER)" } + +external function f_dec_set1(inout bitstring x, out Set y) return integer + with { extension "prototype(sliding) decode(BER)" } + +function f2() { + var Set x := { num := 2, str := "x" }; + var bitstring y := encvalue(x); +} + +external function f_dec_set2(in bitstring x, out Set y) + with { extension "prototype(fast) decode(JSON)" } + + +/* type with multiple PER coding functions */ +external function f_enc_seqof1(in SeqOf x) return bitstring + with { extension "prototype(convert) encode(PER)" } + +external function f_enc_seqof2(in SeqOf x) return bitstring + with { extension "prototype(convert) encode(PER)" } + +external function f_dec_seqof1(inout bitstring x, out SeqOf y) return integer + with { extension "prototype(sliding) decode(PER)" } + +function f3() { + var SeqOf x := { 1, 2 }; + var bitstring y := encvalue(x); + var integer res := decvalue(y, x); +} + +external function f_dec_seqof2(inout bitstring x, out SeqOf y) return integer + with { extension "prototype(sliding) decode(PER)" } + + +/* type with multiple PER encoding functions, but no decvalue; + and both a built-in decoding function and a PER decoding function, but no decvalue */ +external function f_enc_setof1(in SetOf x) return bitstring + with { extension "prototype(convert) encode(PER)" } + +external function f_enc_setof2(in SetOf x) return bitstring + with { extension "prototype(convert) encode(PER)" } + +external function f_dec_setof1(inout bitstring x, out SetOf y) return integer + with { extension "prototype(sliding) decode(PER)" } + +external function f_dec_setof2(inout bitstring x, out SetOf y) return integer + with { extension "prototype(sliding) decode(BER)" } + + +/* type with both a built-in encoding function and a PER encoding function; + and with no decoding functions */ +function f4() { + var Choice x := { str := "p" }; + var bitstring y := encvalue(x); + var integer res := decvalue(y, x); +} + +external function f_enc_choice1(in Choice x) return bitstring + with { extension "prototype(convert) encode(JSON)" } + +external function f_enc_choice2(in Choice x) return bitstring + with { extension "prototype(convert) encode(PER)" } + +} diff --git a/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn b/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..1de761b6d15f61ff095bcb69eaa84066fceb3a7a --- /dev/null +++ b/function_test/Semantic_Analyser/encode/encode_ttcn_SE.ttcn @@ -0,0 +1,95 @@ +/****************************************************************************** + * 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: + * Balasko, Jeno + * Baranyi, Botond + * + ******************************************************************************/ +module encode_ttcn_SE { //^In TTCN-3 module// + + +/* types with no coder functions */ +type integer AnInt with { encode "nonexistent" }; //^error\: No custom decoding function found for type// + +type record ARecord { //^error\: No custom decoding function found for type// + integer i, + octetstring os +} + +function f1() { + var ARecord x; + var AnInt y; + var bitstring bs := '110'B; + + if (decvalue(bs, y) != 0) {} + if (decvalue(bs, x) != 0) {} +} + + +/* invalid custom coding functions */ +type record of integer AList with { encode "codec1" }; + +external function f_enc_list1(in AList x, out bitstring y) //^In external function definition// //Only `prototype\(convert\)' is allowed for custom encoding functions// + with { extension "prototype(fast) encode(codec1)" } + +external function f_enc_list2(in AList x) return octetstring //^In external function definition// //The output type of custom encoding should be `bitstring' instead of `octetstring'// + with { extension "prototype(convert) encode(codec1)" } + +external function f_dec_list1(in bitstring x) return AList //^In external function definition// //Only `prototype\(sliding\)' is allowed for custom decoding functions// + with { extension "prototype(convert) decode(codec1)" } + +external function f_dec_list2(in bitstring x, out AList y) //^In external function definition// //Only `prototype\(sliding\)' is allowed for custom decoding functions// + with { extension "prototype(fast) decode(codec1)" } + +external function f_dec_list3(in bitstring x, out AList y) return integer //^In external function definition// //Only `prototype\(sliding\)' is allowed for custom decoding functions// + with { extension "prototype(backtrack) decode(codec1)" } + +external function f_dec_list4(inout charstring x, out AList y) return integer //^In external function definition// //The input type of custom decoding should be `bitstring' instead of `charstring'// + with { extension "prototype(sliding) decode(codec1)" } + + +/* type with multiple custom coding functions */ +type union AUnion { //Multiple custom encoding functions set for type// //Multiple custom decoding functions set for type// + octetstring field +} +with { + encode "codec2" +} + +external function f_enc_uni1(in AUnion x) return bitstring + with { extension "prototype(convert) encode(codec2)" } + +external function f_enc_uni2(in AUnion x) return bitstring + with { extension "prototype(convert) encode(codec2)" } + +external function f_dec_uni1(inout bitstring x, out AUnion y) return integer + with { extension "prototype(sliding) decode(codec2)" } + +function f2() { //^In function definition// + var AUnion x := { field := '1234'O }; + var bitstring y := encvalue(x); //^In variable definition// //^In the parameter of encvalue// + var integer res := decvalue(y, x); +} + +external function f_dec_uni2(inout bitstring x, out AUnion y) return integer + with { extension "prototype(sliding) decode(codec2)" } + + +/* type with multiple custom encoding functions, but no encvalue */ +type integer AnArray[4] with { encode "codec3" } + +external function f_enc_arr1(in AnArray x) return bitstring + with { extension "prototype(convert) encode(codec3)" } + +external function f_enc_arr2(in AnArray x) return bitstring + with { extension "prototype(convert) encode(codec3)" } + + +} with { + encode "whatever" +} diff --git a/regression_test/customEncoding/Coders.cc b/regression_test/customEncoding/Coders.cc index 139db624d873e52bb9e9d2e92beb1265a4457b39..9fc5647d3b42ca6aeaac7591b7cd63c1ce2f1bbe 100644 --- a/regression_test/customEncoding/Coders.cc +++ b/regression_test/customEncoding/Coders.cc @@ -98,4 +98,54 @@ INTEGER f__dec__recof(BITSTRING& b, RecOf& x) return 0; } +BITSTRING f__enc__seqof(const Types::SeqOf& x) +{ + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer buf; + x.encode(Types::SeqOf_descr_, buf, TTCN_EncDec::CT_JSON, false); + OCTETSTRING tmp; + buf.get_string(tmp); + return oct2bit(tmp); +} + +INTEGER f__dec__seqof(BITSTRING& x, Types::SeqOf& y) +{ + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_Buffer buf(bit2oct(x)); + y.decode(Types::SeqOf_descr_, buf, TTCN_EncDec::CT_JSON); + switch (TTCN_EncDec::get_last_error_type()) { + case TTCN_EncDec::ET_NONE: { + buf.cut(); + OCTETSTRING tmp; + buf.get_string(tmp); + x = oct2bit(tmp); + return 0; } + case TTCN_EncDec::ET_INCOMPL_MSG: + case TTCN_EncDec::ET_LEN_ERR: + return 2; + default: + return 1; + } +} + +INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y) +{ + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); + TTCN_Buffer buf(bit2oct(x)); + y.decode(Types::Choice_descr_, buf, TTCN_EncDec::CT_JSON); + switch (TTCN_EncDec::get_last_error_type()) { + case TTCN_EncDec::ET_NONE: { + buf.cut(); + OCTETSTRING tmp; + buf.get_string(tmp); + x = oct2bit(tmp); + return 0; } + case TTCN_EncDec::ET_INCOMPL_MSG: + case TTCN_EncDec::ET_LEN_ERR: + return 2; + default: + return 1; + } +} + } // namespace Custom1 diff --git a/regression_test/customEncoding/Coders.hh b/regression_test/customEncoding/Coders.hh index c37b61b07a571417f86c644393e29475556501a8..ba40254300d3fd9d0c9b47c77d4f3c9f1ea06480 100644 --- a/regression_test/customEncoding/Coders.hh +++ b/regression_test/customEncoding/Coders.hh @@ -35,6 +35,11 @@ namespace Custom1 { BITSTRING f__enc__recof(const RecOf& x); INTEGER f__dec__recof(BITSTRING& b, RecOf& x); +// "PER" coder functions, using the built-in JSON codec +extern BITSTRING f__enc__seqof(const Types::SeqOf& x); +extern INTEGER f__dec__seqof(BITSTRING& x, Types::SeqOf& y); +extern INTEGER f__dec__choice(BITSTRING& x, Types::Choice& y); + } #endif diff --git a/regression_test/customEncoding/Custom1.ttcn b/regression_test/customEncoding/Custom1.ttcn index 8f253de2f4afe96fbaa3c192009fbc66da86f4b0..c26b7b56ffd3c597ebca7b9d66feb1aedacfa503 100644 --- a/regression_test/customEncoding/Custom1.ttcn +++ b/regression_test/customEncoding/Custom1.ttcn @@ -14,9 +14,11 @@ // This module tests custom encoding for TTCN-3 types and encoding for ASN.1 types // (Encvalue and decvalue encode and decode values of TTCN-3 types using manually written // external functions, as long as they have the same encoding name as the value's type. -// A similar technique is used when using encvalue or decvalue on a value of -// and ASN.1 type: an encoding/decoding external function, of a built-in encoding type, -// must be declared for the ASN.1 type). +// When using encvalue or decvalue on a value of an ASN.1 type an encoding/decoding +// external function, of a built-in encoding type, must be declared for the ASN.1 type. +// PER encoding for ASN.1 types works similarly to custom encoding for TTCN-3 types: +// encoding and decoding is done by manually written coders, that are declared with +// the 'PER' encoding attribute, instead of a custom encoding attribute). module Custom1 { import from Custom2 all; @@ -326,6 +328,128 @@ testcase tc_asn_decmatch() runs on CT } } +// PER coder functions, these need to be implemented manually, just like custom +// coder functions +external function f_enc_seqof(in SeqOf x) return bitstring + with { extension "prototype(convert) encode(PER)" }; + +external function f_dec_seqof(inout bitstring x, out SeqOf y) return integer + with { extension "prototype(sliding) decode(PER)" }; + +// Test 11. +// PER coder with encvalue and decvalue. +testcase tc_per() runs on CT +{ + var SeqOf x := { 1, 2, 3 }; + // the manually written "PER" coder for this module uses the built-in JSON coder + var bitstring enc_exp := oct2bit(char2oct("[1,2,3]")); + var SeqOf dec_exp := x; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var SeqOf dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Failed to decode ", enc_exp); + } + if (dec != dec_exp) { + setverdict(fail, "Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +// Test 12. +// The redirected parameter is decoded using the PER coder. +// Same input value as in test 11. +testcase tc_per_param_redirect() runs on CT +{ + connect(self:pt_proc, self:pt_proc); + var SeqOf val := { 1, 2, 3 }; + var charstring str_fmt := "UTF-8"; + var universal charstring val_enc := encvalue_unichar(val, str_fmt); + var SeqOf res; + pt_proc.reply(Sig: { p := val_enc }); + timer tmr := 1.0; + tmr.start; + alt { + [] pt_proc.getreply(Sig: { p := val_enc }) -> param (res := @decoded(str_fmt) p) { + if (res != val) { + setverdict(fail, "Invalid decoded parameter. Expected: ", val, ", got: ", res); + } + else { + setverdict(pass); + } + } + [] pt_proc.getreply(Sig: { p := ?}) { + setverdict(fail, "Invalid reply received."); + } + [] tmr.timeout { + setverdict(fail, "Timed out."); + } + } +} + +// Test 13. +// Decoded content matching with the PER coder. +// Same input value as in test 11. +testcase tc_per_decmatch() runs on CT +{ + connect(self:pt_msg, self:pt_msg); + var SeqOf val := { 1, 2, 3 }; + var Msg msg := { data := omit, list := { encvalue(val) } }; + var SeqOf res; + pt_msg.send(msg); + timer tmr := 1.0; + tmr.start; + alt { + [] pt_msg.receive(Msg: { data := omit, list := { decmatch val } }) { + setverdict(pass); + } + [] pt_msg.receive(?) { + setverdict(fail, "Invalid message received or decoded content matching failed."); + } + [] tmr.timeout { + setverdict(fail, "Timed out."); + } + } +} + +// encoder function for ASN.1 type Choice, using the built-in JSON codec +external function f_enc_choice(in Choice x) return bitstring + with { extension "prototype(convert) encode(JSON)" }; + +// PER decoder function for ASN.1 type Choice, which needs to be implemented manually +external function f_dec_choice(inout bitstring x, out Choice y) return integer + with { extension "prototype(sliding) decode(PER)" }; + +// Test 14. +// Encoding an ASN.1 type with JSON (built-in) and decoding the same type with PER (manual). +testcase tc_asn_mixed() runs on CT +{ + var Choice x := { num := 2 }; + var bitstring enc_exp := oct2bit(char2oct("{\"num\":2}")); + // the manually written "PER" decoder for this module uses the built-in JSON coder, + // so the encoding result can safely be used as input for the decoder, and the + // decoding result will be the initial value + var Choice dec_exp := x; + + var bitstring enc := encvalue(x); + if (enc != enc_exp) { + setverdict(fail, "Expected: ", enc_exp, ", got: ", enc); + } + var Choice dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Failed to decode ", enc_exp); + } + if (dec != dec_exp) { + setverdict(fail, "Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + control { execute(tc_custom1()); execute(tc_custom2()); @@ -337,6 +461,10 @@ control { execute(tc_asn()); execute(tc_asn_param_redirect()); execute(tc_asn_decmatch()); + execute(tc_per()); + execute(tc_per_param_redirect()); + execute(tc_per_decmatch()); + execute(tc_asn_mixed()); } } diff --git a/regression_test/customEncoding/Custom4.ttcn b/regression_test/customEncoding/Custom4.ttcn index 9326226fe0675ac0d2457e35ffe57e075b3ae6d1..9a6bfbe50f5a180d92d7efb22f9ec0b4d251ad8b 100644 --- a/regression_test/customEncoding/Custom4.ttcn +++ b/regression_test/customEncoding/Custom4.ttcn @@ -19,7 +19,7 @@ import from Custom2 all; import from Custom3 all; import from Types all; -// Test 11 (RT2 only). +// Test 15 (RT2 only). // Using custom encoding on a decoded value redirect. // Same input value as in test 1. testcase tc_custom_value_redirect() runs on CT @@ -50,7 +50,7 @@ testcase tc_custom_value_redirect() runs on CT } } -// Test 12 (RT2 only). +// Test 16 (RT2 only). // The redirected value is decoded into a value of ASN.1 type Seq. // Same input value as in test 8. testcase tc_asn_value_redirect() runs on CT @@ -80,9 +80,40 @@ testcase tc_asn_value_redirect() runs on CT } } +// Test 17 (RT2 only). +// The redirected value is decoded using the PER coder. +// Same input value as in test 11. +testcase tc_per_value_redirect() runs on CT +{ + connect(self:pt_msg, self:pt_msg); + var SeqOf val := { 1, 2, 3 }; + var Msg msg := { data := bit2oct(encvalue(val)), list := { } }; + var SeqOf res; + pt_msg.send(msg); + timer tmr := 1.0; + tmr.start; + alt { + [] pt_msg.receive(msg) -> value (res := @decoded data) { + if (res != val) { + setverdict(fail, "Invalid decoded value. Expected: ", val, ", got: ", res); + } + else { + setverdict(pass); + } + } + [] pt_msg.receive(?) { + setverdict(fail, "Invalid message received."); + } + [] tmr.timeout { + setverdict(fail, "Timed out."); + } + } +} + control { execute(tc_custom_value_redirect()); execute(tc_asn_value_redirect()); + execute(tc_per_value_redirect()); } } diff --git a/regression_test/customEncoding/Types.asn b/regression_test/customEncoding/Types.asn index b3ce172b1ce327e92a7272335bfa32f57070a054..19381f6f7671fb6209bb9e5a1e1e153b1b297ba7 100644 --- a/regression_test/customEncoding/Types.asn +++ b/regression_test/customEncoding/Types.asn @@ -23,4 +23,11 @@ Seq ::= SEQUENCE { str VisibleString } +SeqOf ::= SEQUENCE OF INTEGER + +Choice ::= CHOICE { + num INTEGER, + str VisibleString +} + END diff --git a/regression_test/json/Functions.ttcn b/regression_test/json/Functions.ttcn index 888eab1e7b952de4e49ffd0c66995853aba4fe9e..2387a5737b808e5403ee54bbfed393acc1f1daf0 100644 --- a/regression_test/json/Functions.ttcn +++ b/regression_test/json/Functions.ttcn @@ -67,7 +67,7 @@ external function f_enc_A(in A u) return octetstring external function f_enc_ER(in EmptyRec u) return octetstring with { extension "prototype(convert)"; extension "encode(JSON)"; } -external function f_enc_roi(in RoI u) return octetstring +external function f_enc_roi(in RoI u) return bitstring with { extension "prototype(convert)"; extension "encode(JSON)"; } external function f_enc_rof(in RoF u) return octetstring @@ -215,7 +215,7 @@ external function f_dec_A(in octetstring x) return A external function f_dec_ER(in octetstring x) return EmptyRec with { extension "prototype(convert)"; extension "decode(JSON)"; } -external function f_dec_roi(in octetstring x) return RoI +external function f_dec_roi(in bitstring x) return RoI with { extension "prototype(convert)"; extension "decode(JSON)"; } external function f_dec_rof(in octetstring x) return RoF @@ -302,6 +302,15 @@ function f_check_encoding(in octetstring encoded, in octetstring expected) { } } with { extension "transparent"} + function f_check_encoding_bit(in bitstring encoded, in bitstring expected) { + log("encoded: ",encoded," expected: ",expected) + if(encoded == expected) { + setverdict(pass); + } else { + setverdict(fail, "expected:", expected,"received: ", encoded); + } + } with { extension "transparent"} + function f_bool2verdict(in boolean b) { diff --git a/regression_test/json/Testcases.ttcn b/regression_test/json/Testcases.ttcn index aead2100a0c40b96a1207740eb100274f67ac05d..0e06cd7d0acf0d225e8bc6fa8c88192c42b933d0 100644 --- a/regression_test/json/Testcases.ttcn +++ b/regression_test/json/Testcases.ttcn @@ -367,35 +367,35 @@ testcase tc_record_empty() runs on MTC{ //====== Record of=============== -//ROI +//ROI (with bitstring as stream type) testcase tc_recordofinteger_empty() runs on MTC{ var RoI r:={} - var octetstring os := char2oct("[]"); - f_check_encoding(encoded:= f_enc_roi(r), expected := os) + var bitstring bs := oct2bit(char2oct("[]")); + f_check_encoding_bit(encoded:= f_enc_roi(r), expected := bs) f_bool2verdict(match(f_dec_roi(f_enc_roi(r)), r)); } testcase tc_recordofinteger_short() runs on MTC{ var RoI r:= { 1, 4, 5, 7, 6, 6, 4, 0 , -1 }; - var octetstring os := char2oct("[1,4,5,7,6,6,4,0,-1]"); - f_check_encoding(encoded:= f_enc_roi(r), expected := os) + var bitstring bs := oct2bit(char2oct("[1,4,5,7,6,6,4,0,-1]")); + f_check_encoding_bit(encoded:= f_enc_roi(r), expected := bs) f_bool2verdict(match(f_dec_roi(f_enc_roi(r)), r)); } testcase tc_recordofinteger_long() runs on MTC{ var RoI r:= {0}; - var octetstring os := char2oct("[0"); + var bitstring bs := oct2bit(char2oct("[0")); //init: for(var integer i:=1; i<50; i:=i+1) { r[i]:=i; - os := os & commao & char2oct(int2str(i)); + bs := bs & oct2bit(commao) & oct2bit(char2oct(int2str(i))); } - os := os & char2oct("]") + bs := bs & oct2bit(char2oct("]")); log(r); - log(os) + log(bs) //test: - f_check_encoding(encoded:= f_enc_roi(r), expected := os) + f_check_encoding_bit(encoded:= f_enc_roi(r), expected := bs) f_bool2verdict(match(f_dec_roi(f_enc_roi(r)), r)); } diff --git a/usrguide/referenceguide.doc b/usrguide/referenceguide.doc index a88648aaab64708ff3359ed4b851a533b6c262be..a4e2530b477741e8b22beb353ba707e7dcfd28a8 100644 Binary files a/usrguide/referenceguide.doc and b/usrguide/referenceguide.doc differ